diff options
276 files changed, 4060 insertions, 1955 deletions
diff --git a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt new file mode 100644 index 00000000000..bf984d23862 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt @@ -0,0 +1,27 @@ +Device Tree bindings for the Armada 370 DB audio +================================================ + +These Device Tree bindings are used to describe the audio complex +found on the Armada 370 DB platform. + +Mandatory properties: + + * compatible: must be "marvell,a370db-audio" + + * marvell,audio-controller: a phandle that points to the audio + controller of the Armada 370 SoC. + + * marvell,audio-codec: a set of three phandles that points to: + + 1/ the analog audio codec connected to the Armada 370 SoC + 2/ the S/PDIF transceiver + 3/ the S/PDIF receiver + +Example: + + sound { + compatible = "marvell,a370db-audio"; + marvell,audio-controller = <&audio_controller>; + marvell,audio-codec = <&audio_codec &spdif_out &spdif_in>; + status = "okay"; + }; diff --git a/Documentation/devicetree/bindings/sound/cs42xx8.txt b/Documentation/devicetree/bindings/sound/cs42xx8.txt new file mode 100644 index 00000000000..f631fbca628 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs42xx8.txt @@ -0,0 +1,28 @@ +CS42448/CS42888 audio CODEC + +Required properties: + + - compatible : must contain one of "cirrus,cs42448" and "cirrus,cs42888" + + - reg : the I2C address of the device for I2C + + - clocks : a list of phandles + clock-specifiers, one for each entry in + clock-names + + - clock-names : must contain "mclk" + + - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, + as covered in Documentation/devicetree/bindings/regulator/regulator.txt + +Example: + +codec: cs42888@48 { + compatible = "cirrus,cs42888"; + reg = <0x48>; + clocks = <&codec_mclk 0>; + clock-names = "mclk"; + VA-supply = <®_audio>; + VD-supply = <®_audio>; + VLS-supply = <®_audio>; + VLC-supply = <®_audio>; +}; diff --git a/Documentation/devicetree/bindings/sound/mvebu-audio.txt b/Documentation/devicetree/bindings/sound/mvebu-audio.txt index f0062c5871b..cb8c07c81ce 100644 --- a/Documentation/devicetree/bindings/sound/mvebu-audio.txt +++ b/Documentation/devicetree/bindings/sound/mvebu-audio.txt @@ -5,6 +5,7 @@ Required properties: - compatible: "marvell,kirkwood-audio" for Kirkwood platforms "marvell,dove-audio" for Dove platforms + "marvell,armada370-audio" for Armada 370 platforms - reg: physical base address of the controller and length of memory mapped region. diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt new file mode 100644 index 00000000000..74c66dee3e1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt @@ -0,0 +1,61 @@ +Texas Instruments - tlv320aic31xx Codec module + +The tlv320aic31xx serial control bus communicates through I2C protocols + +Required properties: + +- compatible - "string" - One of: + "ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp + "ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp + "ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP) + "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) + "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) + "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) + +- reg - <int> - I2C slave address + + +Optional properties: + +- gpio-reset - gpio pin number used for codec reset +- ai31xx-micbias-vg - MicBias Voltage setting + 1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V + 2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V + 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD + If this node is not mentioned or if the value is unknown, then + micbias is set to 2.0V. +- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, + DVDD-supply : power supplies for the device as covered in + Documentation/devicetree/bindings/regulator/regulator.txt + +CODEC output pins: + * HPL + * HPR + * SPL, devices with stereo speaker amp + * SPR, devices with stereo speaker amp + * SPK, devices with mono speaker amp + * MICBIAS + +CODEC input pins: + * MIC1LP + * MIC1RP + * MIC1LM + +The pins can be used in referring sound node's audio-routing property. + +Example: +#include <dt-bindings/sound/tlv320aic31xx-micbias.h> + +tlv320aic31xx: tlv320aic31xx@18 { + compatible = "ti,tlv320aic311x"; + reg = <0x18>; + + ai31xx-micbias-vg = <MICBIAS_OFF>; + + HPVDD-supply = <®ulator>; + SPRVDD-supply = <®ulator>; + SPLVDD-supply = <®ulator>; + AVDD-supply = <®ulator>; + IOVDD-supply = <®ulator>; + DVDD-supply = <®ulator>; +}; diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 1404674c0a0..6fea79efb4c 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -453,7 +453,7 @@ TP_STATUS_COPY : This flag indicates that the frame (and associated enabled previously with setsockopt() and the PACKET_COPY_THRESH option. - The number of frames than can be buffered to + The number of frames that can be buffered to be read with recvfrom is limited like a normal socket. See the SO_RCVBUF option in the socket (7) man page. diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index 661d3c316a1..048c92b487f 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt @@ -21,26 +21,38 @@ has such a feature). SO_TIMESTAMPING: -Instructs the socket layer which kind of information is wanted. The -parameter is an integer with some of the following bits set. Setting -other bits is an error and doesn't change the current state. - -SOF_TIMESTAMPING_TX_HARDWARE: try to obtain send time stamp in hardware -SOF_TIMESTAMPING_TX_SOFTWARE: if SOF_TIMESTAMPING_TX_HARDWARE is off or - fails, then do it in software -SOF_TIMESTAMPING_RX_HARDWARE: return the original, unmodified time stamp - as generated by the hardware -SOF_TIMESTAMPING_RX_SOFTWARE: if SOF_TIMESTAMPING_RX_HARDWARE is off or - fails, then do it in software -SOF_TIMESTAMPING_RAW_HARDWARE: return original raw hardware time stamp -SOF_TIMESTAMPING_SYS_HARDWARE: return hardware time stamp transformed to - the system time base -SOF_TIMESTAMPING_SOFTWARE: return system time stamp generated in - software - -SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. -SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the -following control message: +Instructs the socket layer which kind of information should be collected +and/or reported. The parameter is an integer with some of the following +bits set. Setting other bits is an error and doesn't change the current +state. + +Four of the bits are requests to the stack to try to generate +timestamps. Any combination of them is valid. + +SOF_TIMESTAMPING_TX_HARDWARE: try to obtain send time stamps in hardware +SOF_TIMESTAMPING_TX_SOFTWARE: try to obtain send time stamps in software +SOF_TIMESTAMPING_RX_HARDWARE: try to obtain receive time stamps in hardware +SOF_TIMESTAMPING_RX_SOFTWARE: try to obtain receive time stamps in software + +The other three bits control which timestamps will be reported in a +generated control message. If none of these bits are set or if none of +the set bits correspond to data that is available, then the control +message will not be generated: + +SOF_TIMESTAMPING_SOFTWARE: report systime if available +SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available +SOF_TIMESTAMPING_RAW_HARDWARE: report hwtimeraw if available + +It is worth noting that timestamps may be collected for reasons other +than being requested by a particular socket with +SOF_TIMESTAMPING_[TR]X_(HARD|SOFT)WARE. For example, most drivers that +can generate hardware receive timestamps ignore +SOF_TIMESTAMPING_RX_HARDWARE. It is still a good idea to set that flag +in case future drivers pay attention. + +If timestamps are reported, they will appear in a control message with +cmsg_level==SOL_SOCKET, cmsg_type==SO_TIMESTAMPING, and a payload like +this: struct scm_timestamping { struct timespec systime; diff --git a/MAINTAINERS b/MAINTAINERS index b7befe75842..7c42d59effa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1738,6 +1738,7 @@ F: include/uapi/linux/bfs_fs.h BLACKFIN ARCHITECTURE M: Steven Miao <realmz6@gmail.com> L: adi-buildroot-devel@lists.sourceforge.net +T: git git://git.code.sf.net/p/adi-linux/code W: http://blackfin.uclinux.org S: Supported F: arch/blackfin/ @@ -2202,6 +2203,13 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Odd Fixes F: sound/soc/codecs/cs4270* +CIRRUS LOGIC AUDIO CODEC DRIVERS +M: Brian Austin <brian.austin@cirrus.com> +M: Paul Handrigan <Paul.Handrigan@cirrus.com> +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +S: Maintained +F: sound/soc/codecs/cs* + CLEANCACHE API M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> L: linux-kernel@vger.kernel.org @@ -6002,6 +6010,8 @@ F: include/linux/netdevice.h F: include/uapi/linux/in.h F: include/uapi/linux/net.h F: include/uapi/linux/netdevice.h +F: tools/net/ +F: tools/testing/selftests/net/ NETWORKING [IPv4/IPv6] M: "David S. Miller" <davem@davemloft.net> @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Shuffling Zombie Juror # *DOCUMENTATION* diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 93533e2710a..9323854242c 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -988,14 +988,12 @@ static struct asoc_simple_card_info fsi_wm8978_info = { .card = "FSI2A-WM8978", .codec = "wm8978.0-001a", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "wm8978-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, .sysclk = 12288000, }, }; diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index bc40b853ffd..03dc3ac8450 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -589,14 +589,12 @@ static struct asoc_simple_card_info fsi2_ak4648_info = { .card = "FSI2A-AK4648", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 3aba0372f63..0ff4d8e45cf 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -509,9 +509,9 @@ static struct asoc_simple_card_info fsi2_hdmi_info = { .card = "FSI2B-HDMI", .codec = "sh-mobile-hdmi", .platform = "sh_fsi2", + .daifmt = SND_SOC_DAIFMT_CBS_CFS, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "sh_mobile_hdmi-hifi", @@ -905,14 +905,12 @@ static struct asoc_simple_card_info fsi2_ak4643_info = { .card = "FSI2A-AK4643", .codec = "ak4642-codec.0-0013", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h index 184066ceb1f..053c17b3655 100644 --- a/arch/cris/include/asm/bitops.h +++ b/arch/cris/include/asm/bitops.h @@ -144,7 +144,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) * definition, which doesn't have the same semantics. We don't want to * use -fno-builtin, so just hide the name ffs. */ -#define ffs kernel_ffs +#define ffs(x) kernel_ffs(x) #include <asm-generic/bitops/fls.h> #include <asm-generic/bitops/__fls.h> diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index a96bcf83a73..20e8a9b21d7 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -98,7 +98,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid) /* attempt to allocate a granule's worth of cached memory pages */ page = alloc_pages_exact_node(nid, - GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, IA64_GRANULE_SHIFT-PAGE_SHIFT); if (!page) { mutex_unlock(&uc_pool->add_chunk_mutex); diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 5ec1e47a0d7..e865d748179 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -123,7 +123,8 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order) area->nid = nid; area->order = order; - area->pages = alloc_pages_exact_node(area->nid, GFP_KERNEL|GFP_THISNODE, + area->pages = alloc_pages_exact_node(area->nid, + GFP_KERNEL|__GFP_THISNODE, area->order); if (!area->pages) { diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 5bc3a15465c..85d5255d259 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -861,14 +861,12 @@ static struct asoc_simple_card_info fsi_da7210_info = { .card = "FSIB-DA7210", .codec = "da7210.0-001a", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "da7210-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, }, }; diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 21e4230659a..1162bc6945a 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -304,14 +304,12 @@ static struct asoc_simple_card_info fsi_ak4642_info = { .card = "FSIA-AK4642", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index c026cca5602..f3aaf231b4e 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -341,10 +341,6 @@ config X86_USE_3DNOW def_bool y depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML -config X86_OOSTORE - def_bool y - depends on (MWINCHIP3D || MWINCHIPC6) && MTRR - # # P6_NOPs are a relatively minor optimization that require a family >= # 6 processor, except that it is broken on certain VIA chips. diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index 04a48903b2e..69bbb484502 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -85,11 +85,7 @@ #else # define smp_rmb() barrier() #endif -#ifdef CONFIG_X86_OOSTORE -# define smp_wmb() wmb() -#else -# define smp_wmb() barrier() -#endif +#define smp_wmb() barrier() #define smp_read_barrier_depends() read_barrier_depends() #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) #else /* !SMP */ @@ -100,7 +96,7 @@ #define set_mb(var, value) do { var = value; barrier(); } while (0) #endif /* SMP */ -#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE) +#if defined(CONFIG_X86_PPRO_FENCE) /* * For either of these options x86 doesn't have a strong TSO memory diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 34f69cb9350..91d9c69a629 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -237,7 +237,7 @@ memcpy_toio(volatile void __iomem *dst, const void *src, size_t count) static inline void flush_write_buffers(void) { -#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE) +#if defined(CONFIG_X86_PPRO_FENCE) asm volatile("lock; addl $0,0(%%esp)": : :"memory"); #endif } diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index bf156ded74b..0f62f5482d9 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -26,10 +26,9 @@ # define LOCK_PTR_REG "D" #endif -#if defined(CONFIG_X86_32) && \ - (defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)) +#if defined(CONFIG_X86_32) && (defined(CONFIG_X86_PPRO_FENCE)) /* - * On PPro SMP or if we are using OOSTORE, we use a locked operation to unlock + * On PPro SMP, we use a locked operation to unlock * (PPro errata 66, 92) */ # define UNLOCK_LOCK_PREFIX LOCK_PREFIX diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 8779edab684..d8fba5c15fb 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -8,236 +8,6 @@ #include "cpu.h" -#ifdef CONFIG_X86_OOSTORE - -static u32 power2(u32 x) -{ - u32 s = 1; - - while (s <= x) - s <<= 1; - - return s >>= 1; -} - - -/* - * Set up an actual MCR - */ -static void centaur_mcr_insert(int reg, u32 base, u32 size, int key) -{ - u32 lo, hi; - - hi = base & ~0xFFF; - lo = ~(size-1); /* Size is a power of 2 so this makes a mask */ - lo &= ~0xFFF; /* Remove the ctrl value bits */ - lo |= key; /* Attribute we wish to set */ - wrmsr(reg+MSR_IDT_MCR0, lo, hi); - mtrr_centaur_report_mcr(reg, lo, hi); /* Tell the mtrr driver */ -} - -/* - * Figure what we can cover with MCR's - * - * Shortcut: We know you can't put 4Gig of RAM on a winchip - */ -static u32 ramtop(void) -{ - u32 clip = 0xFFFFFFFFUL; - u32 top = 0; - int i; - - for (i = 0; i < e820.nr_map; i++) { - unsigned long start, end; - - if (e820.map[i].addr > 0xFFFFFFFFUL) - continue; - /* - * Don't MCR over reserved space. Ignore the ISA hole - * we frob around that catastrophe already - */ - if (e820.map[i].type == E820_RESERVED) { - if (e820.map[i].addr >= 0x100000UL && - e820.map[i].addr < clip) - clip = e820.map[i].addr; - continue; - } - start = e820.map[i].addr; - end = e820.map[i].addr + e820.map[i].size; - if (start >= end) - continue; - if (end > top) - top = end; - } - /* - * Everything below 'top' should be RAM except for the ISA hole. - * Because of the limited MCR's we want to map NV/ACPI into our - * MCR range for gunk in RAM - * - * Clip might cause us to MCR insufficient RAM but that is an - * acceptable failure mode and should only bite obscure boxes with - * a VESA hole at 15Mb - * - * The second case Clip sometimes kicks in is when the EBDA is marked - * as reserved. Again we fail safe with reasonable results - */ - if (top > clip) - top = clip; - - return top; -} - -/* - * Compute a set of MCR's to give maximum coverage - */ -static int centaur_mcr_compute(int nr, int key) -{ - u32 mem = ramtop(); - u32 root = power2(mem); - u32 base = root; - u32 top = root; - u32 floor = 0; - int ct = 0; - - while (ct < nr) { - u32 fspace = 0; - u32 high; - u32 low; - - /* - * Find the largest block we will fill going upwards - */ - high = power2(mem-top); - - /* - * Find the largest block we will fill going downwards - */ - low = base/2; - - /* - * Don't fill below 1Mb going downwards as there - * is an ISA hole in the way. - */ - if (base <= 1024*1024) - low = 0; - - /* - * See how much space we could cover by filling below - * the ISA hole - */ - - if (floor == 0) - fspace = 512*1024; - else if (floor == 512*1024) - fspace = 128*1024; - - /* And forget ROM space */ - - /* - * Now install the largest coverage we get - */ - if (fspace > high && fspace > low) { - centaur_mcr_insert(ct, floor, fspace, key); - floor += fspace; - } else if (high > low) { - centaur_mcr_insert(ct, top, high, key); - top += high; - } else if (low > 0) { - base -= low; - centaur_mcr_insert(ct, base, low, key); - } else - break; - ct++; - } - /* - * We loaded ct values. We now need to set the mask. The caller - * must do this bit. - */ - return ct; -} - -static void centaur_create_optimal_mcr(void) -{ - int used; - int i; - - /* - * Allocate up to 6 mcrs to mark as much of ram as possible - * as write combining and weak write ordered. - * - * To experiment with: Linux never uses stack operations for - * mmio spaces so we could globally enable stack operation wc - * - * Load the registers with type 31 - full write combining, all - * writes weakly ordered. - */ - used = centaur_mcr_compute(6, 31); - - /* - * Wipe unused MCRs - */ - for (i = used; i < 8; i++) - wrmsr(MSR_IDT_MCR0+i, 0, 0); -} - -static void winchip2_create_optimal_mcr(void) -{ - u32 lo, hi; - int used; - int i; - - /* - * Allocate up to 6 mcrs to mark as much of ram as possible - * as write combining, weak store ordered. - * - * Load the registers with type 25 - * 8 - weak write ordering - * 16 - weak read ordering - * 1 - write combining - */ - used = centaur_mcr_compute(6, 25); - - /* - * Mark the registers we are using. - */ - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - for (i = 0; i < used; i++) - lo |= 1<<(9+i); - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - - /* - * Wipe unused MCRs - */ - - for (i = used; i < 8; i++) - wrmsr(MSR_IDT_MCR0+i, 0, 0); -} - -/* - * Handle the MCR key on the Winchip 2. - */ -static void winchip2_unprotect_mcr(void) -{ - u32 lo, hi; - u32 key; - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - lo &= ~0x1C0; /* blank bits 8-6 */ - key = (lo>>17) & 7; - lo |= key<<6; /* replace with unlock key */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); -} - -static void winchip2_protect_mcr(void) -{ - u32 lo, hi; - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - lo &= ~0x1C0; /* blank bits 8-6 */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); -} -#endif /* CONFIG_X86_OOSTORE */ - #define ACE_PRESENT (1 << 6) #define ACE_ENABLED (1 << 7) #define ACE_FCR (1 << 28) /* MSR_VIA_FCR */ @@ -362,20 +132,6 @@ static void init_centaur(struct cpuinfo_x86 *c) fcr_clr = DPDC; printk(KERN_NOTICE "Disabling bugged TSC.\n"); clear_cpu_cap(c, X86_FEATURE_TSC); -#ifdef CONFIG_X86_OOSTORE - centaur_create_optimal_mcr(); - /* - * Enable: - * write combining on non-stack, non-string - * write combining on string, all types - * weak write ordering - * - * The C6 original lacks weak read order - * - * Note 0x120 is write only on Winchip 1 - */ - wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); -#endif break; case 8: switch (c->x86_mask) { @@ -392,40 +148,12 @@ static void init_centaur(struct cpuinfo_x86 *c) fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK| E2MMX|EAMD3D; fcr_clr = DPDC; -#ifdef CONFIG_X86_OOSTORE - winchip2_unprotect_mcr(); - winchip2_create_optimal_mcr(); - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - /* - * Enable: - * write combining on non-stack, non-string - * write combining on string, all types - * weak write ordering - */ - lo |= 31; - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - winchip2_protect_mcr(); -#endif break; case 9: name = "3"; fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK| E2MMX|EAMD3D; fcr_clr = DPDC; -#ifdef CONFIG_X86_OOSTORE - winchip2_unprotect_mcr(); - winchip2_create_optimal_mcr(); - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - /* - * Enable: - * write combining on non-stack, non-string - * write combining on string, all types - * weak write ordering - */ - lo |= 31; - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - winchip2_protect_mcr(); -#endif break; default: name = "??"; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index c88f7f4b03e..047f540cf3f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -3334,6 +3334,8 @@ static int __init uncore_type_init(struct intel_uncore_type *type) if (!pmus) return -ENOMEM; + type->pmus = pmus; + type->unconstrainted = (struct event_constraint) __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1, 0, type->num_counters, 0, 0); @@ -3369,7 +3371,6 @@ static int __init uncore_type_init(struct intel_uncore_type *type) } type->pmu_group = &uncore_pmu_attr_group; - type->pmus = pmus; return 0; fail: uncore_type_exit(type); diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index e8368c6dd2a..d5dd8081441 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -86,10 +86,19 @@ EXPORT_SYMBOL(__kernel_fpu_begin); void __kernel_fpu_end(void) { - if (use_eager_fpu()) - math_state_restore(); - else + if (use_eager_fpu()) { + /* + * For eager fpu, most the time, tsk_used_math() is true. + * Restore the user math as we are done with the kernel usage. + * At few instances during thread exit, signal handling etc, + * tsk_used_math() is false. Those few places will take proper + * actions, so we don't need to restore the math here. + */ + if (likely(tsk_used_math(current))) + math_state_restore(); + } else { stts(); + } } EXPORT_SYMBOL(__kernel_fpu_end); diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 7c6acd4b899..ff898bbf579 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -529,7 +529,7 @@ static void quirk_amd_nb_node(struct pci_dev *dev) return; pci_read_config_dword(nb_ht, 0x60, &val); - node = val & 7; + node = pcibus_to_node(dev->bus) | (val & 7); /* * Some hardware may return an invalid node ID, * so check it first: diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e81df8fce02..2de1bc09a8d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3002,10 +3002,8 @@ static int cr8_write_interception(struct vcpu_svm *svm) u8 cr8_prev = kvm_get_cr8(&svm->vcpu); /* instruction emulation calls kvm_set_cr8() */ r = cr_interception(svm); - if (irqchip_in_kernel(svm->vcpu.kvm)) { - clr_cr_intercept(svm, INTERCEPT_CR8_WRITE); + if (irqchip_in_kernel(svm->vcpu.kvm)) return r; - } if (cr8_prev <= kvm_get_cr8(&svm->vcpu)) return r; kvm_run->exit_reason = KVM_EXIT_SET_TPR; @@ -3567,6 +3565,8 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK)) return; + clr_cr_intercept(svm, INTERCEPT_CR8_WRITE); + if (irr == -1) return; diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S index 877b9a1b215..01495755701 100644 --- a/arch/x86/net/bpf_jit.S +++ b/arch/x86/net/bpf_jit.S @@ -140,7 +140,7 @@ bpf_slow_path_byte_msh: push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ - mov $SIZE,%ecx; /* size */ \ + mov $SIZE,%edx; /* size */ \ call bpf_internal_load_pointer_neg_helper; \ test %rax,%rax; \ pop SKBDATA; \ diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h index 7d01b8c56c0..cc04e67bfd0 100644 --- a/arch/x86/um/asm/barrier.h +++ b/arch/x86/um/asm/barrier.h @@ -40,11 +40,7 @@ #define smp_rmb() barrier() #endif /* CONFIG_X86_PPRO_FENCE */ -#ifdef CONFIG_X86_OOSTORE -#define smp_wmb() wmb() -#else /* CONFIG_X86_OOSTORE */ #define smp_wmb() barrier() -#endif /* CONFIG_X86_OOSTORE */ #define smp_read_barrier_depends() read_barrier_depends() #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index b718806657c..c40fb2e81bb 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -71,6 +71,17 @@ static int acpi_sleep_prepare(u32 acpi_state) return 0; } +static bool acpi_sleep_state_supported(u8 sleep_state) +{ + acpi_status status; + u8 type_a, type_b; + + status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b); + return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware + || (acpi_gbl_FADT.sleep_control.address + && acpi_gbl_FADT.sleep_status.address)); +} + #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; @@ -604,15 +615,9 @@ static void acpi_sleep_suspend_setup(void) { int i; - for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { - acpi_status status; - u8 type_a, type_b; - - status = acpi_get_sleep_type_data(i, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { + for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) + if (acpi_sleep_state_supported(i)) sleep_states[i] = 1; - } - } suspend_set_ops(old_suspend_ordering ? &acpi_suspend_ops_old : &acpi_suspend_ops); @@ -740,11 +745,7 @@ static const struct platform_hibernation_ops acpi_hibernation_ops_old = { static void acpi_sleep_hibernate_setup(void) { - acpi_status status; - u8 type_a, type_b; - - status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); - if (ACPI_FAILURE(status)) + if (!acpi_sleep_state_supported(ACPI_STATE_S4)) return; hibernation_set_ops(old_suspend_ordering ? @@ -793,8 +794,6 @@ static void acpi_power_off(void) int __init acpi_sleep_init(void) { - acpi_status status; - u8 type_a, type_b; char supported[ACPI_S_STATE_COUNT * 3 + 1]; char *pos = supported; int i; @@ -806,8 +805,7 @@ int __init acpi_sleep_init(void) acpi_sleep_suspend_setup(); acpi_sleep_hibernate_setup(); - status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { + if (acpi_sleep_state_supported(ACPI_STATE_S5)) { sleep_states[ACPI_STATE_S5] = 1; pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 65d3f1b5966..8cb2522d592 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4225,8 +4225,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* devices that don't properly handle queued TRIM commands */ { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, - { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, - { "Crucial_CT???M500SSD3", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, /* * Some WD SATA-I drives spin up and down erratically when the link diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index cf485d92890..199b52b7c3e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1129,7 +1129,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, per_cpu(cpufreq_cpu_data, j) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - if (cpufreq_driver->get) { + if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { policy->cur = cpufreq_driver->get(policy->cpu); if (!policy->cur) { pr_err("%s: ->get() failed\n", __func__); @@ -2143,7 +2143,7 @@ int cpufreq_update_policy(unsigned int cpu) * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ - if (cpufreq_driver->get) { + if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { new_policy.cur = cpufreq_driver->get(cpu); if (!policy->cur) { pr_debug("Driver did not initialize current freq"); diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e22be8458d9..bbb17841a9e 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -4134,8 +4134,11 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable) { if (enable) WREG32(CP_MEC_CNTL, 0); - else + else { WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT)); + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + } udelay(50); } diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 1ecb3f1070e..94626ea90fa 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -264,6 +264,8 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl); WREG32(SDMA0_GFX_IB_CNTL + reg_offset, 0); } + rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false; } /** @@ -291,6 +293,11 @@ void cik_sdma_enable(struct radeon_device *rdev, bool enable) u32 me_cntl, reg_offset; int i; + if (enable == false) { + cik_sdma_gfx_stop(rdev); + cik_sdma_rlc_stop(rdev); + } + for (i = 0; i < 2; i++) { if (i == 0) reg_offset = SDMA0_REGISTER_OFFSET; @@ -420,10 +427,6 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev) if (!rdev->sdma_fw) return -EINVAL; - /* stop the gfx rings and rlc compute queues */ - cik_sdma_gfx_stop(rdev); - cik_sdma_rlc_stop(rdev); - /* halt the MEs */ cik_sdma_enable(rdev, false); @@ -492,9 +495,6 @@ int cik_sdma_resume(struct radeon_device *rdev) */ void cik_sdma_fini(struct radeon_device *rdev) { - /* stop the gfx rings and rlc compute queues */ - cik_sdma_gfx_stop(rdev); - cik_sdma_rlc_stop(rdev); /* halt the MEs */ cik_sdma_enable(rdev, false); radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 2aecd6dc261..66ed3ea7144 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -33,6 +33,13 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> #include <linux/pm_runtime.h> + +#if defined(CONFIG_VGA_SWITCHEROO) +bool radeon_is_px(void); +#else +static inline bool radeon_is_px(void) { return false; } +#endif + /** * radeon_driver_unload_kms - Main unload function for KMS. * @@ -130,7 +137,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) "Error during ACPI methods call\n"); } - if (radeon_runtime_pm != 0) { + if ((radeon_runtime_pm == 1) || + ((radeon_runtime_pm == -1) && radeon_is_px())) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a0665130938..214b7992a3a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -351,9 +351,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, moved: if (bo->evicted) { - ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement); - if (ret) - pr_err("Can not flush read caches\n"); + if (bdev->driver->invalidate_caches) { + ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement); + if (ret) + pr_err("Can not flush read caches\n"); + } bo->evicted = false; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 801231c9ae4..0ce48e5a9cb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -339,11 +339,13 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, vma->vm_private_data = bo; /* - * PFNMAP is faster than MIXEDMAP due to reduced page - * administration. So use MIXEDMAP only if private VMA, where - * we need to support COW. + * We'd like to use VM_PFNMAP on shared mappings, where + * (vma->vm_flags & VM_SHARED) != 0, for performance reasons, + * but for some reason VM_PFNMAP + x86 PAT + write-combine is very + * bad for performance. Until that has been sorted out, use + * VM_MIXEDMAP on all mappings. See freedesktop.org bug #75719 */ - vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP; + vma->vm_flags |= VM_MIXEDMAP; vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; return 0; out_unref: @@ -359,7 +361,7 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo) vma->vm_ops = &ttm_bo_vm_ops; vma->vm_private_data = ttm_bo_reference(bo); - vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP; + vma->vm_flags |= VM_MIXEDMAP; vma->vm_flags |= VM_IO | VM_DONTEXPAND; return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 82468d90291..e7af580ab97 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -830,6 +830,24 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, if (unlikely(ret != 0)) goto out_unlock; + /* + * A gb-aware client referencing a shared surface will + * expect a backup buffer to be present. + */ + if (dev_priv->has_mob && req->shareable) { + uint32_t backup_handle; + + ret = vmw_user_dmabuf_alloc(dev_priv, tfile, + res->backup_size, + true, + &backup_handle, + &res->backup); + if (unlikely(ret != 0)) { + vmw_resource_unreference(&res); + goto out_unlock; + } + } + tmp = vmw_resource_reference(&srf->res); ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime, req->shareable, VMW_RES_SURFACE, diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index f5ed03164d8..de17c5593d9 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -387,7 +387,7 @@ config I2C_CBUS_GPIO config I2C_CPM tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" - depends on (CPM1 || CPM2) && OF_I2C + depends on CPM1 || CPM2 help This supports the use of the I2C interface on Freescale processors with CPM1 or CPM2. diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1af70145fab..074b9c8e4cf 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -979,12 +979,13 @@ static void issue_copy_real(struct dm_cache_migration *mg) int r; struct dm_io_region o_region, c_region; struct cache *cache = mg->cache; + sector_t cblock = from_cblock(mg->cblock); o_region.bdev = cache->origin_dev->bdev; o_region.count = cache->sectors_per_block; c_region.bdev = cache->cache_dev->bdev; - c_region.sector = from_cblock(mg->cblock) * cache->sectors_per_block; + c_region.sector = cblock * cache->sectors_per_block; c_region.count = cache->sectors_per_block; if (mg->writeback || mg->demote) { @@ -2464,20 +2465,18 @@ static int cache_map(struct dm_target *ti, struct bio *bio) bool discarded_block; struct dm_bio_prison_cell *cell; struct policy_result lookup_result; - struct per_bio_data *pb; + struct per_bio_data *pb = init_per_bio_data(bio, pb_data_size); - if (from_oblock(block) > from_oblock(cache->origin_blocks)) { + if (unlikely(from_oblock(block) >= from_oblock(cache->origin_blocks))) { /* * This can only occur if the io goes to a partial block at * the end of the origin device. We don't cache these. * Just remap to the origin and carry on. */ - remap_to_origin_clear_discard(cache, bio, block); + remap_to_origin(cache, bio); return DM_MAPIO_REMAPPED; } - pb = init_per_bio_data(bio, pb_data_size); - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) { defer_bio(cache, bio); return DM_MAPIO_SUBMITTED; diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index b9e2000969f..95c894482fd 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -240,7 +240,7 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, nid = cpu_to_node(cpu); page = alloc_pages_exact_node(nid, - GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index a2c47476804..e8f133e926a 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -730,7 +730,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon client_info->ntt = 0; } - if (!vlan_get_tag(skb, &client_info->vlan_id)) + if (vlan_get_tag(skb, &client_info->vlan_id)) client_info->vlan_id = 0; if (!client_info->assigned) { diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index c3787843271..298c2650909 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -121,6 +121,7 @@ static struct bond_opt_value bond_resend_igmp_tbl[] = { static struct bond_opt_value bond_lp_interval_tbl[] = { { "minval", 1, BOND_VALFLAG_MIN | BOND_VALFLAG_DEFAULT}, { "maxval", INT_MAX, BOND_VALFLAG_MAX}, + { NULL, -1, 0}, }; static struct bond_option bond_opts[] = { diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index cda25ac45b4..6c9e1c9bdeb 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2507,6 +2507,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent) bp->fw_wr_seq++; msg_data |= bp->fw_wr_seq; + bp->fw_last_msg = msg_data; bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); @@ -4000,8 +4001,23 @@ bnx2_setup_wol(struct bnx2 *bp) wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; } - if (!(bp->flags & BNX2_FLAG_NO_WOL)) - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 1, 0); + if (!(bp->flags & BNX2_FLAG_NO_WOL)) { + u32 val; + + wol_msg |= BNX2_DRV_MSG_DATA_WAIT3; + if (bp->fw_last_msg || BNX2_CHIP(bp) != BNX2_CHIP_5709) { + bnx2_fw_sync(bp, wol_msg, 1, 0); + return; + } + /* Tell firmware not to power down the PHY yet, otherwise + * the chip will take a long time to respond to MMIO reads. + */ + val = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE); + bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, + val | BNX2_PORT_FEATURE_ASF_ENABLED); + bnx2_fw_sync(bp, wol_msg, 1, 0); + bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, val); + } } @@ -4033,9 +4049,22 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) if (bp->wol) pci_set_power_state(bp->pdev, PCI_D3hot); - } else { - pci_set_power_state(bp->pdev, PCI_D3hot); + break; + + } + if (!bp->fw_last_msg && BNX2_CHIP(bp) == BNX2_CHIP_5709) { + u32 val; + + /* Tell firmware not to power down the PHY yet, + * otherwise the other port may not respond to + * MMIO reads. + */ + val = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); + val &= ~BNX2_CONDITION_PM_STATE_MASK; + val |= BNX2_CONDITION_PM_STATE_UNPREP; + bnx2_shmem_wr(bp, BNX2_BC_STATE_CONDITION, val); } + pci_set_power_state(bp->pdev, PCI_D3hot); /* No more memory access after this point until * device is brought back to D0. diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h index f1cf2c44e7e..e341bc366fa 100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@ -6900,6 +6900,7 @@ struct bnx2 { u16 fw_wr_seq; u16 fw_drv_pulse_wr_seq; + u32 fw_last_msg; int rx_max_ring; int rx_ring_size; @@ -7406,6 +7407,10 @@ struct bnx2_rv2p_fw_file { #define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000 #define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000 #define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000 +#define BNX2_CONDITION_PM_STATE_MASK 0x00030000 +#define BNX2_CONDITION_PM_STATE_FULL 0x00030000 +#define BNX2_CONDITION_PM_STATE_PREP 0x00020000 +#define BNX2_CONDITION_PM_STATE_UNPREP 0x00010000 #define BNX2_BC_STATE_DEBUG_CMD 0x1dc #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 1803c395904..354ae9792ba 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -1704,7 +1704,7 @@ bfa_flash_sem_get(void __iomem *bar) while (!bfa_raw_sem_get(bar)) { if (--n <= 0) return BFA_STATUS_BADFLASH; - udelay(10000); + mdelay(10); } return BFA_STATUS_OK; } diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 3190d38e16f..d0c38e01e99 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -632,11 +632,16 @@ static void gem_rx_refill(struct macb *bp) "Unable to allocate sk_buff\n"); break; } - bp->rx_skbuff[entry] = skb; /* now fill corresponding descriptor entry */ paddr = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buffer_size, DMA_FROM_DEVICE); + if (dma_mapping_error(&bp->pdev->dev, paddr)) { + dev_kfree_skb(skb); + break; + } + + bp->rx_skbuff[entry] = skb; if (entry == RX_RING_SIZE - 1) paddr |= MACB_BIT(RX_WRAP); @@ -725,7 +730,7 @@ static int gem_rx(struct macb *bp, int budget) skb_put(skb, len); addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, addr)); dma_unmap_single(&bp->pdev->dev, addr, - len, DMA_FROM_DEVICE); + bp->rx_buffer_size, DMA_FROM_DEVICE); skb->protocol = eth_type_trans(skb, bp->dev); skb_checksum_none_assert(skb); @@ -1036,11 +1041,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) } entry = macb_tx_ring_wrap(bp->tx_head); - bp->tx_head++; netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry); mapping = dma_map_single(&bp->pdev->dev, skb->data, len, DMA_TO_DEVICE); + if (dma_mapping_error(&bp->pdev->dev, mapping)) { + kfree_skb(skb); + goto unlock; + } + bp->tx_head++; tx_skb = &bp->tx_skb[entry]; tx_skb->skb = skb; tx_skb->mapping = mapping; @@ -1066,6 +1075,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) netif_stop_queue(dev); +unlock: spin_unlock_irqrestore(&bp->lock, flags); return NETDEV_TX_OK; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 479a7cba45c..03a35130001 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -528,13 +528,6 @@ fec_restart(struct net_device *ndev, int duplex) /* Clear any outstanding interrupt. */ writel(0xffc00000, fep->hwp + FEC_IEVENT); - /* Setup multicast filter. */ - set_multicast_list(ndev); -#ifndef CONFIG_M5272 - writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -#endif - /* Set maximum receive buffer size. */ writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); @@ -655,6 +648,13 @@ fec_restart(struct net_device *ndev, int duplex) writel(rcntl, fep->hwp + FEC_R_CNTRL); + /* Setup multicast filter. */ + set_multicast_list(ndev); +#ifndef CONFIG_M5272 + writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +#endif + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { /* enable ENET endian swap */ ecntl |= (1 << 8); diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 4be97159046..1fc8334fc18 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -522,10 +522,21 @@ retry: return rc; } +static u64 ibmveth_encode_mac_addr(u8 *mac) +{ + int i; + u64 encoded = 0; + + for (i = 0; i < ETH_ALEN; i++) + encoded = (encoded << 8) | mac[i]; + + return encoded; +} + static int ibmveth_open(struct net_device *netdev) { struct ibmveth_adapter *adapter = netdev_priv(netdev); - u64 mac_address = 0; + u64 mac_address; int rxq_entries = 1; unsigned long lpar_rc; int rc; @@ -579,8 +590,7 @@ static int ibmveth_open(struct net_device *netdev) adapter->rx_queue.num_slots = rxq_entries; adapter->rx_queue.toggle = 1; - memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); - mac_address = mac_address >> 16; + mac_address = ibmveth_encode_mac_addr(netdev->dev_addr); rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len; @@ -1183,8 +1193,8 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) /* add the addresses to the filter table */ netdev_for_each_mc_addr(ha, netdev) { /* add the multicast address to the filter table */ - unsigned long mcast_addr = 0; - memcpy(((char *)&mcast_addr)+2, ha->addr, ETH_ALEN); + u64 mcast_addr; + mcast_addr = ibmveth_encode_mac_addr(ha->addr); lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastAddFilter, mcast_addr); @@ -1372,9 +1382,6 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); - adapter->mac_addr = 0; - memcpy(&adapter->mac_addr, mac_addr_p, ETH_ALEN); - netdev->irq = dev->irq; netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; @@ -1383,7 +1390,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; netdev->features |= netdev->hw_features; - memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); + memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { struct kobject *kobj = &adapter->rx_buff_pool[i].kobj; diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h index 451ba7949e1..1f37499d439 100644 --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -138,7 +138,6 @@ struct ibmveth_adapter { struct napi_struct napi; struct net_device_stats stats; unsigned int mcastFilterSize; - unsigned long mac_addr; void * buffer_list_addr; void * filter_list_addr; dma_addr_t buffer_list_dma; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index fad45316200..84a96f70dfb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -742,6 +742,14 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn, err = mlx4_en_uc_steer_add(priv, new_mac, &qpn, &entry->reg_id); + if (err) + return err; + if (priv->tunnel_reg_id) { + mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id); + priv->tunnel_reg_id = 0; + } + err = mlx4_en_tunnel_steer_add(priv, new_mac, qpn, + &priv->tunnel_reg_id); return err; } } @@ -1792,6 +1800,8 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) mc_list[5] = priv->port; mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list, MLX4_PROT_ETH, mclist->reg_id); + if (mclist->tunnel_reg_id) + mlx4_flow_detach(mdev->dev, mclist->tunnel_reg_id); } mlx4_en_clear_list(dev); list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) { diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 91b69ff4b4a..7e2995ecea6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -129,13 +129,14 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [0] = "RSS support", [1] = "RSS Toeplitz Hash Function support", [2] = "RSS XOR Hash Function support", - [3] = "Device manage flow steering support", + [3] = "Device managed flow steering support", [4] = "Automatic MAC reassignment support", [5] = "Time stamping support", [6] = "VST (control vlan insertion/stripping) support", [7] = "FSM (MAC anti-spoofing) support", [8] = "Dynamic QP updates support", - [9] = "TCP/IP offloads/flow-steering for VXLAN support" + [9] = "Device managed flow steering IPoIB support", + [10] = "TCP/IP offloads/flow-steering for VXLAN support" }; int i; @@ -859,7 +860,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); /* For guests, disable vxlan tunneling */ - MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN); + MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN); field &= 0xf7; MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN); @@ -869,7 +870,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET); /* For guests, disable mw type 2 */ - MLX4_GET(bmme_flags, outbox, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); + MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN; MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); @@ -883,7 +884,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, } /* turn off ipoib managed steering for guests */ - MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); + MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); field &= ~0x80; MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index d711158b0d4..936c1536473 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -150,6 +150,8 @@ struct mlx4_port_config { struct pci_dev *pdev; }; +static atomic_t pf_loading = ATOMIC_INIT(0); + int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type) { @@ -749,7 +751,7 @@ static void mlx4_request_modules(struct mlx4_dev *dev) has_eth_port = true; } - if (has_ib_port) + if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) request_module_nowait(IB_DRV_NAME); if (has_eth_port) request_module_nowait(EN_DRV_NAME); @@ -1407,6 +1409,11 @@ static int mlx4_init_slave(struct mlx4_dev *dev) u32 slave_read; u32 cmd_channel_ver; + if (atomic_read(&pf_loading)) { + mlx4_warn(dev, "PF is not ready. Deferring probe\n"); + return -EPROBE_DEFER; + } + mutex_lock(&priv->cmd.slave_cmd_mutex); priv->cmd.max_cmds = 1; mlx4_warn(dev, "Sending reset\n"); @@ -2319,7 +2326,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) if (num_vfs) { mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", num_vfs); + + atomic_inc(&pf_loading); err = pci_enable_sriov(pdev, num_vfs); + atomic_dec(&pf_loading); + if (err) { mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n", err); @@ -2684,6 +2695,7 @@ static struct pci_driver mlx4_driver = { .name = DRV_NAME, .id_table = mlx4_pci_table, .probe = mlx4_init_one, + .shutdown = mlx4_remove_one, .remove = mlx4_remove_one, .err_handler = &mlx4_err_handler, }; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e9779653cd4..3ff7bc3e7a2 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -209,7 +209,7 @@ static const struct { [RTL_GIGA_MAC_VER_16] = _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_17] = - _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), + _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_18] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_19] = diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c index 72d282bf33a..c553f6b5a91 100644 --- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c +++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c @@ -151,7 +151,7 @@ static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) sizeof(struct dma_desc))); } -const struct stmmac_chain_mode_ops chain_mode_ops = { +const struct stmmac_mode_ops chain_mode_ops = { .init = stmmac_init_dma_chain, .is_jumbo_frm = stmmac_is_jumbo_frm, .jumbo_frm = stmmac_jumbo_frm, diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 7834a399394..74610f3aca9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -419,20 +419,13 @@ struct mii_regs { unsigned int data; /* MII Data */ }; -struct stmmac_ring_mode_ops { - unsigned int (*is_jumbo_frm) (int len, int ehn_desc); - unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum); - void (*refill_desc3) (void *priv, struct dma_desc *p); - void (*init_desc3) (struct dma_desc *p); - void (*clean_desc3) (void *priv, struct dma_desc *p); - int (*set_16kib_bfsize) (int mtu); -}; - -struct stmmac_chain_mode_ops { +struct stmmac_mode_ops { void (*init) (void *des, dma_addr_t phy_addr, unsigned int size, unsigned int extend_desc); unsigned int (*is_jumbo_frm) (int len, int ehn_desc); unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum); + int (*set_16kib_bfsize)(int mtu); + void (*init_desc3)(struct dma_desc *p); void (*refill_desc3) (void *priv, struct dma_desc *p); void (*clean_desc3) (void *priv, struct dma_desc *p); }; @@ -441,8 +434,7 @@ struct mac_device_info { const struct stmmac_ops *mac; const struct stmmac_desc_ops *desc; const struct stmmac_dma_ops *dma; - const struct stmmac_ring_mode_ops *ring; - const struct stmmac_chain_mode_ops *chain; + const struct stmmac_mode_ops *mode; const struct stmmac_hwtimestamp *ptp; struct mii_regs mii; /* MII register Addresses */ struct mac_link link; @@ -460,7 +452,7 @@ void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, void stmmac_set_mac(void __iomem *ioaddr, bool enable); void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); -extern const struct stmmac_ring_mode_ops ring_mode_ops; -extern const struct stmmac_chain_mode_ops chain_mode_ops; +extern const struct stmmac_mode_ops ring_mode_ops; +extern const struct stmmac_mode_ops chain_mode_ops; #endif /* __COMMON_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c index a96c7c2f5f3..650a4be6bce 100644 --- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c @@ -100,10 +100,9 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p) { struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; - if (unlikely(priv->plat->has_gmac)) - /* Fill DES3 in case of RING mode */ - if (priv->dma_buf_sz >= BUF_SIZE_8KiB) - p->des3 = p->des2 + BUF_SIZE_8KiB; + /* Fill DES3 in case of RING mode */ + if (priv->dma_buf_sz >= BUF_SIZE_8KiB) + p->des3 = p->des2 + BUF_SIZE_8KiB; } /* In ring mode we need to fill the desc3 because it is used as buffer */ @@ -126,7 +125,7 @@ static int stmmac_set_16kib_bfsize(int mtu) return ret; } -const struct stmmac_ring_mode_ops ring_mode_ops = { +const struct stmmac_mode_ops ring_mode_ops = { .is_jumbo_frm = stmmac_is_jumbo_frm, .jumbo_frm = stmmac_jumbo_frm, .refill_desc3 = stmmac_refill_desc3, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 078ad0ec859..8543e1cfd55 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -92,8 +92,8 @@ static int tc = TC_DEFAULT; module_param(tc, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tc, "DMA threshold control value"); -#define DMA_BUFFER_SIZE BUF_SIZE_4KiB -static int buf_sz = DMA_BUFFER_SIZE; +#define DEFAULT_BUFSIZE 1536 +static int buf_sz = DEFAULT_BUFSIZE; module_param(buf_sz, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(buf_sz, "DMA buffer size"); @@ -136,8 +136,8 @@ static void stmmac_verify_args(void) dma_rxsize = DMA_RX_SIZE; if (unlikely(dma_txsize < 0)) dma_txsize = DMA_TX_SIZE; - if (unlikely((buf_sz < DMA_BUFFER_SIZE) || (buf_sz > BUF_SIZE_16KiB))) - buf_sz = DMA_BUFFER_SIZE; + if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB))) + buf_sz = DEFAULT_BUFSIZE; if (unlikely(flow_ctrl > 1)) flow_ctrl = FLOW_AUTO; else if (likely(flow_ctrl < 0)) @@ -286,10 +286,25 @@ bool stmmac_eee_init(struct stmmac_priv *priv) /* MAC core supports the EEE feature. */ if (priv->dma_cap.eee) { + int tx_lpi_timer = priv->tx_lpi_timer; + /* Check if the PHY supports EEE */ - if (phy_init_eee(priv->phydev, 1)) + if (phy_init_eee(priv->phydev, 1)) { + /* To manage at run-time if the EEE cannot be supported + * anymore (for example because the lp caps have been + * changed). + * In that case the driver disable own timers. + */ + if (priv->eee_active) { + pr_debug("stmmac: disable EEE\n"); + del_timer_sync(&priv->eee_ctrl_timer); + priv->hw->mac->set_eee_timer(priv->ioaddr, 0, + tx_lpi_timer); + } + priv->eee_active = 0; goto out; - + } + /* Activate the EEE and start timers */ if (!priv->eee_active) { priv->eee_active = 1; init_timer(&priv->eee_ctrl_timer); @@ -300,13 +315,13 @@ bool stmmac_eee_init(struct stmmac_priv *priv) priv->hw->mac->set_eee_timer(priv->ioaddr, STMMAC_DEFAULT_LIT_LS, - priv->tx_lpi_timer); + tx_lpi_timer); } else /* Set HW EEE according to the speed */ priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link); - pr_info("stmmac: Energy-Efficient Ethernet initialized\n"); + pr_debug("stmmac: Energy-Efficient Ethernet initialized\n"); ret = true; } @@ -886,10 +901,10 @@ static int stmmac_set_bfsize(int mtu, int bufsize) ret = BUF_SIZE_8KiB; else if (mtu >= BUF_SIZE_2KiB) ret = BUF_SIZE_4KiB; - else if (mtu >= DMA_BUFFER_SIZE) + else if (mtu > DEFAULT_BUFSIZE) ret = BUF_SIZE_2KiB; else - ret = DMA_BUFFER_SIZE; + ret = DEFAULT_BUFSIZE; return ret; } @@ -951,9 +966,9 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, p->des2 = priv->rx_skbuff_dma[i]; - if ((priv->mode == STMMAC_RING_MODE) && + if ((priv->hw->mode->init_desc3) && (priv->dma_buf_sz == BUF_SIZE_16KiB)) - priv->hw->ring->init_desc3(p); + priv->hw->mode->init_desc3(p); return 0; } @@ -984,11 +999,8 @@ static int init_dma_desc_rings(struct net_device *dev) unsigned int bfsize = 0; int ret = -ENOMEM; - /* Set the max buffer size according to the DESC mode - * and the MTU. Note that RING mode allows 16KiB bsize. - */ - if (priv->mode == STMMAC_RING_MODE) - bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu); + if (priv->hw->mode->set_16kib_bfsize) + bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); if (bfsize < BUF_SIZE_16KiB) bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); @@ -1029,15 +1041,15 @@ static int init_dma_desc_rings(struct net_device *dev) /* Setup the chained descriptor addresses */ if (priv->mode == STMMAC_CHAIN_MODE) { if (priv->extend_desc) { - priv->hw->chain->init(priv->dma_erx, priv->dma_rx_phy, - rxsize, 1); - priv->hw->chain->init(priv->dma_etx, priv->dma_tx_phy, - txsize, 1); + priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy, + rxsize, 1); + priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy, + txsize, 1); } else { - priv->hw->chain->init(priv->dma_rx, priv->dma_rx_phy, - rxsize, 0); - priv->hw->chain->init(priv->dma_tx, priv->dma_tx_phy, - txsize, 0); + priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy, + rxsize, 0); + priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy, + txsize, 0); } } @@ -1288,7 +1300,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv) DMA_TO_DEVICE); priv->tx_skbuff_dma[entry] = 0; } - priv->hw->ring->clean_desc3(priv, p); + priv->hw->mode->clean_desc3(priv, p); if (likely(skb != NULL)) { dev_kfree_skb(skb); @@ -1844,6 +1856,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) int nfrags = skb_shinfo(skb)->nr_frags; struct dma_desc *desc, *first; unsigned int nopaged_len = skb_headlen(skb); + unsigned int enh_desc = priv->plat->enh_desc; if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { if (!netif_queue_stopped(dev)) { @@ -1871,27 +1884,19 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) first = desc; /* To program the descriptors according to the size of the frame */ - if (priv->mode == STMMAC_RING_MODE) { - is_jumbo = priv->hw->ring->is_jumbo_frm(skb->len, - priv->plat->enh_desc); - if (unlikely(is_jumbo)) - entry = priv->hw->ring->jumbo_frm(priv, skb, - csum_insertion); - } else { - is_jumbo = priv->hw->chain->is_jumbo_frm(skb->len, - priv->plat->enh_desc); - if (unlikely(is_jumbo)) - entry = priv->hw->chain->jumbo_frm(priv, skb, - csum_insertion); - } + if (enh_desc) + is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); + if (likely(!is_jumbo)) { desc->des2 = dma_map_single(priv->device, skb->data, nopaged_len, DMA_TO_DEVICE); priv->tx_skbuff_dma[entry] = desc->des2; priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum_insertion, priv->mode); - } else + } else { desc = first; + entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); + } for (i = 0; i < nfrags; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -2029,7 +2034,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) p->des2 = priv->rx_skbuff_dma[entry]; - priv->hw->ring->refill_desc3(priv, p); + priv->hw->mode->refill_desc3(priv, p); if (netif_msg_rx_status(priv)) pr_debug("\trefill entry #%d\n", entry); @@ -2633,11 +2638,11 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /* To use the chained or ring mode */ if (chain_mode) { - priv->hw->chain = &chain_mode_ops; + priv->hw->mode = &chain_mode_ops; pr_info(" Chain mode enabled\n"); priv->mode = STMMAC_CHAIN_MODE; } else { - priv->hw->ring = &ring_mode_ops; + priv->hw->mode = &ring_mode_ops; pr_info(" Ring mode enabled\n"); priv->mode = STMMAC_RING_MODE; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index c61bc72b8e9..8fb32a80f1c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -36,7 +36,7 @@ static const struct of_device_id stmmac_dt_ids[] = { #ifdef CONFIG_DWMAC_STI { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data}, { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data}, - { .compatible = "st,stih127-dwmac", .data = &sti_gmac_data}, + { .compatible = "st,stid127-dwmac", .data = &sti_gmac_data}, #endif /* SoC specific glue layers should come before generic bindings */ { .compatible = "st,spear600-gmac"}, diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 7141a193736..d6fce9750b9 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -442,6 +442,8 @@ static int netvsc_probe(struct hv_device *dev, if (!net) return -ENOMEM; + netif_carrier_off(net); + net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); @@ -473,6 +475,8 @@ static int netvsc_probe(struct hv_device *dev, pr_err("Unable to register netdev.\n"); rndis_filter_device_remove(dev); free_netdev(net); + } else { + schedule_delayed_work(&net_device_ctx->dwork, 0); } return ret; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 1084e5de3ce..b54fd257652 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -243,6 +243,22 @@ static int rndis_filter_send_request(struct rndis_device *dev, return ret; } +static void rndis_set_link_state(struct rndis_device *rdev, + struct rndis_request *request) +{ + u32 link_status; + struct rndis_query_complete *query_complete; + + query_complete = &request->response_msg.msg.query_complete; + + if (query_complete->status == RNDIS_STATUS_SUCCESS && + query_complete->info_buflen == sizeof(u32)) { + memcpy(&link_status, (void *)((unsigned long)query_complete + + query_complete->info_buf_offset), sizeof(u32)); + rdev->link_state = link_status != 0; + } +} + static void rndis_filter_receive_response(struct rndis_device *dev, struct rndis_message *resp) { @@ -272,6 +288,10 @@ static void rndis_filter_receive_response(struct rndis_device *dev, sizeof(struct rndis_message) + RNDIS_EXT_LEN) { memcpy(&request->response_msg, resp, resp->msg_len); + if (request->request_msg.ndis_msg_type == + RNDIS_MSG_QUERY && request->request_msg.msg. + query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS) + rndis_set_link_state(dev, request); } else { netdev_err(ndev, "rndis response buffer overflow " @@ -620,7 +640,6 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev) ret = rndis_filter_query_device(dev, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &link_status, &size); - dev->link_state = (link_status != 0) ? true : false; return ret; } diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index ab31544bc25..a30258aad13 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -546,12 +546,12 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) int rc; unsigned long flags; - spin_lock(&lp->lock); + spin_lock_irqsave(&lp->lock, flags); if (lp->irq_busy) { - spin_unlock(&lp->lock); + spin_unlock_irqrestore(&lp->lock, flags); return -EBUSY; } - spin_unlock(&lp->lock); + spin_unlock_irqrestore(&lp->lock, flags); might_sleep(); @@ -725,10 +725,11 @@ static void at86rf230_irqwork_level(struct work_struct *work) static irqreturn_t at86rf230_isr(int irq, void *data) { struct at86rf230_local *lp = data; + unsigned long flags; - spin_lock(&lp->lock); + spin_lock_irqsave(&lp->lock, flags); lp->irq_busy = 1; - spin_unlock(&lp->lock); + spin_unlock_irqrestore(&lp->lock, flags); schedule_work(&lp->irqwork); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 19c9eca0ef2..76d96b9ebcd 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -164,9 +164,9 @@ static const struct phy_setting settings[] = { * of that setting. Returns the index of the last setting if * none of the others match. */ -static inline int phy_find_setting(int speed, int duplex) +static inline unsigned int phy_find_setting(int speed, int duplex) { - int idx = 0; + unsigned int idx = 0; while (idx < ARRAY_SIZE(settings) && (settings[idx].speed != speed || settings[idx].duplex != duplex)) @@ -185,7 +185,7 @@ static inline int phy_find_setting(int speed, int duplex) * the mask in features. Returns the index of the last setting * if nothing else matches. */ -static inline int phy_find_valid(int idx, u32 features) +static inline unsigned int phy_find_valid(unsigned int idx, u32 features) { while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) idx++; @@ -204,7 +204,7 @@ static inline int phy_find_valid(int idx, u32 features) static void phy_sanitize_settings(struct phy_device *phydev) { u32 features = phydev->supported; - int idx; + unsigned int idx; /* Sanitize settings based on PHY capabilities */ if ((features & SUPPORTED_Autoneg) == 0) @@ -954,7 +954,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) (phydev->interface == PHY_INTERFACE_MODE_RGMII))) { int eee_lp, eee_cap, eee_adv; u32 lp, cap, adv; - int idx, status; + int status; + unsigned int idx; /* Read phy status to properly get the right settings */ status = phy_read_status(phydev); diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 433f0a00c68..e2797f1e1b3 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o asix-y := asix_devices.o asix_common.o ax88172a.o obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o -obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o +obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SR9700) += sr9700.o diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 42e176912c8..bd363b27e85 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -652,6 +652,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Samsung USB Ethernet Adapters */ +{ + USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* WHITELIST!!! * * CDC Ether uses two interfaces, not necessarily consecutive. diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index d89dbe395ad..adb12f349a6 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -449,9 +449,6 @@ enum rtl8152_flags { #define MCU_TYPE_PLA 0x0100 #define MCU_TYPE_USB 0x0000 -#define REALTEK_USB_DEVICE(vend, prod) \ - USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC) - struct rx_desc { __le32 opts1; #define RX_LEN_MASK 0x7fff @@ -2739,6 +2736,12 @@ static int rtl8152_probe(struct usb_interface *intf, struct net_device *netdev; int ret; + if (udev->actconfig->desc.bConfigurationValue != 1) { + usb_driver_set_configuration(udev, 1); + return -ENODEV; + } + + usb_reset_device(udev); netdev = alloc_etherdev(sizeof(struct r8152)); if (!netdev) { dev_err(&intf->dev, "Out of memory\n"); @@ -2819,9 +2822,9 @@ static void rtl8152_disconnect(struct usb_interface *intf) /* table of devices that work with this driver */ static struct usb_device_id rtl8152_table[] = { - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)}, - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)}, - {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)}, + {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)}, + {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)}, + {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)}, {} }; diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c deleted file mode 100644 index f0a8791b763..00000000000 --- a/drivers/net/usb/r815x.c +++ /dev/null @@ -1,248 +0,0 @@ -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/mii.h> -#include <linux/usb.h> -#include <linux/usb/cdc.h> -#include <linux/usb/usbnet.h> - -#define RTL815x_REQT_READ 0xc0 -#define RTL815x_REQT_WRITE 0x40 -#define RTL815x_REQ_GET_REGS 0x05 -#define RTL815x_REQ_SET_REGS 0x05 - -#define MCU_TYPE_PLA 0x0100 -#define OCP_BASE 0xe86c -#define BASE_MII 0xa400 - -#define BYTE_EN_DWORD 0xff -#define BYTE_EN_WORD 0x33 -#define BYTE_EN_BYTE 0x11 - -#define R815x_PHY_ID 32 -#define REALTEK_VENDOR_ID 0x0bda - - -static int pla_read_word(struct usb_device *udev, u16 index) -{ - int ret; - u8 shift = index & 2; - __le32 *tmp; - - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - index &= ~3; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, - index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); - if (ret < 0) - goto out2; - - ret = __le32_to_cpu(*tmp); - ret >>= (shift * 8); - ret &= 0xffff; - -out2: - kfree(tmp); - return ret; -} - -static int pla_write_word(struct usb_device *udev, u16 index, u32 data) -{ - __le32 *tmp; - u32 mask = 0xffff; - u16 byen = BYTE_EN_WORD; - u8 shift = index & 2; - int ret; - - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - data &= mask; - - if (shift) { - byen <<= shift; - mask <<= (shift * 8); - data <<= (shift * 8); - index &= ~3; - } - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, - index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); - if (ret < 0) - goto out3; - - data |= __le32_to_cpu(*tmp) & ~mask; - *tmp = __cpu_to_le32(data); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, - index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp), - 500); - -out3: - kfree(tmp); - return ret; -} - -static int ocp_reg_read(struct usbnet *dev, u16 addr) -{ - u16 ocp_base, ocp_index; - int ret; - - ocp_base = addr & 0xf000; - ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); - if (ret < 0) - goto out; - - ocp_index = (addr & 0x0fff) | 0xb000; - ret = pla_read_word(dev->udev, ocp_index); - -out: - return ret; -} - -static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data) -{ - u16 ocp_base, ocp_index; - int ret; - - ocp_base = addr & 0xf000; - ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); - if (ret < 0) - goto out1; - - ocp_index = (addr & 0x0fff) | 0xb000; - ret = pla_write_word(dev->udev, ocp_index, data); - -out1: - return ret; -} - -static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) -{ - struct usbnet *dev = netdev_priv(netdev); - int ret; - - if (phy_id != R815x_PHY_ID) - return -EINVAL; - - if (usb_autopm_get_interface(dev->intf) < 0) - return -ENODEV; - - ret = ocp_reg_read(dev, BASE_MII + reg * 2); - - usb_autopm_put_interface(dev->intf); - return ret; -} - -static -void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) -{ - struct usbnet *dev = netdev_priv(netdev); - - if (phy_id != R815x_PHY_ID) - return; - - if (usb_autopm_get_interface(dev->intf) < 0) - return; - - ocp_reg_write(dev, BASE_MII + reg * 2, val); - - usb_autopm_put_interface(dev->intf); -} - -static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int status; - - status = usbnet_cdc_bind(dev, intf); - if (status < 0) - return status; - - dev->mii.dev = dev->net; - dev->mii.mdio_read = r815x_mdio_read; - dev->mii.mdio_write = r815x_mdio_write; - dev->mii.phy_id_mask = 0x3f; - dev->mii.reg_num_mask = 0x1f; - dev->mii.phy_id = R815x_PHY_ID; - dev->mii.supports_gmii = 1; - - return status; -} - -static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int status; - - status = usbnet_cdc_bind(dev, intf); - if (status < 0) - return status; - - dev->mii.dev = dev->net; - dev->mii.mdio_read = r815x_mdio_read; - dev->mii.mdio_write = r815x_mdio_write; - dev->mii.phy_id_mask = 0x3f; - dev->mii.reg_num_mask = 0x1f; - dev->mii.phy_id = R815x_PHY_ID; - dev->mii.supports_gmii = 0; - - return status; -} - -static const struct driver_info r8152_info = { - .description = "RTL8152 ECM Device", - .flags = FLAG_ETHER | FLAG_POINTTOPOINT, - .bind = r8152_bind, - .unbind = usbnet_cdc_unbind, - .status = usbnet_cdc_status, - .manage_power = usbnet_manage_power, -}; - -static const struct driver_info r8153_info = { - .description = "RTL8153 ECM Device", - .flags = FLAG_ETHER | FLAG_POINTTOPOINT, - .bind = r8153_bind, - .unbind = usbnet_cdc_unbind, - .status = usbnet_cdc_status, - .manage_power = usbnet_manage_power, -}; - -static const struct usb_device_id products[] = { -{ - USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &r8152_info, -}, - -{ - USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &r8153_info, -}, - - { }, /* END */ -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver r815x_driver = { - .name = "r815x", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, - .reset_resume = usbnet_resume, - .supports_autosuspend = 1, - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(r815x_driver); - -MODULE_AUTHOR("Hayes Wang"); -MODULE_DESCRIPTION("Realtek USB ECM device"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 3be786faaae..0fa3b44f734 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1762,11 +1762,20 @@ vmxnet3_netpoll(struct net_device *netdev) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); - if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE) - vmxnet3_disable_all_intrs(adapter); - - vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size); - vmxnet3_enable_all_intrs(adapter); + switch (adapter->intr.type) { +#ifdef CONFIG_PCI_MSI + case VMXNET3_IT_MSIX: { + int i; + for (i = 0; i < adapter->num_rx_queues; i++) + vmxnet3_msix_rx(0, &adapter->rx_queue[i]); + break; + } +#endif + case VMXNET3_IT_MSI: + default: + vmxnet3_intr(0, adapter->netdev); + break; + } } #endif /* CONFIG_NET_POLL_CONTROLLER */ diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 76cde6ce655..18a895a949d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -872,8 +872,11 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); - /* Rssi update while not associated ?! */ - if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) + /* + * Rssi update while not associated - can happen since the statistics + * are handled asynchronously + */ + if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) return; /* No BT - reports should be disabled */ diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index f47bcbe2945..3872ead7548 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -359,13 +359,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)}, - {IWL_PCI_DEVICE(0x095A, 0x5112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)}, - {IWL_PCI_DEVICE(0x095A, 0x510A, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)}, - {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)}, diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c index 5e0eec4d71c..5d9a8084665 100644 --- a/drivers/net/wireless/mwifiex/11ac.c +++ b/drivers/net/wireless/mwifiex/11ac.c @@ -189,8 +189,7 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, vht_cap->header.len = cpu_to_le16(sizeof(struct ieee80211_vht_cap)); memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header), - (u8 *)bss_desc->bcn_vht_cap + - sizeof(struct ieee_types_header), + (u8 *)bss_desc->bcn_vht_cap, le16_to_cpu(vht_cap->header.len)); mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band); diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 6261f8c53d4..7db1a89fdd9 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -308,8 +308,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, ht_cap->header.len = cpu_to_le16(sizeof(struct ieee80211_ht_cap)); memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header), - (u8 *) bss_desc->bcn_ht_cap + - sizeof(struct ieee_types_header), + (u8 *)bss_desc->bcn_ht_cap, le16_to_cpu(ht_cap->header.len)); mwifiex_fill_cap_info(priv, radio_type, ht_cap); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 0a8a26e10f0..668547c2de8 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2101,12 +2101,12 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) curr_bss->ht_info_offset); if (curr_bss->bcn_vht_cap) - curr_bss->bcn_ht_cap = (void *)(curr_bss->beacon_buf + - curr_bss->vht_cap_offset); + curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf + + curr_bss->vht_cap_offset); if (curr_bss->bcn_vht_oper) - curr_bss->bcn_ht_oper = (void *)(curr_bss->beacon_buf + - curr_bss->vht_info_offset); + curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf + + curr_bss->vht_info_offset); if (curr_bss->bcn_bss_co_2040) curr_bss->bcn_bss_co_2040 = diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c index 123c4bb50e0..cde0eaf9971 100644 --- a/drivers/net/wireless/ti/wl1251/rx.c +++ b/drivers/net/wireless/ti/wl1251/rx.c @@ -180,7 +180,7 @@ static void wl1251_rx_body(struct wl1251 *wl, wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); /* The actual length doesn't include the target's alignment */ - skb->len = desc->length - PLCP_HEADER_LENGTH; + skb_trim(skb, desc->length - PLCP_HEADER_LENGTH); fc = (u16 *)skb->data; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 7669d49a67e..301cc037fda 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -132,8 +132,7 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) /* If the skb is GSO then we'll also need an extra slot for the * metadata. */ - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || - skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + if (skb_is_gso(skb)) min_slots_needed++; /* If the skb can't possibly fit in the remaining slots diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index e5284bca2d9..438d0c09b7e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -240,7 +240,7 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, struct gnttab_copy *copy_gop; struct xenvif_rx_meta *meta; unsigned long bytes; - int gso_type; + int gso_type = XEN_NETIF_GSO_TYPE_NONE; /* Data must not cross a page boundary. */ BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); @@ -299,12 +299,12 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, } /* Leave a gap for the GSO descriptor. */ - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - gso_type = XEN_NETIF_GSO_TYPE_TCPV4; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - gso_type = XEN_NETIF_GSO_TYPE_TCPV6; - else - gso_type = XEN_NETIF_GSO_TYPE_NONE; + if (skb_is_gso(skb)) { + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) + gso_type = XEN_NETIF_GSO_TYPE_TCPV4; + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + gso_type = XEN_NETIF_GSO_TYPE_TCPV6; + } if (*head && ((1 << gso_type) & vif->gso_mask)) vif->rx.req_cons++; @@ -338,19 +338,15 @@ static int xenvif_gop_skb(struct sk_buff *skb, int head = 1; int old_meta_prod; int gso_type; - int gso_size; old_meta_prod = npo->meta_prod; - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { - gso_type = XEN_NETIF_GSO_TYPE_TCPV4; - gso_size = skb_shinfo(skb)->gso_size; - } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { - gso_type = XEN_NETIF_GSO_TYPE_TCPV6; - gso_size = skb_shinfo(skb)->gso_size; - } else { - gso_type = XEN_NETIF_GSO_TYPE_NONE; - gso_size = 0; + gso_type = XEN_NETIF_GSO_TYPE_NONE; + if (skb_is_gso(skb)) { + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) + gso_type = XEN_NETIF_GSO_TYPE_TCPV4; + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + gso_type = XEN_NETIF_GSO_TYPE_TCPV6; } /* Set up a GSO prefix descriptor, if necessary */ @@ -358,7 +354,7 @@ static int xenvif_gop_skb(struct sk_buff *skb, req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); meta = npo->meta + npo->meta_prod++; meta->gso_type = gso_type; - meta->gso_size = gso_size; + meta->gso_size = skb_shinfo(skb)->gso_size; meta->size = 0; meta->id = req->id; } @@ -368,7 +364,7 @@ static int xenvif_gop_skb(struct sk_buff *skb, if ((1 << gso_type) & vif->gso_mask) { meta->gso_type = gso_type; - meta->gso_size = gso_size; + meta->gso_size = skb_shinfo(skb)->gso_size; } else { meta->gso_type = XEN_NETIF_GSO_TYPE_NONE; meta->gso_size = 0; @@ -500,8 +496,9 @@ static void xenvif_rx_action(struct xenvif *vif) size = skb_frag_size(&skb_shinfo(skb)->frags[i]); max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE); } - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || - skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + if (skb_is_gso(skb) && + (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || + skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)) max_slots_needed++; /* If the skb may not fit then bail out now */ diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 00660cc502c..38901665c77 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -162,8 +162,6 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, avail = *r; pci_clip_resource_to_region(bus, &avail, region); - if (!resource_size(&avail)) - continue; /* * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6b05f6134b6..fdbc294821e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1192,6 +1192,9 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) return err; pci_fixup_device(pci_fixup_enable, dev); + if (dev->msi_enabled || dev->msix_enabled) + return 0; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin) { pci_read_config_word(dev, PCI_COMMAND, &cmd); diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 167f3d00c91..66977ebf13b 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -183,9 +183,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct resource r = {0}; int i, flags; - if (acpi_dev_resource_memory(res, &r) - || acpi_dev_resource_io(res, &r) - || acpi_dev_resource_address_space(res, &r) + if (acpi_dev_resource_address_space(res, &r) || acpi_dev_resource_ext_address_space(res, &r)) { pnp_add_resource(dev, &r); return AE_OK; @@ -217,6 +215,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, } switch (res->type) { + case ACPI_RESOURCE_TYPE_MEMORY24: + case ACPI_RESOURCE_TYPE_MEMORY32: + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + if (acpi_dev_resource_memory(res, &r)) + pnp_add_resource(dev, &r); + break; + case ACPI_RESOURCE_TYPE_IO: + case ACPI_RESOURCE_TYPE_FIXED_IO: + if (acpi_dev_resource_io(res, &r)) + pnp_add_resource(dev, &r); + break; case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 1f375051483..5642a9b250c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -325,7 +325,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) continue; - if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) + if (sc->device->lun != abrt_task->sc->device->lun) continue; /* Invalidate WRB Posted for this Task */ diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4911310a38f..22a9bb1abae 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -311,9 +311,8 @@ static inline struct Scsi_Host *to_shost(struct isci_host *ihost) } #define for_each_isci_host(id, ihost, pdev) \ - for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \ - id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \ - ihost = to_pci_info(pdev)->hosts[++id]) + for (id = 0; id < SCI_MAX_CONTROLLERS && \ + (ihost = to_pci_info(pdev)->hosts[id]); id++) static inline void wait_for_start(struct isci_host *ihost) { diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 85c77f6b802..ac879745ef8 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -615,13 +615,6 @@ static void sci_apc_agent_link_up(struct isci_host *ihost, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION); } else { /* the phy is already the part of the port */ - u32 port_state = iport->sm.current_state_id; - - /* if the PORT'S state is resetting then the link up is from - * port hard reset in this case, we need to tell the port - * that link up is recieved - */ - BUG_ON(port_state != SCI_PORT_RESETTING); port_agent->phy_ready_mask |= 1 << phy_index; sci_port_link_up(iport, iphy); } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 0d30ca849e8..5d6fda72d65 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -801,7 +801,7 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev) /* XXX: need to cleanup any ireqs targeting this * domain_device */ - ret = TMF_RESP_FUNC_COMPLETE; + ret = -ENODEV; goto out; } diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e1fe95ef23e..266724b6b89 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2996,8 +2996,7 @@ struct qla_hw_data { IS_QLA82XX(ha) || IS_QLA83XX(ha) || \ IS_QLA8044(ha)) #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha)) -#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ - IS_QLA83XX(ha)) && (ha)->flags.msix_enabled) +#define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled) #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha)) #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha)) #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 9bc86b9e86b..0a1dcb43d18 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2880,6 +2880,7 @@ static int qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) { #define MIN_MSIX_COUNT 2 +#define ATIO_VECTOR 2 int i, ret; struct msix_entry *entries; struct qla_msix_entry *qentry; @@ -2936,34 +2937,47 @@ msix_failed: } /* Enable MSI-X vectors for the base queue */ - for (i = 0; i < ha->msix_count; i++) { + for (i = 0; i < 2; i++) { qentry = &ha->msix_entries[i]; - if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) { - ret = request_irq(qentry->vector, - qla83xx_msix_entries[i].handler, - 0, qla83xx_msix_entries[i].name, rsp); - } else if (IS_P3P_TYPE(ha)) { + if (IS_P3P_TYPE(ha)) ret = request_irq(qentry->vector, qla82xx_msix_entries[i].handler, 0, qla82xx_msix_entries[i].name, rsp); - } else { + else ret = request_irq(qentry->vector, msix_entries[i].handler, 0, msix_entries[i].name, rsp); - } - if (ret) { - ql_log(ql_log_fatal, vha, 0x00cb, - "MSI-X: unable to register handler -- %x/%d.\n", - qentry->vector, ret); - qla24xx_disable_msix(ha); - ha->mqenable = 0; - goto msix_out; - } + if (ret) + goto msix_register_fail; qentry->have_irq = 1; qentry->rsp = rsp; rsp->msix = qentry; } + /* + * If target mode is enable, also request the vector for the ATIO + * queue. + */ + if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) { + qentry = &ha->msix_entries[ATIO_VECTOR]; + ret = request_irq(qentry->vector, + qla83xx_msix_entries[ATIO_VECTOR].handler, + 0, qla83xx_msix_entries[ATIO_VECTOR].name, rsp); + qentry->have_irq = 1; + qentry->rsp = rsp; + rsp->msix = qentry; + } + +msix_register_fail: + if (ret) { + ql_log(ql_log_fatal, vha, 0x00cb, + "MSI-X: unable to register handler -- %x/%d.\n", + qentry->vector, ret); + qla24xx_disable_msix(ha); + ha->mqenable = 0; + goto msix_out; + } + /* Enable MSI-X vector for response queue update for queue 0 */ if (IS_QLA83XX(ha)) { if (ha->msixbase && ha->mqiobase && diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 17d74042724..9969fa1ef7c 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1419,6 +1419,9 @@ static void storvsc_device_destroy(struct scsi_device *sdevice) { struct stor_mem_pools *memp = sdevice->hostdata; + if (!memp) + return; + mempool_destroy(memp->request_mempool); kmem_cache_destroy(memp->request_pool); kfree(memp); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index cf32f039336..c0f3718b77a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -513,7 +513,7 @@ struct cifs_mnt_data { static inline unsigned int get_rfc1002_length(void *buf) { - return be32_to_cpu(*((__be32 *)buf)); + return be32_to_cpu(*((__be32 *)buf)) & 0xffffff; } static inline void diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 53c15074bb3..834fce759d8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2579,31 +2579,19 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, struct cifsInodeInfo *cinode = CIFS_I(inode); struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; ssize_t rc = -EACCES; + loff_t lock_pos = pos; - BUG_ON(iocb->ki_pos != pos); - + if (file->f_flags & O_APPEND) + lock_pos = i_size_read(inode); /* * We need to hold the sem to be sure nobody modifies lock list * with a brlock that prevents writing. */ down_read(&cinode->lock_sem); - if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), + if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), server->vals->exclusive_lock_type, NULL, - CIFS_WRITE_OP)) { - mutex_lock(&inode->i_mutex); - rc = __generic_file_aio_write(iocb, iov, nr_segs, - &iocb->ki_pos); - mutex_unlock(&inode->i_mutex); - } - - if (rc > 0) { - ssize_t err; - - err = generic_write_sync(file, iocb->ki_pos - rc, rc); - if (err < 0) - rc = err; - } - + CIFS_WRITE_OP)) + rc = generic_file_aio_write(iocb, iov, nr_segs, pos); up_read(&cinode->lock_sem); return rc; } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b3757095284..18cd5650a5f 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -270,6 +270,26 @@ cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, iov->iov_len = rqst->rq_pagesz; } +static unsigned long +rqst_len(struct smb_rqst *rqst) +{ + unsigned int i; + struct kvec *iov = rqst->rq_iov; + unsigned long buflen = 0; + + /* total up iov array first */ + for (i = 0; i < rqst->rq_nvec; i++) + buflen += iov[i].iov_len; + + /* add in the page array if there is one */ + if (rqst->rq_npages) { + buflen += rqst->rq_pagesz * (rqst->rq_npages - 1); + buflen += rqst->rq_tailsz; + } + + return buflen; +} + static int smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) { @@ -277,6 +297,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); + unsigned long send_length; unsigned int i; size_t total_len = 0, sent; struct socket *ssocket = server->ssocket; @@ -285,6 +306,14 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) if (ssocket == NULL) return -ENOTSOCK; + /* sanity check send length */ + send_length = rqst_len(rqst); + if (send_length != smb_buf_length + 4) { + WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n", + send_length, smb_buf_length); + return -EIO; + } + cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length); dump_smb(iov[0].iov_base, iov[0].iov_len); diff --git a/fs/file.c b/fs/file.c index db25c2bdfe4..60a45e9f532 100644 --- a/fs/file.c +++ b/fs/file.c @@ -683,35 +683,65 @@ EXPORT_SYMBOL(fget_raw); * The fput_needed flag returned by fget_light should be passed to the * corresponding fput_light. */ -struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) +static unsigned long __fget_light(unsigned int fd, fmode_t mask) { struct files_struct *files = current->files; struct file *file; - *fput_needed = 0; if (atomic_read(&files->count) == 1) { file = __fcheck_files(files, fd); - if (file && (file->f_mode & mask)) - file = NULL; + if (!file || unlikely(file->f_mode & mask)) + return 0; + return (unsigned long)file; } else { file = __fget(fd, mask); - if (file) - *fput_needed = 1; + if (!file) + return 0; + return FDPUT_FPUT | (unsigned long)file; } - - return file; } -struct file *fget_light(unsigned int fd, int *fput_needed) +unsigned long __fdget(unsigned int fd) { - return __fget_light(fd, FMODE_PATH, fput_needed); + return __fget_light(fd, FMODE_PATH); } -EXPORT_SYMBOL(fget_light); +EXPORT_SYMBOL(__fdget); -struct file *fget_raw_light(unsigned int fd, int *fput_needed) +unsigned long __fdget_raw(unsigned int fd) { - return __fget_light(fd, 0, fput_needed); + return __fget_light(fd, 0); +} + +unsigned long __fdget_pos(unsigned int fd) +{ + struct files_struct *files = current->files; + struct file *file; + unsigned long v; + + if (atomic_read(&files->count) == 1) { + file = __fcheck_files(files, fd); + v = 0; + } else { + file = __fget(fd, 0); + v = FDPUT_FPUT; + } + if (!file) + return 0; + + if (file->f_mode & FMODE_ATOMIC_POS) { + if (file_count(file) > 1) { + v |= FDPUT_POS_UNLOCK; + mutex_lock(&file->f_pos_lock); + } + } + return v | (unsigned long)file; } +/* + * We only lock f_pos if we have threads or if the file might be + * shared with another process. In both cases we'll have an elevated + * file count (done either by fdget() or by fork()). + */ + void set_close_on_exec(unsigned int fd, int flag) { struct files_struct *files = current->files; diff --git a/fs/file_table.c b/fs/file_table.c index 5fff9030be3..5b24008ea4f 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -135,6 +135,7 @@ struct file *get_empty_filp(void) atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); spin_lock_init(&f->f_lock); + mutex_init(&f->f_pos_lock); eventpoll_init_file(f); /* f->f_version: 0 */ return f; diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 968ce411db5..32602c667b4 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c @@ -103,6 +103,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, folder = &entry->folder; memset(folder, 0, sizeof(*folder)); folder->type = cpu_to_be16(HFSPLUS_FOLDER); + if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) + folder->flags |= cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT); folder->id = cpu_to_be32(inode->i_ino); HFSPLUS_I(inode)->create_date = folder->create_date = @@ -203,6 +205,36 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, return hfs_brec_find(fd, hfs_find_rec_by_key); } +static void hfsplus_subfolders_inc(struct inode *dir) +{ + struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + + if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { + /* + * Increment subfolder count. Note, the value is only meaningful + * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set. + */ + HFSPLUS_I(dir)->subfolders++; + } +} + +static void hfsplus_subfolders_dec(struct inode *dir) +{ + struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + + if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { + /* + * Decrement subfolder count. Note, the value is only meaningful + * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set. + * + * Check for zero. Some subfolders may have been created + * by an implementation ignorant of this counter. + */ + if (HFSPLUS_I(dir)->subfolders) + HFSPLUS_I(dir)->subfolders--; + } +} + int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) { @@ -247,6 +279,8 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, goto err1; dir->i_size++; + if (S_ISDIR(inode->i_mode)) + hfsplus_subfolders_inc(dir); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); @@ -336,6 +370,8 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) goto out; dir->i_size--; + if (type == HFSPLUS_FOLDER) + hfsplus_subfolders_dec(dir); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY); @@ -380,6 +416,7 @@ int hfsplus_rename_cat(u32 cnid, hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, src_fd.entrylength); + type = be16_to_cpu(entry.type); /* create new dir entry with the data from the old entry */ hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name); @@ -394,6 +431,8 @@ int hfsplus_rename_cat(u32 cnid, if (err) goto out; dst_dir->i_size++; + if (type == HFSPLUS_FOLDER) + hfsplus_subfolders_inc(dst_dir); dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC; /* finally remove the old entry */ @@ -405,6 +444,8 @@ int hfsplus_rename_cat(u32 cnid, if (err) goto out; src_dir->i_size--; + if (type == HFSPLUS_FOLDER) + hfsplus_subfolders_dec(src_dir); src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC; /* remove old thread entry */ diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 08846425b67..62d571eb69b 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -242,6 +242,7 @@ struct hfsplus_inode_info { */ sector_t fs_blocks; u8 userflags; /* BSD user file flags */ + u32 subfolders; /* Subfolder count (HFSX only) */ struct list_head open_dir_list; loff_t phys_size; diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 8ffb3a8ffe7..5a126828d85 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h @@ -261,7 +261,7 @@ struct hfsplus_cat_folder { struct DInfo user_info; struct DXInfo finder_info; __be32 text_encoding; - u32 reserved; + __be32 subfolders; /* Subfolder count in HFSX. Reserved in HFS+. */ } __packed; /* HFS file info (stolen from hfs.h) */ @@ -301,11 +301,13 @@ struct hfsplus_cat_file { struct hfsplus_fork_raw rsrc_fork; } __packed; -/* File attribute bits */ +/* File and folder flag bits */ #define HFSPLUS_FILE_LOCKED 0x0001 #define HFSPLUS_FILE_THREAD_EXISTS 0x0002 #define HFSPLUS_XATTR_EXISTS 0x0004 #define HFSPLUS_ACL_EXISTS 0x0008 +#define HFSPLUS_HAS_FOLDER_COUNT 0x0010 /* Folder has subfolder count + * (HFSX only) */ /* HFS+ catalog thread (part of a cat_entry) */ struct hfsplus_cat_thread { diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index fa929f325f8..a4f45bd88a6 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -375,6 +375,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode) hip->extent_state = 0; hip->flags = 0; hip->userflags = 0; + hip->subfolders = 0; memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); hip->alloc_blocks = 0; @@ -494,6 +495,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); HFSPLUS_I(inode)->create_date = folder->create_date; HFSPLUS_I(inode)->fs_blocks = 0; + if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { + HFSPLUS_I(inode)->subfolders = + be32_to_cpu(folder->subfolders); + } inode->i_op = &hfsplus_dir_inode_operations; inode->i_fop = &hfsplus_dir_operations; } else if (type == HFSPLUS_FILE) { @@ -566,6 +571,10 @@ int hfsplus_cat_write_inode(struct inode *inode) folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); folder->valence = cpu_to_be32(inode->i_size - 2); + if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { + folder->subfolders = + cpu_to_be32(HFSPLUS_I(inode)->subfolders); + } hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, sizeof(struct hfsplus_cat_folder)); } else if (HFSPLUS_IS_RSRC(inode)) { diff --git a/fs/namei.c b/fs/namei.c index 385f7817bfc..2f730ef9b4b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1884,7 +1884,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, nd->path = f.file->f_path; if (flags & LOOKUP_RCU) { - if (f.need_put) + if (f.flags & FDPUT_FPUT) *fp = f.file; nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); rcu_read_lock(); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8450262bcf2..51632c40e89 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2393,8 +2393,8 @@ out_dio: if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || ((file->f_flags & O_DIRECT) && !direct_io)) { - ret = filemap_fdatawrite_range(file->f_mapping, pos, - pos + count - 1); + ret = filemap_fdatawrite_range(file->f_mapping, *ppos, + *ppos + count - 1); if (ret < 0) written = ret; @@ -2407,8 +2407,8 @@ out_dio: } if (!ret) - ret = filemap_fdatawait_range(file->f_mapping, pos, - pos + count - 1); + ret = filemap_fdatawait_range(file->f_mapping, *ppos, + *ppos + count - 1); } /* diff --git a/fs/open.c b/fs/open.c index 4b3e1edf2fe..b9ed8b25c10 100644 --- a/fs/open.c +++ b/fs/open.c @@ -705,6 +705,10 @@ static int do_dentry_open(struct file *f, return 0; } + /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ + if (S_ISREG(inode->i_mode)) + f->f_mode |= FMODE_ATOMIC_POS; + f->f_op = fops_get(inode->i_fop); if (unlikely(WARN_ON(!f->f_op))) { error = -ENODEV; diff --git a/fs/proc/base.c b/fs/proc/base.c index 51507065263..b9760628e1f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1824,6 +1824,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path) if (rc) goto out_mmput; + rc = -ENOENT; down_read(&mm->mmap_sem); vma = find_exact_vma(mm, vm_start, vm_end); if (vma && vma->vm_file) { diff --git a/fs/read_write.c b/fs/read_write.c index edc5746a902..54e19b9392d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence) } EXPORT_SYMBOL(vfs_llseek); +static inline struct fd fdget_pos(int fd) +{ + return __to_fd(__fdget_pos(fd)); +} + +static inline void fdput_pos(struct fd f) +{ + if (f.flags & FDPUT_POS_UNLOCK) + mutex_unlock(&f.file->f_pos_lock); + fdput(f); +} + SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) { off_t retval; - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); if (!f.file) return -EBADF; @@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ } - fdput(f); + fdput_pos(f); return retval; } @@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos) SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret = -EBADF; if (f.file) { @@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) ret = vfs_read(f.file, buf, count, &pos); if (ret >= 0) file_pos_write(f.file, pos); - fdput(f); + fdput_pos(f); } return ret; } @@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret = -EBADF; if (f.file) { @@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, ret = vfs_write(f.file, buf, count, &pos); if (ret >= 0) file_pos_write(f.file, pos); - fdput(f); + fdput_pos(f); } return ret; @@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev); SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, unsigned long, vlen) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret = -EBADF; if (f.file) { @@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, ret = vfs_readv(f.file, vec, vlen, &pos); if (ret >= 0) file_pos_write(f.file, pos); - fdput(f); + fdput_pos(f); } if (ret > 0) @@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, unsigned long, vlen) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret = -EBADF; if (f.file) { @@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, ret = vfs_writev(f.file, vec, vlen, &pos); if (ret >= 0) file_pos_write(f.file, pos); - fdput(f); + fdput_pos(f); } if (ret > 0) @@ -968,7 +980,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, const struct compat_iovec __user *,vec, compat_ulong_t, vlen) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret; loff_t pos; @@ -978,7 +990,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, ret = compat_readv(f.file, vec, vlen, &pos); if (ret >= 0) f.file->f_pos = pos; - fdput(f); + fdput_pos(f); return ret; } @@ -1035,7 +1047,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, const struct compat_iovec __user *, vec, compat_ulong_t, vlen) { - struct fd f = fdget(fd); + struct fd f = fdget_pos(fd); ssize_t ret; loff_t pos; @@ -1045,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, ret = compat_writev(f.file, vec, vlen, &pos); if (ret >= 0) f.file->f_pos = pos; - fdput(f); + fdput_pos(f); return ret; } diff --git a/include/dt-bindings/sound/tlv320aic31xx-micbias.h b/include/dt-bindings/sound/tlv320aic31xx-micbias.h new file mode 100644 index 00000000000..f5cb772ab9c --- /dev/null +++ b/include/dt-bindings/sound/tlv320aic31xx-micbias.h @@ -0,0 +1,8 @@ +#ifndef __DT_TLV320AIC31XX_MICBIAS_H +#define __DT_TLV320AIC31XX_MICBIAS_H + +#define MICBIAS_2_0V 1 +#define MICBIAS_2_5V 2 +#define MICBIAS_AVDDV 3 + +#endif /* __DT_TLV320AIC31XX_MICBIAS_H */ diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index be85127bfed..f27000f55a8 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -171,6 +171,11 @@ static inline int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 add return 0; } +static inline int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) +{ + return -ENXIO; +} + static inline int kvm_vgic_init(struct kvm *kvm) { return 0; diff --git a/include/linux/audit.h b/include/linux/audit.h index aa865a9a4c4..ec1464df4c6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -43,6 +43,7 @@ struct mq_attr; struct mqstat; struct audit_watch; struct audit_tree; +struct sk_buff; struct audit_krule { int vers_ops; @@ -463,7 +464,7 @@ extern int audit_filter_user(int type); extern int audit_filter_type(int type); extern int audit_rule_change(int type, __u32 portid, int seq, void *data, size_t datasz); -extern int audit_list_rules_send(__u32 portid, int seq); +extern int audit_list_rules_send(struct sk_buff *request_skb, int seq); extern u32 audit_enabled; #else /* CONFIG_AUDIT */ diff --git a/include/linux/file.h b/include/linux/file.h index cbacf4faf44..4d69123377a 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -28,33 +28,36 @@ static inline void fput_light(struct file *file, int fput_needed) struct fd { struct file *file; - int need_put; + unsigned int flags; }; +#define FDPUT_FPUT 1 +#define FDPUT_POS_UNLOCK 2 static inline void fdput(struct fd fd) { - if (fd.need_put) + if (fd.flags & FDPUT_FPUT) fput(fd.file); } extern struct file *fget(unsigned int fd); -extern struct file *fget_light(unsigned int fd, int *fput_needed); +extern struct file *fget_raw(unsigned int fd); +extern unsigned long __fdget(unsigned int fd); +extern unsigned long __fdget_raw(unsigned int fd); +extern unsigned long __fdget_pos(unsigned int fd); -static inline struct fd fdget(unsigned int fd) +static inline struct fd __to_fd(unsigned long v) { - int b; - struct file *f = fget_light(fd, &b); - return (struct fd){f,b}; + return (struct fd){(struct file *)(v & ~3),v & 3}; } -extern struct file *fget_raw(unsigned int fd); -extern struct file *fget_raw_light(unsigned int fd, int *fput_needed); +static inline struct fd fdget(unsigned int fd) +{ + return __to_fd(__fdget(fd)); +} static inline struct fd fdget_raw(unsigned int fd) { - int b; - struct file *f = fget_raw_light(fd, &b); - return (struct fd){f,b}; + return __to_fd(__fdget_raw(fd)); } extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); diff --git a/include/linux/fs.h b/include/linux/fs.h index 60829565e55..23b2a35d712 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -123,6 +123,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* File is opened with O_PATH; almost nothing can be done with it */ #define FMODE_PATH ((__force fmode_t)0x4000) +/* File needs atomic accesses to f_pos */ +#define FMODE_ATOMIC_POS ((__force fmode_t)0x8000) + /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) @@ -780,13 +783,14 @@ struct file { const struct file_operations *f_op; /* - * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR. + * Protects f_ep_links, f_flags. * Must not be taken from IRQ context. */ spinlock_t f_lock; atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; + struct mutex f_pos_lock; loff_t f_pos; struct fown_struct f_owner; const struct cred *f_cred; @@ -808,7 +812,7 @@ struct file { #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif -}; +} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */ struct file_handle { __u32 handle_bytes; diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 0437439bc04..39b81dc7d01 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -123,6 +123,10 @@ struct vm_area_struct; __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \ __GFP_NO_KSWAPD) +/* + * GFP_THISNODE does not perform any reclaim, you most likely want to + * use __GFP_THISNODE to allocate from a given node without fallback! + */ #ifdef CONFIG_NUMA #define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY) #else diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5f2052c8315..9b61b9bf81a 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -590,10 +590,10 @@ static inline bool zone_is_empty(struct zone *zone) /* * The NUMA zonelists are doubled because we need zonelists that restrict the - * allocations to a single node for GFP_THISNODE. + * allocations to a single node for __GFP_THISNODE. * * [0] : Zonelist with fallback - * [1] : No fallback (GFP_THISNODE) + * [1] : No fallback (__GFP_THISNODE) */ #define MAX_ZONELISTS 2 diff --git a/include/linux/slab.h b/include/linux/slab.h index 9260abdd67d..b5b2df60299 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -410,7 +410,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags) * * %GFP_NOWAIT - Allocation will not sleep. * - * %GFP_THISNODE - Allocate node-local memory only. + * %__GFP_THISNODE - Allocate node-local memory only. * * %GFP_DMA - Allocation suitable for DMA. * Should only be used for kmalloc() caches. Otherwise, use a diff --git a/include/net/sock.h b/include/net/sock.h index 5c3f7c3624a..b9586a137ca 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1488,6 +1488,11 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) */ #define sock_owned_by_user(sk) ((sk)->sk_lock.owned) +static inline void sock_release_ownership(struct sock *sk) +{ + sk->sk_lock.owned = 0; +} + /* * Macro so as to not evaluate some arguments when * lockdep is not enabled. @@ -2186,7 +2191,6 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, { #define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL) | \ (1UL << SOCK_RCVTSTAMP) | \ - (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \ (1UL << SOCK_TIMESTAMPING_SOFTWARE) | \ (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE) | \ (1UL << SOCK_TIMESTAMPING_SYS_HARDWARE)) diff --git a/include/sound/soc.h b/include/sound/soc.h index 959f3894996..0b83168d8ff 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -354,12 +354,6 @@ typedef int (*hw_write_t)(void *,const char* ,int); extern struct snd_ac97_bus_ops *soc_ac97_ops; -enum snd_soc_control_type { - SND_SOC_I2C = 1, - SND_SOC_SPI, - SND_SOC_REGMAP, -}; - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, @@ -406,8 +400,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec, int snd_soc_codec_writable_register(struct snd_soc_codec *codec, unsigned int reg); int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control); + struct regmap *regmap); int snd_soc_cache_sync(struct snd_soc_codec *codec); int snd_soc_cache_init(struct snd_soc_codec *codec); int snd_soc_cache_exit(struct snd_soc_codec *codec); @@ -614,7 +607,8 @@ struct snd_soc_jack_gpio { struct snd_soc_jack *jack; struct delayed_work work; - int (*jack_status_check)(void); + void *data; + int (*jack_status_check)(void *data); }; struct snd_soc_jack { @@ -717,7 +711,6 @@ struct snd_soc_codec { /* codec IO */ void *control_data; /* codec control (i2c/3wire) data */ hw_write_t hw_write; - unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); unsigned int (*read)(struct snd_soc_codec *, unsigned int); int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); void *reg_cache; @@ -1114,6 +1107,19 @@ struct soc_enum { const unsigned int *values; }; +/** + * snd_soc_component_to_codec() - Casts a component to the CODEC it is embedded in + * @component: The component to cast to a CODEC + * + * This function must only be used on components that are known to be CODECs. + * Otherwise the behavior is undefined. + */ +static inline struct snd_soc_codec *snd_soc_component_to_codec( + struct snd_soc_component *component) +{ + return container_of(component, struct snd_soc_codec, component); +} + /* codec IO */ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg); unsigned int snd_soc_write(struct snd_soc_codec *codec, diff --git a/init/main.c b/init/main.c index eb03090cdce..9c7fd4c9249 100644 --- a/init/main.c +++ b/init/main.c @@ -561,7 +561,6 @@ asmlinkage void __init start_kernel(void) init_timers(); hrtimers_init(); softirq_init(); - acpi_early_init(); timekeeping_init(); time_init(); sched_clock_postinit(); @@ -613,6 +612,7 @@ asmlinkage void __init start_kernel(void) calibrate_delay(); pidmap_init(); anon_vma_init(); + acpi_early_init(); #ifdef CONFIG_X86 if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_enter_virtual_mode(); diff --git a/ipc/msg.c b/ipc/msg.c index 245db1140ad..649853105a5 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -901,6 +901,8 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl return -EINVAL; if (msgflg & MSG_COPY) { + if ((msgflg & MSG_EXCEPT) || !(msgflg & IPC_NOWAIT)) + return -EINVAL; copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax)); if (IS_ERR(copy)) return PTR_ERR(copy); diff --git a/kernel/audit.c b/kernel/audit.c index 34c5a2310fb..3392d3e0254 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -182,7 +182,7 @@ struct audit_buffer { struct audit_reply { __u32 portid; - pid_t pid; + struct net *net; struct sk_buff *skb; }; @@ -500,7 +500,7 @@ int audit_send_list(void *_dest) { struct audit_netlink_list *dest = _dest; struct sk_buff *skb; - struct net *net = get_net_ns_by_pid(dest->pid); + struct net *net = dest->net; struct audit_net *aunet = net_generic(net, audit_net_id); /* wait for parent to finish and send an ACK */ @@ -510,6 +510,7 @@ int audit_send_list(void *_dest) while ((skb = __skb_dequeue(&dest->q)) != NULL) netlink_unicast(aunet->nlsk, skb, dest->portid, 0); + put_net(net); kfree(dest); return 0; @@ -543,7 +544,7 @@ out_kfree_skb: static int audit_send_reply_thread(void *arg) { struct audit_reply *reply = (struct audit_reply *)arg; - struct net *net = get_net_ns_by_pid(reply->pid); + struct net *net = reply->net; struct audit_net *aunet = net_generic(net, audit_net_id); mutex_lock(&audit_cmd_mutex); @@ -552,12 +553,13 @@ static int audit_send_reply_thread(void *arg) /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0); + put_net(net); kfree(reply); return 0; } /** * audit_send_reply - send an audit reply message via netlink - * @portid: netlink port to which to send reply + * @request_skb: skb of request we are replying to (used to target the reply) * @seq: sequence number * @type: audit message type * @done: done (last) flag @@ -568,9 +570,11 @@ static int audit_send_reply_thread(void *arg) * Allocates an skb, builds the netlink message, and sends it to the port id. * No failure notifications. */ -static void audit_send_reply(__u32 portid, int seq, int type, int done, +static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done, int multi, const void *payload, int size) { + u32 portid = NETLINK_CB(request_skb).portid; + struct net *net = sock_net(NETLINK_CB(request_skb).sk); struct sk_buff *skb; struct task_struct *tsk; struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), @@ -583,8 +587,8 @@ static void audit_send_reply(__u32 portid, int seq, int type, int done, if (!skb) goto out; + reply->net = get_net(net); reply->portid = portid; - reply->pid = task_pid_vnr(current); reply->skb = skb; tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); @@ -673,8 +677,7 @@ static int audit_get_feature(struct sk_buff *skb) seq = nlmsg_hdr(skb)->nlmsg_seq; - audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, - &af, sizeof(af)); + audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af)); return 0; } @@ -794,8 +797,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) s.backlog = skb_queue_len(&audit_skb_queue); s.version = AUDIT_VERSION_LATEST; s.backlog_wait_time = audit_backlog_wait_time; - audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, - &s, sizeof(s)); + audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); break; } case AUDIT_SET: { @@ -905,7 +907,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) seq, data, nlmsg_len(nlh)); break; case AUDIT_LIST_RULES: - err = audit_list_rules_send(NETLINK_CB(skb).portid, seq); + err = audit_list_rules_send(skb, seq); break; case AUDIT_TRIM: audit_trim_trees(); @@ -970,8 +972,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memcpy(sig_data->ctx, ctx, len); security_release_secctx(ctx, len); } - audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_SIGNAL_INFO, - 0, 0, sig_data, sizeof(*sig_data) + len); + audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0, + sig_data, sizeof(*sig_data) + len); kfree(sig_data); break; case AUDIT_TTY_GET: { @@ -983,8 +985,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) s.log_passwd = tsk->signal->audit_tty_log_passwd; spin_unlock(&tsk->sighand->siglock); - audit_send_reply(NETLINK_CB(skb).portid, seq, - AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); + audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); break; } case AUDIT_TTY_SET: { diff --git a/kernel/audit.h b/kernel/audit.h index 57cc64d6771..8df13221460 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -247,7 +247,7 @@ extern void audit_panic(const char *message); struct audit_netlink_list { __u32 portid; - pid_t pid; + struct net *net; struct sk_buff_head q; }; diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 14a78cca384..92062fd6cc8 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -29,6 +29,8 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/security.h> +#include <net/net_namespace.h> +#include <net/sock.h> #include "audit.h" /* @@ -1065,11 +1067,13 @@ int audit_rule_change(int type, __u32 portid, int seq, void *data, /** * audit_list_rules_send - list the audit rules - * @portid: target portid for netlink audit messages + * @request_skb: skb of request we are replying to (used to target the reply) * @seq: netlink audit message sequence (serial) number */ -int audit_list_rules_send(__u32 portid, int seq) +int audit_list_rules_send(struct sk_buff *request_skb, int seq) { + u32 portid = NETLINK_CB(request_skb).portid; + struct net *net = sock_net(NETLINK_CB(request_skb).sk); struct task_struct *tsk; struct audit_netlink_list *dest; int err = 0; @@ -1083,8 +1087,8 @@ int audit_list_rules_send(__u32 portid, int seq) dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL); if (!dest) return -ENOMEM; + dest->net = get_net(net); dest->portid = portid; - dest->pid = task_pid_vnr(current); skb_queue_head_init(&dest->q); mutex_lock(&audit_filter_mutex); diff --git a/kernel/profile.c b/kernel/profile.c index 6631e1ef55a..ebdd9c1a86b 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -549,14 +549,14 @@ static int create_hash_tables(void) struct page *page; page = alloc_pages_exact_node(node, - GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, 0); if (!page) goto out_cleanup; per_cpu(cpu_profile_hits, cpu)[1] = (struct profile_hit *)page_address(page); page = alloc_pages_exact_node(node, - GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, 0); if (!page) goto out_cleanup; diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index 43c2bcc3576..b30a2924ef1 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -301,14 +301,14 @@ u64 sched_clock_cpu(int cpu) if (unlikely(!sched_clock_running)) return 0ull; - preempt_disable(); + preempt_disable_notrace(); scd = cpu_sdc(cpu); if (cpu != smp_processor_id()) clock = sched_clock_remote(scd); else clock = sched_clock_local(scd); - preempt_enable(); + preempt_enable_notrace(); return clock; } diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 6edbef296ec..f5c6635b806 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3338,6 +3338,15 @@ recheck: return -EPERM; } + /* + * Can't set/change SCHED_DEADLINE policy at all for now + * (safest behavior); in the future we would like to allow + * unprivileged DL tasks to increase their relative deadline + * or reduce their runtime (both ways reducing utilization) + */ + if (dl_policy(policy)) + return -EPERM; + /* * Treat SCHED_IDLE as nice 20. Only allow a switch to * SCHED_NORMAL if the RLIMIT_NICE would normally permit it. diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 84571e09c90..01fbae5b97b 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -293,7 +293,7 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void * */ smp_call_function_single(min(cpu1, cpu2), &irq_cpu_stop_queue_work, - &call_args, 0); + &call_args, 1); lg_local_unlock(&stop_cpus_lock); preempt_enable(); diff --git a/mm/Kconfig b/mm/Kconfig index 2d9f1504d75..2888024e0b0 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -575,5 +575,5 @@ config PGTABLE_MAPPING then you should select this. This causes zsmalloc to use page table mapping rather than copying for object mapping. - You can check speed with zsmalloc benchmark[1]. - [1] https://github.com/spartacus06/zsmalloc + You can check speed with zsmalloc benchmark: + https://github.com/spartacus06/zsmapbench diff --git a/mm/compaction.c b/mm/compaction.c index b48c5259ea3..918577595ea 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -251,7 +251,6 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, { int nr_scanned = 0, total_isolated = 0; struct page *cursor, *valid_page = NULL; - unsigned long nr_strict_required = end_pfn - blockpfn; unsigned long flags; bool locked = false; @@ -264,11 +263,12 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, nr_scanned++; if (!pfn_valid_within(blockpfn)) - continue; + goto isolate_fail; + if (!valid_page) valid_page = page; if (!PageBuddy(page)) - continue; + goto isolate_fail; /* * The zone lock must be held to isolate freepages. @@ -289,12 +289,10 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, /* Recheck this is a buddy page under lock */ if (!PageBuddy(page)) - continue; + goto isolate_fail; /* Found a free page, break it into order-0 pages */ isolated = split_free_page(page); - if (!isolated && strict) - break; total_isolated += isolated; for (i = 0; i < isolated; i++) { list_add(&page->lru, freelist); @@ -305,7 +303,15 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, if (isolated) { blockpfn += isolated - 1; cursor += isolated - 1; + continue; } + +isolate_fail: + if (strict) + break; + else + continue; + } trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated); @@ -315,7 +321,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, * pages requested were isolated. If there were any failures, 0 is * returned and CMA will fail. */ - if (strict && nr_strict_required > total_isolated) + if (strict && blockpfn < end_pfn) total_isolated = 0; if (locked) diff --git a/mm/migrate.c b/mm/migrate.c index 482a33d8913..b494fdb9a63 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1158,7 +1158,7 @@ static struct page *new_page_node(struct page *p, unsigned long private, pm->node); else return alloc_pages_exact_node(pm->node, - GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0); + GFP_HIGHUSER_MOVABLE | __GFP_THISNODE, 0); } /* @@ -1544,9 +1544,9 @@ static struct page *alloc_misplaced_dst_page(struct page *page, struct page *newpage; newpage = alloc_pages_exact_node(nid, - (GFP_HIGHUSER_MOVABLE | GFP_THISNODE | - __GFP_NOMEMALLOC | __GFP_NORETRY | - __GFP_NOWARN) & + (GFP_HIGHUSER_MOVABLE | + __GFP_THISNODE | __GFP_NOMEMALLOC | + __GFP_NORETRY | __GFP_NOWARN) & ~GFP_IOFS, 0); return newpage; @@ -1747,7 +1747,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, goto out_dropref; new_page = alloc_pages_node(node, - (GFP_TRANSHUGE | GFP_THISNODE) & ~__GFP_WAIT, HPAGE_PMD_ORDER); + (GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_WAIT, + HPAGE_PMD_ORDER); if (!new_page) goto out_fail; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index de51c48c439..4b65aa492fb 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -538,6 +538,9 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; + if (saddr == NULL) + saddr = dev->dev_addr; + return dev_hard_header(skb, real_dev, type, daddr, saddr, len); } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ef66365b735..93067ecdb9a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1127,9 +1127,10 @@ static void br_multicast_query_received(struct net_bridge *br, struct net_bridge_port *port, struct bridge_mcast_querier *querier, int saddr, + bool is_general_query, unsigned long max_delay) { - if (saddr) + if (saddr && is_general_query) br_multicast_update_querier_timer(br, querier, max_delay); else if (timer_pending(&querier->timer)) return; @@ -1181,8 +1182,16 @@ static int br_ip4_multicast_query(struct net_bridge *br, IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; } + /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer + * all-systems destination addresses (224.0.0.1) for general queries + */ + if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) { + err = -EINVAL; + goto out; + } + br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, - max_delay); + !group, max_delay); if (!group) goto out; @@ -1228,6 +1237,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, unsigned long max_delay; unsigned long now = jiffies; const struct in6_addr *group = NULL; + bool is_general_query; int err = 0; spin_lock(&br->multicast_lock); @@ -1235,6 +1245,12 @@ static int br_ip6_multicast_query(struct net_bridge *br, (port && port->state == BR_STATE_DISABLED)) goto out; + /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */ + if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) { + err = -EINVAL; + goto out; + } + if (skb->len == sizeof(*mld)) { if (!pskb_may_pull(skb, sizeof(*mld))) { err = -EINVAL; @@ -1256,8 +1272,19 @@ static int br_ip6_multicast_query(struct net_bridge *br, max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); } + is_general_query = group && ipv6_addr_any(group); + + /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer + * all-nodes destination address (ff02::1) for general queries + */ + if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) { + err = -EINVAL; + goto out; + } + br_multicast_query_received(br, port, &br->ip6_querier, - !ipv6_addr_any(&ip6h->saddr), max_delay); + !ipv6_addr_any(&ip6h->saddr), + is_general_query, max_delay); if (!group) goto out; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5d6236d9fdc..869c7afe3b0 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2838,81 +2838,84 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); /** * skb_segment - Perform protocol segmentation on skb. - * @skb: buffer to segment + * @head_skb: buffer to segment * @features: features for the output path (see dev->features) * * This function performs segmentation on the given skb. It returns * a pointer to the first in a list of new skbs for the segments. * In case of error it returns ERR_PTR(err). */ -struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) +struct sk_buff *skb_segment(struct sk_buff *head_skb, + netdev_features_t features) { struct sk_buff *segs = NULL; struct sk_buff *tail = NULL; - struct sk_buff *fskb = skb_shinfo(skb)->frag_list; - skb_frag_t *skb_frag = skb_shinfo(skb)->frags; - unsigned int mss = skb_shinfo(skb)->gso_size; - unsigned int doffset = skb->data - skb_mac_header(skb); + struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; + skb_frag_t *frag = skb_shinfo(head_skb)->frags; + unsigned int mss = skb_shinfo(head_skb)->gso_size; + unsigned int doffset = head_skb->data - skb_mac_header(head_skb); + struct sk_buff *frag_skb = head_skb; unsigned int offset = doffset; - unsigned int tnl_hlen = skb_tnl_header_len(skb); + unsigned int tnl_hlen = skb_tnl_header_len(head_skb); unsigned int headroom; unsigned int len; __be16 proto; bool csum; int sg = !!(features & NETIF_F_SG); - int nfrags = skb_shinfo(skb)->nr_frags; + int nfrags = skb_shinfo(head_skb)->nr_frags; int err = -ENOMEM; int i = 0; int pos; - proto = skb_network_protocol(skb); + proto = skb_network_protocol(head_skb); if (unlikely(!proto)) return ERR_PTR(-EINVAL); csum = !!can_checksum_protocol(features, proto); - __skb_push(skb, doffset); - headroom = skb_headroom(skb); - pos = skb_headlen(skb); + __skb_push(head_skb, doffset); + headroom = skb_headroom(head_skb); + pos = skb_headlen(head_skb); do { struct sk_buff *nskb; - skb_frag_t *frag; + skb_frag_t *nskb_frag; int hsize; int size; - len = skb->len - offset; + len = head_skb->len - offset; if (len > mss) len = mss; - hsize = skb_headlen(skb) - offset; + hsize = skb_headlen(head_skb) - offset; if (hsize < 0) hsize = 0; if (hsize > len || !sg) hsize = len; - if (!hsize && i >= nfrags && skb_headlen(fskb) && - (skb_headlen(fskb) == len || sg)) { - BUG_ON(skb_headlen(fskb) > len); + if (!hsize && i >= nfrags && skb_headlen(list_skb) && + (skb_headlen(list_skb) == len || sg)) { + BUG_ON(skb_headlen(list_skb) > len); i = 0; - nfrags = skb_shinfo(fskb)->nr_frags; - skb_frag = skb_shinfo(fskb)->frags; - pos += skb_headlen(fskb); + nfrags = skb_shinfo(list_skb)->nr_frags; + frag = skb_shinfo(list_skb)->frags; + frag_skb = list_skb; + pos += skb_headlen(list_skb); while (pos < offset + len) { BUG_ON(i >= nfrags); - size = skb_frag_size(skb_frag); + size = skb_frag_size(frag); if (pos + size > offset + len) break; i++; pos += size; - skb_frag++; + frag++; } - nskb = skb_clone(fskb, GFP_ATOMIC); - fskb = fskb->next; + nskb = skb_clone(list_skb, GFP_ATOMIC); + list_skb = list_skb->next; if (unlikely(!nskb)) goto err; @@ -2933,7 +2936,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) __skb_push(nskb, doffset); } else { nskb = __alloc_skb(hsize + doffset + headroom, - GFP_ATOMIC, skb_alloc_rx_flag(skb), + GFP_ATOMIC, skb_alloc_rx_flag(head_skb), NUMA_NO_NODE); if (unlikely(!nskb)) @@ -2949,12 +2952,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) segs = nskb; tail = nskb; - __copy_skb_header(nskb, skb); - nskb->mac_len = skb->mac_len; + __copy_skb_header(nskb, head_skb); + nskb->mac_len = head_skb->mac_len; skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); - skb_copy_from_linear_data_offset(skb, -tnl_hlen, + skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, nskb->data - tnl_hlen, doffset + tnl_hlen); @@ -2963,30 +2966,32 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) if (!sg) { nskb->ip_summed = CHECKSUM_NONE; - nskb->csum = skb_copy_and_csum_bits(skb, offset, + nskb->csum = skb_copy_and_csum_bits(head_skb, offset, skb_put(nskb, len), len, 0); continue; } - frag = skb_shinfo(nskb)->frags; + nskb_frag = skb_shinfo(nskb)->frags; - skb_copy_from_linear_data_offset(skb, offset, + skb_copy_from_linear_data_offset(head_skb, offset, skb_put(nskb, hsize), hsize); - skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; + skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & + SKBTX_SHARED_FRAG; while (pos < offset + len) { if (i >= nfrags) { - BUG_ON(skb_headlen(fskb)); + BUG_ON(skb_headlen(list_skb)); i = 0; - nfrags = skb_shinfo(fskb)->nr_frags; - skb_frag = skb_shinfo(fskb)->frags; + nfrags = skb_shinfo(list_skb)->nr_frags; + frag = skb_shinfo(list_skb)->frags; + frag_skb = list_skb; BUG_ON(!nfrags); - fskb = fskb->next; + list_skb = list_skb->next; } if (unlikely(skb_shinfo(nskb)->nr_frags >= @@ -2997,27 +3002,30 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) goto err; } - *frag = *skb_frag; - __skb_frag_ref(frag); - size = skb_frag_size(frag); + if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC))) + goto err; + + *nskb_frag = *frag; + __skb_frag_ref(nskb_frag); + size = skb_frag_size(nskb_frag); if (pos < offset) { - frag->page_offset += offset - pos; - skb_frag_size_sub(frag, offset - pos); + nskb_frag->page_offset += offset - pos; + skb_frag_size_sub(nskb_frag, offset - pos); } skb_shinfo(nskb)->nr_frags++; if (pos + size <= offset + len) { i++; - skb_frag++; + frag++; pos += size; } else { - skb_frag_size_sub(frag, pos + size - (offset + len)); + skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); goto skip_fraglist; } - frag++; + nskb_frag++; } skip_fraglist: @@ -3031,7 +3039,7 @@ perform_csum_check: nskb->len - doffset, 0); nskb->ip_summed = CHECKSUM_NONE; } - } while ((offset += len) < skb->len); + } while ((offset += len) < head_skb->len); return segs; diff --git a/net/core/sock.c b/net/core/sock.c index 5b6a9431b01..c0fc6bdad1e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2357,10 +2357,13 @@ void release_sock(struct sock *sk) if (sk->sk_backlog.tail) __release_sock(sk); + /* Warning : release_cb() might need to release sk ownership, + * ie call sock_release_ownership(sk) before us. + */ if (sk->sk_prot->release_cb) sk->sk_prot->release_cb(sk); - sk->sk_lock.owned = 0; + sock_release_ownership(sk); if (waitqueue_active(&sk->sk_lock.wq)) wake_up(&sk->sk_lock.wq); spin_unlock_bh(&sk->sk_lock.slock); diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index bb075fc9a14..3b01959bf4b 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -208,7 +208,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force) } work = frag_mem_limit(nf) - nf->low_thresh; - while (work > 0) { + while (work > 0 || force) { spin_lock(&nf->lru_lock); if (list_empty(&nf->lru_list)) { @@ -278,9 +278,10 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, atomic_inc(&qp->refcnt); hlist_add_head(&qp->list, &hb->chain); + inet_frag_lru_add(nf, qp); spin_unlock(&hb->chain_lock); read_unlock(&f->lock); - inet_frag_lru_add(nf, qp); + return qp; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f0eb4e337ec..17a11e65e57 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -767,6 +767,17 @@ void tcp_release_cb(struct sock *sk) if (flags & (1UL << TCP_TSQ_DEFERRED)) tcp_tsq_handler(sk); + /* Here begins the tricky part : + * We are called from release_sock() with : + * 1) BH disabled + * 2) sk_lock.slock spinlock held + * 3) socket owned by us (sk->sk_lock.owned == 1) + * + * But following code is meant to be called from BH handlers, + * so we should keep BH disabled, but early release socket ownership + */ + sock_release_ownership(sk); + if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { tcp_write_timer_handler(sk); __sock_put(sk); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fdbfeca36d6..344e972426d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1103,8 +1103,11 @@ retry: * Lifetime is greater than REGEN_ADVANCE time units. In particular, * an implementation must not create a temporary address with a zero * Preferred Lifetime. + * Use age calculation as in addrconf_verify to avoid unnecessary + * temporary addresses being generated. */ - if (tmp_prefered_lft <= regen_advance) { + age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; + if (tmp_prefered_lft <= regen_advance + age) { in6_ifa_put(ifp); in6_dev_put(idev); ret = -1; diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c index cf77f3abfd0..447a7fbd1bb 100644 --- a/net/ipv6/exthdrs_offload.c +++ b/net/ipv6/exthdrs_offload.c @@ -25,11 +25,11 @@ int __init ipv6_exthdrs_offload_init(void) int ret; ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); - if (!ret) + if (ret) goto out; ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); - if (!ret) + if (ret) goto out_rt; out: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 11dac21e658..fba54a407bb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg) if (!table) goto out; - rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table); + rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); if (!rt) { err = -ENOMEM; diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 735d0f60c83..85d9d94c0a3 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -112,7 +112,6 @@ struct l2tp_net { spinlock_t l2tp_session_hlist_lock; }; -static void l2tp_session_set_header_len(struct l2tp_session *session, int version); static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) @@ -1863,7 +1862,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete); /* We come here whenever a session's send_seq, cookie_len or * l2specific_len parameters are set. */ -static void l2tp_session_set_header_len(struct l2tp_session *session, int version) +void l2tp_session_set_header_len(struct l2tp_session *session, int version) { if (version == L2TP_HDR_VER_2) { session->hdr_len = 6; @@ -1876,6 +1875,7 @@ static void l2tp_session_set_header_len(struct l2tp_session *session, int versio } } +EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) { diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 1f01ba3435b..3f93ccd6ba9 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -263,6 +263,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, int length, int (*payload_hook)(struct sk_buff *skb)); int l2tp_session_queue_purge(struct l2tp_session *session); int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); +void l2tp_session_set_header_len(struct l2tp_session *session, int version); int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4cfd722e915..bd7387adea9 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -578,8 +578,10 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf if (info->attrs[L2TP_ATTR_RECV_SEQ]) session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); - if (info->attrs[L2TP_ATTR_SEND_SEQ]) + if (info->attrs[L2TP_ATTR_SEND_SEQ]) { session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); + l2tp_session_set_header_len(session, session->tunnel->version); + } if (info->attrs[L2TP_ATTR_LNS_MODE]) session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index be5fadf3473..5990919356a 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -254,12 +254,14 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int po = pppox_sk(sk); ppp_input(&po->chan, skb); } else { - l2tp_info(session, PPPOL2TP_MSG_DATA, "%s: socket not bound\n", - session->name); + l2tp_dbg(session, PPPOL2TP_MSG_DATA, + "%s: recv %d byte data frame, passing to L2TP socket\n", + session->name, data_len); - /* Not bound. Nothing we can do, so discard. */ - atomic_long_inc(&session->stats.rx_errors); - kfree_skb(skb); + if (sock_queue_rcv_skb(sk, skb) < 0) { + atomic_long_inc(&session->stats.rx_errors); + kfree_skb(skb); + } } return; @@ -1312,6 +1314,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk, po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; } + l2tp_session_set_header_len(session, session->tunnel->version); l2tp_info(session, PPPOL2TP_MSG_CONTROL, "%s: set send_seq=%d\n", session->name, session->send_seq); diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a97dd..0c1ecfdf9a1 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -100,6 +100,12 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, } max_bw = max(max_bw, width); } + + /* use the configured bandwidth in case of monitor interface */ + sdata = rcu_dereference(local->monitor_sdata); + if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf) + max_bw = max(max_bw, conf->def.width); + rcu_read_unlock(); return max_bw; diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c index 2802f9d9279..ad8b377b4b9 100644 --- a/net/mac80211/mesh_ps.c +++ b/net/mac80211/mesh_ps.c @@ -36,6 +36,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta) sdata->vif.addr); nullfunc->frame_control = fc; nullfunc->duration_id = 0; + nullfunc->seq_ctrl = 0; /* no address resolution for this frame -> set addr 1 immediately */ memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a023b432143..137a192e64b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1206,6 +1206,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); + nullfunc->seq_ctrl = 0; skb->priority = tid; skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 1313145e3b8..a07d55e7569 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -273,11 +273,12 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) void qdisc_list_add(struct Qdisc *q) { - struct Qdisc *root = qdisc_dev(q)->qdisc; + if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { + struct Qdisc *root = qdisc_dev(q)->qdisc; - WARN_ON_ONCE(root == &noop_qdisc); - if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) + WARN_ON_ONCE(root == &noop_qdisc); list_add_tail(&q->list, &root->list); + } } EXPORT_SYMBOL(qdisc_list_add); diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 08ef7a42c0e..21e251766eb 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -601,6 +601,7 @@ static int fq_resize(struct Qdisc *sch, u32 log) { struct fq_sched_data *q = qdisc_priv(sch); struct rb_root *array; + void *old_fq_root; u32 idx; if (q->fq_root && log == q->fq_trees_log) @@ -615,13 +616,19 @@ static int fq_resize(struct Qdisc *sch, u32 log) for (idx = 0; idx < (1U << log); idx++) array[idx] = RB_ROOT; - if (q->fq_root) { - fq_rehash(q, q->fq_root, q->fq_trees_log, array, log); - fq_free(q->fq_root); - } + sch_tree_lock(sch); + + old_fq_root = q->fq_root; + if (old_fq_root) + fq_rehash(q, old_fq_root, q->fq_trees_log, array, log); + q->fq_root = array; q->fq_trees_log = log; + sch_tree_unlock(sch); + + fq_free(old_fq_root); + return 0; } @@ -697,9 +704,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) q->flow_refill_delay = usecs_to_jiffies(usecs_delay); } - if (!err) + if (!err) { + sch_tree_unlock(sch); err = fq_resize(sch, fq_log); - + sch_tree_lock(sch); + } while (sch->q.qlen > sch->limit) { struct sk_buff *skb = fq_dequeue(sch); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 632090b961c..3a1767ef320 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1421,8 +1421,8 @@ static void sctp_chunk_destroy(struct sctp_chunk *chunk) BUG_ON(!list_empty(&chunk->list)); list_del_init(&chunk->transmitted_list); - /* Free the chunk skb data and the SCTP_chunk stub itself. */ - dev_kfree_skb(chunk->skb); + consume_skb(chunk->skb); + consume_skb(chunk->auth_chunk); SCTP_DBG_OBJCNT_DEC(chunk); kmem_cache_free(sctp_chunk_cachep, chunk); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ae65b6b5973..01e002430c8 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -760,7 +760,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, /* Make sure that we and the peer are AUTH capable */ if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { - kfree_skb(chunk->auth_chunk); sctp_association_free(new_asoc); return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); } @@ -775,10 +774,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, auth.transport = chunk->transport; ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); - - /* We can now safely free the auth_chunk clone */ - kfree_skb(chunk->auth_chunk); - if (ret != SCTP_IERROR_NO_ERROR) { sctp_association_free(new_asoc); return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); diff --git a/net/socket.c b/net/socket.c index 879933aaed4..a19ae1968d3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup); static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) { - struct file *file; + struct fd f = fdget(fd); struct socket *sock; *err = -EBADF; - file = fget_light(fd, fput_needed); - if (file) { - sock = sock_from_file(file, err); - if (sock) + if (f.file) { + sock = sock_from_file(f.file, err); + if (likely(sock)) { + *fput_needed = f.flags; return sock; - fput_light(file, *fput_needed); + } + fdput(f); } return NULL; } @@ -1985,6 +1986,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, { if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) return -EFAULT; + + if (kmsg->msg_namelen < 0) + return -EINVAL; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) kmsg->msg_namelen = sizeof(struct sockaddr_storage); return 0; diff --git a/net/tipc/config.c b/net/tipc/config.c index e74eef2e749..e6d721692ae 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, struct tipc_cfg_msg_hdr *req_hdr; struct tipc_cfg_msg_hdr *rep_hdr; struct sk_buff *rep_buf; - int ret; /* Validate configuration message header (ignore invalid message) */ req_hdr = (struct tipc_cfg_msg_hdr *)buf; @@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); rep_hdr->tcm_len = htonl(rep_buf->len); rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); - - ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, - rep_buf->len); - if (ret < 0) - pr_err("Sending cfg reply message failed, no memory\n"); - + tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, + rep_buf->len); kfree_skb(rep_buf); } } diff --git a/net/tipc/handler.c b/net/tipc/handler.c index e4bc8a29674..1fabf160501 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument) spin_lock_bh(&qitem_lock); if (!handler_enabled) { - pr_err("Signal request ignored by handler\n"); spin_unlock_bh(&qitem_lock); return -ENOPROTOOPT; } diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 48302be175c..042e8e3cabc 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -941,17 +941,48 @@ int tipc_nametbl_init(void) return 0; } +/** + * tipc_purge_publications - remove all publications for a given type + * + * tipc_nametbl_lock must be held when calling this function + */ +static void tipc_purge_publications(struct name_seq *seq) +{ + struct publication *publ, *safe; + struct sub_seq *sseq; + struct name_info *info; + + if (!seq->sseqs) { + nameseq_delete_empty(seq); + return; + } + sseq = seq->sseqs; + info = sseq->info; + list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { + tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, + publ->ref, publ->key); + } +} + void tipc_nametbl_stop(void) { u32 i; + struct name_seq *seq; + struct hlist_head *seq_head; + struct hlist_node *safe; - /* Verify name table is empty, then release it */ + /* Verify name table is empty and purge any lingering + * publications, then release the name table + */ write_lock_bh(&tipc_nametbl_lock); for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { if (hlist_empty(&table.types[i])) continue; - pr_err("nametbl_stop(): orphaned hash chain detected\n"); - break; + seq_head = &table.types[i]; + hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { + tipc_purge_publications(seq); + } + continue; } kfree(table.types); table.types = NULL; diff --git a/net/tipc/server.c b/net/tipc/server.c index 373979789a7..646a930eefb 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con); static void tipc_conn_kref_release(struct kref *kref) { struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); - struct tipc_server *s = con->server; if (con->sock) { tipc_sock_release_local(con->sock); @@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref) } tipc_clean_outqueues(con); - - if (con->conid) - s->tipc_conn_shutdown(con->conid, con->usr_data); - kfree(con); } @@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con) struct tipc_server *s = con->server; if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { + if (con->conid) + s->tipc_conn_shutdown(con->conid, con->usr_data); + spin_lock_bh(&s->idr_lock); idr_remove(&s->conn_idr, con->conid); s->idr_in_use--; @@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, list_add_tail(&e->list, &con->outqueue); spin_unlock_bh(&con->outqueue_lock); - if (test_bit(CF_CONNECTED, &con->flags)) + if (test_bit(CF_CONNECTED, &con->flags)) { if (!queue_work(s->send_wq, &con->swork)) conn_put(con); - + } else { + conn_put(con); + } return 0; } diff --git a/net/tipc/socket.c b/net/tipc/socket.c index a4cf274455a..0ed0eaa62f2 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -997,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - if (skb_queue_empty(&sk->sk_receive_queue)) { + if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { if (sock->state == SS_DISCONNECTING) { err = -ENOTCONN; break; @@ -1623,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) for (;;) { prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - if (skb_queue_empty(&sk->sk_receive_queue)) { + if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7cb0bd5b117..11c9ae00837 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, { struct tipc_subscriber *subscriber = sub->subscriber; struct kvec msg_sect; - int ret; msg_sect.iov_base = (void *)&sub->evt; msg_sect.iov_len = sizeof(struct tipc_event); - sub->evt.event = htohl(event, sub->swap); sub->evt.found_lower = htohl(found_lower, sub->swap); sub->evt.found_upper = htohl(found_upper, sub->swap); sub->evt.port.ref = htohl(port_ref, sub->swap); sub->evt.port.node = htohl(node, sub->swap); - ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, - msg_sect.iov_base, msg_sect.iov_len); - if (ret < 0) - pr_err("Sending subscription event failed, no memory\n"); + tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, + msg_sect.iov_len); } /** @@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub) /* The spin lock per subscriber is used to protect its members */ spin_lock_bh(&subscriber->lock); - /* Validate if the connection related to the subscriber is - * closed (in case subscriber is terminating) - */ - if (subscriber->conid == 0) { - spin_unlock_bh(&subscriber->lock); - return; - } - /* Validate timeout (in case subscription is being cancelled) */ if (sub->timeout == TIPC_WAIT_FOREVER) { spin_unlock_bh(&subscriber->lock); @@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber) spin_lock_bh(&subscriber->lock); - /* Invalidate subscriber reference */ - subscriber->conid = 0; - /* Destroy any existing subscriptions for subscriber */ list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, subscription_list) { diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 29fc8bee970..ce6ec6c2f4d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -163,9 +163,8 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) static inline unsigned int unix_hash_fold(__wsum n) { - unsigned int hash = (__force unsigned int)n; + unsigned int hash = (__force unsigned int)csum_fold(n); - hash ^= hash>>16; hash ^= hash>>8; return hash&(UNIX_HASH_SIZE-1); } diff --git a/net/wireless/core.c b/net/wireless/core.c index 010892b81a0..a3bf18d1160 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -788,8 +788,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, default: break; } - - wdev->beacon_interval = 0; } static int cfg80211_netdev_notifier_call(struct notifier_block *nb, diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 276e84b8a8e..10085de886f 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -330,7 +330,8 @@ static void write_src(void) printf("\tPTR\t_text + %#llx\n", table[i].addr - _text); else - printf("\tPTR\t%#llx\n", table[i].addr); + printf("\tPTR\t_text - %#llx\n", + _text - table[i].addr); } else { printf("\tPTR\t%#llx\n", table[i].addr); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 850296a1e0f..8d0a8443667 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3616,6 +3616,19 @@ static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec, } } +static void alc_no_shutup(struct hda_codec *codec) +{ +} + +static void alc_fixup_no_shutup(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + struct alc_spec *spec = codec->spec; + spec->shutup = alc_no_shutup; + } +} + static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -3844,6 +3857,7 @@ enum { ALC269_FIXUP_HP_GPIO_LED, ALC269_FIXUP_INV_DMIC, ALC269_FIXUP_LENOVO_DOCK, + ALC269_FIXUP_NO_SHUTUP, ALC286_FIXUP_SONY_MIC_NO_PRESENCE, ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, @@ -4020,6 +4034,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_inv_dmic_0x12, }, + [ALC269_FIXUP_NO_SHUTUP] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_no_shutup, + }, [ALC269_FIXUP_LENOVO_DOCK] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -4405,6 +4423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 29238a7476d..5b68b106cfc 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -65,18 +65,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; -} - static struct snd_soc_dai_link snappercl15_dai = { .name = "tlv320aic23", .stream_name = "AIC23", @@ -84,7 +72,6 @@ static struct snd_soc_dai_link snappercl15_dai = { .codec_dai_name = "tlv320aic23-hifi", .codec_name = "tlv320aic23-codec.0-001a", .platform_name = "ep93xx-i2s", - .init = snappercl15_tlv320aic23_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, @@ -95,6 +82,11 @@ static struct snd_soc_card snd_soc_snappercl15 = { .owner = THIS_MODULE, .dai_link = &snappercl15_dai, .num_links = 1, + + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int snappercl15_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 8703244ee9f..b07e17160f9 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1327,8 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; - codec->control_data = pm860x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, pm860x->regmap); if (ret) return ret; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 32d7a6f04b7..f0e84013788 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS42L73 if I2C select SND_SOC_CS4270 if I2C select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI + select SND_SOC_CS42XX8_I2C if I2C select SND_SOC_CX20442 if TTY select SND_SOC_DA7210 if I2C select SND_SOC_DA7213 if I2C @@ -85,6 +86,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TLV320AIC23_I2C if I2C select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C @@ -303,6 +305,15 @@ config SND_SOC_CS4271 tristate "Cirrus Logic CS4271 CODEC" depends on SND_SOC_I2C_AND_SPI +config SND_SOC_CS42XX8 + tristate + +config SND_SOC_CS42XX8_I2C + tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" + depends on I2C + select SND_SOC_CS42XX8 + select REGMAP_I2C + config SND_SOC_CX20442 tristate depends on TTY @@ -449,6 +460,9 @@ config SND_SOC_TLV320AIC26 tristate depends on SPI +config SND_SOC_TLV320AIC31XX + tristate + config SND_SOC_TLV320AIC32X4 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index cb46c4c78dc..3c4d275d064 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -30,6 +30,8 @@ snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs42l73-objs := cs42l73.o snd-soc-cs4270-objs := cs4270.o snd-soc-cs4271-objs := cs4271.o +snd-soc-cs42xx8-objs := cs42xx8.o +snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o snd-soc-da7213-objs := da7213.o @@ -79,6 +81,7 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o +snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o @@ -178,6 +181,8 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o +obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o +obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o @@ -223,6 +228,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o +obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 9381a767e75..6844d0b2af6 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -322,14 +322,6 @@ static struct snd_soc_dai_driver ad193x_dai = { static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ad193x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } /* default setting for ad193x */ @@ -347,7 +339,7 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); - return ret; + return 0; } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 5223800775a..877f5737bb6 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1376,15 +1376,8 @@ static int adau1373_probe(struct snd_soc_codec *codec) struct adau1373_platform_data *pdata = codec->dev->platform_data; bool lineout_differential = false; unsigned int val; - int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - if (pdata) { if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) return -EINVAL; diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 7470831ba75..5062e34ee8d 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -801,15 +801,8 @@ static struct snd_soc_dai_driver adav80x_dais[] = { static int adav80x_probe(struct snd_soc_codec *codec) { - int ret; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - /* Force PLLs on for SYSCLK output */ snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 684fe910669..30e297890fe 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -388,15 +388,6 @@ static int ak4535_resume(struct snd_soc_codec *codec) static int ak4535_probe(struct snd_soc_codec *codec) { - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ak4535->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 684b56f2856..868c0e2da1e 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -519,14 +519,6 @@ static int ak4641_resume(struct snd_soc_codec *codec) static int ak4641_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 1f646c6e90c..92655cc189a 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -465,14 +465,6 @@ static int ak4642_resume(struct snd_soc_codec *codec) static int ak4642_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index deb2b44669d..998fa0c5a0b 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -613,17 +613,7 @@ static struct snd_soc_dai_driver ak4671_dai = { static int ak4671_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; + return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int ak4671_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index ed506253a91..09f7e773baf 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -904,13 +904,6 @@ static int alc5623_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - codec->control_data = alc5623->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - alc5623_reset(codec); /* power on device */ diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index d885056ad8f..ec071a6306e 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1063,14 +1063,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = alc5632->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 43737a27d79..1e25c7af853 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -138,9 +138,8 @@ static int cq93vc_probe(struct snd_soc_codec *codec) struct davinci_vc *davinci_vc = codec->dev->platform_data; davinci_vc->cq93vc.codec = codec; - codec->control_data = davinci_vc->regmap; - snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, davinci_vc->regmap); /* Off, with power on */ cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 83c835d9fd8..3920e626494 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -506,15 +506,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int ret; - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; - } - /* Disable auto-mute. This feature appears to be buggy. In some * situations, auto-mute will not deactivate when it should, so we want * this feature disabled by default. An application (e.g. alsactl) can diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 5caf75bc6bc..6c0da2baa15 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -106,9 +106,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); -/* This is a lie. after -102 db, it stays at -102 */ -/* maybe a range would be better */ -static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); + +static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0); static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); static const char *chan_mix[] = { @@ -122,7 +121,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix); static const struct snd_kcontrol_new cs42l51_snd_controls[] = { SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("PCM Playback Switch", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", @@ -130,7 +129,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { 0, 0x34, 0xE4, aout_tlv), SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("ADC Mixer Switch", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), @@ -488,12 +487,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) { int ret, reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* * DAC configuration * - Use signal processor diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index be455ea5f2f..f0ca6bee677 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -341,7 +341,7 @@ static const char * const right_swap_text[] = { static const unsigned int swap_values[] = { 0, 1, 3 }; static const struct soc_enum adca_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -350,7 +350,7 @@ static const struct snd_kcontrol_new adca_mixer = SOC_DAPM_ENUM("Route", adca_swap_enum); static const struct soc_enum pcma_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -359,7 +359,7 @@ static const struct snd_kcontrol_new pcma_mixer = SOC_DAPM_ENUM("Route", pcma_swap_enum); static const struct soc_enum adcb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); @@ -368,7 +368,7 @@ static const struct snd_kcontrol_new adcb_mixer = SOC_DAPM_ENUM("Route", adcb_swap_enum); static const struct soc_enum pcmb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); @@ -1109,14 +1109,7 @@ static void cs42l52_free_beep(struct snd_soc_codec *codec) static int cs42l52_probe(struct snd_soc_codec *codec) { struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); - int ret; - codec->control_data = cs42l52->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } regcache_cache_only(cs42l52->regmap, true); cs42l52_add_mic_controls(codec); @@ -1128,7 +1121,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec) cs42l52->sysclk = CS42L52_DEFAULT_CLK; cs42l52->config.format = CS42L52_DEFAULT_FORMAT; - return ret; + return 0; } static int cs42l52_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 06f42918482..0ee60a19a26 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -319,7 +319,7 @@ static const char * const cs42l73_mono_mix_texts[] = { static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; static const struct soc_enum spk_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -337,7 +337,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer = SOC_DAPM_ENUM("Route", spk_xsp_enum); static const struct soc_enum esl_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -346,7 +346,7 @@ static const struct snd_kcontrol_new esl_asp_mixer = SOC_DAPM_ENUM("Route", esl_asp_enum); static const struct soc_enum esl_xsp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -1345,17 +1345,8 @@ static int cs42l73_resume(struct snd_soc_codec *codec) static int cs42l73_probe(struct snd_soc_codec *codec) { - int ret; struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); - codec->control_data = cs42l73->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Set Charge Pump Frequency */ @@ -1368,7 +1359,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec) cs42l73->mclksel = CS42L73_CLKID_MCLK1; cs42l73->mclk = 0; - return ret; + return 0; } static int cs42l73_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c new file mode 100644 index 00000000000..657dce27ead --- /dev/null +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -0,0 +1,64 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <sound/soc.h> + +#include "cs42xx8.h" + +static int cs42xx8_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + u32 ret = cs42xx8_probe(&i2c->dev, + devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); + if (ret) + return ret; + + pm_runtime_enable(&i2c->dev); + pm_request_idle(&i2c->dev); + + return 0; +} + +static int cs42xx8_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + pm_runtime_disable(&i2c->dev); + + return 0; +} + +static struct i2c_device_id cs42xx8_i2c_id[] = { + {"cs42448", (kernel_ulong_t)&cs42448_data}, + {"cs42888", (kernel_ulong_t)&cs42888_data}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); + +static struct i2c_driver cs42xx8_i2c_driver = { + .driver = { + .name = "cs42xx8", + .owner = THIS_MODULE, + .pm = &cs42xx8_pm, + }, + .probe = cs42xx8_i2c_probe, + .remove = cs42xx8_i2c_remove, + .id_table = cs42xx8_i2c_id, +}; + +module_i2c_driver(cs42xx8_i2c_driver); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c new file mode 100644 index 00000000000..082299a4e2f --- /dev/null +++ b/sound/soc/codecs/cs42xx8.c @@ -0,0 +1,602 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include "cs42xx8.h" + +#define CS42XX8_NUM_SUPPLIES 4 +static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = { + "VA", + "VD", + "VLS", + "VLC", +}; + +#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* codec private data */ +struct cs42xx8_priv { + struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES]; + const struct cs42xx8_driver_data *drvdata; + struct regmap *regmap; + struct clk *clk; + + bool slave_mode; + unsigned long sysclk; +}; + +/* -127.5dB to 0dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); +/* -64dB to 24dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0); + +static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" }; +static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross", + "Soft Ramp", "Soft Ramp on Zero Cross" }; + +static const struct soc_enum adc1_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single); +static const struct soc_enum adc2_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single); +static const struct soc_enum adc3_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single); +static const struct soc_enum dac_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc); +static const struct soc_enum adc_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc); + +static const struct snd_kcontrol_new cs42xx8_snd_controls[] = { + SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1, + CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3, + CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5, + CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7, + CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1, + CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3, + CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0), + SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0), + SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0), + SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0), + SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0), + SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0), + SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1), + SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0), + SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum), + SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum), + SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0), + SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), + SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0), + SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0), + SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0), + SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum), +}; + +static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5, + CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0), + SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum), +}; + +static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1), + SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1), + SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1), + SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1), + + SND_SOC_DAPM_OUTPUT("AOUT1L"), + SND_SOC_DAPM_OUTPUT("AOUT1R"), + SND_SOC_DAPM_OUTPUT("AOUT2L"), + SND_SOC_DAPM_OUTPUT("AOUT2R"), + SND_SOC_DAPM_OUTPUT("AOUT3L"), + SND_SOC_DAPM_OUTPUT("AOUT3R"), + SND_SOC_DAPM_OUTPUT("AOUT4L"), + SND_SOC_DAPM_OUTPUT("AOUT4R"), + + SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1), + SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1), + + SND_SOC_DAPM_INPUT("AIN1L"), + SND_SOC_DAPM_INPUT("AIN1R"), + SND_SOC_DAPM_INPUT("AIN2L"), + SND_SOC_DAPM_INPUT("AIN2R"), + + SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0), +}; + +static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = { + SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1), + + SND_SOC_DAPM_INPUT("AIN3L"), + SND_SOC_DAPM_INPUT("AIN3R"), +}; + +static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = { + /* Playback */ + { "AOUT1L", NULL, "DAC1" }, + { "AOUT1R", NULL, "DAC1" }, + { "DAC1", NULL, "PWR" }, + + { "AOUT2L", NULL, "DAC2" }, + { "AOUT2R", NULL, "DAC2" }, + { "DAC2", NULL, "PWR" }, + + { "AOUT3L", NULL, "DAC3" }, + { "AOUT3R", NULL, "DAC3" }, + { "DAC3", NULL, "PWR" }, + + { "AOUT4L", NULL, "DAC4" }, + { "AOUT4R", NULL, "DAC4" }, + { "DAC4", NULL, "PWR" }, + + /* Capture */ + { "ADC1", NULL, "AIN1L" }, + { "ADC1", NULL, "AIN1R" }, + { "ADC1", NULL, "PWR" }, + + { "ADC2", NULL, "AIN2L" }, + { "ADC2", NULL, "AIN2R" }, + { "ADC2", NULL, "PWR" }, +}; + +static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { + /* Capture */ + { "ADC3", NULL, "AIN3L" }, + { "ADC3", NULL, "AIN3R" }, + { "ADC3", NULL, "PWR" }, +}; + +struct cs42xx8_ratios { + unsigned int ratio; + unsigned char speed; + unsigned char mclk; +}; + +static const struct cs42xx8_ratios cs42xx8_ratios[] = { + { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, + { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, + { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, + { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, + { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, + { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, + { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, + { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, + { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } +}; + +static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + cs42xx8->sysclk = freq; + + return 0; +} + +static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int format) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + u32 val; + + /* Set DAI format */ + switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ; + break; + case SND_SOC_DAIFMT_I2S: + val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; + break; + default: + dev_err(codec->dev, "unsupported dai format\n"); + return -EINVAL; + } + + regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF, + CS42XX8_INTF_DAC_DIF_MASK | + CS42XX8_INTF_ADC_DIF_MASK, val); + + /* Set master/slave audio interface */ + switch (format & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + cs42xx8->slave_mode = true; + break; + case SND_SOC_DAIFMT_CBM_CFM: + cs42xx8->slave_mode = false; + break; + default: + dev_err(codec->dev, "unsupported master/slave mode\n"); + return -EINVAL; + } + + return 0; +} + +static int cs42xx8_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u32 ratio = cs42xx8->sysclk / params_rate(params); + u32 i, fm, val, mask; + + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { + if (cs42xx8_ratios[i].ratio == ratio) + break; + } + + if (i == ARRAY_SIZE(cs42xx8_ratios)) { + dev_err(codec->dev, "unsupported sysclk ratio\n"); + return -EINVAL; + } + + mask = CS42XX8_FUNCMOD_MFREQ_MASK; + val = cs42xx8_ratios[i].mclk; + + fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; + + regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, + CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, + CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); + + return 0; +} + +static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, + CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); + + return 0; +} + +static const struct snd_soc_dai_ops cs42xx8_dai_ops = { + .set_fmt = cs42xx8_set_dai_fmt, + .set_sysclk = cs42xx8_set_dai_sysclk, + .hw_params = cs42xx8_hw_params, + .digital_mute = cs42xx8_digital_mute, +}; + +static struct snd_soc_dai_driver cs42xx8_dai = { + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .ops = &cs42xx8_dai_ops, +}; + +static const struct reg_default cs42xx8_reg[] = { + { 0x01, 0x01 }, /* Chip I.D. and Revision Register */ + { 0x02, 0x00 }, /* Power Control */ + { 0x03, 0xF0 }, /* Functional Mode */ + { 0x04, 0x46 }, /* Interface Formats */ + { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */ + { 0x06, 0x10 }, /* Transition Control */ + { 0x07, 0x00 }, /* DAC Channel Mute */ + { 0x08, 0x00 }, /* Volume Control AOUT1 */ + { 0x09, 0x00 }, /* Volume Control AOUT2 */ + { 0x0a, 0x00 }, /* Volume Control AOUT3 */ + { 0x0b, 0x00 }, /* Volume Control AOUT4 */ + { 0x0c, 0x00 }, /* Volume Control AOUT5 */ + { 0x0d, 0x00 }, /* Volume Control AOUT6 */ + { 0x0e, 0x00 }, /* Volume Control AOUT7 */ + { 0x0f, 0x00 }, /* Volume Control AOUT8 */ + { 0x10, 0x00 }, /* DAC Channel Invert */ + { 0x11, 0x00 }, /* Volume Control AIN1 */ + { 0x12, 0x00 }, /* Volume Control AIN2 */ + { 0x13, 0x00 }, /* Volume Control AIN3 */ + { 0x14, 0x00 }, /* Volume Control AIN4 */ + { 0x15, 0x00 }, /* Volume Control AIN5 */ + { 0x16, 0x00 }, /* Volume Control AIN6 */ + { 0x17, 0x00 }, /* ADC Channel Invert */ + { 0x18, 0x00 }, /* Status Control */ + { 0x1a, 0x00 }, /* Status Mask */ + { 0x1b, 0x00 }, /* MUTEC Pin Control */ +}; + +static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_STATUS: + return true; + default: + return false; + } +} + +static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_CHIPID: + case CS42XX8_STATUS: + return false; + default: + return true; + } +} + +const struct regmap_config cs42xx8_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42XX8_LASTREG, + .reg_defaults = cs42xx8_reg, + .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg), + .volatile_reg = cs42xx8_volatile_register, + .writeable_reg = cs42xx8_writeable_register, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); + +static int cs42xx8_codec_probe(struct snd_soc_codec *codec) +{ + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + switch (cs42xx8->drvdata->num_adcs) { + case 3: + snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls, + ARRAY_SIZE(cs42xx8_adc3_snd_controls)); + snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets, + ARRAY_SIZE(cs42xx8_adc3_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes, + ARRAY_SIZE(cs42xx8_adc3_dapm_routes)); + break; + default: + break; + } + + /* Mute all DAC channels */ + regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL); + + return 0; +} + +static const struct snd_soc_codec_driver cs42xx8_driver = { + .probe = cs42xx8_codec_probe, + .idle_bias_off = true, + + .controls = cs42xx8_snd_controls, + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), + .dapm_widgets = cs42xx8_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), + .dapm_routes = cs42xx8_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), +}; + +const struct cs42xx8_driver_data cs42448_data = { + .name = "cs42448", + .num_adcs = 3, +}; +EXPORT_SYMBOL_GPL(cs42448_data); + +const struct cs42xx8_driver_data cs42888_data = { + .name = "cs42888", + .num_adcs = 2, +}; +EXPORT_SYMBOL_GPL(cs42888_data); + +const struct of_device_id cs42xx8_of_match[] = { + { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, + { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cs42xx8_of_match); +EXPORT_SYMBOL_GPL(cs42xx8_of_match); + +int cs42xx8_probe(struct device *dev, struct regmap *regmap) +{ + const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); + struct cs42xx8_priv *cs42xx8; + int ret, val, i; + + cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); + if (cs42xx8 == NULL) + return -ENOMEM; + + dev_set_drvdata(dev, cs42xx8); + + if (of_id) + cs42xx8->drvdata = of_id->data; + + if (!cs42xx8->drvdata) { + dev_err(dev, "failed to find driver data\n"); + return -EINVAL; + } + + cs42xx8->clk = devm_clk_get(dev, "mclk"); + if (IS_ERR(cs42xx8->clk)) { + dev_err(dev, "failed to get the clock: %ld\n", + PTR_ERR(cs42xx8->clk)); + return -EINVAL; + } + + cs42xx8->sysclk = clk_get_rate(cs42xx8->clk); + + for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++) + cs42xx8->supplies[i].supply = cs42xx8_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + return ret; + } + + /* Make sure hardware reset done */ + msleep(5); + + cs42xx8->regmap = regmap; + if (IS_ERR(cs42xx8->regmap)) { + ret = PTR_ERR(cs42xx8->regmap); + dev_err(dev, "failed to allocate regmap: %d\n", ret); + goto err_enable; + } + + /* + * We haven't marked the chip revision as volatile due to + * sharing a register with the right input volume; explicitly + * bypass the cache to read it. + */ + regcache_cache_bypass(cs42xx8->regmap, true); + + /* Validate the chip ID */ + regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val); + if (val < 0) { + dev_err(dev, "failed to get device ID: %x", val); + ret = -EINVAL; + goto err_enable; + } + + /* The top four bits of the chip ID should be 0000 */ + if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) { + dev_err(dev, "unmatched chip ID: %d\n", + val & CS42XX8_CHIPID_CHIP_ID_MASK); + ret = -EINVAL; + goto err_enable; + } + + dev_info(dev, "found device, revision %X\n", + val & CS42XX8_CHIPID_REV_ID_MASK); + + regcache_cache_bypass(cs42xx8->regmap, false); + + cs42xx8_dai.name = cs42xx8->drvdata->name; + + /* Each adc supports stereo input */ + cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2; + + ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1); + if (ret) { + dev_err(dev, "failed to register codec:%d\n", ret); + goto err_enable; + } + + regcache_cache_only(cs42xx8->regmap, true); + +err_enable: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + return ret; +} +EXPORT_SYMBOL_GPL(cs42xx8_probe); + +#ifdef CONFIG_PM_RUNTIME +static int cs42xx8_runtime_resume(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(cs42xx8->clk); + if (ret) { + dev_err(dev, "failed to enable mclk: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + goto err_clk; + } + + /* Make sure hardware reset done */ + msleep(5); + + regcache_cache_only(cs42xx8->regmap, false); + + ret = regcache_sync(cs42xx8->regmap); + if (ret) { + dev_err(dev, "failed to sync regmap: %d\n", ret); + goto err_bulk; + } + + return 0; + +err_bulk: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); +err_clk: + clk_disable_unprepare(cs42xx8->clk); + + return ret; +} + +static int cs42xx8_runtime_suspend(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + + regcache_cache_only(cs42xx8->regmap, true); + + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + clk_disable_unprepare(cs42xx8->clk); + + return 0; +} +#endif + +const struct dev_pm_ops cs42xx8_pm = { + SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(cs42xx8_pm); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h new file mode 100644 index 00000000000..da0b94aee41 --- /dev/null +++ b/sound/soc/codecs/cs42xx8.h @@ -0,0 +1,238 @@ +/* + * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _CS42XX8_H +#define _CS42XX8_H + +struct cs42xx8_driver_data { + char name[32]; + int num_adcs; +}; + +extern const struct dev_pm_ops cs42xx8_pm; +extern const struct cs42xx8_driver_data cs42448_data; +extern const struct cs42xx8_driver_data cs42888_data; +extern const struct regmap_config cs42xx8_regmap_config; +int cs42xx8_probe(struct device *dev, struct regmap *regmap); + +/* CS42888 register map */ +#define CS42XX8_CHIPID 0x01 /* Chip ID */ +#define CS42XX8_PWRCTL 0x02 /* Power Control */ +#define CS42XX8_FUNCMOD 0x03 /* Functional Mode */ +#define CS42XX8_INTF 0x04 /* Interface Formats */ +#define CS42XX8_ADCCTL 0x05 /* ADC Control */ +#define CS42XX8_TXCTL 0x06 /* Transition Control */ +#define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */ +#define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */ +#define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */ +#define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */ +#define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */ +#define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */ +#define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */ +#define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */ +#define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */ +#define CS42XX8_DACINV 0x10 /* DAC Channel Invert */ +#define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */ +#define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */ +#define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */ +#define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */ +#define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */ +#define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */ +#define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */ +#define CS42XX8_STATUSCTL 0x18 /* Status Control */ +#define CS42XX8_STATUS 0x19 /* Status */ +#define CS42XX8_STATUSM 0x1A /* Status Mask */ +#define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */ + +#define CS42XX8_FIRSTREG CS42XX8_CHIPID +#define CS42XX8_LASTREG CS42XX8_MUTEC +#define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1) +#define CS42XX8_I2C_INCR 0x80 + +/* Chip I.D. and Revision Register (Address 01h) */ +#define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0 +#define CS42XX8_CHIPID_REV_ID_MASK 0x0F + +/* Power Control (Address 02h) */ +#define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7 +#define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6 +#define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5 +#define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4 +#define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3 +#define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2 +#define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1 +#define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_SHIFT 0 +#define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT) +#define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT) + +/* Functional Mode (Address 03h) */ +#define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6 +#define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4 +#define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK) +#define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v)) +#define CS42XX8_FUNCMOD_MFREQ_SHIFT 1 +#define CS42XX8_FUNCMOD_MFREQ_WIDTH 3 +#define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT) +#define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) + +#define CS42XX8_FM_SINGLE 0 +#define CS42XX8_FM_DOUBLE 1 +#define CS42XX8_FM_QUAD 2 +#define CS42XX8_FM_AUTO 3 + +/* Interface Formats (Address 04h) */ +#define CS42XX8_INTF_FREEZE_SHIFT 7 +#define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_AUX_DIF_SHIFT 6 +#define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_SHIFT 3 +#define CS42XX8_INTF_DAC_DIF_WIDTH 3 +#define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_SHIFT 0 +#define CS42XX8_INTF_ADC_DIF_WIDTH 3 +#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) + +/* ADC Control & DAC De-Emphasis (Address 05h) */ +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5 +#define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4 +#define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3 +#define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2 +#define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1 +#define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0 +#define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) + +/* Transition Control (Address 06h) */ +#define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7 +#define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SHIFT 5 +#define CS42XX8_TXCTL_DAC_SZC_WIDTH 2 +#define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_AMUTE_SHIFT 4 +#define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3 +#define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2 +#define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SHIFT 0 +#define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT) + +/* DAC Channel Mute (Address 07h) */ +#define CS42XX8_DACMUTE_AOUT(n) (0x1 << n) +#define CS42XX8_DACMUTE_ALL 0xff + +/* Status Control (Address 18h)*/ +#define CS42XX8_STATUSCTL_INI_SHIFT 2 +#define CS42XX8_STATUSCTL_INI_WIDTH 2 +#define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT) + +/* Status (Address 19h)*/ +#define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT) + +/* Status Mask (Address 1Ah) */ +#define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT) + +/* MUTEC Pin Control (Address 1Bh) */ +#define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1 +#define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0 +#define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#endif /* _CS42XX8_H */ diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 01e55fc7230..137e8ebc092 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1071,17 +1071,9 @@ static struct snd_soc_dai_driver da7210_dai = { static int da7210_probe(struct snd_soc_codec *codec) { struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); - int ret; dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - codec->control_data = da7210->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - da7210->mclk_rate = 0; /* This will be set from set_sysclk() */ da7210->master = 0; /* This will be set from set_fmt() */ diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 439d10387f1..738fa18a50d 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1393,17 +1393,9 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, static int da7213_probe(struct snd_soc_codec *codec) { - int ret; struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); struct da7213_platform_data *pdata = da7213->pdata; - codec->control_data = da7213->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Default to using ALC auto offset calibration mode. */ snd_soc_update_bits(codec, DA7213_ALC_CTRL1, DA7213_ALC_CALIB_MODE_MAN, 0); diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 4d1c302f5a7..7d168ec71cd 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1297,9 +1297,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check DAC offset sign */ - sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); - sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); /* Binary search DAC offset values (both channels at once) */ @@ -1316,10 +1316,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) offset[DA732X_HPL_DAC] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) offset[DA732X_HPR_DAC] &= ~step; @@ -1360,9 +1360,9 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check output offset sign */ - sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & + sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO; - sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & + sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO; snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | @@ -1383,10 +1383,10 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL) & + if ((snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) offset[DA732X_HPL_AMP] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR) & + if ((snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) offset[DA732X_HPR_AMP] &= ~step; @@ -1512,23 +1512,14 @@ static int da732x_probe(struct snd_soc_codec *codec) { struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; da732x->codec = codec; dapm->idle_bias_off = false; - codec->control_data = da732x->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec.\n"); - goto err; - } - da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -err: - return ret; + + return 0; } static int da732x_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index f118daa9123..4ff06b50fbb 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1383,16 +1383,8 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, static int da9055_probe(struct snd_soc_codec *codec) { - int ret; struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); - codec->control_data = da9055->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable all Gain Ramps */ snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index cb736ddc446..3a89ce66d51 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -918,8 +918,7 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 aif = 0; unsigned int fs_val = 0; @@ -1090,23 +1089,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = { }, }; -static int isabelle_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - codec->control_data = dev_get_regmap(codec->dev, NULL); - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - static struct snd_soc_codec_driver soc_codec_dev_isabelle = { - .probe = isabelle_probe, .set_bias_level = isabelle_set_bias_level, .controls = isabelle_snd_controls, .num_controls = ARRAY_SIZE(isabelle_snd_controls), diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 0e5743ea79d..4f048db9f55 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -101,8 +101,7 @@ static const char *lm4857_mode[] = { "Headphone", }; -static const struct soc_enum lm4857_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); +static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { SND_SOC_DAPM_INPUT("IN"), diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 6b7fe5e5488..275b3f72f3f 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -213,15 +213,13 @@ static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" }; -static const struct soc_enum lm49453_adcl_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0, - ARRAY_SIZE(lm49453_adcl_mux_text), - lm49453_adcl_mux_text); +static SOC_ENUM_SINGLE_DECL(lm49453_adcl_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 0, + lm49453_adcl_mux_text); -static const struct soc_enum lm49453_adcr_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1, - ARRAY_SIZE(lm49453_adcr_mux_text), - lm49453_adcr_mux_text); +static SOC_ENUM_SINGLE_DECL(lm49453_adcr_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 1, + lm49453_adcr_mux_text); static const struct snd_kcontrol_new lm49453_adcl_mux_control = SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum); @@ -1409,22 +1407,6 @@ static int lm49453_resume(struct snd_soc_codec *codec) return 0; } -static int lm49453_probe(struct snd_soc_codec *codec) -{ - struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - codec->control_data = lm49453->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - /* power down chip */ static int lm49453_remove(struct snd_soc_codec *codec) { @@ -1433,7 +1415,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { - .probe = lm49453_probe, .remove = lm49453_remove, .suspend = lm49453_suspend, .resume = lm49453_resume, diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 31f91560e9f..ec481fc428c 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -135,11 +135,6 @@ static int max9768_probe(struct snd_soc_codec *codec) struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = max9768->regmap; - ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); - if (ret) - return ret; - if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); if (ret) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index bb1ecfc4459..ef7cf89f562 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -597,28 +597,27 @@ static const unsigned int max98088_exmode_values[] = { 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 }; -static const struct soc_enum max98088_exmode_enum = - SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, - ARRAY_SIZE(max98088_exmode_texts), - max98088_exmode_texts, - max98088_exmode_values); +static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, + M98088_REG_41_SPKDHP, 0, 127, + max98088_exmode_texts, + max98088_exmode_values); static const char *max98088_ex_thresh[] = { /* volts PP */ "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; -static const struct soc_enum max98088_ex_thresh_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, - max98088_ex_thresh), -}; +static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, + M98088_REG_42_SPKDHP_THRESH, 0, + max98088_ex_thresh); static const char *max98088_fltr_mode[] = {"Voice", "Music" }; -static const struct soc_enum max98088_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, + M98088_REG_18_DAI1_FILTERS, 7, + max98088_fltr_mode); static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98088_extmic_enum = - SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, + M98088_REG_48_CFG_MIC, 0, + max98088_extmic_text); static const struct snd_kcontrol_new max98088_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); @@ -626,12 +625,12 @@ static const struct snd_kcontrol_new max98088_extmic_mux = static const char *max98088_dai1_fltr[] = { "Off", "fc=258/fs=16k", "fc=500/fs=16k", "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; -static const struct soc_enum max98088_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), -}; -static const struct soc_enum max98088_dai1_adc_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, + M98088_REG_18_DAI1_FILTERS, 0, + max98088_dai1_fltr); +static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, + M98088_REG_18_DAI1_FILTERS, 4, + max98088_dai1_fltr); static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1915,12 +1914,6 @@ static int max98088_probe(struct snd_soc_codec *codec) regcache_mark_dirty(max98088->regmap); - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* initialize private data */ max98088->sysclk = (unsigned)-1; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index f363de19be0..96a47459b3d 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2218,14 +2218,6 @@ static int max98090_probe(struct snd_soc_codec *codec) max98090->codec = codec; - codec->control_data = max98090->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset the codec, the DSP core, and disable all interrupts */ max98090_reset(max98090); diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 5bce9cde4a6..03f0536e6f6 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -560,25 +560,27 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, } static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; -static const struct soc_enum max98095_dai1_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), -}; -static const struct soc_enum max98095_dai2_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum, + M98095_02E_DAI1_FILTERS, 7, + max98095_fltr_mode); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum, + M98095_038_DAI2_FILTERS, 7, + max98095_fltr_mode); static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98095_extmic_enum = - SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum, + M98095_087_CFG_MIC, 0, + max98095_extmic_text); static const struct snd_kcontrol_new max98095_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); static const char * const max98095_linein_text[] = { "INA", "INB" }; -static const struct soc_enum max98095_linein_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_enum, + M98095_086_CFG_LINE, 6, + max98095_linein_text); static const struct snd_kcontrol_new max98095_linein_mux = SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); @@ -586,24 +588,26 @@ static const struct snd_kcontrol_new max98095_linein_mux = static const char * const max98095_line_mode_text[] = { "Stereo", "Differential"}; -static const struct soc_enum max98095_linein_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum, + M98095_086_CFG_LINE, 7, + max98095_line_mode_text); -static const struct soc_enum max98095_lineout_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum, + M98095_086_CFG_LINE, 4, + max98095_line_mode_text); static const char * const max98095_dai_fltr[] = { "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; -static const struct soc_enum max98095_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai2_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai3_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum, + M98095_02E_DAI1_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum, + M98095_038_DAI2_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum, + M98095_042_DAI3_FILTERS, 0, + max98095_dai_fltr); static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -2234,12 +2238,6 @@ static int max98095_probe(struct snd_soc_codec *codec) struct i2c_client *client; int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* reset the codec, the DSP core, and disable all interrupts */ max98095_reset(codec); diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 82757ebf030..4fdf5aaa236 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -312,14 +312,6 @@ static int max9850_resume(struct snd_soc_codec *codec) static int max9850_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* enable zero-detect */ snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); /* enable slew-rate control */ diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index ec89b8f90a6..2c59b1fb69d 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -106,8 +106,7 @@ static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); int i; @@ -126,8 +125,7 @@ static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); unsigned int val; @@ -612,8 +610,8 @@ static int mc13783_probe(struct snd_soc_codec *codec) struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, + dev_get_regmap(codec->dev->parent, NULL)); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 577fb8776ce..e661e8420e3 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -586,16 +586,6 @@ static int ml26124_resume(struct snd_soc_codec *codec) static int ml26124_probe(struct snd_soc_codec *codec) { - int ret; - struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Software Reset */ snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index ce199d37520..d4c229f0233 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1570,15 +1570,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) { struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); unsigned int val; - int ret; - - codec->control_data = rt5631->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); if (val & 0x0002) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 1a1e1150237..0061ae6b671 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1594,8 +1594,7 @@ static int get_clk_info(int sclk, int rate) static int rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0, val_clk, mask_clk; int dai_sel, pre_div, bclk_ms, frame_size; @@ -1936,16 +1935,8 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, static int rt5640_probe(struct snd_soc_codec *codec) { struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); - int ret; rt5640->codec = codec; - codec->control_data = rt5640->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } codec->dapm.idle_bias_off = 1; rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index ab4754a7a88..d3ed1be5a18 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1352,14 +1352,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) int ret; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - /* setup i2c data ops */ - codec->control_data = sgtl5000->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = sgtl5000_enable_regulators(codec); if (ret) return ret; diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index fa2b8e07f42..244c097cd90 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <linux/regmap.h> #include <sound/soc.h> #include <sound/initval.h> @@ -209,8 +210,9 @@ out: static int si476x_codec_probe(struct snd_soc_codec *codec) { - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + struct regmap *regmap = dev_get_regmap(codec->dev->parent, NULL); + + return snd_soc_codec_set_cache_io(codec, regmap); } static struct snd_soc_dai_ops si476x_dai_ops = { diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index bca7d02b362..42dff26b3a2 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -825,8 +825,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) { pr_debug("codec_probe called\n"); - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - /* PCM interface config * This sets the pcm rx slot conguration to max 6 slots * for max 4 dais (2 stereo and 2 mono) diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 806f3d826ff..56adb3e2def 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -648,16 +648,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { static int ssm2518_probe(struct snd_soc_codec *codec) { - struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ssm2518->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); } diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 12947096897..97b0454eb34 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -562,13 +562,6 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec) struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ssm2602->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 2735361a4c3..12577749b17 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -872,16 +872,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) return ret; } - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - codec->control_data = sta32x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - goto err; - } - /* Chip documentation explicitly requires that the reset values * of reserved register bits are left untouched. * Write the register default value to cache for reserved registers, @@ -946,10 +936,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; - -err: - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - return ret; } static int sta32x_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index f15b0e37274..a40c4b0196a 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -193,8 +193,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; int pdata, play_freq_val, record_freq_val; int bclk_to_fs_ratio; @@ -322,16 +321,6 @@ static struct snd_soc_dai_driver sta529_dai = { static int sta529_probe(struct snd_soc_codec *codec) { - struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = sta529->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index dc9a52fcb39..20864ee8793 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -559,14 +559,6 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset codec */ snd_soc_write(codec, TLV320AIC23_RESET, 0); diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index ff5f23d482b..43069de3d56 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -296,8 +296,6 @@ static int aic26_probe(struct snd_soc_codec *codec) struct aic26 *aic26 = dev_get_drvdata(codec->dev); int ret, reg; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - aic26->codec = codec; /* Reset the codec to power on defaults */ diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c new file mode 100644 index 00000000000..fa158cfe9b3 --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -0,0 +1,1280 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Jyri Sarha <jsarha@ti.com> + * + * Based on ground work by: Ajit Kulkarni <x0175765@ti.com> + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * The TLV320AIC31xx series of audio codec is a low-power, highly integrated + * high performance codec which provides a stereo DAC, a mono ADC, + * and mono/stereo Class-D speaker driver. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/initval.h> +#include <sound/tlv.h> +#include <dt-bindings/sound/tlv320aic31xx-micbias.h> + +#include "tlv320aic31xx.h" + +static const struct reg_default aic31xx_reg_defaults[] = { + { AIC31XX_CLKMUX, 0x00 }, + { AIC31XX_PLLPR, 0x11 }, + { AIC31XX_PLLJ, 0x04 }, + { AIC31XX_PLLDMSB, 0x00 }, + { AIC31XX_PLLDLSB, 0x00 }, + { AIC31XX_NDAC, 0x01 }, + { AIC31XX_MDAC, 0x01 }, + { AIC31XX_DOSRMSB, 0x00 }, + { AIC31XX_DOSRLSB, 0x80 }, + { AIC31XX_NADC, 0x01 }, + { AIC31XX_MADC, 0x01 }, + { AIC31XX_AOSR, 0x80 }, + { AIC31XX_IFACE1, 0x00 }, + { AIC31XX_DATA_OFFSET, 0x00 }, + { AIC31XX_IFACE2, 0x00 }, + { AIC31XX_BCLKN, 0x01 }, + { AIC31XX_DACSETUP, 0x14 }, + { AIC31XX_DACMUTE, 0x0c }, + { AIC31XX_LDACVOL, 0x00 }, + { AIC31XX_RDACVOL, 0x00 }, + { AIC31XX_ADCSETUP, 0x00 }, + { AIC31XX_ADCFGA, 0x80 }, + { AIC31XX_ADCVOL, 0x00 }, + { AIC31XX_HPDRIVER, 0x04 }, + { AIC31XX_SPKAMP, 0x06 }, + { AIC31XX_DACMIXERROUTE, 0x00 }, + { AIC31XX_LANALOGHPL, 0x7f }, + { AIC31XX_RANALOGHPR, 0x7f }, + { AIC31XX_LANALOGSPL, 0x7f }, + { AIC31XX_RANALOGSPR, 0x7f }, + { AIC31XX_HPLGAIN, 0x02 }, + { AIC31XX_HPRGAIN, 0x02 }, + { AIC31XX_SPLGAIN, 0x00 }, + { AIC31XX_SPRGAIN, 0x00 }, + { AIC31XX_MICBIAS, 0x00 }, + { AIC31XX_MICPGA, 0x80 }, + { AIC31XX_MICPGAPI, 0x00 }, + { AIC31XX_MICPGAMI, 0x00 }, +}; + +static bool aic31xx_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_PAGECTL: /* regmap implementation requires this */ + case AIC31XX_RESET: /* always clears after write */ + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return true; + } + return false; +} + +static bool aic31xx_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return false; + } + return true; +} + +static const struct regmap_range_cfg aic31xx_ranges[] = { + { + .range_min = 0, + .range_max = 12 * 128, + .selector_reg = AIC31XX_PAGECTL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +static const struct regmap_config aic31xx_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = aic31xx_writeable, + .volatile_reg = aic31xx_volatile, + .reg_defaults = aic31xx_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .ranges = aic31xx_ranges, + .num_ranges = ARRAY_SIZE(aic31xx_ranges), + .max_register = 12 * 128, +}; + +#define AIC31XX_NUM_SUPPLIES 6 +static const char * const aic31xx_supply_names[AIC31XX_NUM_SUPPLIES] = { + "HPVDD", + "SPRVDD", + "SPLVDD", + "AVDD", + "IOVDD", + "DVDD", +}; + +struct aic31xx_disable_nb { + struct notifier_block nb; + struct aic31xx_priv *aic31xx; +}; + +struct aic31xx_priv { + struct snd_soc_codec *codec; + u8 i2c_regs_status; + struct device *dev; + struct regmap *regmap; + struct aic31xx_pdata pdata; + struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; + struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; + unsigned int sysclk; + int rate_div_line; +}; + +struct aic31xx_rate_divs { + u32 mclk; + u32 rate; + u8 p_val; + u8 pll_j; + u16 pll_d; + u16 dosr; + u8 ndac; + u8 mdac; + u8 aosr; + u8 nadc; + u8 madc; +}; + +/* ADC dividers can be disabled by cofiguring them to 0 */ +static const struct aic31xx_rate_divs aic31xx_divs[] = { + /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */ + /* 8k rate */ + {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2}, + {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2}, + {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2}, + /* 11.025k rate */ + {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2}, + {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2}, + {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2}, + /* 16k rate */ + {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2}, + {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2}, + {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2}, + /* 22.05k rate */ + {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2}, + {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2}, + {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2}, + /* 32k rate */ + {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2}, + {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2}, + {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2}, + /* 44.1k rate */ + {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2}, + {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2}, + {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2}, + /* 48k rate */ + {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2}, + {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2}, + {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2}, + /* 88.2k rate */ + {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2}, + {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2}, + {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2}, + /* 96k rate */ + {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2}, + {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2}, + {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2}, + /* 176.4k rate */ + {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2}, + {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2}, + {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2}, + /* 192k rate */ + {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2}, + {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2}, + {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2}, +}; + +static const char * const ldac_in_text[] = { + "Off", "Left Data", "Right Data", "Mono" +}; + +static const char * const rdac_in_text[] = { + "Off", "Right Data", "Left Data", "Mono" +}; + +static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text); + +static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text); + +static const char * const mic_select_text[] = { + "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" +}; + +static const +SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); + +static const +SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); +static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0); +static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0); +static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0); +static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0); +static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); + +/* + * controls to be exported to the user space + */ +static const struct snd_kcontrol_new aic31xx_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, + AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), + + SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, + adc_fgain_tlv), + + SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1), + SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL, + 0, -24, 40, 6, 0, adc_cgain_tlv), + + SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, + 119, 0, mic_pga_tlv), + + SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), + + SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, + AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic311x_snd_controls[] = { + SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv), + + SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic310x_snd_controls[] = { + SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + 2, 1, 0), + SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + 3, 3, 0, class_D_drv_tlv), + + SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new ldac_in_control = + SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum); + +static const struct snd_kcontrol_new rdac_in_control = + SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum); + +static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, + unsigned int mask, unsigned int wbits, int sleep, + int count) +{ + unsigned int bits; + int counter = count; + int ret = regmap_read(aic31xx->regmap, reg, &bits); + while ((bits & mask) != wbits && counter && !ret) { + usleep_range(sleep, sleep * 2); + ret = regmap_read(aic31xx->regmap, reg, &bits); + counter--; + } + if ((bits & mask) != wbits) { + dev_err(aic31xx->dev, + "%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n", + __func__, reg, bits, wbits, ret, mask, + (count - counter) * sleep); + ret = -1; + } + return ret; +} + +#define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg)) + +static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec); + unsigned int reg = AIC31XX_DACFLAG1; + unsigned int mask; + + switch (WIDGET_BIT(w->reg, w->shift)) { + case WIDGET_BIT(AIC31XX_DACSETUP, 7): + mask = AIC31XX_LDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_DACSETUP, 6): + mask = AIC31XX_RDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 7): + mask = AIC31XX_HPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 6): + mask = AIC31XX_HPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 7): + mask = AIC31XX_SPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 6): + mask = AIC31XX_SPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_ADCSETUP, 7): + mask = AIC31XX_ADCPWRSTATUS_MASK; + reg = AIC31XX_ADCFLAG; + break; + default: + dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n", + w->name, __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100); + case SND_SOC_DAPM_POST_PMD: + return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); + default: + dev_dbg(w->codec->dev, + "Unhandled dapm widget event %d from %s\n", + event, w->name); + } + return 0; +} + +static const struct snd_kcontrol_new left_output_switches[] = { + SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), + SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), +}; + +static const struct snd_kcontrol_new right_output_switches[] = { + SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), +}; + +static const struct snd_kcontrol_new p_term_mic1lp = + SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1rp = + SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum); + +static const struct snd_kcontrol_new m_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum); + +static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0); + +static int mic_bias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* change mic bias voltage to user defined */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, + aic31xx->pdata.micbias_vg << + AIC31XX_MICBIAS_SHIFT); + dev_dbg(codec->dev, "%s: turned on\n", __func__); + break; + case SND_SOC_DAPM_PRE_PMD: + /* turn mic bias off */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, 0); + dev_dbg(codec->dev, "%s: turned off\n", __func__); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("DAC Left Input", + SND_SOC_NOPM, 0, 0, &ldac_in_control), + SND_SOC_DAPM_MUX("DAC Right Input", + SND_SOC_NOPM, 0, 0, &rdac_in_control), + /* DACs */ + SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback", + AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback", + AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + left_output_switches, + ARRAY_SIZE(left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + right_output_switches, + ARRAY_SIZE(right_output_switches)), + + SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpl_switch), + SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpr_switch), + + /* Output drivers */ + SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + + /* ADC */ + SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + /* Input Selection to MIC_PGA */ + SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lp), + SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1rp), + SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lm), + + SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, + &m_term_mic1lm), + /* Enabling & Disabling MIC Gain Ctl */ + SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, + 7, 1, NULL, 0), + + /* Mic Bias */ + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1LP"), + SND_SOC_DAPM_INPUT("MIC1RP"), + SND_SOC_DAPM_INPUT("MIC1LM"), +}; + +static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { + /* AIC3111 and AIC3110 have stereo class-D amplifier */ + SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spr_switch), + SND_SOC_DAPM_OUTPUT("SPL"), + SND_SOC_DAPM_OUTPUT("SPR"), +}; + +/* AIC3100 and AIC3120 have only mono class-D amplifier */ +static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_OUTPUT("SPK"), +}; + +static const struct snd_soc_dapm_route +aic31xx_audio_map[] = { + /* DAC Input Routing */ + {"DAC Left Input", "Left Data", "DAC IN"}, + {"DAC Left Input", "Right Data", "DAC IN"}, + {"DAC Left Input", "Mono", "DAC IN"}, + {"DAC Right Input", "Left Data", "DAC IN"}, + {"DAC Right Input", "Right Data", "DAC IN"}, + {"DAC Right Input", "Mono", "DAC IN"}, + {"DAC Left", NULL, "DAC Left Input"}, + {"DAC Right", NULL, "DAC Right Input"}, + + /* Mic input */ + {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"}, + {"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"}, + {"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"}, + + {"ADC", NULL, "MIC_GAIN_CTL"}, + + /* Left Output */ + {"Output Left", "From Left DAC", "DAC Left"}, + {"Output Left", "From MIC1LP", "MIC1LP"}, + {"Output Left", "From MIC1RP", "MIC1RP"}, + + /* Right Output */ + {"Output Right", "From Right DAC", "DAC Right"}, + {"Output Right", "From MIC1RP", "MIC1RP"}, + + /* HPL path */ + {"HP Left", "Switch", "Output Left"}, + {"HPL Driver", NULL, "HP Left"}, + {"HPL", NULL, "HPL Driver"}, + + /* HPR path */ + {"HP Right", "Switch", "Output Right"}, + {"HPR Driver", NULL, "HP Right"}, + {"HPR", NULL, "HPR Driver"}, +}; + +static const struct snd_soc_dapm_route +aic311x_audio_map[] = { + /* SP L path */ + {"Speaker Left", "Switch", "Output Left"}, + {"SPL ClassD", NULL, "Speaker Left"}, + {"SPL", NULL, "SPL ClassD"}, + + /* SP R path */ + {"Speaker Right", "Switch", "Output Right"}, + {"SPR ClassD", NULL, "Speaker Right"}, + {"SPR", NULL, "SPR ClassD"}, +}; + +static const struct snd_soc_dapm_route +aic310x_audio_map[] = { + /* SP L path */ + {"Speaker", "Switch", "Output Left"}, + {"SPK ClassD", NULL, "Speaker"}, + {"SPK", NULL, "SPK ClassD"}, +}; + +static int aic31xx_add_controls(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) + ret = snd_soc_add_codec_controls( + codec, aic311x_snd_controls, + ARRAY_SIZE(aic311x_snd_controls)); + else + ret = snd_soc_add_codec_controls( + codec, aic310x_snd_controls, + ARRAY_SIZE(aic310x_snd_controls)); + + return ret; +} + +static int aic31xx_add_widgets(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { + ret = snd_soc_dapm_new_controls( + dapm, aic311x_dapm_widgets, + ARRAY_SIZE(aic311x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map, + ARRAY_SIZE(aic311x_audio_map)); + if (ret) + return ret; + } else { + ret = snd_soc_dapm_new_controls( + dapm, aic310x_dapm_widgets, + ARRAY_SIZE(aic310x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map, + ARRAY_SIZE(aic310x_audio_map)); + if (ret) + return ret; + } + + return 0; +} + +static int aic31xx_setup_pll(struct snd_soc_codec *codec, + struct snd_pcm_hw_params *params) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int bclk_n = 0; + int i; + + /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, + AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); + + for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { + if (aic31xx_divs[i].rate == params_rate(params) && + aic31xx_divs[i].mclk == aic31xx->sysclk) + break; + } + + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(codec->dev, "%s: Sampling rate %u not supported\n", + __func__, params_rate(params)); + return -EINVAL; + } + + /* PLL configuration */ + snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, + (aic31xx_divs[i].p_val << 4) | 0x01); + snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); + + snd_soc_write(codec, AIC31XX_PLLDMSB, + aic31xx_divs[i].pll_d >> 8); + snd_soc_write(codec, AIC31XX_PLLDLSB, + aic31xx_divs[i].pll_d & 0xff); + + /* DAC dividers configuration */ + snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].ndac); + snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].mdac); + + snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); + snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); + + /* ADC dividers configuration. Write reset value 1 if not used. */ + snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); + snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); + + snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); + + /* Bit clock divider configuration. */ + bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) + / snd_soc_params_to_frame_size(params); + if (bclk_n == 0) { + dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n", + __func__); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_BCLKN, + AIC31XX_PLL_MASK, bclk_n); + + aic31xx->rate_div_line = i; + + dev_dbg(codec->dev, + "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", + aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, + aic31xx_divs[i].p_val, aic31xx_divs[i].dosr, + aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, + aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, + aic31xx_divs[i].madc, bclk_n); + + return 0; +} + +static int aic31xx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + u8 data = 0; + + dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", + __func__, params_format(params), params_width(params), + params_rate(params)); + + switch (params_width(params)) { + case 16: + break; + case 20: + data = (AIC31XX_WORD_LEN_20BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 24: + data = (AIC31XX_WORD_LEN_24BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 32: + data = (AIC31XX_WORD_LEN_32BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + default: + dev_err(codec->dev, "%s: Unsupported format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATALEN_MASK, + data); + + return aic31xx_setup_pll(codec, params); +} + +static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + + if (mute) { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, + AIC31XX_DACMUTE_MASK); + } else { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, 0x0); + } + + return 0; +} + +static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u8 iface_reg1 = 0; + u8 iface_reg3 = 0; + u8 dsp_a_val = 0; + + dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; + break; + default: + dev_alert(codec->dev, "Invalid DAI master/slave interface\n"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_DSP_A: + dsp_a_val = 0x1; + case SND_SOC_DAIFMT_DSP_B: + /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + iface_reg3 |= AIC31XX_BCLKINV_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + break; + default: + return -EINVAL; + } + iface_reg1 |= (AIC31XX_DSP_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_RIGHT_J: + iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_LEFT_J: + iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + default: + dev_err(codec->dev, "Invalid DAI interface format\n"); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATATYPE_MASK | + AIC31XX_IFACE1_MASTER_MASK, + iface_reg1); + snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET, + AIC31XX_DATA_OFFSET_MASK, + dsp_a_val); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BCLKINV_MASK, + iface_reg3); + + return 0; +} + +static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", + __func__, clk_id, freq, dir); + + for (i = 0; aic31xx_divs[i].mclk != freq; i++) { + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", + __func__, freq); + return -EINVAL; + } + } + + /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK, + clk_id << AIC31XX_PLL_CLKIN_SHIFT); + + aic31xx->sysclk = freq; + return 0; +} + +static int aic31xx_regulator_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct aic31xx_disable_nb *disable_nb = + container_of(nb, struct aic31xx_disable_nb, nb); + struct aic31xx_priv *aic31xx = disable_nb->aic31xx; + + if (event & REGULATOR_EVENT_DISABLE) { + /* + * Put codec to reset and as at least one of the + * supplies was disabled. + */ + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) + gpio_set_value(aic31xx->pdata.gpio_reset, 0); + + regcache_mark_dirty(aic31xx->regmap); + dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__); + } + + return 0; +} + +static void aic31xx_clk_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + u8 mask = AIC31XX_PM_MASK; + u8 on = AIC31XX_PM_MASK; + + dev_dbg(codec->dev, "codec clock -> on (rate %d)\n", + aic31xx_divs[aic31xx->rate_div_line].rate); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on); + mdelay(10); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].nadc) + snd_soc_update_bits(codec, AIC31XX_NADC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].madc) + snd_soc_update_bits(codec, AIC31XX_MADC, mask, on); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on); +} + +static void aic31xx_clk_off(struct snd_soc_codec *codec) +{ + u8 mask = AIC31XX_PM_MASK; + u8 off = 0; + + dev_dbg(codec->dev, "codec clock -> off\n"); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off); + snd_soc_update_bits(codec, AIC31XX_MADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off); +} + +static int aic31xx_power_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret) + return ret; + + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) { + gpio_set_value(aic31xx->pdata.gpio_reset, 1); + udelay(100); + } + regcache_cache_only(aic31xx->regmap, false); + ret = regcache_sync(aic31xx->regmap); + if (ret != 0) { + dev_err(codec->dev, + "Failed to restore cache: %d\n", ret); + regcache_cache_only(aic31xx->regmap, true); + regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + return ret; + } + return 0; +} + +static int aic31xx_power_off(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + regcache_cache_only(aic31xx->regmap, true); + ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + + return ret; +} + +static int aic31xx_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, + codec->dapm.bias_level, level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_clk_on(codec); + break; + case SND_SOC_BIAS_STANDBY: + switch (codec->dapm.bias_level) { + case SND_SOC_BIAS_OFF: + aic31xx_power_on(codec); + break; + case SND_SOC_BIAS_PREPARE: + aic31xx_clk_off(codec); + break; + default: + BUG(); + } + break; + case SND_SOC_BIAS_OFF: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_power_off(codec); + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int aic31xx_suspend(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int aic31xx_resume(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; +} + +static int aic31xx_codec_probe(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(aic31xx->dev, "## %s\n", __func__); + + aic31xx = snd_soc_codec_get_drvdata(codec); + + aic31xx->codec = codec; + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) { + aic31xx->disable_nb[i].nb.notifier_call = + aic31xx_regulator_event; + aic31xx->disable_nb[i].aic31xx = aic31xx; + ret = regulator_register_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + if (ret) { + dev_err(codec->dev, + "Failed to request regulator notifier: %d\n", + ret); + return ret; + } + } + + regcache_cache_only(aic31xx->regmap, true); + regcache_mark_dirty(aic31xx->regmap); + + ret = aic31xx_add_controls(codec); + if (ret) + return ret; + + ret = aic31xx_add_widgets(codec); + + return ret; +} + +static int aic31xx_codec_remove(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + /* power down chip */ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + regulator_unregister_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { + .probe = aic31xx_codec_probe, + .remove = aic31xx_codec_remove, + .suspend = aic31xx_suspend, + .resume = aic31xx_resume, + .set_bias_level = aic31xx_set_bias_level, + .controls = aic31xx_snd_controls, + .num_controls = ARRAY_SIZE(aic31xx_snd_controls), + .dapm_widgets = aic31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), + .dapm_routes = aic31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), +}; + +static struct snd_soc_dai_ops aic31xx_dai_ops = { + .hw_params = aic31xx_hw_params, + .set_sysclk = aic31xx_set_dai_sysclk, + .set_fmt = aic31xx_set_dai_fmt, + .digital_mute = aic31xx_dac_mute, +}; + +static struct snd_soc_dai_driver aic31xx_dai_driver[] = { + { + .name = "tlv320aic31xx-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .ops = &aic31xx_dai_ops, + .symmetric_rates = 1, + } +}; + +#if defined(CONFIG_OF) +static const struct of_device_id tlv320aic31xx_of_match[] = { + { .compatible = "ti,tlv320aic310x" }, + { .compatible = "ti,tlv320aic311x" }, + { .compatible = "ti,tlv320aic3100" }, + { .compatible = "ti,tlv320aic3110" }, + { .compatible = "ti,tlv320aic3120" }, + { .compatible = "ti,tlv320aic3111" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match); + +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ + struct device_node *np = aic31xx->dev->of_node; + unsigned int value = MICBIAS_2_0V; + int ret; + + of_property_read_u32(np, "ai31xx-micbias-vg", &value); + switch (value) { + case MICBIAS_2_0V: + case MICBIAS_2_5V: + case MICBIAS_AVDDV: + aic31xx->pdata.micbias_vg = value; + break; + default: + dev_err(aic31xx->dev, + "Bad ai31xx-micbias-vg value %d DT\n", + value); + aic31xx->pdata.micbias_vg = MICBIAS_2_0V; + } + + ret = of_get_named_gpio(np, "gpio-reset", 0); + if (ret > 0) + aic31xx->pdata.gpio_reset = ret; +} +#else /* CONFIG_OF */ +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ +} +#endif /* CONFIG_OF */ + +static void aic31xx_device_init(struct aic31xx_priv *aic31xx) +{ + int ret, i; + + dev_set_drvdata(aic31xx->dev, aic31xx); + + if (dev_get_platdata(aic31xx->dev)) + memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev), + sizeof(aic31xx->pdata)); + else if (aic31xx->dev->of_node) + aic31xx_pdata_from_of(aic31xx); + + if (aic31xx->pdata.gpio_reset) { + ret = devm_gpio_request_one(aic31xx->dev, + aic31xx->pdata.gpio_reset, + GPIOF_OUT_INIT_HIGH, + "aic31xx-reset-pin"); + if (ret < 0) { + dev_err(aic31xx->dev, "not able to acquire gpio\n"); + return; + } + } + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + aic31xx->supplies[i].supply = aic31xx_supply_names[i]; + + ret = devm_regulator_bulk_get(aic31xx->dev, + ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret != 0) + dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); + +} + +static int aic31xx_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct aic31xx_priv *aic31xx; + int ret; + const struct regmap_config *regmap_config; + + dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__, + id->name, (int) id->driver_data); + + regmap_config = &aic31xx_i2c_regmap; + + aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL); + if (aic31xx == NULL) + return -ENOMEM; + + aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config); + if (IS_ERR(aic31xx->regmap)) { + ret = PTR_ERR(aic31xx->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + aic31xx->dev = &i2c->dev; + + aic31xx->pdata.codec_type = id->driver_data; + + aic31xx_device_init(aic31xx); + + return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, + aic31xx_dai_driver, + ARRAY_SIZE(aic31xx_dai_driver)); +} + +static int aic31xx_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id aic31xx_i2c_id[] = { + { "tlv320aic310x", AIC3100 }, + { "tlv320aic311x", AIC3110 }, + { "tlv320aic3100", AIC3100 }, + { "tlv320aic3110", AIC3110 }, + { "tlv320aic3120", AIC3120 }, + { "tlv320aic3111", AIC3111 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); + +static struct i2c_driver aic31xx_i2c_driver = { + .driver = { + .name = "tlv320aic31xx-codec", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tlv320aic31xx_of_match), + }, + .probe = aic31xx_i2c_probe, + .remove = aic31xx_i2c_remove, + .id_table = aic31xx_i2c_id, +}; + +module_i2c_driver(aic31xx_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver"); +MODULE_AUTHOR("Jyri Sarha"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h new file mode 100644 index 00000000000..52ed57c69df --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -0,0 +1,258 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +#ifndef _TLV320AIC31XX_H +#define _TLV320AIC31XX_H + +#define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 + +#define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ + | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + +#define AIC31XX_STEREO_CLASS_D_BIT 0x1 +#define AIC31XX_MINIDSP_BIT 0x2 + +enum aic31xx_type { + AIC3100 = 0, + AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, + AIC3120 = AIC31XX_MINIDSP_BIT, + AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), +}; + +struct aic31xx_pdata { + enum aic31xx_type codec_type; + unsigned int gpio_reset; + int micbias_vg; +}; + +/* Page Control Register */ +#define AIC31XX_PAGECTL 0x00 + +/* Page 0 Registers */ +/* Software reset register */ +#define AIC31XX_RESET 0x01 +/* OT FLAG register */ +#define AIC31XX_OT_FLAG 0x03 +/* Clock clock Gen muxing, Multiplexers*/ +#define AIC31XX_CLKMUX 0x04 +/* PLL P and R-VAL register */ +#define AIC31XX_PLLPR 0x05 +/* PLL J-VAL register */ +#define AIC31XX_PLLJ 0x06 +/* PLL D-VAL MSB register */ +#define AIC31XX_PLLDMSB 0x07 +/* PLL D-VAL LSB register */ +#define AIC31XX_PLLDLSB 0x08 +/* DAC NDAC_VAL register*/ +#define AIC31XX_NDAC 0x0B +/* DAC MDAC_VAL register */ +#define AIC31XX_MDAC 0x0C +/* DAC OSR setting register 1, MSB value */ +#define AIC31XX_DOSRMSB 0x0D +/* DAC OSR setting register 2, LSB value */ +#define AIC31XX_DOSRLSB 0x0E +#define AIC31XX_MINI_DSP_INPOL 0x10 +/* Clock setting register 8, PLL */ +#define AIC31XX_NADC 0x12 +/* Clock setting register 9, PLL */ +#define AIC31XX_MADC 0x13 +/* ADC Oversampling (AOSR) Register */ +#define AIC31XX_AOSR 0x14 +/* Clock setting register 9, Multiplexers */ +#define AIC31XX_CLKOUTMUX 0x19 +/* Clock setting register 10, CLOCKOUT M divider value */ +#define AIC31XX_CLKOUTMVAL 0x1A +/* Audio Interface Setting Register 1 */ +#define AIC31XX_IFACE1 0x1B +/* Audio Data Slot Offset Programming */ +#define AIC31XX_DATA_OFFSET 0x1C +/* Audio Interface Setting Register 2 */ +#define AIC31XX_IFACE2 0x1D +/* Clock setting register 11, BCLK N Divider */ +#define AIC31XX_BCLKN 0x1E +/* Audio Interface Setting Register 3, Secondary Audio Interface */ +#define AIC31XX_IFACESEC1 0x1F +/* Audio Interface Setting Register 4 */ +#define AIC31XX_IFACESEC2 0x20 +/* Audio Interface Setting Register 5 */ +#define AIC31XX_IFACESEC3 0x21 +/* I2C Bus Condition */ +#define AIC31XX_I2C 0x22 +/* ADC FLAG */ +#define AIC31XX_ADCFLAG 0x24 +/* DAC Flag Registers */ +#define AIC31XX_DACFLAG1 0x25 +#define AIC31XX_DACFLAG2 0x26 +/* Sticky Interrupt flag (overflow) */ +#define AIC31XX_OFFLAG 0x27 +/* Sticy DAC Interrupt flags */ +#define AIC31XX_INTRDACFLAG 0x2C +/* Sticy ADC Interrupt flags */ +#define AIC31XX_INTRADCFLAG 0x2D +/* DAC Interrupt flags 2 */ +#define AIC31XX_INTRDACFLAG2 0x2E +/* ADC Interrupt flags 2 */ +#define AIC31XX_INTRADCFLAG2 0x2F +/* INT1 interrupt control */ +#define AIC31XX_INT1CTRL 0x30 +/* INT2 interrupt control */ +#define AIC31XX_INT2CTRL 0x31 +/* GPIO1 control */ +#define AIC31XX_GPIO1 0x33 + +#define AIC31XX_DACPRB 0x3C +/* ADC Instruction Set Register */ +#define AIC31XX_ADCPRB 0x3D +/* DAC channel setup register */ +#define AIC31XX_DACSETUP 0x3F +/* DAC Mute and volume control register */ +#define AIC31XX_DACMUTE 0x40 +/* Left DAC channel digital volume control */ +#define AIC31XX_LDACVOL 0x41 +/* Right DAC channel digital volume control */ +#define AIC31XX_RDACVOL 0x42 +/* Headset detection */ +#define AIC31XX_HSDETECT 0x43 +/* ADC Digital Mic */ +#define AIC31XX_ADCSETUP 0x51 +/* ADC Digital Volume Control Fine Adjust */ +#define AIC31XX_ADCFGA 0x52 +/* ADC Digital Volume Control Coarse Adjust */ +#define AIC31XX_ADCVOL 0x53 + + +/* Page 1 Registers */ +/* Headphone drivers */ +#define AIC31XX_HPDRIVER 0x9F +/* Class-D Speakear Amplifier */ +#define AIC31XX_SPKAMP 0xA0 +/* HP Output Drivers POP Removal Settings */ +#define AIC31XX_HPPOP 0xA1 +/* Output Driver PGA Ramp-Down Period Control */ +#define AIC31XX_SPPGARAMP 0xA2 +/* DAC_L and DAC_R Output Mixer Routing */ +#define AIC31XX_DACMIXERROUTE 0xA3 +/* Left Analog Vol to HPL */ +#define AIC31XX_LANALOGHPL 0xA4 +/* Right Analog Vol to HPR */ +#define AIC31XX_RANALOGHPR 0xA5 +/* Left Analog Vol to SPL */ +#define AIC31XX_LANALOGSPL 0xA6 +/* Right Analog Vol to SPR */ +#define AIC31XX_RANALOGSPR 0xA7 +/* HPL Driver */ +#define AIC31XX_HPLGAIN 0xA8 +/* HPR Driver */ +#define AIC31XX_HPRGAIN 0xA9 +/* SPL Driver */ +#define AIC31XX_SPLGAIN 0xAA +/* SPR Driver */ +#define AIC31XX_SPRGAIN 0xAB +/* HP Driver Control */ +#define AIC31XX_HPCONTROL 0xAC +/* MIC Bias Control */ +#define AIC31XX_MICBIAS 0xAE +/* MIC PGA*/ +#define AIC31XX_MICPGA 0xAF +/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */ +#define AIC31XX_MICPGAPI 0xB0 +/* ADC Input Selection for M-Terminal */ +#define AIC31XX_MICPGAMI 0xB1 +/* Input CM Settings */ +#define AIC31XX_MICPGACM 0xB2 + +/* Bits, masks and shifts */ + +/* AIC31XX_CLKMUX */ +#define AIC31XX_PLL_CLKIN_MASK 0x0c +#define AIC31XX_PLL_CLKIN_SHIFT 2 +#define AIC31XX_PLL_CLKIN_MCLK 0 +#define AIC31XX_CODEC_CLKIN_MASK 0x03 +#define AIC31XX_CODEC_CLKIN_SHIFT 0 +#define AIC31XX_CODEC_CLKIN_PLL 3 +#define AIC31XX_CODEC_CLKIN_BCLK 1 + +/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC, + AIC31XX_BCLKN */ +#define AIC31XX_PLL_MASK 0x7f +#define AIC31XX_PM_MASK 0x80 + +/* AIC31XX_IFACE1 */ +#define AIC31XX_WORD_LEN_16BITS 0x00 +#define AIC31XX_WORD_LEN_20BITS 0x01 +#define AIC31XX_WORD_LEN_24BITS 0x02 +#define AIC31XX_WORD_LEN_32BITS 0x03 +#define AIC31XX_IFACE1_DATALEN_MASK 0x30 +#define AIC31XX_IFACE1_DATALEN_SHIFT (4) +#define AIC31XX_IFACE1_DATATYPE_MASK 0xC0 +#define AIC31XX_IFACE1_DATATYPE_SHIFT (6) +#define AIC31XX_I2S_MODE 0x00 +#define AIC31XX_DSP_MODE 0x01 +#define AIC31XX_RIGHT_JUSTIFIED_MODE 0x02 +#define AIC31XX_LEFT_JUSTIFIED_MODE 0x03 +#define AIC31XX_IFACE1_MASTER_MASK 0x0C +#define AIC31XX_BCLK_MASTER 0x08 +#define AIC31XX_WCLK_MASTER 0x04 + +/* AIC31XX_DATA_OFFSET */ +#define AIC31XX_DATA_OFFSET_MASK 0xFF + +/* AIC31XX_IFACE2 */ +#define AIC31XX_BCLKINV_MASK 0x08 +#define AIC31XX_BDIVCLK_MASK 0x03 +#define AIC31XX_DAC2BCLK 0x00 +#define AIC31XX_DACMOD2BCLK 0x01 +#define AIC31XX_ADC2BCLK 0x02 +#define AIC31XX_ADCMOD2BCLK 0x03 + +/* AIC31XX_ADCFLAG */ +#define AIC31XX_ADCPWRSTATUS_MASK 0x40 + +/* AIC31XX_DACFLAG1 */ +#define AIC31XX_LDACPWRSTATUS_MASK 0x80 +#define AIC31XX_RDACPWRSTATUS_MASK 0x08 +#define AIC31XX_HPLDRVPWRSTATUS_MASK 0x20 +#define AIC31XX_HPRDRVPWRSTATUS_MASK 0x02 +#define AIC31XX_SPLDRVPWRSTATUS_MASK 0x10 +#define AIC31XX_SPRDRVPWRSTATUS_MASK 0x01 + +/* AIC31XX_INTRDACFLAG */ +#define AIC31XX_HPSCDETECT_MASK 0x80 +#define AIC31XX_BUTTONPRESS_MASK 0x20 +#define AIC31XX_HSPLUG_MASK 0x10 +#define AIC31XX_LDRCTHRES_MASK 0x08 +#define AIC31XX_RDRCTHRES_MASK 0x04 +#define AIC31XX_DACSINT_MASK 0x02 +#define AIC31XX_DACAINT_MASK 0x01 + +/* AIC31XX_INT1CTRL */ +#define AIC31XX_HSPLUGDET_MASK 0x80 +#define AIC31XX_BUTTONPRESSDET_MASK 0x40 +#define AIC31XX_DRCTHRES_MASK 0x20 +#define AIC31XX_AGCNOISE_MASK 0x10 +#define AIC31XX_OC_MASK 0x08 +#define AIC31XX_ENGINE_MASK 0x04 + +/* AIC31XX_DACSETUP */ +#define AIC31XX_SOFTSTEP_MASK 0x03 + +/* AIC31XX_DACMUTE */ +#define AIC31XX_DACMUTE_MASK 0x0C + +/* AIC31XX_MICBIAS */ +#define AIC31XX_MICBIAS_MASK 0x03 +#define AIC31XX_MICBIAS_SHIFT 0 + +#endif /* _TLV320AIC31XX_H */ diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c6bd7e75352..1d9b117345a 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -614,8 +614,6 @@ static int aic32x4_probe(struct snd_soc_codec *codec) struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u32 tmp_reg; - snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 470fbfb4b38..b1835103e9b 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1344,12 +1344,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) INIT_LIST_HEAD(&aic3x->list); aic3x->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; aic3x->disable_nb[i].aic3x = aic3x; diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 79351614667..6bfc8a17331 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -122,7 +122,6 @@ struct tlv320dac33_priv { unsigned int uthr; enum dac33_state state; - enum snd_soc_control_type control_type; void *control_data; }; diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index c94d4c1e3da..edf27acc1d7 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -203,8 +203,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); u8 hw_params; diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 4dadaa8ad46..e62e70781ec 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -566,8 +566,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 8ae50274ea8..83a2c872925 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -786,8 +786,6 @@ static int wm2000_probe(struct snd_soc_codec *codec) { struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); - /* This will trigger a transition to standby mode by default */ wm2000_anc_set_mode(wm2000); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 1e0a083d834..2e721e06671 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1554,15 +1554,8 @@ static int wm2200_probe(struct snd_soc_codec *codec) int ret; wm2200->codec = codec; - codec->control_data = wm2200->regmap; codec->dapm.bias_level = SND_SOC_BIAS_OFF; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index d3fa65fd9e8..eca983fad89 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2343,13 +2343,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) int ret, i; wm5100->codec = codec; - codec->control_data = wm5100->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 34109050cee..dcf1d12cfef 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1760,9 +1760,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index d7bf8848174..df5a38dd832 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1587,10 +1587,9 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; priv->core.arizona->dapm = &codec->dapm; - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index a183dcf3d5c..757256bf767 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1505,9 +1505,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) if (ret != 0) return ret; - codec->control_data = wm8350->regmap; - - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8350->regmap); /* Put the codec into reset if it wasn't already */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 6d684d934f4..146564feaea 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1316,10 +1316,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, priv); priv->wm8400 = wm8400; - codec->control_data = wm8400->regmap; priv->codec = codec; - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8400->regmap); ret = devm_regulator_bulk_get(wm8400->dev, ARRAY_SIZE(power), &power[0]); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 7df7d457275..1c1e328feeb 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -589,20 +589,12 @@ static int wm8510_resume(struct snd_soc_codec *codec) static int wm8510_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8510_reset(codec); /* power on device */ wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 5dfd571b1a0..601ee8178af 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -392,18 +392,11 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 318989acbbe..af7ed8b5d4e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -504,8 +504,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); u16 paifa = 0; u16 paifb = 0; @@ -869,12 +868,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); if (ret != 0) { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 6efcc40a7cb..b0fbcb377ba 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -367,12 +367,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8711_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index cd89033e84c..bac7fc28fe7 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -228,19 +228,10 @@ static int wm8728_resume(struct snd_soc_codec *codec) static int wm8728_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", - ret); - return ret; - } - /* power on device */ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } static int wm8728_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index d9655f981df..d74f43975b9 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -583,13 +583,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); int ret = 0, i; - codec->control_data = wm8731->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) wm8731->supplies[i].supply = wm8731_supply_names[i]; diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index ecc4e8725d5..b27f26cdc04 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -570,12 +570,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index dd02ebf8801..b33542a0460 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -429,12 +429,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) goto err_get; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err_enable; - } - ret = wm8741_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 78616a638a5..33990b63d21 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -702,12 +702,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8750_reset(codec); if (ret < 0) { printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 6a6855d8b8e..cbb8d55052a 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1470,13 +1470,6 @@ static int wm8753_probe(struct snd_soc_codec *codec) INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); - codec->control_data = wm8753->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8753_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 5bce2101348..c61aeb38efb 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -580,12 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec) wm8770 = snd_soc_codec_get_drvdata(codec); wm8770->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); if (ret) { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index ef824672523..70952ceb278 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -430,12 +430,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8776_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 72d12bbe1a5..ee76f0fb429 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -546,14 +546,6 @@ static int wm8804_probe(struct snd_soc_codec *codec) wm8804 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8804->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) wm8804->supplies[i].supply = wm8804_supply_names[i]; diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 43c2201cb90..d09fdce57f5 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1178,13 +1178,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) static int wm8900_probe(struct snd_soc_codec *codec) { - int ret = 0, reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } + int reg; reg = snd_soc_read(codec, WM8900_REG_ID); if (reg != 0x8900) { diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index b82b70a3b3d..b0084a127d1 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1897,21 +1897,13 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int ret; wm8903->codec = codec; - codec->control_data = wm8903->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 27299cda0e9..49c35c36935 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2048,9 +2048,6 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm8904->regmap; switch (wm8904->devtype) { case WM8904: @@ -2064,12 +2061,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) return -EINVAL; } - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - wm8904_handle_pdata(codec); wm8904_add_widgets(codec); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 87f032d0d19..fc6eec9ad66 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -712,12 +712,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) int ret; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8940_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index d4dcaecc8a5..fecd4e4f4c5 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -895,14 +895,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); int ret, i; - codec->control_data = wm8955->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) wm8955->supplies[i].supply = wm8955_supply_names[i]; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f156010e52b..d04e9cad445 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -976,12 +976,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) wm8960->set_bias_level = wm8960_set_bias_level_capless; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index ce8fa6e01cb..9c88f04442b 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -836,15 +836,8 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 62af9dc59fc..5522d2566c6 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3424,13 +3424,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) bool dmicclk, dmicdat; wm8962->codec = codec; - codec->control_data = wm8962->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 67aba78a7ca..09b7b420022 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -648,12 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - return ret; - } - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); wm8971_workq = create_workqueue("wm8971"); if (wm8971_workq == NULL) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 6e16c430646..0627c56fa44 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -593,12 +593,6 @@ static int wm8974_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8974_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a9e2f465c33..28ef46c91f6 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -975,19 +975,13 @@ static const int update_reg[] = { static int wm8978_probe(struct snd_soc_codec *codec) { struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0, i; + int i; /* * Set default system clock to PLL, it is more precise, this is also the * default hardware setting */ wm8978->sysclk = WM8978_PLL; - codec->control_data = wm8978->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* * Set the update bit in all registers, that have one. This way all diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 58f0551eed2..2b9bfa53efb 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -995,12 +995,6 @@ static int wm8983_probe(struct snd_soc_codec *codec) int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index d786f2b3976..5473dc96958 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -995,13 +995,6 @@ static int wm8985_probe(struct snd_soc_codec *codec) int ret; wm8985 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8985->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) wm8985->supplies[i].supply = wm8985_supply_names[i]; diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 0277a76c6be..3a1ae4f5164 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -810,16 +810,8 @@ static int wm8988_resume(struct snd_soc_codec *codec) static int wm8988_probe(struct snd_soc_codec *codec) { - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8988->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 33f53ab1e7b..c413c199145 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1289,14 +1289,6 @@ static int wm8990_resume(struct snd_soc_codec *codec) */ static int wm8990_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8990_reset(codec); /* charge output caps */ diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 32d219570cc..844cc4a60d6 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1248,14 +1248,6 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 7b0630a076f..f825dc04ebe 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1493,13 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->hubs_data.dcs_codes_r = -2; wm8993->hubs_data.series_startup = 1; - codec->control_data = wm8993->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Latch volume update bits and default ZC on */ snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, WM8993_DAC_VU, WM8993_DAC_VU); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 79854cb7feb..6303537f54c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3998,9 +3998,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) int ret, i; wm8994->hubs.codec = codec; - codec->control_data = control->regmap; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, control->regmap); mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index ddb197dc1d5..d3152cf5bd5 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2042,13 +2042,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) wm8995 = snd_soc_codec_get_drvdata(codec); wm8995->codec = codec; - codec->control_data = wm8995->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) wm8995->supplies[i].supply = wm8995_supply_names[i]; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index c8244af7d56..c6cbb3b8ace 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2633,14 +2633,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) init_completion(&wm8996->dcs_done); init_completion(&wm8996->fll_lock); - codec->control_data = wm8996->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - if (wm8996->pdata.num_retune_mobile_cfgs) wm8996_retune_mobile_pdata(codec); else @@ -2679,13 +2671,11 @@ static int wm8996_probe(struct snd_soc_codec *codec) } else { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); + return ret; } } return 0; - -err: - return ret; } static int wm8996_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index e10f44d7fdb..004186b6bd4 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1053,9 +1053,7 @@ static int wm8997_codec_probe(struct snd_soc_codec *codec) struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 721cee71d5f..d18eff31fbb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1260,15 +1260,6 @@ static struct snd_soc_dai_driver wm9081_dai = { static int wm9081_probe(struct snd_soc_codec *codec) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm9081->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* Enable zero cross by default */ snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, @@ -1283,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) ARRAY_SIZE(wm9081_eq_controls)); } - return ret; + return 0; } static int wm9081_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index a07fe1618ee..87934171f06 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -522,16 +522,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { - struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev); - int ret; - - codec->control_data = wm9090->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Configure some defaults; they will be written out when we * bring the bias up. */ diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 621e9a997d4..cab98a58005 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -123,35 +123,29 @@ static const struct snd_soc_dapm_route audio_map[] = { /* Logic for a aic3x as connected on a davinci-evm */ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_card *card = rtd->card; struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; struct device_node *np = codec->card->dev->of_node; int ret; /* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, + snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); if (np) { - ret = snd_soc_of_parse_audio_routing(codec->card, - "ti,audio-routing"); + ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); if (ret) return ret; } else { /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_add_routes(&card->dapm, audio_map, + ARRAY_SIZE(audio_map)); } /* not connected */ - snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); - snd_soc_dapm_disable_pin(dapm, "HPLCOM"); - snd_soc_dapm_disable_pin(dapm, "HPRCOM"); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Out"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); + snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM"); return 0; } diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b0ae0677f02..a01ae97c90a 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1026,6 +1026,7 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_params; + struct snd_dmaengine_dai_dma_data *dma_data; struct resource *mem, *ioarea, *res, *dat; struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; @@ -1095,6 +1096,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp->dat_port = true; dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dma_params->asp_chan_q = pdata->asp_chan_q; dma_params->ram_chan_q = pdata->ram_chan_q; dma_params->sram_pool = pdata->sram_pool; @@ -1105,7 +1107,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_params->dma_addr = mem->start + pdata->tx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_params->dma_addr; + dma_data->addr = dma_params->dma_addr; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) @@ -1113,7 +1115,14 @@ static int davinci_mcasp_probe(struct platform_device *pdev) else dma_params->channel = pdata->tx_dma_channel; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "tx"; + else + dma_data->filter_data = &dma_params->channel; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; dma_params->asp_chan_q = pdata->asp_chan_q; dma_params->ram_chan_q = pdata->ram_chan_q; dma_params->sram_pool = pdata->sram_pool; @@ -1124,7 +1133,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_params->dma_addr = mem->start + pdata->rx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_params->dma_addr; + dma_data->addr = dma_params->dma_addr; if (mcasp->version < MCASP_VERSION_3) { mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; @@ -1140,9 +1149,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) else dma_params->channel = pdata->rx_dma_channel; - /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx"; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "rx"; + else + dma_data->filter_data = &dma_params->channel; dev_set_drvdata(&pdev->dev, mcasp); diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c new file mode 100644 index 00000000000..d38afb1c61a --- /dev/null +++ b/sound/soc/davinci/edma-pcm.c @@ -0,0 +1,57 @@ +/* + * edma-pcm.c - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + * + * Based on: sound/soc/tegra/tegra_pcm.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#include <linux/module.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/dmaengine_pcm.h> +#include <linux/edma.h> + +static const struct snd_pcm_hardware edma_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_INTERLEAVED, + .buffer_bytes_max = 128 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 64 * 1024, + .periods_min = 2, + .periods_max = 19, /* Limit by edma dmaengine driver */ +}; + +static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { + .pcm_hardware = &edma_pcm_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .compat_filter_fn = edma_filter_fn, + .prealloc_buffer_size = 128 * 1024, +}; + +int edma_pcm_platform_register(struct device *dev) +{ + return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_COMPAT); +} +EXPORT_SYMBOL_GPL(edma_pcm_platform_register); + +MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); +MODULE_DESCRIPTION("eDMA PCM ASoC platform driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h new file mode 100644 index 00000000000..894c378c0f7 --- /dev/null +++ b/sound/soc/davinci/edma-pcm.h @@ -0,0 +1,25 @@ +/* + * edma-pcm.h - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + * + * Based on: sound/soc/tegra/tegra_pcm.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __EDMA_PCM_H__ +#define __EDMA_PCM_H__ + +int edma_pcm_platform_register(struct device *dev); + +#endif /* __EDMA_PCM_H__ */ diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 78ed4a42ad2..49f8437665d 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -1,11 +1,20 @@ config SND_KIRKWOOD_SOC tristate "SoC Audio for the Marvell Kirkwood and Dove chips" - depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST + depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST help Say Y or M if you want to add support for codecs attached to the Kirkwood I2S interface. You will also need to select the audio interfaces to support below. +config SND_KIRKWOOD_SOC_ARMADA370_DB + tristate "SoC Audio support for Armada 370 DB" + depends on SND_KIRKWOOD_SOC && (ARCH_MVEBU || COMPILE_TEST) && I2C + select SND_SOC_CS42L51 + select SND_SOC_SPDIF + help + Say Y if you want to add support for SoC audio on + the Armada 370 Development Board. + config SND_KIRKWOOD_SOC_OPENRD tristate "SoC Audio support for Kirkwood Openrd Client" depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 9e781385cb8..7c1d8fe09e6 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o snd-soc-openrd-objs := kirkwood-openrd.o snd-soc-t5325-objs := kirkwood-t5325.o +snd-soc-armada-370-db-objs := armada-370-db.o +obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c new file mode 100644 index 00000000000..c4433384925 --- /dev/null +++ b/sound/soc/kirkwood/armada-370-db.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <sound/soc.h> +#include <linux/of.h> +#include <linux/platform_data/asoc-kirkwood.h> +#include "../codecs/cs42l51.h" + +static int a370db_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int freq; + + switch (params_rate(params)) { + default: + case 44100: + freq = 11289600; + break; + case 48000: + freq = 12288000; + break; + case 96000: + freq = 24576000; + break; + } + + return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); +} + +static struct snd_soc_ops a370db_ops = { + .hw_params = a370db_hw_params, +}; + +static const struct snd_soc_dapm_widget a370db_dapm_widgets[] = { + SND_SOC_DAPM_HP("Out Jack", NULL), + SND_SOC_DAPM_LINE("In Jack", NULL), +}; + +static const struct snd_soc_dapm_route a370db_route[] = { + { "Out Jack", NULL, "HPL" }, + { "Out Jack", NULL, "HPR" }, + { "AIN1L", NULL, "In Jack" }, + { "AIN1L", NULL, "In Jack" }, +}; + +static struct snd_soc_dai_link a370db_dai[] = { +{ + .name = "CS42L51", + .stream_name = "analog", + .cpu_dai_name = "i2s", + .codec_dai_name = "cs42l51-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .ops = &a370db_ops, +}, +{ + .name = "S/PDIF out", + .stream_name = "spdif-out", + .cpu_dai_name = "spdif", + .codec_dai_name = "dit-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, +{ + .name = "S/PDIF in", + .stream_name = "spdif-in", + .cpu_dai_name = "spdif", + .codec_dai_name = "dir-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, +}; + +static struct snd_soc_card a370db = { + .name = "a370db", + .owner = THIS_MODULE, + .dai_link = a370db_dai, + .num_links = ARRAY_SIZE(a370db_dai), + .dapm_widgets = a370db_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(a370db_dapm_widgets), + .dapm_routes = a370db_route, + .num_dapm_routes = ARRAY_SIZE(a370db_route), +}; + +static int a370db_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &a370db; + + card->dev = &pdev->dev; + + a370db_dai[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-controller", 0); + a370db_dai[0].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 0); + + a370db_dai[1].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[1].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[1].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 1); + + a370db_dai[2].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[2].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[2].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 2); + + return devm_snd_soc_register_card(card->dev, card); +} + +static const struct of_device_id a370db_dt_ids[] = { + { .compatible = "marvell,a370db-audio" }, + { }, +}; + +static struct platform_driver a370db_driver = { + .driver = { + .name = "a370db-audio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(a370db_dt_ids), + }, + .probe = a370db_probe, +}; + +module_platform_driver(a370db_driver); + +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); +MODULE_DESCRIPTION("ALSA SoC a370db audio client"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:a370db-audio"); diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3920a5e8125..9f842222e79 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -633,6 +633,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) static struct of_device_id mvebu_audio_of_match[] = { { .compatible = "marvell,kirkwood-audio" }, { .compatible = "marvell,dove-audio" }, + { .compatible = "marvell,armada370-audio" }, { } }; MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index f141435b0b4..56a5219c0a0 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -325,7 +325,7 @@ static void cx81801_close(struct tty_struct *tty) snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_mutex_unlock(codec); + snd_soc_dapm_mutex_unlock(dapm); } /* Line discipline .hangup() */ diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 41ab6678b65..259e048681c 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -41,9 +41,8 @@ static int magician_hp_switch; static int magician_spk_switch = 1; static int magician_in_sel = MAGICIAN_MIC; -static void magician_ext_control(struct snd_soc_codec *codec) +static void magician_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; snd_soc_dapm_mutex_lock(dapm); @@ -75,10 +74,9 @@ static void magician_ext_control(struct snd_soc_codec *codec) static int magician_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - magician_ext_control(codec); + magician_ext_control(&rtd->card->dapm); return 0; } @@ -277,13 +275,13 @@ static int magician_get_hp(struct snd_kcontrol *kcontrol, static int magician_set_hp(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_hp_switch == ucontrol->value.integer.value[0]) return 0; magician_hp_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -297,13 +295,13 @@ static int magician_get_spk(struct snd_kcontrol *kcontrol, static int magician_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_spk_switch == ucontrol->value.integer.value[0]) return 0; magician_spk_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -400,7 +398,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* NC codec pins */ snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); @@ -410,19 +407,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "VINL"); snd_soc_dapm_nc_pin(dapm, "VINR"); - /* Add magician specific controls */ - err = snd_soc_add_codec_controls(codec, uda1380_magician_controls, - ARRAY_SIZE(uda1380_magician_controls)); - if (err < 0) - return err; - - /* Add magician specific widgets */ - snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, - ARRAY_SIZE(uda1380_dapm_widgets)); - - /* Set up magician specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -456,6 +440,12 @@ static struct snd_soc_card snd_soc_card_magician = { .dai_link = magician_dai, .num_links = ARRAY_SIZE(magician_dai), + .controls = uda1380_magician_controls, + .num_controls = ARRAY_SIZE(uda1380_magician_controls), + .dapm_widgets = uda1380_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *magician_snd_device; diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index cead1658d10..4a956d1cb26 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -44,9 +44,8 @@ static int tosa_jack_func; static int tosa_spk_func; -static void tosa_ext_control(struct snd_soc_codec *codec) +static void tosa_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; snd_soc_dapm_mutex_lock(dapm); @@ -82,10 +81,9 @@ static void tosa_ext_control(struct snd_soc_codec *codec) static int tosa_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - tosa_ext_control(codec); + tosa_ext_control(&rtd->card->dapm); return 0; } @@ -104,13 +102,13 @@ static int tosa_get_jack(struct snd_kcontrol *kcontrol, static int tosa_set_jack(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_jack_func == ucontrol->value.integer.value[0]) return 0; tosa_jack_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -124,13 +122,13 @@ static int tosa_get_spk(struct snd_kcontrol *kcontrol, static int tosa_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_spk_func == ucontrol->value.integer.value[0]) return 0; tosa_spk_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -191,24 +189,10 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_nc_pin(dapm, "OUT3"); snd_soc_dapm_nc_pin(dapm, "MONOOUT"); - /* add tosa specific controls */ - err = snd_soc_add_codec_controls(codec, tosa_controls, - ARRAY_SIZE(tosa_controls)); - if (err < 0) - return err; - - /* add tosa specific widgets */ - snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets, - ARRAY_SIZE(tosa_dapm_widgets)); - - /* set up tosa specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -239,6 +223,13 @@ static struct snd_soc_card tosa = { .owner = THIS_MODULE, .dai_link = tosa_dai, .num_links = ARRAY_SIZE(tosa_dai), + + .controls = tosa_controls, + .num_controls = ARRAY_SIZE(tosa_controls), + .dapm_widgets = tosa_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int tosa_probe(struct platform_device *pdev) diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 945e8abdc10..0b21d1dc80c 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -104,8 +104,8 @@ static int output_type_get(struct snd_kcontrol *kcontrol, static int output_type_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = kcontrol->private_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = kcontrol->private_data; + struct snd_soc_dapm_context *dapm = &card->dapm; unsigned int val = (ucontrol->value.enumerated.item[0] != 0); char *differential = "Audio Out Differential"; char *stereo = "Audio Out Stereo"; @@ -137,13 +137,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add s6105 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - /* Set up s6105 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + struct snd_soc_card *card = rtd->card; /* not present */ snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); @@ -157,17 +151,10 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "RLOUT"); snd_soc_dapm_nc_pin(dapm, "HPRCOM"); - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Audio In"); - /* must correspond to audio_out_mux.private_value initializer */ - snd_soc_dapm_disable_pin(dapm, "Audio Out Differential"); - snd_soc_dapm_sync(dapm); - snd_soc_dapm_enable_pin(dapm, "Audio Out Stereo"); - - snd_soc_dapm_sync(dapm); + snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); - snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); + snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card)); return 0; } @@ -190,6 +177,11 @@ static struct snd_soc_card snd_soc_card_s6105 = { .owner = THIS_MODULE, .dai_link = &s6105_dai, .num_links = 1, + + .dapm_widgets = aic3x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct s6000_snd_platform_data s6105_snd_data __initdata = { diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1967f44e7cd..710a079a737 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1711,9 +1711,9 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - fsi->clk_master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: + fsi->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 6a1b45df810..d836e8a9fdc 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -510,10 +510,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - rdai->clk_master = 1; + rdai->clk_master = 0; break; case SND_SOC_DAIFMT_CBS_CFS: - rdai->clk_master = 0; + rdai->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 359c2849b36..b322cf294d0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1137,6 +1137,16 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->dapm.idle_bias_off = driver->idle_bias_off; + if (!codec->write && dev_get_regmap(codec->dev, NULL)) { + /* Set the default I/O up try regmap */ + ret = snd_soc_codec_set_cache_io(codec, NULL); + if (ret < 0) { + dev_err(codec->dev, + "Failed to set cache I/O: %d\n", ret); + goto err_probe; + } + } + if (driver->probe) { ret = driver->probe(codec); if (ret < 0) { @@ -1150,10 +1160,6 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->name); } - /* If the driver didn't set I/O up try regmap */ - if (!codec->write && dev_get_regmap(codec->dev, NULL)) - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (driver->controls) snd_soc_add_codec_controls(codec, driver->controls, driver->num_controls); diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index aa886cca3ec..260efc8466f 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -23,21 +23,6 @@ static int hw_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { - int ret; - - if (!snd_soc_codec_volatile_register(codec, reg) && - reg < codec->driver->reg_cache_size && - !codec->cache_bypass) { - ret = snd_soc_cache_write(codec, reg, value); - if (ret < 0) - return -1; - } - - if (codec->cache_only) { - codec->cache_sync = 1; - return 0; - } - return regmap_write(codec->control_data, reg, value); } @@ -46,32 +31,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) int ret; unsigned int val; - if (reg >= codec->driver->reg_cache_size || - snd_soc_codec_volatile_register(codec, reg) || - codec->cache_bypass) { - if (codec->cache_only) - return -1; - - ret = regmap_read(codec->control_data, reg, &val); - if (ret == 0) - return val; - else - return -1; - } - - ret = snd_soc_cache_read(codec, reg, &val); - if (ret < 0) + ret = regmap_read(codec->control_data, reg, &val); + if (ret == 0) + return val; + else return -1; - return val; } /** * snd_soc_codec_set_cache_io: Set up standard I/O functions. * * @codec: CODEC to configure. - * @addr_bits: Number of bits of register address data. - * @data_bits: Number of bits of data per register. - * @control: Control bus used. + * @map: Register map to write to * * Register formats are frequently shared between many I2C and SPI * devices. In order to promote code reuse the ASoC core provides @@ -85,60 +56,36 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) * volatile registers. */ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { - struct regmap_config config; int ret; - memset(&config, 0, sizeof(config)); - codec->write = hw_write; - codec->read = hw_read; - - config.reg_bits = addr_bits; - config.val_bits = data_bits; + /* Device has made its own regmap arrangements */ + if (!regmap) + codec->control_data = dev_get_regmap(codec->dev, NULL); + else + codec->control_data = regmap; - switch (control) { -#if IS_ENABLED(CONFIG_REGMAP_I2C) - case SND_SOC_I2C: - codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), - &config); - break; -#endif + if (IS_ERR(codec->control_data)) + return PTR_ERR(codec->control_data); -#if IS_ENABLED(CONFIG_REGMAP_SPI) - case SND_SOC_SPI: - codec->control_data = regmap_init_spi(to_spi_device(codec->dev), - &config); - break; -#endif - - case SND_SOC_REGMAP: - /* Device has made its own regmap arrangements */ - codec->using_regmap = true; - if (!codec->control_data) - codec->control_data = dev_get_regmap(codec->dev, NULL); + codec->write = hw_write; + codec->read = hw_read; - if (codec->control_data) { - ret = regmap_get_val_bytes(codec->control_data); - /* Errors are legitimate for non-integer byte - * multiples */ - if (ret > 0) - codec->val_bytes = ret; - } - break; + ret = regmap_get_val_bytes(codec->control_data); + /* Errors are legitimate for non-integer byte + * multiples */ + if (ret > 0) + codec->val_bytes = ret; - default: - return -EINVAL; - } + codec->using_regmap = true; - return PTR_ERR_OR_ZERO(codec->control_data); + return 0; } EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); #else int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { return -ENOTSUPP; } diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 23d43dac91d..b903f822d1b 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -250,7 +250,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) report = 0; if (gpio->jack_status_check) - report = gpio->jack_status_check(); + report = gpio->jack_status_check(gpio->data); snd_soc_jack_report(jack, report, gpio->report); } @@ -342,7 +342,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, gpio_export(gpios[i].gpio, false); /* Update initial jack status */ - snd_soc_jack_gpio_detect(&gpios[i]); + schedule_delayed_work(&gpios[i].work, + msecs_to_jiffies(gpios[i].debounce_time)); } return 0; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 330eaf007d8..2cedf09f6d9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2050,7 +2050,6 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "playback"); mutex_unlock(&card->mutex); @@ -2080,7 +2079,6 @@ capture: paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "capture"); mutex_unlock(&card->mutex); @@ -2145,7 +2143,6 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; if (dpcm_path_get(fe, stream, &list) <= 0) { - dpcm_path_put(&list); dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); } diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index cf5e1cfe818..0a59e2383ef 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -306,7 +306,7 @@ static const struct regmap_config tegra20_ac97_regmap_config = { .readable_reg = tegra20_ac97_wr_rd_reg, .volatile_reg = tegra20_ac97_volatile_reg, .precious_reg = tegra20_ac97_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_ac97_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index e72392927bd..a634f13b3ff 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -128,7 +128,7 @@ static const struct regmap_config tegra20_das_regmap_config = { .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL), .writeable_reg = tegra20_das_wr_rd_reg, .readable_reg = tegra20_das_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_das_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 42c1f6bfaf2..79a9932ffe6 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -333,7 +333,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = { .readable_reg = tegra20_i2s_wr_rd_reg, .volatile_reg = tegra20_i2s_volatile_reg, .precious_reg = tegra20_i2s_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_i2s_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 8c7c1028e57..a0ce92400fa 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -259,7 +259,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = { .readable_reg = tegra20_spdif_wr_rd_reg, .volatile_reg = tegra20_spdif_volatile_reg, .precious_reg = tegra20_spdif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_spdif_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d6f4c9940e0..0db68f49f4d 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -471,7 +471,7 @@ static const struct regmap_config tegra30_ahub_apbif_regmap_config = { .readable_reg = tegra30_ahub_apbif_wr_rd_reg, .volatile_reg = tegra30_ahub_apbif_volatile_reg, .precious_reg = tegra30_ahub_apbif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) @@ -490,7 +490,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { .max_register = LAST_REG(AUDIO_RX), .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, .readable_reg = tegra30_ahub_ahub_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static struct tegra30_ahub_soc_data soc_data_tegra30 = { diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 49ad9366add..f146c41dd3e 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -357,7 +357,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = { .writeable_reg = tegra30_i2s_wr_rd_reg, .readable_reg = tegra30_i2s_wr_rd_reg, .volatile_reg = tegra30_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static const struct tegra30_i2s_soc_data tegra30_i2s_config = { diff --git a/tools/net/Makefile b/tools/net/Makefile index 004cd74734b..ee577ea03ba 100644 --- a/tools/net/Makefile +++ b/tools/net/Makefile @@ -12,7 +12,7 @@ YACC = bison all : bpf_jit_disasm bpf_dbg bpf_asm -bpf_jit_disasm : CFLAGS = -Wall -O2 +bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm' bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl bpf_jit_disasm : bpf_jit_disasm.o diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6aa6fb6f7bd..f954c26de23 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -825,7 +825,6 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal P_SIGNUM(PIPE); P_SIGNUM(ALRM); P_SIGNUM(TERM); - P_SIGNUM(STKFLT); P_SIGNUM(CHLD); P_SIGNUM(CONT); P_SIGNUM(STOP); @@ -841,6 +840,15 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal P_SIGNUM(IO); P_SIGNUM(PWR); P_SIGNUM(SYS); +#ifdef SIGEMT + P_SIGNUM(EMT); +#endif +#ifdef SIGSTKFLT + P_SIGNUM(STKFLT); +#endif +#ifdef SIGSWI + P_SIGNUM(SWI); +#endif default: break; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index c872991e0f6..620a1983b76 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1213,7 +1213,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread, */ thread__find_addr_location(thread, machine, m, MAP__FUNCTION, ip, &al); - if (al.sym) + if (al.map) goto found; } found: diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 3e9f336740f..516d19fb999 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -151,15 +151,15 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, gelf_getshdr(sec, shp); str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); - if (!strcmp(name, str)) { + if (str && !strcmp(name, str)) { if (idx) *idx = cnt; - break; + return sec; } ++cnt; } - return sec; + return NULL; } #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c index d66418237d2..aa290c0de6f 100644 --- a/tools/testing/selftests/ipc/msgque.c +++ b/tools/testing/selftests/ipc/msgque.c @@ -201,6 +201,7 @@ int main(int argc, char **argv) msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666); if (msgque.msq_id == -1) { + err = -errno; printf("Can't create queue\n"); goto err_out; } |