Home Home > GIT Browse > openSUSE-15.1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Tesarik <ptesarik@suse.cz>2019-01-11 17:15:48 +0100
committerPetr Tesarik <ptesarik@suse.cz>2019-01-11 17:15:48 +0100
commit233a6f55ab6479ce319292bae60b5de93bca3f6d (patch)
tree6a57cfd87997f9ae788e8452f7e48391ecf3653f
parent22b35258f480b2fdccf2bab6efa10f3466eacd13 (diff)
Revert alsa fixes from Takashi Iwai
This reverts changes pulled with merge commit 1f2c22ffd207d2f4725fd6feec155229d70213eb. suse-commit: 097dbea51c1e2cd7a1130a8cef279085b6a16eab
-rw-r--r--Documentation/sound/alsa-configuration.rst7
-rw-r--r--include/linux/usb/audio-v2.h29
-rw-r--r--include/linux/usb/audio-v3.h454
-rw-r--r--include/sound/core.h23
-rw-r--r--include/sound/emux_synth.h8
-rw-r--r--include/sound/mixer_oss.h2
-rw-r--r--include/sound/opl3.h8
-rw-r--r--include/sound/pcm.h153
-rw-r--r--include/sound/rawmidi.h5
-rw-r--r--include/sound/seq_midi_event.h6
-rw-r--r--include/sound/seq_virmidi.h3
-rw-r--r--include/sound/soc-dai.h2
-rw-r--r--include/uapi/linux/usb/audio.h83
-rw-r--r--include/uapi/sound/asound.h13
-rw-r--r--sound/aoa/codecs/tas.c14
-rw-r--r--sound/aoa/fabrics/layout.c8
-rw-r--r--sound/core/Kconfig59
-rw-r--r--sound/core/Makefile3
-rw-r--r--sound/core/compress_offload.c12
-rw-r--r--sound/core/control.c599
-rw-r--r--sound/core/control_compat.c34
-rw-r--r--sound/core/ctljack.c2
-rw-r--r--sound/core/device.c4
-rw-r--r--sound/core/hrtimer.c2
-rw-r--r--sound/core/hwdep.c4
-rw-r--r--sound/core/info.c12
-rw-r--r--sound/core/info_oss.c1
-rw-r--r--sound/core/init.c50
-rw-r--r--sound/core/isadma.c3
-rw-r--r--sound/core/jack.c2
-rw-r--r--sound/core/memalloc.c13
-rw-r--r--sound/core/memory.c2
-rw-r--r--sound/core/misc.c1
-rw-r--r--sound/core/oss/io.c4
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c121
-rw-r--r--sound/core/oss/pcm_plugin.c18
-rw-r--r--sound/core/oss/pcm_plugin.h10
-rw-r--r--sound/core/pcm.c129
-rw-r--r--sound/core/pcm_compat.c24
-rw-r--r--sound/core/pcm_drm_eld.c8
-rw-r--r--sound/core/pcm_lib.c703
-rw-r--r--sound/core/pcm_local.h70
-rw-r--r--sound/core/pcm_memory.c6
-rw-r--r--sound/core/pcm_misc.c33
-rw-r--r--sound/core/pcm_native.c1303
-rw-r--r--sound/core/pcm_param_trace.h142
-rw-r--r--sound/core/pcm_timer.c14
-rw-r--r--sound/core/pcm_trace.h50
-rw-r--r--sound/core/rawmidi.c275
-rw-r--r--sound/core/seq/Kconfig68
-rw-r--r--sound/core/seq/Makefile21
-rw-r--r--sound/core/seq/oss/Makefile2
-rw-r--r--sound/core/seq/oss/seq_oss.c2
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c2
-rw-r--r--sound/core/seq/oss/seq_oss_timer.c2
-rw-r--r--sound/core/seq/seq.c33
-rw-r--r--sound/core/seq/seq_clientmgr.c42
-rw-r--r--sound/core/seq/seq_device.c (renamed from sound/core/seq_device.c)0
-rw-r--r--sound/core/seq/seq_info.c10
-rw-r--r--sound/core/seq/seq_info.h6
-rw-r--r--sound/core/seq/seq_lock.c1
-rw-r--r--sound/core/seq/seq_memory.c14
-rw-r--r--sound/core/seq/seq_memory.h6
-rw-r--r--sound/core/seq/seq_midi.c24
-rw-r--r--sound/core/seq/seq_midi_emul.c21
-rw-r--r--sound/core/seq/seq_midi_event.c106
-rw-r--r--sound/core/seq/seq_ports.c4
-rw-r--r--sound/core/seq/seq_queue.c16
-rw-r--r--sound/core/seq/seq_queue.h27
-rw-r--r--sound/core/seq/seq_system.c22
-rw-r--r--sound/core/seq/seq_timer.c17
-rw-r--r--sound/core/seq/seq_timer.h2
-rw-r--r--sound/core/seq/seq_virmidi.c143
-rw-r--r--sound/core/sound.c2
-rw-r--r--sound/core/sound_oss.c3
-rw-r--r--sound/core/timer.c202
-rw-r--r--sound/core/vmaster.c18
-rw-r--r--sound/drivers/Kconfig15
-rw-r--r--sound/drivers/opl3/opl3_lib.c2
-rw-r--r--sound/drivers/opl3/opl3_seq.c4
-rw-r--r--sound/drivers/opl3/opl3_voice.h5
-rw-r--r--sound/drivers/opl4/opl4_lib.c4
-rw-r--r--sound/drivers/opl4/opl4_local.h2
-rw-r--r--sound/drivers/vx/vx_mixer.c24
-rw-r--r--sound/firewire/bebob/bebob_maudio.c8
-rw-r--r--sound/isa/Kconfig7
-rw-r--r--sound/isa/sb/emu8000.c2
-rw-r--r--sound/isa/sb/emu8000_callback.c6
-rw-r--r--sound/isa/sb/sb16.c2
-rw-r--r--sound/mips/hal2.c4
-rw-r--r--sound/mips/sgio2audio.c14
-rw-r--r--sound/pci/Kconfig7
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pcmcia/vx/vxp_mixer.c4
-rw-r--r--sound/ppc/awacs.c4
-rw-r--r--sound/ppc/beep.c2
-rw-r--r--sound/ppc/tumbler.c8
-rw-r--r--sound/sh/aica.c4
-rw-r--r--sound/soc/sh/siu_dai.c4
-rw-r--r--sound/soc/soc-core.c2
-rw-r--r--sound/soc/soc-pcm.c5
-rw-r--r--sound/synth/emux/emux.c6
-rw-r--r--sound/synth/emux/emux_effect.c2
-rw-r--r--sound/synth/emux/emux_oss.c4
-rw-r--r--sound/usb/6fire/chip.c35
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/bcd2000/bcd2000.c2
-rw-r--r--sound/usb/caiaq/audio.c5
-rw-r--r--sound/usb/caiaq/device.c3
-rw-r--r--sound/usb/card.c106
-rw-r--r--sound/usb/card.h4
-rw-r--r--sound/usb/clock.c330
-rw-r--r--sound/usb/clock.h4
-rw-r--r--sound/usb/endpoint.c2
-rw-r--r--sound/usb/format.c93
-rw-r--r--sound/usb/format.h6
-rw-r--r--sound/usb/helper.h4
-rw-r--r--sound/usb/line6/capture.c2
-rw-r--r--sound/usb/line6/capture.h2
-rw-r--r--sound/usb/line6/driver.c4
-rw-r--r--sound/usb/line6/driver.h3
-rw-r--r--sound/usb/line6/playback.c2
-rw-r--r--sound/usb/line6/playback.h2
-rw-r--r--sound/usb/line6/pod.c11
-rw-r--r--sound/usb/line6/podhd.c10
-rw-r--r--sound/usb/line6/toneport.c12
-rw-r--r--sound/usb/line6/variax.c32
-rw-r--r--sound/usb/midi.c15
-rw-r--r--sound/usb/misc/ua101.c2
-rw-r--r--sound/usb/mixer.c1295
-rw-r--r--sound/usb/mixer.h8
-rw-r--r--sound/usb/mixer_maps.c65
-rw-r--r--sound/usb/mixer_quirks.c392
-rw-r--r--sound/usb/mixer_scarlett.c6
-rw-r--r--sound/usb/pcm.c261
-rw-r--r--sound/usb/pcm.h3
-rw-r--r--sound/usb/power.c104
-rw-r--r--sound/usb/power.h19
-rw-r--r--sound/usb/quirks.c178
-rw-r--r--sound/usb/quirks.h4
-rw-r--r--sound/usb/stream.c827
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--sound/usb/usx2y/us122l.c91
-rw-r--r--sound/usb/usx2y/us122l.h2
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c28
-rw-r--r--sound/usb/usx2y/usb_stream.c18
147 files changed, 3316 insertions, 6184 deletions
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index b1052e18292d..aed6b4fb8e46 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -2224,13 +2224,6 @@ quirk_alias
Quirk alias list, pass strings like ``0123abcd:5678beef``, which
applies the existing quirk for the device 5678:beef to a new
device 0123:abcd.
-use_vmalloc
- Use vmalloc() for allocations of the PCM buffers (default: yes).
- For architectures with non-coherent memory like ARM or MIPS, the
- mmap access may give inconsistent results with vmalloc'ed
- buffers. If mmap is used on such architectures, turn off this
- option, so that the DMA-coherent buffers are allocated and used
- instead.
This module supports multiple devices, autoprobe and hotplugging.
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index bfc5659a9e28..76706391ce6d 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -33,14 +33,14 @@
*
*/
-static inline bool uac_v2v3_control_is_readable(u32 bmControls, u8 control)
+static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
{
- return (bmControls >> ((control - 1) * 2)) & 0x1;
+ return (bmControls >> (control * 2)) & 0x1;
}
-static inline bool uac_v2v3_control_is_writeable(u32 bmControls, u8 control)
+static inline bool uac2_control_is_writeable(u32 bmControls, u8 control)
{
- return (bmControls >> ((control - 1) * 2)) & 0x2;
+ return (bmControls >> (control * 2)) & 0x2;
}
/* 4.7.2 Class-Specific AC Interface Descriptor */
@@ -115,13 +115,13 @@ struct uac2_input_terminal_descriptor {
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bTerminalID;
- __le16 wTerminalType;
+ __u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bCSourceID;
__u8 bNrChannels;
- __le32 bmChannelConfig;
+ __u32 bmChannelConfig;
__u8 iChannelNames;
- __le16 bmControls;
+ __u16 bmControls;
__u8 iTerminal;
} __attribute__((packed));
@@ -132,11 +132,11 @@ struct uac2_output_terminal_descriptor {
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bTerminalID;
- __le16 wTerminalType;
+ __u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bSourceID;
__u8 bCSourceID;
- __le16 bmControls;
+ __u16 bmControls;
__u8 iTerminal;
} __attribute__((packed));
@@ -164,9 +164,9 @@ struct uac2_as_header_descriptor {
__u8 bTerminalLink;
__u8 bmControls;
__u8 bFormatType;
- __le32 bmFormats;
+ __u32 bmFormats;
__u8 bNrChannels;
- __le32 bmChannelConfig;
+ __u32 bmChannelConfig;
__u8 iChannelNames;
} __attribute__((packed));
@@ -188,13 +188,6 @@ struct uac2_iso_endpoint_descriptor {
#define UAC2_CONTROL_DATA_OVERRUN (3 << 2)
#define UAC2_CONTROL_DATA_UNDERRUN (3 << 4)
-/* 5.2.5.4.2 Connector Control Parameter Block */
-struct uac2_connectors_ctl_blk {
- __u8 bNrChannels;
- __le32 bmChannelConfig;
- __u8 iChannelNames;
-} __attribute__((packed));
-
/* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)
diff --git a/include/linux/usb/audio-v3.h b/include/linux/usb/audio-v3.h
deleted file mode 100644
index 6b708434b7f9..000000000000
--- a/include/linux/usb/audio-v3.h
+++ /dev/null
@@ -1,454 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2017 Ruslan Bilovol <ruslan.bilovol@gmail.com>
- *
- * This file holds USB constants and structures defined
- * by the USB DEVICE CLASS DEFINITION FOR AUDIO DEVICES Release 3.0.
- */
-
-#ifndef __LINUX_USB_AUDIO_V3_H
-#define __LINUX_USB_AUDIO_V3_H
-
-#include <linux/types.h>
-
-/*
- * v1.0, v2.0 and v3.0 of this standard have many things in common. For the rest
- * of the definitions, please refer to audio.h and audio-v2.h
- */
-
-/* All High Capability descriptors have these 2 fields at the beginning */
-struct uac3_hc_descriptor_header {
- __le16 wLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __le16 wDescriptorID;
-} __attribute__ ((packed));
-
-/* 4.3.1 CLUSTER DESCRIPTOR HEADER */
-struct uac3_cluster_header_descriptor {
- __le16 wLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __le16 wDescriptorID;
- __u8 bNrChannels;
-} __attribute__ ((packed));
-
-/* 4.3.2.1 SEGMENTS */
-struct uac3_cluster_segment_descriptor {
- __le16 wLength;
- __u8 bSegmentType;
- /* __u8[0]; segment-specific data */
-} __attribute__ ((packed));
-
-/* 4.3.2.1.1 END SEGMENT */
-struct uac3_cluster_end_segment_descriptor {
- __le16 wLength;
- __u8 bSegmentType; /* Constant END_SEGMENT */
-} __attribute__ ((packed));
-
-/* 4.3.2.1.3.1 INFORMATION SEGMENT */
-struct uac3_cluster_information_segment_descriptor {
- __le16 wLength;
- __u8 bSegmentType;
- __u8 bChPurpose;
- __u8 bChRelationship;
- __u8 bChGroupID;
-} __attribute__ ((packed));
-
-/* 4.5.2 CLASS-SPECIFIC AC INTERFACE DESCRIPTOR */
-struct uac3_ac_header_descriptor {
- __u8 bLength; /* 10 */
- __u8 bDescriptorType; /* CS_INTERFACE descriptor type */
- __u8 bDescriptorSubtype; /* HEADER descriptor subtype */
- __u8 bCategory;
-
- /* includes Clock Source, Unit, Terminal, and Power Domain desc. */
- __le16 wTotalLength;
-
- __le32 bmControls;
-} __attribute__ ((packed));
-
-/* 4.5.2.1 INPUT TERMINAL DESCRIPTOR */
-struct uac3_input_terminal_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bTerminalID;
- __le16 wTerminalType;
- __u8 bAssocTerminal;
- __u8 bCSourceID;
- __le32 bmControls;
- __le16 wClusterDescrID;
- __le16 wExTerminalDescrID;
- __le16 wConnectorsDescrID;
- __le16 wTerminalDescrStr;
-} __attribute__((packed));
-
-/* 4.5.2.2 OUTPUT TERMINAL DESCRIPTOR */
-struct uac3_output_terminal_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bTerminalID;
- __le16 wTerminalType;
- __u8 bAssocTerminal;
- __u8 bSourceID;
- __u8 bCSourceID;
- __le32 bmControls;
- __le16 wExTerminalDescrID;
- __le16 wConnectorsDescrID;
- __le16 wTerminalDescrStr;
-} __attribute__((packed));
-
-/* 4.5.2.7 FEATURE UNIT DESCRIPTOR */
-struct uac3_feature_unit_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bUnitID;
- __u8 bSourceID;
- /* bmaControls is actually u32,
- * but u8 is needed for the hybrid parser */
- __u8 bmaControls[0]; /* variable length */
- /* wFeatureDescrStr omitted */
-} __attribute__((packed));
-
-#define UAC3_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 4)
-
-/* As above, but more useful for defining your own descriptors */
-#define DECLARE_UAC3_FEATURE_UNIT_DESCRIPTOR(ch) \
-struct uac3_feature_unit_descriptor_##ch { \
- __u8 bLength; \
- __u8 bDescriptorType; \
- __u8 bDescriptorSubtype; \
- __u8 bUnitID; \
- __u8 bSourceID; \
- __le32 bmaControls[ch + 1]; \
- __le16 wFeatureDescrStr; \
-} __attribute__ ((packed))
-
-/* 4.5.2.12 CLOCK SOURCE DESCRIPTOR */
-struct uac3_clock_source_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bClockID;
- __u8 bmAttributes;
- __le32 bmControls;
- __u8 bReferenceTerminal;
- __le16 wClockSourceStr;
-} __attribute__((packed));
-
-/* bmAttribute fields */
-#define UAC3_CLOCK_SOURCE_TYPE_EXT 0x0
-#define UAC3_CLOCK_SOURCE_TYPE_INT 0x1
-#define UAC3_CLOCK_SOURCE_ASYNC (0 << 2)
-#define UAC3_CLOCK_SOURCE_SYNCED_TO_SOF (1 << 1)
-
-/* 4.5.2.13 CLOCK SELECTOR DESCRIPTOR */
-struct uac3_clock_selector_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bClockID;
- __u8 bNrInPins;
- __u8 baCSourceID[];
- /* bmControls and wCSelectorDescrStr omitted */
-} __attribute__((packed));
-
-/* 4.5.2.14 CLOCK MULTIPLIER DESCRIPTOR */
-struct uac3_clock_multiplier_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bClockID;
- __u8 bCSourceID;
- __le32 bmControls;
- __le16 wCMultiplierDescrStr;
-} __attribute__((packed));
-
-/* 4.5.2.15 POWER DOMAIN DESCRIPTOR */
-struct uac3_power_domain_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bPowerDomainID;
- __le16 waRecoveryTime1;
- __le16 waRecoveryTime2;
- __u8 bNrEntities;
- __u8 baEntityID[];
- /* wPDomainDescrStr omitted */
-} __attribute__((packed));
-
-/* As above, but more useful for defining your own descriptors */
-#define DECLARE_UAC3_POWER_DOMAIN_DESCRIPTOR(n) \
-struct uac3_power_domain_descriptor_##n { \
- __u8 bLength; \
- __u8 bDescriptorType; \
- __u8 bDescriptorSubtype; \
- __u8 bPowerDomainID; \
- __le16 waRecoveryTime1; \
- __le16 waRecoveryTime2; \
- __u8 bNrEntities; \
- __u8 baEntityID[n]; \
- __le16 wPDomainDescrStr; \
-} __attribute__ ((packed))
-
-/* 4.7.2 CLASS-SPECIFIC AS INTERFACE DESCRIPTOR */
-struct uac3_as_header_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __u8 bTerminalLink;
- __le32 bmControls;
- __le16 wClusterDescrID;
- __le64 bmFormats;
- __u8 bSubslotSize;
- __u8 bBitResolution;
- __le16 bmAuxProtocols;
- __u8 bControlSize;
-} __attribute__((packed));
-
-#define UAC3_FORMAT_TYPE_I_RAW_DATA (1 << 6)
-
-/* 4.8.1.2 CLASS-SPECIFIC AS ISOCHRONOUS AUDIO DATA ENDPOINT DESCRIPTOR */
-struct uac3_iso_endpoint_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubtype;
- __le32 bmControls;
- __u8 bLockDelayUnits;
- __le16 wLockDelay;
-} __attribute__((packed));
-
-/* 5.2.1.6.1 INSERTION CONTROL PARAMETER BLOCK */
-struct uac3_insertion_ctl_blk {
- __u8 bSize;
- __u8 bmConInserted;
-} __attribute__ ((packed));
-
-/* 6.1 INTERRUPT DATA MESSAGE */
-struct uac3_interrupt_data_msg {
- __u8 bInfo;
- __u8 bSourceType;
- __le16 wValue;
- __le16 wIndex;
-} __attribute__((packed));
-
-/* A.2 AUDIO AUDIO FUNCTION SUBCLASS CODES */
-#define UAC3_FUNCTION_SUBCLASS_UNDEFINED 0x00
-#define UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 0x01
-/* BADD profiles */
-#define UAC3_FUNCTION_SUBCLASS_GENERIC_IO 0x20
-#define UAC3_FUNCTION_SUBCLASS_HEADPHONE 0x21
-#define UAC3_FUNCTION_SUBCLASS_SPEAKER 0x22
-#define UAC3_FUNCTION_SUBCLASS_MICROPHONE 0x23
-#define UAC3_FUNCTION_SUBCLASS_HEADSET 0x24
-#define UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER 0x25
-#define UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE 0x26
-
-/* A.7 AUDIO FUNCTION CATEGORY CODES */
-#define UAC3_FUNCTION_SUBCLASS_UNDEFINED 0x00
-#define UAC3_FUNCTION_DESKTOP_SPEAKER 0x01
-#define UAC3_FUNCTION_HOME_THEATER 0x02
-#define UAC3_FUNCTION_MICROPHONE 0x03
-#define UAC3_FUNCTION_HEADSET 0x04
-#define UAC3_FUNCTION_TELEPHONE 0x05
-#define UAC3_FUNCTION_CONVERTER 0x06
-#define UAC3_FUNCTION_SOUND_RECORDER 0x07
-#define UAC3_FUNCTION_IO_BOX 0x08
-#define UAC3_FUNCTION_MUSICAL_INSTRUMENT 0x09
-#define UAC3_FUNCTION_PRO_AUDIO 0x0a
-#define UAC3_FUNCTION_AUDIO_VIDEO 0x0b
-#define UAC3_FUNCTION_CONTROL_PANEL 0x0c
-#define UAC3_FUNCTION_HEADPHONE 0x0d
-#define UAC3_FUNCTION_GENERIC_SPEAKER 0x0e
-#define UAC3_FUNCTION_HEADSET_ADAPTER 0x0f
-#define UAC3_FUNCTION_SPEAKERPHONE 0x10
-#define UAC3_FUNCTION_OTHER 0xff
-
-/* A.8 AUDIO CLASS-SPECIFIC DESCRIPTOR TYPES */
-#define UAC3_CS_UNDEFINED 0x20
-#define UAC3_CS_DEVICE 0x21
-#define UAC3_CS_CONFIGURATION 0x22
-#define UAC3_CS_STRING 0x23
-#define UAC3_CS_INTERFACE 0x24
-#define UAC3_CS_ENDPOINT 0x25
-#define UAC3_CS_CLUSTER 0x26
-
-/* A.10 CLUSTER DESCRIPTOR SEGMENT TYPES */
-#define UAC3_SEGMENT_UNDEFINED 0x00
-#define UAC3_CLUSTER_DESCRIPTION 0x01
-#define UAC3_CLUSTER_VENDOR_DEFINED 0x1F
-#define UAC3_CHANNEL_INFORMATION 0x20
-#define UAC3_CHANNEL_AMBISONIC 0x21
-#define UAC3_CHANNEL_DESCRIPTION 0x22
-#define UAC3_CHANNEL_VENDOR_DEFINED 0xFE
-#define UAC3_END_SEGMENT 0xFF
-
-/* A.11 CHANNEL PURPOSE DEFINITIONS */
-#define UAC3_PURPOSE_UNDEFINED 0x00
-#define UAC3_PURPOSE_GENERIC_AUDIO 0x01
-#define UAC3_PURPOSE_VOICE 0x02
-#define UAC3_PURPOSE_SPEECH 0x03
-#define UAC3_PURPOSE_AMBIENT 0x04
-#define UAC3_PURPOSE_REFERENCE 0x05
-#define UAC3_PURPOSE_ULTRASONIC 0x06
-#define UAC3_PURPOSE_VIBROKINETIC 0x07
-#define UAC3_PURPOSE_NON_AUDIO 0xFF
-
-/* A.12 CHANNEL RELATIONSHIP DEFINITIONS */
-#define UAC3_CH_RELATIONSHIP_UNDEFINED 0x00
-#define UAC3_CH_MONO 0x01
-#define UAC3_CH_LEFT 0x02
-#define UAC3_CH_RIGHT 0x03
-#define UAC3_CH_ARRAY 0x04
-#define UAC3_CH_PATTERN_X 0x20
-#define UAC3_CH_PATTERN_Y 0x21
-#define UAC3_CH_PATTERN_A 0x22
-#define UAC3_CH_PATTERN_B 0x23
-#define UAC3_CH_PATTERN_M 0x24
-#define UAC3_CH_PATTERN_S 0x25
-#define UAC3_CH_FRONT_LEFT 0x80
-#define UAC3_CH_FRONT_RIGHT 0x81
-#define UAC3_CH_FRONT_CENTER 0x82
-#define UAC3_CH_FRONT_LEFT_OF_CENTER 0x83
-#define UAC3_CH_FRONT_RIGHT_OF_CENTER 0x84
-#define UAC3_CH_FRONT_WIDE_LEFT 0x85
-#define UAC3_CH_FRONT_WIDE_RIGHT 0x86
-#define UAC3_CH_SIDE_LEFT 0x87
-#define UAC3_CH_SIDE_RIGHT 0x88
-#define UAC3_CH_SURROUND_ARRAY_LEFT 0x89
-#define UAC3_CH_SURROUND_ARRAY_RIGHT 0x8A
-#define UAC3_CH_BACK_LEFT 0x8B
-#define UAC3_CH_BACK_RIGHT 0x8C
-#define UAC3_CH_BACK_CENTER 0x8D
-#define UAC3_CH_BACK_LEFT_OF_CENTER 0x8E
-#define UAC3_CH_BACK_RIGHT_OF_CENTER 0x8F
-#define UAC3_CH_BACK_WIDE_LEFT 0x90
-#define UAC3_CH_BACK_WIDE_RIGHT 0x91
-#define UAC3_CH_TOP_CENTER 0x92
-#define UAC3_CH_TOP_FRONT_LEFT 0x93
-#define UAC3_CH_TOP_FRONT_RIGHT 0x94
-#define UAC3_CH_TOP_FRONT_CENTER 0x95
-#define UAC3_CH_TOP_FRONT_LOC 0x96
-#define UAC3_CH_TOP_FRONT_ROC 0x97
-#define UAC3_CH_TOP_FRONT_WIDE_LEFT 0x98
-#define UAC3_CH_TOP_FRONT_WIDE_RIGHT 0x99
-#define UAC3_CH_TOP_SIDE_LEFT 0x9A
-#define UAC3_CH_TOP_SIDE_RIGHT 0x9B
-#define UAC3_CH_TOP_SURR_ARRAY_LEFT 0x9C
-#define UAC3_CH_TOP_SURR_ARRAY_RIGHT 0x9D
-#define UAC3_CH_TOP_BACK_LEFT 0x9E
-#define UAC3_CH_TOP_BACK_RIGHT 0x9F
-#define UAC3_CH_TOP_BACK_CENTER 0xA0
-#define UAC3_CH_TOP_BACK_LOC 0xA1
-#define UAC3_CH_TOP_BACK_ROC 0xA2
-#define UAC3_CH_TOP_BACK_WIDE_LEFT 0xA3
-#define UAC3_CH_TOP_BACK_WIDE_RIGHT 0xA4
-#define UAC3_CH_BOTTOM_CENTER 0xA5
-#define UAC3_CH_BOTTOM_FRONT_LEFT 0xA6
-#define UAC3_CH_BOTTOM_FRONT_RIGHT 0xA7
-#define UAC3_CH_BOTTOM_FRONT_CENTER 0xA8
-#define UAC3_CH_BOTTOM_FRONT_LOC 0xA9
-#define UAC3_CH_BOTTOM_FRONT_ROC 0xAA
-#define UAC3_CH_BOTTOM_FRONT_WIDE_LEFT 0xAB
-#define UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT 0xAC
-#define UAC3_CH_BOTTOM_SIDE_LEFT 0xAD
-#define UAC3_CH_BOTTOM_SIDE_RIGHT 0xAE
-#define UAC3_CH_BOTTOM_SURR_ARRAY_LEFT 0xAF
-#define UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT 0xB0
-#define UAC3_CH_BOTTOM_BACK_LEFT 0xB1
-#define UAC3_CH_BOTTOM_BACK_RIGHT 0xB2
-#define UAC3_CH_BOTTOM_BACK_CENTER 0xB3
-#define UAC3_CH_BOTTOM_BACK_LOC 0xB4
-#define UAC3_CH_BOTTOM_BACK_ROC 0xB5
-#define UAC3_CH_BOTTOM_BACK_WIDE_LEFT 0xB6
-#define UAC3_CH_BOTTOM_BACK_WIDE_RIGHT 0xB7
-#define UAC3_CH_LOW_FREQUENCY_EFFECTS 0xB8
-#define UAC3_CH_LFE_LEFT 0xB9
-#define UAC3_CH_LFE_RIGHT 0xBA
-#define UAC3_CH_HEADPHONE_LEFT 0xBB
-#define UAC3_CH_HEADPHONE_RIGHT 0xBC
-
-/* A.15 AUDIO CLASS-SPECIFIC AC INTERFACE DESCRIPTOR SUBTYPES */
-/* see audio.h for the rest, which is identical to v1 */
-#define UAC3_EXTENDED_TERMINAL 0x04
-#define UAC3_MIXER_UNIT 0x05
-#define UAC3_SELECTOR_UNIT 0x06
-#define UAC3_FEATURE_UNIT 0x07
-#define UAC3_EFFECT_UNIT 0x08
-#define UAC3_PROCESSING_UNIT 0x09
-#define UAC3_EXTENSION_UNIT 0x0a
-#define UAC3_CLOCK_SOURCE 0x0b
-#define UAC3_CLOCK_SELECTOR 0x0c
-#define UAC3_CLOCK_MULTIPLIER 0x0d
-#define UAC3_SAMPLE_RATE_CONVERTER 0x0e
-#define UAC3_CONNECTORS 0x0f
-#define UAC3_POWER_DOMAIN 0x10
-
-/* A.20 PROCESSING UNIT PROCESS TYPES */
-#define UAC3_PROCESS_UNDEFINED 0x00
-#define UAC3_PROCESS_UP_DOWNMIX 0x01
-#define UAC3_PROCESS_STEREO_EXTENDER 0x02
-#define UAC3_PROCESS_MULTI_FUNCTION 0x03
-
-/* A.22 AUDIO CLASS-SPECIFIC REQUEST CODES */
-/* see audio-v2.h for the rest, which is identical to v2 */
-#define UAC3_CS_REQ_INTEN 0x04
-#define UAC3_CS_REQ_STRING 0x05
-#define UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR 0x06
-
-/* A.23.1 AUDIOCONTROL INTERFACE CONTROL SELECTORS */
-#define UAC3_AC_CONTROL_UNDEFINED 0x00
-#define UAC3_AC_ACTIVE_INTERFACE_CONTROL 0x01
-#define UAC3_AC_POWER_DOMAIN_CONTROL 0x02
-
-/* A.23.5 TERMINAL CONTROL SELECTORS */
-#define UAC3_TE_UNDEFINED 0x00
-#define UAC3_TE_INSERTION 0x01
-#define UAC3_TE_OVERLOAD 0x02
-#define UAC3_TE_UNDERFLOW 0x03
-#define UAC3_TE_OVERFLOW 0x04
-#define UAC3_TE_LATENCY 0x05
-
-/* A.23.10 PROCESSING UNITS CONTROL SELECTROS */
-
-/* Up/Down Mixer */
-#define UAC3_UD_MODE_SELECT 0x01
-
-/* Stereo Extender */
-#define UAC3_EXT_WIDTH_CONTROL 0x01
-
-
-/* BADD predefined Unit/Terminal values */
-#define UAC3_BADD_IT_ID1 1 /* Input Terminal ID1: bTerminalID = 1 */
-#define UAC3_BADD_FU_ID2 2 /* Feature Unit ID2: bUnitID = 2 */
-#define UAC3_BADD_OT_ID3 3 /* Output Terminal ID3: bTerminalID = 3 */
-#define UAC3_BADD_IT_ID4 4 /* Input Terminal ID4: bTerminalID = 4 */
-#define UAC3_BADD_FU_ID5 5 /* Feature Unit ID5: bUnitID = 5 */
-#define UAC3_BADD_OT_ID6 6 /* Output Terminal ID6: bTerminalID = 6 */
-#define UAC3_BADD_FU_ID7 7 /* Feature Unit ID7: bUnitID = 7 */
-#define UAC3_BADD_MU_ID8 8 /* Mixer Unit ID8: bUnitID = 8 */
-#define UAC3_BADD_CS_ID9 9 /* Clock Source Entity ID9: bClockID = 9 */
-#define UAC3_BADD_PD_ID10 10 /* Power Domain ID10: bPowerDomainID = 10 */
-#define UAC3_BADD_PD_ID11 11 /* Power Domain ID11: bPowerDomainID = 11 */
-
-/* BADD wMaxPacketSize of AS endpoints */
-#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16 0x0060
-#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16 0x0062
-#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24 0x0090
-#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24 0x0093
-#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16 0x00C0
-#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16 0x00C4
-#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24 0x0120
-#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24 0x0126
-
-/* BADD sample rate is always fixed to 48kHz */
-#define UAC3_BADD_SAMPLING_RATE 48000
-
-/* BADD power domains recovery times in 50us increments */
-#define UAC3_BADD_PD_RECOVER_D1D0 0x0258 /* 30ms */
-#define UAC3_BADD_PD_RECOVER_D2D0 0x1770 /* 300ms */
-
-#endif /* __LINUX_USB_AUDIO_V3_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 36a5934cf4b1..f1f0c148cc9d 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -118,6 +118,8 @@ struct snd_card {
int user_ctl_count; /* count of all user controls */
struct list_head controls; /* all controls for this card */
struct list_head ctl_files; /* active control files */
+ struct mutex user_ctl_lock; /* protects user controls against
+ concurrent access */
struct snd_info_entry *proc_root; /* root for soundcard specific files */
struct snd_info_entry *proc_id; /* the card id */
@@ -133,14 +135,14 @@ struct snd_card {
struct device card_dev; /* cardX object for sysfs */
const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
bool registered; /* card_dev is registered? */
- wait_queue_head_t remove_sleep;
#ifdef CONFIG_PM
unsigned int power_state; /* power state */
+ struct mutex power_lock; /* power lock */
wait_queue_head_t power_sleep;
#endif
-#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
struct snd_mixer_oss *mixer_oss;
int mixer_oss_change_count;
#endif
@@ -149,6 +151,16 @@ struct snd_card {
#define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
#ifdef CONFIG_PM
+static inline void snd_power_lock(struct snd_card *card)
+{
+ mutex_lock(&card->power_lock);
+}
+
+static inline void snd_power_unlock(struct snd_card *card)
+{
+ mutex_unlock(&card->power_lock);
+}
+
static inline unsigned int snd_power_get_state(struct snd_card *card)
{
return card->power_state;
@@ -165,6 +177,8 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state);
#else /* ! CONFIG_PM */
+#define snd_power_lock(card) do { (void)(card); } while (0)
+#define snd_power_unlock(card) do { (void)(card); } while (0)
static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
#define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
@@ -229,7 +243,7 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
extern struct snd_card *snd_cards[SNDRV_CARDS];
int snd_card_locked(int card);
-#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
#define SND_MIXER_OSS_NOTIFY_REGISTER 0
#define SND_MIXER_OSS_NOTIFY_DISCONNECT 1
#define SND_MIXER_OSS_NOTIFY_FREE 2
@@ -241,7 +255,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
struct snd_card **card_ret);
int snd_card_disconnect(struct snd_card *card);
-void snd_card_disconnect_sync(struct snd_card *card);
int snd_card_free(struct snd_card *card);
int snd_card_free_when_closed(struct snd_card *card);
void snd_card_set_id(struct snd_card *card, const char *id);
@@ -381,7 +394,7 @@ static inline void snd_printdd(const char *format, ...) {}
#define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
/* for easier backward-porting */
-#if IS_ENABLED(CONFIG_GAMEPORT)
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
#define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
#define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
#define gameport_get_port_data(gp) (gp)->port_data
diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h
index 19a0cb561ffc..a0a40b74bf13 100644
--- a/include/sound/emux_synth.h
+++ b/include/sound/emux_synth.h
@@ -25,7 +25,9 @@
#include <sound/seq_device.h>
#include <sound/soundfont.h>
#include <sound/seq_midi_emul.h>
+#ifdef CONFIG_SND_SEQUENCER_OSS
#include <sound/seq_oss.h>
+#endif
#include <sound/emux_legacy.h>
#include <sound/seq_virmidi.h>
@@ -64,7 +66,7 @@ struct snd_emux_operators {
const void __user *data, long count);
void (*sysex)(struct snd_emux *emu, char *buf, int len, int parsed,
struct snd_midi_channel_set *chset);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
int (*oss_ioctl)(struct snd_emux *emu, int cmd, int p1, int p2);
#endif
};
@@ -127,7 +129,7 @@ struct snd_emux {
struct snd_info_entry *proc;
#endif
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
struct snd_seq_device *oss_synth;
#endif
};
@@ -148,7 +150,7 @@ struct snd_emux_port {
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
struct snd_emux_effect_table *effect;
#endif
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
struct snd_seq_oss_arg *oss_arg;
#endif
};
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
index 930da10fb65b..13cb0b430a1b 100644
--- a/include/sound/mixer_oss.h
+++ b/include/sound/mixer_oss.h
@@ -22,7 +22,7 @@
*
*/
-#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
#define SNDRV_OSS_MAX_MIXERS 32
diff --git a/include/sound/opl3.h b/include/sound/opl3.h
index a4a593590cff..6ba670707831 100644
--- a/include/sound/opl3.h
+++ b/include/sound/opl3.h
@@ -55,8 +55,10 @@
#include <sound/hwdep.h>
#include <sound/timer.h>
#include <sound/seq_midi_emul.h>
+#ifdef CONFIG_SND_SEQUENCER_OSS
#include <sound/seq_oss.h>
#include <sound/seq_oss_legacy.h>
+#endif
#include <sound/seq_device.h>
#include <sound/asound_fm.h>
@@ -319,7 +321,7 @@ struct snd_opl3 {
unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
unsigned char rhythm; /* percussion mode flag */
unsigned char max_voices; /* max number of voices */
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
#define SNDRV_OPL3_MODE_SYNTH 0 /* OSS - voices allocated by application */
#define SNDRV_OPL3_MODE_SEQ 1 /* ALSA - driver handles voice allocation */
int synth_mode; /* synth mode */
@@ -328,7 +330,7 @@ struct snd_opl3 {
struct snd_seq_device *seq_dev; /* sequencer device */
struct snd_midi_channel_set * chset;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
struct snd_seq_device *oss_seq_dev; /* OSS sequencer device */
struct snd_midi_channel_set * oss_chset;
#endif
@@ -372,7 +374,7 @@ int snd_opl3_release(struct snd_hwdep * hw, struct file *file);
void snd_opl3_reset(struct snd_opl3 * opl3);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count,
loff_t *offset);
int snd_opl3_load_patch(struct snd_opl3 *opl3,
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index cebbe0cfd80c..361749e60799 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -34,7 +34,7 @@
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
#define snd_pcm_chip(pcm) ((pcm)->private_data)
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
#include <sound/pcm_oss.h>
#endif
@@ -78,13 +78,11 @@ struct snd_pcm_ops {
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
- int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
- unsigned long pos, unsigned long bytes);
- int (*copy_user)(struct snd_pcm_substream *substream, int channel,
- unsigned long pos, void __user *buf,
- unsigned long bytes);
- int (*copy_kernel)(struct snd_pcm_substream *substream, int channel,
- unsigned long pos, void *buf, unsigned long bytes);
+ int (*copy)(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos,
+ void __user *buf, snd_pcm_uframes_t count);
+ int (*silence)(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
struct page *(*page)(struct snd_pcm_substream *substream,
unsigned long offset);
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
@@ -102,9 +100,9 @@ struct snd_pcm_ops {
#endif
#define SNDRV_PCM_IOCTL1_RESET 0
-/* 1 is absent slot. */
+#define SNDRV_PCM_IOCTL1_INFO 1
#define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
-/* 3 is absent slot. */
+#define SNDRV_PCM_IOCTL1_GSTATE 3
#define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
#define SNDRV_PCM_TRIGGER_STOP 0
@@ -169,10 +167,6 @@ struct snd_pcm_ops {
#define SNDRV_PCM_FMTBIT_IMA_ADPCM _SNDRV_PCM_FMTBIT(IMA_ADPCM)
#define SNDRV_PCM_FMTBIT_MPEG _SNDRV_PCM_FMTBIT(MPEG)
#define SNDRV_PCM_FMTBIT_GSM _SNDRV_PCM_FMTBIT(GSM)
-#define SNDRV_PCM_FMTBIT_S20_LE _SNDRV_PCM_FMTBIT(S20_LE)
-#define SNDRV_PCM_FMTBIT_U20_LE _SNDRV_PCM_FMTBIT(U20_LE)
-#define SNDRV_PCM_FMTBIT_S20_BE _SNDRV_PCM_FMTBIT(S20_BE)
-#define SNDRV_PCM_FMTBIT_U20_BE _SNDRV_PCM_FMTBIT(U20_BE)
#define SNDRV_PCM_FMTBIT_SPECIAL _SNDRV_PCM_FMTBIT(SPECIAL)
#define SNDRV_PCM_FMTBIT_S24_3LE _SNDRV_PCM_FMTBIT(S24_3LE)
#define SNDRV_PCM_FMTBIT_U24_3LE _SNDRV_PCM_FMTBIT(U24_3LE)
@@ -206,8 +200,6 @@ struct snd_pcm_ops {
#define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_LE
#define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_LE
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
-#define SNDRV_PCM_FMTBIT_S20 SNDRV_PCM_FMTBIT_S20_LE
-#define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_LE
#endif
#ifdef SNDRV_BIG_ENDIAN
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_BE
@@ -219,14 +211,11 @@ struct snd_pcm_ops {
#define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_BE
#define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_BE
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE
-#define SNDRV_PCM_FMTBIT_S20 SNDRV_PCM_FMTBIT_S20_BE
-#define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_BE
#endif
struct snd_pcm_file {
struct snd_pcm_substream *substream;
int no_compat_mmap;
- unsigned int user_pversion; /* supported protocol version */
};
struct snd_pcm_hw_rule;
@@ -429,7 +418,7 @@ struct snd_pcm_runtime {
struct snd_pcm_audio_tstamp_report audio_tstamp_report;
struct timespec driver_tstamp;
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
struct snd_pcm_oss_runtime oss;
#endif
@@ -462,7 +451,6 @@ struct snd_pcm_substream {
/* -- timer section -- */
struct snd_timer *timer; /* timer */
unsigned timer_running: 1; /* time is running */
- long wait_time; /* time in ms for R/W to wait for avail */
/* -- next substream -- */
struct snd_pcm_substream *next;
/* -- linked substreams -- */
@@ -476,7 +464,7 @@ struct snd_pcm_substream {
unsigned int f_flags;
void (*pcm_release)(struct snd_pcm_substream *);
struct pid *pid;
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
struct snd_pcm_oss_substream oss;
#endif
@@ -506,7 +494,7 @@ struct snd_pcm_str {
unsigned int substream_count;
unsigned int substream_opened;
struct snd_pcm_substream *substream;
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
struct snd_pcm_oss_stream oss;
#endif
@@ -538,11 +526,18 @@ struct snd_pcm {
void (*private_free) (struct snd_pcm *pcm);
bool internal; /* pcm is for internal use only */
bool nonatomic; /* whole PCM operations are in non-atomic context */
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
struct snd_pcm_oss oss;
#endif
};
+struct snd_pcm_notify {
+ int (*n_register) (struct snd_pcm * pcm);
+ int (*n_disconnect) (struct snd_pcm * pcm);
+ int (*n_unregister) (struct snd_pcm * pcm);
+ struct list_head list;
+};
+
/*
* Registering
*/
@@ -557,15 +552,7 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
struct snd_pcm **rpcm);
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
-struct snd_pcm_notify {
- int (*n_register) (struct snd_pcm * pcm);
- int (*n_disconnect) (struct snd_pcm * pcm);
- int (*n_unregister) (struct snd_pcm * pcm);
- struct list_head list;
-};
int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
-#endif
/*
* Native I/O
@@ -981,6 +968,12 @@ static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p
}
int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
+void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b,
+ unsigned int k, struct snd_interval *c);
+void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+ const struct snd_interval *b, struct snd_interval *c);
int snd_interval_list(struct snd_interval *i, unsigned int count,
const unsigned int *list, unsigned int mask);
int snd_interval_ranges(struct snd_interval *i, unsigned int count,
@@ -991,9 +984,15 @@ int snd_interval_ratnum(struct snd_interval *i,
void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var);
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
+int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
+
+int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
+ u_int32_t mask);
int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int64_t mask);
int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
@@ -1055,7 +1054,7 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
int snd_pcm_format_linear(snd_pcm_format_t format);
int snd_pcm_format_little_endian(snd_pcm_format_t format);
int snd_pcm_format_big_endian(snd_pcm_format_t format);
-#if 0 /* just for kernel-doc */
+#if 0 /* just for DocBook */
/**
* snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
* @format: the format to check
@@ -1081,66 +1080,22 @@ void snd_pcm_set_ops(struct snd_pcm * pcm, int direction,
void snd_pcm_set_sync(struct snd_pcm_substream *substream);
int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
+int snd_pcm_update_state(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime);
+int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr);
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
-snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
- void *buf, bool interleaved,
- snd_pcm_uframes_t frames, bool in_kernel);
-
-static inline snd_pcm_sframes_t
-snd_pcm_lib_write(struct snd_pcm_substream *substream,
- const void __user *buf, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, (void __force *)buf, true, frames, false);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_lib_read(struct snd_pcm_substream *substream,
- void __user *buf, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, (void __force *)buf, true, frames, false);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_lib_writev(struct snd_pcm_substream *substream,
- void __user **bufs, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_lib_readv(struct snd_pcm_substream *substream,
- void __user **bufs, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_kernel_write(struct snd_pcm_substream *substream,
- const void *buf, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, true);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_kernel_read(struct snd_pcm_substream *substream,
- void *buf, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, buf, true, frames, true);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_kernel_writev(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
-}
-
-static inline snd_pcm_sframes_t
-snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames)
-{
- return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
-}
+snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf,
+ snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ void __user *buf, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames);
+
+extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
@@ -1175,6 +1130,20 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea
}
}
+/*
+ * Timer interface
+ */
+
+#ifdef CONFIG_SND_PCM_TIMER
+void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
+void snd_pcm_timer_init(struct snd_pcm_substream *substream);
+void snd_pcm_timer_done(struct snd_pcm_substream *substream);
+#else
+static inline void
+snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
+static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
+static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
+#endif
/**
* snd_pcm_gettime - Fill the timespec depending on the timestamp mode
* @runtime: PCM runtime instance
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 3b5a061132b6..492a3ca7f17b 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -30,7 +30,7 @@
#include <linux/workqueue.h>
#include <linux/device.h>
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
#include <sound/seq_device.h>
#endif
@@ -144,7 +144,7 @@ struct snd_rawmidi {
struct snd_info_entry *proc_entry;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
struct snd_seq_device *seq_dev;
#endif
};
@@ -171,7 +171,6 @@ int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
unsigned char *buffer, int count);
int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
int count);
-int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream);
/* main midi functions */
diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h
index 2f135bccf457..e40f43e6fc7b 100644
--- a/include/sound/seq_midi_event.h
+++ b/include/sound/seq_midi_event.h
@@ -43,8 +43,10 @@ void snd_midi_event_free(struct snd_midi_event *dev);
void snd_midi_event_reset_encode(struct snd_midi_event *dev);
void snd_midi_event_reset_decode(struct snd_midi_event *dev);
void snd_midi_event_no_status(struct snd_midi_event *dev, int on);
-bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c,
- struct snd_seq_event *ev);
+/* encode from byte stream - return number of written bytes if success */
+long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev);
+int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, struct snd_seq_event *ev);
/* decode from event to bytes - return number of written bytes if success */
long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count,
struct snd_seq_event *ev);
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index 796ce7772213..695257ae64ac 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -36,12 +36,11 @@ struct snd_virmidi {
int seq_mode;
int client;
int port;
- bool trigger;
+ unsigned int trigger: 1;
struct snd_midi_event *parser;
struct snd_seq_event event;
struct snd_virmidi_dev *rdev;
struct snd_rawmidi_substream *substream;
- struct work_struct output_work;
};
#define SNDRV_VIRMIDI_SUBSCRIBE (1<<0)
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index d970879944fc..58acd00cae19 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -102,8 +102,6 @@ struct snd_compr_stream;
SNDRV_PCM_FMTBIT_S16_BE |\
SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S20_3BE |\
- SNDRV_PCM_FMTBIT_S20_LE |\
- SNDRV_PCM_FMTBIT_S20_BE |\
SNDRV_PCM_FMTBIT_S24_3LE |\
SNDRV_PCM_FMTBIT_S24_3BE |\
SNDRV_PCM_FMTBIT_S32_LE |\
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index 77b0748b71e3..19f9dc2c06f6 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -26,7 +26,6 @@
/* bInterfaceProtocol values to denote the version of the standard used */
#define UAC_VERSION_1 0x00
#define UAC_VERSION_2 0x20
-#define UAC_VERSION_3 0x30
/* A.2 Audio Interface Subclass Codes */
#define USB_SUBCLASS_AUDIOCONTROL 0x01
@@ -229,14 +228,6 @@ struct uac1_output_terminal_descriptor {
#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306
#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307
-/* Terminals - 2.4 Bi-directional Terminal Types */
-#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400
-#define UAC_BIDIR_TERMINAL_HANDSET 0x401
-#define UAC_BIDIR_TERMINAL_HEADSET 0x402
-#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403
-#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404
-#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405
-
/* Set bControlSize = 2 as default setting */
#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2)
@@ -292,22 +283,9 @@ static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor
static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
- switch (protocol) {
- case UAC_VERSION_1:
- return &desc->baSourceID[desc->bNrInPins + 4];
- case UAC_VERSION_2:
- return &desc->baSourceID[desc->bNrInPins + 6];
- case UAC_VERSION_3:
- return &desc->baSourceID[desc->bNrInPins + 2];
- default:
- return NULL;
- }
-}
-
-static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc)
-{
- return (desc->baSourceID[desc->bNrInPins + 1] << 8) |
- desc->baSourceID[desc->bNrInPins];
+ return (protocol == UAC_VERSION_1) ?
+ &desc->baSourceID[desc->bNrInPins + 4] :
+ &desc->baSourceID[desc->bNrInPins + 6];
}
static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
@@ -355,7 +333,7 @@ struct uac_processing_unit_descriptor {
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bUnitID;
- __le16 wProcessType;
+ __u16 wProcessType;
__u8 bNrInPins;
__u8 baSourceID[];
} __attribute__ ((packed));
@@ -389,64 +367,33 @@ static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_
static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
int protocol)
{
- switch (protocol) {
- case UAC_VERSION_1:
- return desc->baSourceID[desc->bNrInPins + 4];
- case UAC_VERSION_2:
- return 2; /* in UAC2, this value is constant */
- case UAC_VERSION_3:
- return 4; /* in UAC3, this value is constant */
- default:
- return 1;
- }
+ return (protocol == UAC_VERSION_1) ?
+ desc->baSourceID[desc->bNrInPins + 4] :
+ 2; /* in UAC2, this value is constant */
}
static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
int protocol)
{
- switch (protocol) {
- case UAC_VERSION_1:
- return &desc->baSourceID[desc->bNrInPins + 5];
- case UAC_VERSION_2:
- return &desc->baSourceID[desc->bNrInPins + 6];
- case UAC_VERSION_3:
- return &desc->baSourceID[desc->bNrInPins + 2];
- default:
- return NULL;
- }
+ return (protocol == UAC_VERSION_1) ?
+ &desc->baSourceID[desc->bNrInPins + 5] :
+ &desc->baSourceID[desc->bNrInPins + 6];
}
static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
int protocol)
{
__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-
- switch (protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
- return *(uac_processing_unit_bmControls(desc, protocol)
- + control_size);
- case UAC_VERSION_3:
- return 0; /* UAC3 does not have this field */
- }
+ return *(uac_processing_unit_bmControls(desc, protocol)
+ + control_size);
}
static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
int protocol)
{
__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-
- switch (protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
- return uac_processing_unit_bmControls(desc, protocol)
+ return uac_processing_unit_bmControls(desc, protocol)
+ control_size + 1;
- case UAC_VERSION_3:
- return uac_processing_unit_bmControls(desc, protocol)
- + control_size;
- }
}
/* 4.5.2 Class-Specific AS Interface Descriptor */
@@ -544,8 +491,8 @@ struct uac_format_type_ii_ext_descriptor {
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bFormatType;
- __le16 wMaxBitRate;
- __le16 wSamplesPerFrame;
+ __u16 wMaxBitRate;
+ __u16 wSamplesPerFrame;
__u8 bHeaderLength;
__u8 bSideBandProtocol;
} __attribute__((packed));
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index ae51aaf11e10..67a839a12e3c 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image {
* *
*****************************************************************************/
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13)
typedef unsigned long snd_pcm_uframes_t;
typedef signed long snd_pcm_sframes_t;
@@ -213,11 +213,6 @@ typedef int __bitwise snd_pcm_format_t;
#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
-#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */
-/* gap in the numbering for a future standard linear format */
#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
@@ -252,8 +247,6 @@ typedef int __bitwise snd_pcm_format_t;
#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE
-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE
#endif
#ifdef SNDRV_BIG_ENDIAN
#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
@@ -265,8 +258,6 @@ typedef int __bitwise snd_pcm_format_t;
#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE
-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE
#endif
typedef int __bitwise snd_pcm_subformat_t;
@@ -277,7 +268,6 @@ typedef int __bitwise snd_pcm_subformat_t;
#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
-#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
@@ -573,7 +563,6 @@ enum {
#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index 733b6365dad6..78ed1ffbf786 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -271,7 +271,7 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new volume_control = {
+static struct snd_kcontrol_new volume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -314,7 +314,7 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new mute_control = {
+static struct snd_kcontrol_new mute_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -426,7 +426,7 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new drc_range_control = {
+static struct snd_kcontrol_new drc_range_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Range",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -466,7 +466,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new drc_switch_control = {
+static struct snd_kcontrol_new drc_switch_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Range Switch",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -524,7 +524,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new capture_source_control = {
+static struct snd_kcontrol_new capture_source_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* If we name this 'Input Source', it properly shows up in
* alsamixer as a selection, * but it's shown under the
@@ -586,7 +586,7 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new treble_control = {
+static struct snd_kcontrol_new treble_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Treble",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -637,7 +637,7 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new bass_control = {
+static struct snd_kcontrol_new bass_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Bass",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index 1eddf8fa188f..a0c4a5de809c 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -707,7 +707,7 @@ static int detect_choice_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new headphone_detect_choice = {
+static struct snd_kcontrol_new headphone_detect_choice = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Detect Autoswitch",
.info = control_info,
@@ -717,7 +717,7 @@ static const struct snd_kcontrol_new headphone_detect_choice = {
.private_value = 0,
};
-static const struct snd_kcontrol_new lineout_detect_choice = {
+static struct snd_kcontrol_new lineout_detect_choice = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line-Out Detect Autoswitch",
.info = control_info,
@@ -749,7 +749,7 @@ static int detected_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static const struct snd_kcontrol_new headphone_detected = {
+static struct snd_kcontrol_new headphone_detected = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Detected",
.info = control_info,
@@ -758,7 +758,7 @@ static const struct snd_kcontrol_new headphone_detected = {
.private_value = 0,
};
-static const struct snd_kcontrol_new lineout_detected = {
+static struct snd_kcontrol_new lineout_detected = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line-Out Detected",
.info = control_info,
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 6e937a8146a1..9749f9e8b45c 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -18,12 +18,8 @@ config SND_DMAENGINE_PCM
config SND_HWDEP
tristate
-config SND_SEQ_DEVICE
- tristate
-
config SND_RAWMIDI
tristate
- select SND_SEQ_DEVICE if SND_SEQUENCER != n
config SND_COMPRESS_OFFLOAD
tristate
@@ -37,15 +33,38 @@ config SND_JACK_INPUT_DEV
depends on SND_JACK
default y if INPUT=y || INPUT=SND
+config SND_SEQUENCER
+ tristate "Sequencer support"
+ select SND_TIMER
+ help
+ Say Y or M to enable MIDI sequencer and router support. This
+ feature allows routing and enqueueing of MIDI events. Events
+ can be processed at a given time.
+
+ Many programs require this feature, so you should enable it
+ unless you know what you're doing.
+
+config SND_SEQ_DUMMY
+ tristate "Sequencer dummy client"
+ depends on SND_SEQUENCER
+ help
+ Say Y here to enable the dummy sequencer client. This client
+ is a simple MIDI-through client: all normal input events are
+ redirected to the output port immediately.
+
+ You don't need this unless you want to connect many MIDI
+ devices or applications together.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-seq-dummy.
+
config SND_OSSEMUL
- bool "Enable OSS Emulation"
select SOUND_OSS_CORE
- help
- This option enables the build of OSS emulation layer.
+ bool
config SND_MIXER_OSS
tristate "OSS Mixer API"
- depends on SND_OSSEMUL
+ select SND_OSSEMUL
help
To enable OSS mixer API emulation (/dev/mixer*), say Y here
and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
@@ -57,7 +76,7 @@ config SND_MIXER_OSS
config SND_PCM_OSS
tristate "OSS PCM (digital audio) API"
- depends on SND_OSSEMUL
+ select SND_OSSEMUL
select SND_PCM
help
To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
@@ -88,6 +107,20 @@ config SND_PCM_TIMER
For some embedded devices, we may disable it to reduce memory
footprint, about 20KB on x86_64 platform.
+config SND_SEQUENCER_OSS
+ bool "OSS Sequencer API"
+ depends on SND_SEQUENCER
+ select SND_OSSEMUL
+ help
+ Say Y here to enable OSS sequencer emulation (both
+ /dev/sequencer and /dev/music interfaces).
+
+ Many programs still use the OSS API, so say Y.
+
+ If you choose M in "Sequencer support" (SND_SEQUENCER),
+ this will be compiled as a module. The module will be called
+ snd-seq-oss.
+
config SND_HRTIMER
tristate "HR-timer backend support"
depends on HIGH_RES_TIMERS
@@ -100,6 +133,14 @@ config SND_HRTIMER
To compile this driver as a module, choose M here: the module
will be called snd-hrtimer.
+config SND_SEQ_HRTIMER_DEFAULT
+ bool "Use HR-timer as default sequencer timer"
+ depends on SND_HRTIMER && SND_SEQUENCER
+ default y
+ help
+ Say Y here to use the HR-timer backend as the default sequencer
+ timer.
+
config SND_DYNAMIC_MINORS
bool "Dynamic device file minor numbers"
help
diff --git a/sound/core/Makefile b/sound/core/Makefile
index e2066e2ef9f8..e85d9dd12c2d 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -22,7 +22,6 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
# for trace-points
CFLAGS_pcm_lib.o := -I$(src)
-CFLAGS_pcm_native.o := -I$(src)
snd-pcm-dmaengine-objs := pcm_dmaengine.o
@@ -31,7 +30,6 @@ snd-timer-objs := timer.o
snd-hrtimer-objs := hrtimer.o
snd-rtctimer-objs := rtctimer.o
snd-hwdep-objs := hwdep.o
-snd-seq-device-objs := seq_device.o
snd-compress-objs := compress_offload.o
@@ -41,7 +39,6 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o
obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o
obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
-obj-$(CONFIG_SND_SEQ_DEVICE) += snd-seq-device.o
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 809d220f08e5..4490a699030b 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1160,6 +1160,18 @@ int snd_compress_deregister(struct snd_compr *device)
}
EXPORT_SYMBOL_GPL(snd_compress_deregister);
+static int __init snd_compress_init(void)
+{
+ return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
MODULE_DESCRIPTION("ALSA Compressed offload framework");
MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/core/control.c b/sound/core/control.c
index f0f69aa2f26e..5a097cd149c3 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -104,7 +104,7 @@ static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
{
unsigned long flags;
struct snd_kctl_event *cread;
-
+
spin_lock_irqsave(&ctl->read_lock, flags);
while (!list_empty(&ctl->events)) {
cread = snd_kctl_event(ctl->events.next);
@@ -158,7 +158,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
unsigned long flags;
struct snd_ctl_file *ctl;
struct snd_kctl_event *ev;
-
+
if (snd_BUG_ON(!card || !id))
return;
if (card->shutdown)
@@ -212,7 +212,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
{
unsigned int size;
unsigned int idx;
-
+
if (count == 0 || count > MAX_CONTROL_COUNT)
return -EINVAL;
@@ -237,7 +237,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
* @ncontrol: the initialization record
* @private_data: the private data to set
*
- * Allocates a new struct snd_kcontrol instance and initialize from the given
+ * Allocates a new struct snd_kcontrol instance and initialize from the given
* template. When the access field of ncontrol is 0, it's assumed as
* READWRITE access. When the count field is 0, it's assumes as one.
*
@@ -250,7 +250,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
unsigned int count;
unsigned int access;
int err;
-
+
if (snd_BUG_ON(!ncontrol || !ncontrol->info))
return NULL;
@@ -347,41 +347,22 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
return 0;
}
-enum snd_ctl_add_mode {
- CTL_ADD_EXCLUSIVE, CTL_REPLACE, CTL_ADD_ON_REPLACE,
-};
-
-/* add/replace a new kcontrol object; call with card->controls_rwsem locked */
-static int __snd_ctl_add_replace(struct snd_card *card,
- struct snd_kcontrol *kcontrol,
- enum snd_ctl_add_mode mode)
+/* add a new kcontrol object; call with card->controls_rwsem locked */
+static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
struct snd_ctl_elem_id id;
unsigned int idx;
unsigned int count;
- struct snd_kcontrol *old;
- int err;
id = kcontrol->id;
if (id.index > UINT_MAX - kcontrol->count)
return -EINVAL;
- old = snd_ctl_find_id(card, &id);
- if (!old) {
- if (mode == CTL_REPLACE)
- return -EINVAL;
- } else {
- if (mode == CTL_ADD_EXCLUSIVE) {
- dev_err(card->dev,
- "control %i:%i:%i:%s:%i is already present\n",
- id.iface, id.device, id.subdevice, id.name,
- id.index);
- return -EBUSY;
- }
-
- err = snd_ctl_remove(card, old);
- if (err < 0)
- return err;
+ if (snd_ctl_find_id(card, &id)) {
+ dev_err(card->dev,
+ "control %i:%i:%i:%s:%i is already present\n",
+ id.iface, id.device, id.subdevice, id.name, id.index);
+ return -EBUSY;
}
if (snd_ctl_find_hole(card, kcontrol->count) < 0)
@@ -400,9 +381,21 @@ static int __snd_ctl_add_replace(struct snd_card *card,
return 0;
}
-static int snd_ctl_add_replace(struct snd_card *card,
- struct snd_kcontrol *kcontrol,
- enum snd_ctl_add_mode mode)
+/**
+ * snd_ctl_add - add the control instance to the card
+ * @card: the card instance
+ * @kcontrol: the control instance to add
+ *
+ * Adds the control instance created via snd_ctl_new() or
+ * snd_ctl_new1() to the given card. Assigns also an unique
+ * numid used for fast search.
+ *
+ * It frees automatically the control which cannot be added.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
+ *
+ */
+int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
int err = -EINVAL;
@@ -412,7 +405,7 @@ static int snd_ctl_add_replace(struct snd_card *card,
goto error;
down_write(&card->controls_rwsem);
- err = __snd_ctl_add_replace(card, kcontrol, mode);
+ err = __snd_ctl_add(card, kcontrol);
up_write(&card->controls_rwsem);
if (err < 0)
goto error;
@@ -422,25 +415,6 @@ static int snd_ctl_add_replace(struct snd_card *card,
snd_ctl_free_one(kcontrol);
return err;
}
-
-/**
- * snd_ctl_add - add the control instance to the card
- * @card: the card instance
- * @kcontrol: the control instance to add
- *
- * Adds the control instance created via snd_ctl_new() or
- * snd_ctl_new1() to the given card. Assigns also an unique
- * numid used for fast search.
- *
- * It frees automatically the control which cannot be added.
- *
- * Return: Zero if successful, or a negative error code on failure.
- *
- */
-int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
-{
- return snd_ctl_add_replace(card, kcontrol, CTL_ADD_EXCLUSIVE);
-}
EXPORT_SYMBOL(snd_ctl_add);
/**
@@ -460,8 +434,53 @@ EXPORT_SYMBOL(snd_ctl_add);
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
bool add_on_replace)
{
- return snd_ctl_add_replace(card, kcontrol,
- add_on_replace ? CTL_ADD_ON_REPLACE : CTL_REPLACE);
+ struct snd_ctl_elem_id id;
+ unsigned int count;
+ unsigned int idx;
+ struct snd_kcontrol *old;
+ int ret;
+
+ if (!kcontrol)
+ return -EINVAL;
+ if (snd_BUG_ON(!card || !kcontrol->info)) {
+ ret = -EINVAL;
+ goto error;
+ }
+ id = kcontrol->id;
+ down_write(&card->controls_rwsem);
+ old = snd_ctl_find_id(card, &id);
+ if (!old) {
+ if (add_on_replace)
+ goto add;
+ up_write(&card->controls_rwsem);
+ ret = -EINVAL;
+ goto error;
+ }
+ ret = snd_ctl_remove(card, old);
+ if (ret < 0) {
+ up_write(&card->controls_rwsem);
+ goto error;
+ }
+add:
+ if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
+ up_write(&card->controls_rwsem);
+ ret = -ENOMEM;
+ goto error;
+ }
+ list_add_tail(&kcontrol->list, &card->controls);
+ card->controls_count += kcontrol->count;
+ kcontrol->id.numid = card->last_numid + 1;
+ card->last_numid += kcontrol->count;
+ id = kcontrol->id;
+ count = kcontrol->count;
+ up_write(&card->controls_rwsem);
+ for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+ return 0;
+
+error:
+ snd_ctl_free_one(kcontrol);
+ return ret;
}
EXPORT_SYMBOL(snd_ctl_replace);
@@ -735,45 +754,65 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
static int snd_ctl_elem_list(struct snd_card *card,
struct snd_ctl_elem_list __user *_list)
{
+ struct list_head *plist;
struct snd_ctl_elem_list list;
struct snd_kcontrol *kctl;
- struct snd_ctl_elem_id id;
+ struct snd_ctl_elem_id *dst, *id;
unsigned int offset, space, jidx;
- int err = 0;
-
+
if (copy_from_user(&list, _list, sizeof(list)))
return -EFAULT;
offset = list.offset;
space = list.space;
-
- down_read(&card->controls_rwsem);
- list.count = card->controls_count;
- list.used = 0;
+ /* try limit maximum space */
+ if (space > 16384)
+ return -ENOMEM;
if (space > 0) {
- list_for_each_entry(kctl, &card->controls, list) {
- if (offset >= kctl->count) {
- offset -= kctl->count;
- continue;
- }
- for (jidx = offset; jidx < kctl->count; jidx++) {
- snd_ctl_build_ioff(&id, kctl, jidx);
- if (copy_to_user(list.pids + list.used, &id,
- sizeof(id))) {
- err = -EFAULT;
- goto out;
- }
+ /* allocate temporary buffer for atomic operation */
+ dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
+ if (dst == NULL)
+ return -ENOMEM;
+ down_read(&card->controls_rwsem);
+ list.count = card->controls_count;
+ plist = card->controls.next;
+ while (plist != &card->controls) {
+ if (offset == 0)
+ break;
+ kctl = snd_kcontrol(plist);
+ if (offset < kctl->count)
+ break;
+ offset -= kctl->count;
+ plist = plist->next;
+ }
+ list.used = 0;
+ id = dst;
+ while (space > 0 && plist != &card->controls) {
+ kctl = snd_kcontrol(plist);
+ for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
+ snd_ctl_build_ioff(id, kctl, jidx);
+ id++;
+ space--;
list.used++;
- if (!--space)
- goto out;
}
+ plist = plist->next;
offset = 0;
}
+ up_read(&card->controls_rwsem);
+ if (list.used > 0 &&
+ copy_to_user(list.pids, dst,
+ list.used * sizeof(struct snd_ctl_elem_id))) {
+ vfree(dst);
+ return -EFAULT;
+ }
+ vfree(dst);
+ } else {
+ down_read(&card->controls_rwsem);
+ list.count = card->controls_count;
+ up_read(&card->controls_rwsem);
}
- out:
- up_read(&card->controls_rwsem);
- if (!err && copy_to_user(_list, &list, sizeof(list)))
- err = -EFAULT;
- return err;
+ if (copy_to_user(_list, &list, sizeof(list)))
+ return -EFAULT;
+ return 0;
}
static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
@@ -814,7 +853,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
int result;
-
+
down_read(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, &info->id);
if (kctl == NULL) {
@@ -852,14 +891,14 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
+ snd_power_lock(ctl->card);
result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (result < 0)
- return result;
- result = snd_ctl_elem_info(ctl, &info);
- if (result < 0)
- return result;
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
+ if (result >= 0)
+ result = snd_ctl_elem_info(ctl, &info);
+ snd_power_unlock(ctl->card);
+ if (result >= 0)
+ if (copy_to_user(_info, &info, sizeof(info)))
+ return -EFAULT;
return result;
}
@@ -869,18 +908,24 @@ static int snd_ctl_elem_read(struct snd_card *card,
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
+ int result;
+ down_read(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, &control->id);
- if (kctl == NULL)
- return -ENOENT;
-
- index_offset = snd_ctl_get_ioff(kctl, &control->id);
- vd = &kctl->vd[index_offset];
- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
- return -EPERM;
-
- snd_ctl_build_ioff(&control->id, kctl, index_offset);
- return kctl->get(kctl, control);
+ if (kctl == NULL) {
+ result = -ENOENT;
+ } else {
+ index_offset = snd_ctl_get_ioff(kctl, &control->id);
+ vd = &kctl->vd[index_offset];
+ if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) &&
+ kctl->get != NULL) {
+ snd_ctl_build_ioff(&control->id, kctl, index_offset);
+ result = kctl->get(kctl, control);
+ } else
+ result = -EPERM;
+ }
+ up_read(&card->controls_rwsem);
+ return result;
}
static int snd_ctl_elem_read_user(struct snd_card *card,
@@ -893,19 +938,14 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
if (IS_ERR(control))
return PTR_ERR(control);
+ snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result < 0)
- goto error;
-
- down_read(&card->controls_rwsem);
- result = snd_ctl_elem_read(card, control);
- up_read(&card->controls_rwsem);
- if (result < 0)
- goto error;
-
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
- error:
+ if (result >= 0)
+ result = snd_ctl_elem_read(card, control);
+ snd_power_unlock(card);
+ if (result >= 0)
+ if (copy_to_user(_control, control, sizeof(*control)))
+ result = -EFAULT;
kfree(control);
return result;
}
@@ -918,28 +958,30 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
unsigned int index_offset;
int result;
+ down_read(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, &control->id);
- if (kctl == NULL)
- return -ENOENT;
-
- index_offset = snd_ctl_get_ioff(kctl, &control->id);
- vd = &kctl->vd[index_offset];
- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
- (file && vd->owner && vd->owner != file)) {
- return -EPERM;
- }
-
- snd_ctl_build_ioff(&control->id, kctl, index_offset);
- result = kctl->put(kctl, control);
- if (result < 0)
- return result;
-
- if (result > 0) {
- struct snd_ctl_elem_id id = control->id;
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+ if (kctl == NULL) {
+ result = -ENOENT;
+ } else {
+ index_offset = snd_ctl_get_ioff(kctl, &control->id);
+ vd = &kctl->vd[index_offset];
+ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
+ kctl->put == NULL ||
+ (file && vd->owner && vd->owner != file)) {
+ result = -EPERM;
+ } else {
+ snd_ctl_build_ioff(&control->id, kctl, index_offset);
+ result = kctl->put(kctl, control);
+ }
+ if (result > 0) {
+ struct snd_ctl_elem_id id = control->id;
+ up_read(&card->controls_rwsem);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+ return 0;
+ }
}
-
- return 0;
+ up_read(&card->controls_rwsem);
+ return result;
}
static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
@@ -954,19 +996,14 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
return PTR_ERR(control);
card = file->card;
+ snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result < 0)
- goto error;
-
- down_write(&card->controls_rwsem);
- result = snd_ctl_elem_write(card, file, control);
- up_write(&card->controls_rwsem);
- if (result < 0)
- goto error;
-
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
- error:
+ if (result >= 0)
+ result = snd_ctl_elem_write(card, file, control);
+ snd_power_unlock(card);
+ if (result >= 0)
+ if (copy_to_user(_control, control, sizeof(*control)))
+ result = -EFAULT;
kfree(control);
return result;
}
@@ -979,7 +1016,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
int result;
-
+
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
down_write(&card->controls_rwsem);
@@ -1007,7 +1044,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
int result;
-
+
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
down_write(&card->controls_rwsem);
@@ -1085,7 +1122,9 @@ static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
char *src = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
+ mutex_lock(&ue->card->user_ctl_lock);
memcpy(&ucontrol->value, src, size);
+ mutex_unlock(&ue->card->user_ctl_lock);
return 0;
}
@@ -1098,83 +1137,60 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
char *dst = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
+ mutex_lock(&ue->card->user_ctl_lock);
change = memcmp(&ucontrol->value, dst, size) != 0;
if (change)
memcpy(dst, &ucontrol->value, size);
+ mutex_unlock(&ue->card->user_ctl_lock);
return change;
}
-static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
- unsigned int size)
+static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
+ int op_flag,
+ unsigned int size,
+ unsigned int __user *tlv)
{
- struct user_element *ue = kctl->private_data;
- unsigned int *container;
- struct snd_ctl_elem_id id;
- unsigned int mask = 0;
- int i;
- int change;
-
- if (size > 1024 * 128) /* sane value */
- return -EINVAL;
-
- container = memdup_user(buf, size);
- if (IS_ERR(container))
- return PTR_ERR(container);
-
- change = ue->tlv_data_size != size;
- if (!change)
- change = memcmp(ue->tlv_data, container, size);
- if (!change) {
- kfree(container);
- return 0;
- }
+ struct user_element *ue = kcontrol->private_data;
+ int change = 0;
+ void *new_data;
- if (ue->tlv_data == NULL) {
- /* Now TLV data is available. */
- for (i = 0; i < kctl->count; ++i)
- kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- mask = SNDRV_CTL_EVENT_MASK_INFO;
- }
+ if (op_flag == SNDRV_CTL_TLV_OP_WRITE) {
+ if (size > 1024 * 128) /* sane value */
+ return -EINVAL;
- kfree(ue->tlv_data);
- ue->tlv_data = container;
- ue->tlv_data_size = size;
+ new_data = memdup_user(tlv, size);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
+ mutex_lock(&ue->card->user_ctl_lock);
+ change = ue->tlv_data_size != size;
+ if (!change)
+ change = memcmp(ue->tlv_data, new_data, size) != 0;
+ kfree(ue->tlv_data);
+ ue->tlv_data = new_data;
+ ue->tlv_data_size = size;
+ mutex_unlock(&ue->card->user_ctl_lock);
+ } else {
+ int ret = 0;
- mask |= SNDRV_CTL_EVENT_MASK_TLV;
- for (i = 0; i < kctl->count; ++i) {
- snd_ctl_build_ioff(&id, kctl, i);
- snd_ctl_notify(ue->card, mask, &id);
+ mutex_lock(&ue->card->user_ctl_lock);
+ if (!ue->tlv_data_size || !ue->tlv_data) {
+ ret = -ENXIO;
+ goto err_unlock;
+ }
+ if (size < ue->tlv_data_size) {
+ ret = -ENOSPC;
+ goto err_unlock;
+ }
+ if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
+ ret = -EFAULT;
+err_unlock:
+ mutex_unlock(&ue->card->user_ctl_lock);
+ if (ret)
+ return ret;
}
-
return change;
}
-static int read_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
- unsigned int size)
-{
- struct user_element *ue = kctl->private_data;
-
- if (ue->tlv_data_size == 0 || ue->tlv_data == NULL)
- return -ENXIO;
-
- if (size < ue->tlv_data_size)
- return -ENOSPC;
-
- if (copy_to_user(buf, ue->tlv_data, ue->tlv_data_size))
- return -EFAULT;
-
- return 0;
-}
-
-static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
- unsigned int size, unsigned int __user *buf)
-{
- if (op_flag == SNDRV_CTL_TLV_OP_WRITE)
- return replace_user_tlv(kctl, buf, size);
- else
- return read_user_tlv(kctl, buf, size);
-}
-
static int snd_ctl_elem_init_enum_names(struct user_element *ue)
{
char *names, *p;
@@ -1278,10 +1294,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_INACTIVE |
- SNDRV_CTL_ELEM_ACCESS_TLV_WRITE);
-
- /* In initial state, nothing is available as TLV container. */
- if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+ SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE);
+ if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
access |= SNDRV_CTL_ELEM_ACCESS_USER;
@@ -1344,12 +1358,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
kctl->get = snd_ctl_elem_user_get;
if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
kctl->put = snd_ctl_elem_user_put;
- if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+ if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
kctl->tlv.c = snd_ctl_elem_user_tlv;
/* This function manage to free the instance on failure. */
down_write(&card->controls_rwsem);
- err = __snd_ctl_add_replace(card, kctl, CTL_ADD_EXCLUSIVE);
+ err = __snd_ctl_add(card, kctl);
if (err < 0) {
snd_ctl_free_one(kctl);
goto unlock;
@@ -1421,107 +1435,71 @@ static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
return 0;
}
-static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
- struct snd_kcontrol *kctl,
- struct snd_ctl_elem_id *id,
- unsigned int __user *buf, unsigned int size)
-{
- static const struct {
- int op;
- int perm;
- } pairs[] = {
- {SNDRV_CTL_TLV_OP_READ, SNDRV_CTL_ELEM_ACCESS_TLV_READ},
- {SNDRV_CTL_TLV_OP_WRITE, SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
- {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
- };
- struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
- int i;
-
- /* Check support of the request for this element. */
- for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
- if (op_flag == pairs[i].op && (vd->access & pairs[i].perm))
- break;
- }
- if (i == ARRAY_SIZE(pairs))
- return -ENXIO;
-
- if (kctl->tlv.c == NULL)
- return -ENXIO;
-
- /* When locked, this is unavailable. */
- if (vd->owner != NULL && vd->owner != file)
- return -EPERM;
-
- return kctl->tlv.c(kctl, op_flag, size, buf);
-}
-
-static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
- unsigned int __user *buf, unsigned int size)
-{
- struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
- unsigned int len;
-
- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ))
- return -ENXIO;
-
- if (kctl->tlv.p == NULL)
- return -ENXIO;
-
- len = sizeof(unsigned int) * 2 + kctl->tlv.p[1];
- if (size < len)
- return -ENOMEM;
-
- if (copy_to_user(buf, kctl->tlv.p, len))
- return -EFAULT;
-
- return 0;
-}
-
static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
- struct snd_ctl_tlv __user *buf,
+ struct snd_ctl_tlv __user *_tlv,
int op_flag)
{
- struct snd_ctl_tlv header;
- unsigned int __user *container;
- unsigned int container_size;
+ struct snd_card *card = file->card;
+ struct snd_ctl_tlv tlv;
struct snd_kcontrol *kctl;
- struct snd_ctl_elem_id id;
struct snd_kcontrol_volatile *vd;
+ unsigned int len;
+ int err = 0;
- if (copy_from_user(&header, buf, sizeof(header)))
+ if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
return -EFAULT;
-
- /* In design of control core, numerical ID starts at 1. */
- if (header.numid == 0)
+ if (tlv.length < sizeof(unsigned int) * 2)
return -EINVAL;
-
- /* At least, container should include type and length fields. */
- if (header.length < sizeof(unsigned int) * 2)
+ if (!tlv.numid)
return -EINVAL;
- container_size = header.length;
- container = buf->tlv;
-
- kctl = snd_ctl_find_numid(file->card, header.numid);
- if (kctl == NULL)
- return -ENOENT;
-
- /* Calculate index of the element in this set. */
- id = kctl->id;
- snd_ctl_build_ioff(&id, kctl, header.numid - id.numid);
- vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
-
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_numid(card, tlv.numid);
+ if (kctl == NULL) {
+ err = -ENOENT;
+ goto __kctl_end;
+ }
+ if (kctl->tlv.p == NULL) {
+ err = -ENXIO;
+ goto __kctl_end;
+ }
+ vd = &kctl->vd[tlv.numid - kctl->id.numid];
+ if ((op_flag == SNDRV_CTL_TLV_OP_READ &&
+ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) ||
+ (op_flag == SNDRV_CTL_TLV_OP_WRITE &&
+ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) ||
+ (op_flag == SNDRV_CTL_TLV_OP_CMD &&
+ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) {
+ err = -ENXIO;
+ goto __kctl_end;
+ }
if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
- return call_tlv_handler(file, op_flag, kctl, &id, container,
- container_size);
+ if (vd->owner != NULL && vd->owner != file) {
+ err = -EPERM;
+ goto __kctl_end;
+ }
+ err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+ if (err > 0) {
+ struct snd_ctl_elem_id id = kctl->id;
+ up_read(&card->controls_rwsem);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
+ return 0;
+ }
} else {
- if (op_flag == SNDRV_CTL_TLV_OP_READ) {
- return read_tlv_buf(kctl, &id, container,
- container_size);
+ if (op_flag != SNDRV_CTL_TLV_OP_READ) {
+ err = -ENXIO;
+ goto __kctl_end;
+ }
+ len = kctl->tlv.p[1] + 2 * sizeof(unsigned int);
+ if (tlv.length < len) {
+ err = -ENOMEM;
+ goto __kctl_end;
}
+ if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
+ err = -EFAULT;
}
-
- /* Not supported. */
- return -ENXIO;
+ __kctl_end:
+ up_read(&card->controls_rwsem);
+ return err;
}
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1563,20 +1541,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
case SNDRV_CTL_IOCTL_TLV_READ:
- down_read(&ctl->card->controls_rwsem);
- err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
- up_read(&ctl->card->controls_rwsem);
- return err;
+ return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
case SNDRV_CTL_IOCTL_TLV_WRITE:
- down_write(&ctl->card->controls_rwsem);
- err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
- up_write(&ctl->card->controls_rwsem);
- return err;
+ return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
case SNDRV_CTL_IOCTL_TLV_COMMAND:
- down_write(&ctl->card->controls_rwsem);
- err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
- up_write(&ctl->card->controls_rwsem);
- return err;
+ return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE:
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 507fd5210c1c..84ee29c3b1a0 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -111,10 +111,12 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
goto error;
+ snd_power_lock(ctl->card);
err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (err < 0)
- goto error;
- err = snd_ctl_elem_info(ctl, data);
+ if (err >= 0)
+ err = snd_ctl_elem_info(ctl, data);
+ snd_power_unlock(ctl->card);
+
if (err < 0)
goto error;
/* restore info to 32bit */
@@ -313,13 +315,14 @@ static int ctl_elem_read_user(struct snd_card *card,
if (err < 0)
goto error;
+ snd_power_lock(card);
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err < 0)
- goto error;
- err = snd_ctl_elem_read(card, data);
- if (err < 0)
- goto error;
- err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
+ if (err >= 0)
+ err = snd_ctl_elem_read(card, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+ err = copy_ctl_value_to_user(userdata, valuep, data,
+ type, count);
error:
kfree(data);
return err;
@@ -341,13 +344,14 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
if (err < 0)
goto error;
+ snd_power_lock(card);
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err < 0)
- goto error;
- err = snd_ctl_elem_write(card, file, data);
- if (err < 0)
- goto error;
- err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
+ if (err >= 0)
+ err = snd_ctl_elem_write(card, file, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+ err = copy_ctl_value_to_user(userdata, valuep, data,
+ type, count);
error:
kfree(data);
return err;
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
index 0249d5e6ac23..84a3cd683068 100644
--- a/sound/core/ctljack.c
+++ b/sound/core/ctljack.c
@@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static const struct snd_kcontrol_new jack_detect_kctl = {
+static struct snd_kcontrol_new jack_detect_kctl = {
/* name is filled later */
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.access = SNDRV_CTL_ELEM_ACCESS_READ,
diff --git a/sound/core/device.c b/sound/core/device.c
index 535102d564e3..12d5cbefd85e 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -128,7 +128,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data)
if (dev)
__snd_device_disconnect(dev);
else
- dev_dbg(card->dev, "device disconnect %p (from %pS), not found\n",
+ dev_dbg(card->dev, "device disconnect %p (from %pF), not found\n",
device_data, __builtin_return_address(0));
}
EXPORT_SYMBOL_GPL(snd_device_disconnect);
@@ -152,7 +152,7 @@ void snd_device_free(struct snd_card *card, void *device_data)
if (dev)
__snd_device_free(dev);
else
- dev_dbg(card->dev, "device free %p (from %pS), not found\n",
+ dev_dbg(card->dev, "device free %p (from %pF), not found\n",
device_data, __builtin_return_address(0));
}
EXPORT_SYMBOL(snd_device_free);
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index 18cb6f476bf4..6e47b823bcaa 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -127,7 +127,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
return 0;
}
-static const struct snd_timer_hardware hrtimer_hw __initconst = {
+static struct snd_timer_hardware hrtimer_hw = {
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
.open = snd_hrtimer_open,
.close = snd_hrtimer_close,
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 25b8f2234fc7..a73baa1242be 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -228,11 +228,11 @@ static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
- if (info.index >= 32)
- return -EINVAL;
/* check whether the dsp was already loaded */
if (hw->dsp_loaded & (1 << info.index))
return -EBUSY;
+ if (!access_ok(VERIFY_READ, info.image, info.length))
+ return -EFAULT;
err = hw->ops.dsp_load(hw, &info);
if (err < 0)
return err;
diff --git a/sound/core/info.c b/sound/core/info.c
index bcf6a48cc70d..8ab72e0f5932 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file,
}
}
if (next > buf->len) {
- char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL);
+ char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next),
+ GFP_KERNEL | __GFP_ZERO);
if (!nbuf) {
err = -ENOMEM;
goto error;
}
- kvfree(buf->buffer);
buf->buffer = nbuf;
buf->len = PAGE_ALIGN(next);
}
@@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file)
single_release(inode, file);
kfree(data->rbuffer);
if (data->wbuffer) {
- kvfree(data->wbuffer->buffer);
+ kfree(data->wbuffer->buffer);
kfree(data->wbuffer);
}
@@ -652,6 +652,7 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
*line = '\0';
return 0;
}
+
EXPORT_SYMBOL(snd_info_get_line);
/**
@@ -689,6 +690,7 @@ const char *snd_info_get_str(char *dest, const char *src, int len)
src++;
return src;
}
+
EXPORT_SYMBOL(snd_info_get_str);
/*
@@ -746,6 +748,7 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module,
entry->module = module;
return entry;
}
+
EXPORT_SYMBOL(snd_info_create_module_entry);
/**
@@ -769,6 +772,7 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
}
return entry;
}
+
EXPORT_SYMBOL(snd_info_create_card_entry);
static void snd_info_disconnect(struct snd_info_entry *entry)
@@ -811,6 +815,7 @@ void snd_info_free_entry(struct snd_info_entry * entry)
entry->private_free(entry);
kfree(entry);
}
+
EXPORT_SYMBOL(snd_info_free_entry);
/**
@@ -853,6 +858,7 @@ int snd_info_register(struct snd_info_entry * entry)
mutex_unlock(&info_mutex);
return 0;
}
+
EXPORT_SYMBOL(snd_info_register);
/*
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index f479374b6bd8..1478c8dfd473 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -61,6 +61,7 @@ int snd_oss_info_register(int dev, int num, char *string)
mutex_unlock(&strings);
return 0;
}
+
EXPORT_SYMBOL(snd_oss_info_register);
static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
diff --git a/sound/core/init.c b/sound/core/init.c
index 4a51a068d42e..d61d2b3cd521 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -248,14 +248,15 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
INIT_LIST_HEAD(&card->devices);
init_rwsem(&card->controls_rwsem);
rwlock_init(&card->ctl_files_rwlock);
+ mutex_init(&card->user_ctl_lock);
INIT_LIST_HEAD(&card->controls);
INIT_LIST_HEAD(&card->ctl_files);
spin_lock_init(&card->files_lock);
INIT_LIST_HEAD(&card->files_list);
#ifdef CONFIG_PM
+ mutex_init(&card->power_lock);
init_waitqueue_head(&card->power_sleep);
#endif
- init_waitqueue_head(&card->remove_sleep);
device_initialize(&card->card_dev);
card->card_dev.parent = parent;
@@ -451,36 +452,8 @@ int snd_card_disconnect(struct snd_card *card)
#endif
return 0;
}
-EXPORT_SYMBOL(snd_card_disconnect);
-
-/**
- * snd_card_disconnect_sync - disconnect card and wait until files get closed
- * @card: card object to disconnect
- *
- * This calls snd_card_disconnect() for disconnecting all belonging components
- * and waits until all pending files get closed.
- * It assures that all accesses from user-space finished so that the driver
- * can release its resources gracefully.
- */
-void snd_card_disconnect_sync(struct snd_card *card)
-{
- int err;
-
- err = snd_card_disconnect(card);
- if (err < 0) {
- dev_err(card->dev,
- "snd_card_disconnect error (%d), skipping sync\n",
- err);
- return;
- }
- spin_lock_irq(&card->files_lock);
- wait_event_lock_irq(card->remove_sleep,
- list_empty(&card->files_list),
- card->files_lock);
- spin_unlock_irq(&card->files_lock);
-}
-EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
+EXPORT_SYMBOL(snd_card_disconnect);
static int snd_card_do_free(struct snd_card *card)
{
@@ -670,7 +643,7 @@ card_id_show_attr(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
- return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
+ return snprintf(buf, PAGE_SIZE, "%s\n", card->id);
}
static ssize_t
@@ -710,7 +683,7 @@ card_number_show_attr(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_card *card = container_of(dev, struct snd_card, card_dev);
- return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
+ return snprintf(buf, PAGE_SIZE, "%i\n", card->number);
}
static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
@@ -745,7 +718,7 @@ int snd_card_add_dev_attr(struct snd_card *card,
dev_err(card->dev, "Too many groups assigned\n");
return -ENOSPC;
-}
+};
EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
/**
@@ -802,6 +775,7 @@ int snd_card_register(struct snd_card *card)
#endif
return 0;
}
+
EXPORT_SYMBOL(snd_card_register);
#ifdef CONFIG_SND_PROC_FS
@@ -921,6 +895,7 @@ int snd_component_add(struct snd_card *card, const char *component)
strcat(card->components, component);
return 0;
}
+
EXPORT_SYMBOL(snd_component_add);
/**
@@ -955,6 +930,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
spin_unlock(&card->files_lock);
return 0;
}
+
EXPORT_SYMBOL(snd_card_file_add);
/**
@@ -987,8 +963,6 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
break;
}
}
- if (list_empty(&card->files_list))
- wake_up_all(&card->remove_sleep);
spin_unlock(&card->files_lock);
if (!found) {
dev_err(card->dev, "card file remove problem (%p)\n", file);
@@ -998,6 +972,7 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
put_device(&card->card_dev);
return 0;
}
+
EXPORT_SYMBOL(snd_card_file_remove);
#ifdef CONFIG_PM
@@ -1009,6 +984,8 @@ EXPORT_SYMBOL(snd_card_file_remove);
* Waits until the power-state is changed.
*
* Return: Zero if successful, or a negative error code.
+ *
+ * Note: the power lock must be active before call.
*/
int snd_power_wait(struct snd_card *card, unsigned int power_state)
{
@@ -1028,10 +1005,13 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
if (snd_power_get_state(card) == power_state)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
+ snd_power_unlock(card);
schedule_timeout(30 * HZ);
+ snd_power_lock(card);
}
remove_wait_queue(&card->power_sleep, &wait);
return result;
}
+
EXPORT_SYMBOL(snd_power_wait);
#endif /* CONFIG_PM */
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 7a8515abb5f9..31e8544d7f2d 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -55,6 +55,7 @@ void snd_dma_program(unsigned long dma,
enable_dma(dma);
release_dma_lock(flags);
}
+
EXPORT_SYMBOL(snd_dma_program);
/**
@@ -72,6 +73,7 @@ void snd_dma_disable(unsigned long dma)
disable_dma(dma);
release_dma_lock(flags);
}
+
EXPORT_SYMBOL(snd_dma_disable);
/**
@@ -111,4 +113,5 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
else
return size - result;
}
+
EXPORT_SYMBOL(snd_dma_pointer);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 84c2a17c56ee..f652e90efd7e 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -310,7 +310,7 @@ EXPORT_SYMBOL(snd_jack_set_parent);
* @type: Jack report type for this key
* @keytype: Input layer key type to be reported
*
- * Map a SND_JACK_BTN_* button type to an input layer key, allowing
+ * Map a SND_JACK_BTN_ button type to an input layer key, allowing
* reporting of keys on accessories via the jack abstraction. If no
* mapping is provided but keys are enabled in the jack type then
* BTN_n numeric buttons will be reported.
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 59a4adc286ed..bb50e0e2a1b5 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -57,7 +57,6 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
pg = get_order(size);
return (void *) __get_free_pages(gfp_flags, pg);
}
-EXPORT_SYMBOL(snd_malloc_pages);
/**
* snd_free_pages - release the pages
@@ -75,7 +74,6 @@ void snd_free_pages(void *ptr, size_t size)
pg = get_order(size);
free_pages((unsigned long) ptr, pg);
}
-EXPORT_SYMBOL(snd_free_pages);
/*
*
@@ -226,7 +224,6 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
dmab->bytes = size;
return 0;
}
-EXPORT_SYMBOL(snd_dma_alloc_pages);
/**
* snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
@@ -260,7 +257,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
return -ENOMEM;
return 0;
}
-EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
/**
@@ -296,4 +292,13 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
}
}
+
+/*
+ * exports
+ */
+EXPORT_SYMBOL(snd_dma_alloc_pages);
+EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
EXPORT_SYMBOL(snd_dma_free_pages);
+
+EXPORT_SYMBOL(snd_malloc_pages);
+EXPORT_SYMBOL(snd_free_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 19c9ea90d9bf..4cd664efad77 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -55,6 +55,7 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
return 0;
#endif
}
+
EXPORT_SYMBOL(copy_to_user_fromio);
/**
@@ -87,4 +88,5 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
return 0;
#endif
}
+
EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 0f818d593c9e..21b228046e88 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -48,6 +48,7 @@ void release_and_free_resource(struct resource *res)
kfree(res);
}
}
+
EXPORT_SYMBOL(release_and_free_resource);
#ifdef CONFIG_SND_VERBOSE_PRINTK
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index d870b2d93135..6faa1d719206 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -26,9 +26,9 @@
#include "pcm_plugin.h"
#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
+#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
+#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
/*
* Basic io plugin
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 379bf486ccc7..2ff9c12d664a 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -395,7 +395,6 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l
fmixer.mixer = card->mixer_oss;
return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
}
-EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
#ifdef CONFIG_COMPAT
/* all compatible */
@@ -1426,3 +1425,5 @@ static void __exit alsa_mixer_oss_exit(void)
module_init(alsa_mixer_oss_init)
module_exit(alsa_mixer_oss_exit)
+
+EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index da21ee2e6e38..45ced1d81287 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -67,6 +67,18 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
+static inline mm_segment_t snd_enter_user(void)
+{
+ mm_segment_t fs = get_fs();
+ set_fs(get_ds());
+ return fs;
+}
+
+static inline void snd_leave_user(mm_segment_t fs)
+{
+ set_fs(fs);
+}
+
/*
* helper functions to process hw_params
*/
@@ -186,7 +198,7 @@ static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
{
int changed;
changed = snd_mask_refine(hw_param_mask(params, var), val);
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -233,7 +245,7 @@ static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
val, open);
else
return -EINVAL;
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -294,7 +306,7 @@ static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
val, open);
else
return -EINVAL;
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -499,7 +511,7 @@ static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
}
} else
return -EINVAL;
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -539,7 +551,7 @@ static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
{
int changed;
changed = snd_interval_setinteger(hw_param_interval(params, var));
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -786,7 +798,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
static int choose_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, unsigned int best_rate)
{
- const struct snd_interval *it;
+ struct snd_interval *it;
struct snd_pcm_hw_params *save;
unsigned int rate, prev;
@@ -794,7 +806,7 @@ static int choose_rate(struct snd_pcm_substream *substream,
if (save == NULL)
return -ENOMEM;
*save = *params;
- it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE);
+ it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
/* try multiples of the best rate */
rate = best_rate;
@@ -852,7 +864,7 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
int direct;
snd_pcm_format_t format, sformat;
int n;
- const struct snd_mask *sformat_mask;
+ struct snd_mask sformat_mask;
struct snd_mask mask;
if (!runtime->oss.params)
@@ -892,18 +904,18 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
format = snd_pcm_oss_format_from(runtime->oss.format);
- sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
+ sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
if (direct)
sformat = format;
else
- sformat = snd_pcm_plug_slave_format(format, sformat_mask);
+ sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
if ((__force int)sformat < 0 ||
- !snd_mask_test(sformat_mask, (__force int)sformat)) {
+ !snd_mask_test(&sformat_mask, (__force int)sformat)) {
for (sformat = (__force snd_pcm_format_t)0;
(__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
- if (snd_mask_test(sformat_mask, (__force int)sformat) &&
+ if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
snd_pcm_oss_format_to(sformat) >= 0)
break;
}
@@ -1234,8 +1246,14 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
if (ret < 0)
break;
}
- ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
- frames, in_kernel);
+ if (in_kernel) {
+ mm_segment_t fs;
+ fs = snd_enter_user();
+ ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
+ snd_leave_user(fs);
+ } else {
+ ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
+ }
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
@@ -1271,8 +1289,14 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
if (ret < 0)
break;
- ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
- frames, in_kernel);
+ if (in_kernel) {
+ mm_segment_t fs;
+ fs = snd_enter_user();
+ ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
+ snd_leave_user(fs);
+ } else {
+ ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
+ }
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1287,8 +1311,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
return ret;
}
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1305,7 +1328,14 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
if (ret < 0)
break;
}
- ret = snd_pcm_kernel_writev(substream, bufs, frames);
+ if (in_kernel) {
+ mm_segment_t fs;
+ fs = snd_enter_user();
+ ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
+ snd_leave_user(fs);
+ } else {
+ ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
+ }
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
@@ -1317,7 +1347,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1338,13 +1368,19 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
- ret = snd_pcm_kernel_readv(substream, bufs, frames);
+ if (in_kernel) {
+ mm_segment_t fs;
+ fs = snd_enter_user();
+ ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
+ snd_leave_user(fs);
+ } else {
+ ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
+ }
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
return ret;
}
-#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
{
@@ -1691,10 +1727,27 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
size = runtime->control->appl_ptr % runtime->period_size;
if (size > 0) {
size = runtime->period_size - size;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
- snd_pcm_lib_write(substream, NULL, size);
- else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- snd_pcm_lib_writev(substream, NULL, size);
+ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
+ size = (runtime->frame_bits * size) / 8;
+ while (size > 0) {
+ mm_segment_t fs;
+ size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
+ size -= size1;
+ size1 *= 8;
+ size1 /= runtime->sample_bits;
+ snd_pcm_format_set_silence(runtime->format,
+ runtime->oss.buffer,
+ size1);
+ size1 /= runtime->channels; /* frames */
+ fs = snd_enter_user();
+ snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
+ snd_leave_user(fs);
+ }
+ } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
+ void __user *buffers[runtime->channels];
+ memset(buffers, 0, runtime->channels * sizeof(void *));
+ snd_pcm_lib_writev(substream, buffers, size);
+ }
}
unlock:
mutex_unlock(&runtime->oss.params_lock);
@@ -1824,7 +1877,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
int direct;
struct snd_pcm_hw_params *params;
unsigned int formats = 0;
- const struct snd_mask *format_mask;
+ struct snd_mask format_mask;
int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1846,20 +1899,18 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
return -ENOMEM;
_snd_pcm_hw_params_any(params);
err = snd_pcm_hw_refine(substream, params);
+ format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ kfree(params);
if (err < 0)
- goto error;
- format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ return err;
for (fmt = 0; fmt < 32; ++fmt) {
- if (snd_mask_test(format_mask, fmt)) {
- int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt);
+ if (snd_mask_test(&format_mask, fmt)) {
+ int f = snd_pcm_oss_format_to(fmt);
if (f >= 0)
formats |= f;
}
}
-
- error:
- kfree(params);
- return err < 0 ? err : formats;
+ return formats;
}
static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 31cb2acf8afc..194b7f7ae830 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -111,7 +111,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
while (plugin->next) {
if (plugin->dst_frames)
frames = plugin->dst_frames(plugin, frames);
- if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0))
+ if (snd_BUG_ON(frames <= 0))
return -ENXIO;
plugin = plugin->next;
err = snd_pcm_plugin_alloc(plugin, frames);
@@ -123,7 +123,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
while (plugin->prev) {
if (plugin->src_frames)
frames = plugin->src_frames(plugin, frames);
- if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0))
+ if (snd_BUG_ON(frames <= 0))
return -ENXIO;
plugin = plugin->prev;
err = snd_pcm_plugin_alloc(plugin, frames);
@@ -266,8 +266,7 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
return frames;
}
-static int snd_pcm_plug_formats(const struct snd_mask *mask,
- snd_pcm_format_t format)
+static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
{
struct snd_mask formats = *mask;
u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
@@ -281,10 +280,10 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask,
SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
- if (formats.bits[0] & lower_32_bits(linfmts))
- formats.bits[0] |= lower_32_bits(linfmts);
- if (formats.bits[1] & upper_32_bits(linfmts))
- formats.bits[1] |= upper_32_bits(linfmts);
+ if (formats.bits[0] & (u32)linfmts)
+ formats.bits[0] |= (u32)linfmts;
+ if (formats.bits[1] & (u32)(linfmts >> 32))
+ formats.bits[1] |= (u32)(linfmts >> 32);
return snd_mask_test(&formats, (__force int)format);
}
@@ -310,7 +309,7 @@ static snd_pcm_format_t preferred_formats[] = {
};
snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- const struct snd_mask *format_mask)
+ struct snd_mask *format_mask)
{
int i;
@@ -353,7 +352,6 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
if (snd_mask_test(format_mask, (__force int)format1))
return format1;
}
- /* fall through */
default:
return (__force snd_pcm_format_t)-EINVAL;
}
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index c9cd29d86efd..a5035c2369a6 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *slave_params);
snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- const struct snd_mask *format_mask);
+ struct snd_mask *format_mask);
int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
@@ -162,15 +162,17 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
char *ptr, snd_pcm_uframes_t size, int in_kernel);
snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames);
+ void **bufs, snd_pcm_uframes_t frames,
+ int in_kernel);
snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames);
+ void **bufs, snd_pcm_uframes_t frames,
+ int in_kernel);
#else
static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
-static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
+static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index cdf41c403763..cdff5f976480 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -33,17 +33,13 @@
#include <sound/control.h>
#include <sound/info.h>
-#include "pcm_local.h"
-
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL");
static LIST_HEAD(snd_pcm_devices);
-static DEFINE_MUTEX(register_mutex);
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
static LIST_HEAD(snd_pcm_notify_list);
-#endif
+static DEFINE_MUTEX(register_mutex);
static int snd_pcm_free(struct snd_pcm *pcm);
static int snd_pcm_dev_free(struct snd_device *device);
@@ -494,8 +490,13 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_substream *substream = entry->private_data;
+ struct snd_pcm_runtime *runtime;
- snd_pcm_stop_xrun(substream);
+ snd_pcm_stream_lock_irq(substream);
+ runtime = substream->runtime;
+ if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock_irq(substream);
}
static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
@@ -523,9 +524,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
sprintf(name, "pcm%i%c", pcm->device,
pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
- entry = snd_info_create_card_entry(pcm->card, name,
- pcm->card->proc_root);
- if (!entry)
+ if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
@@ -533,8 +532,8 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
return -ENOMEM;
}
pstr->proc_root = entry;
- entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root);
- if (entry) {
+
+ if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@@ -544,9 +543,8 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
pstr->proc_info_entry = entry;
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
- entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
- pstr->proc_root);
- if (entry) {
+ if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
+ pstr->proc_root)) != NULL) {
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write = snd_pcm_xrun_debug_write;
entry->mode |= S_IWUSR;
@@ -583,9 +581,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
card = substream->pcm->card;
sprintf(name, "sub%i", substream->number);
- entry = snd_info_create_card_entry(card, name,
- substream->pstr->proc_root);
- if (!entry)
+ if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
@@ -593,8 +589,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
return -ENOMEM;
}
substream->proc_root = entry;
- entry = snd_info_create_card_entry(card, "info", substream->proc_root);
- if (entry) {
+
+ if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_info_read);
if (snd_info_register(entry) < 0) {
@@ -603,9 +599,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
}
}
substream->proc_info_entry = entry;
- entry = snd_info_create_card_entry(card, "hw_params",
- substream->proc_root);
- if (entry) {
+
+ if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_hw_params_read);
if (snd_info_register(entry) < 0) {
@@ -614,9 +609,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
}
}
substream->proc_hw_params_entry = entry;
- entry = snd_info_create_card_entry(card, "sw_params",
- substream->proc_root);
- if (entry) {
+
+ if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_sw_params_read);
if (snd_info_register(entry) < 0) {
@@ -625,9 +619,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
}
}
substream->proc_sw_params_entry = entry;
- entry = snd_info_create_card_entry(card, "status",
- substream->proc_root);
- if (entry) {
+
+ if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_status_read);
if (snd_info_register(entry) < 0) {
@@ -775,9 +768,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
.dev_register = snd_pcm_dev_register,
.dev_disconnect = snd_pcm_dev_disconnect,
};
- static struct snd_device_ops internal_ops = {
- .dev_free = snd_pcm_dev_free,
- };
if (snd_BUG_ON(!card))
return -ENXIO;
@@ -794,28 +784,21 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
INIT_LIST_HEAD(&pcm->list);
if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
-
- err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- playback_count);
- if (err < 0)
- goto free_pcm;
-
- err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count);
- if (err < 0)
- goto free_pcm;
-
- err = snd_device_new(card, SNDRV_DEV_PCM, pcm,
- internal ? &internal_ops : &ops);
- if (err < 0)
- goto free_pcm;
-
+ if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
+ snd_pcm_free(pcm);
+ return err;
+ }
+ if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) {
+ snd_pcm_free(pcm);
+ return err;
+ }
+ if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
+ snd_pcm_free(pcm);
+ return err;
+ }
if (rpcm)
*rpcm = pcm;
return 0;
-
-free_pcm:
- snd_pcm_free(pcm);
- return err;
}
/**
@@ -906,23 +889,16 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
put_device(&pstr->dev);
}
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
-#define pcm_call_notify(pcm, call) \
- do { \
- struct snd_pcm_notify *_notify; \
- list_for_each_entry(_notify, &snd_pcm_notify_list, list) \
- _notify->call(pcm); \
- } while (0)
-#else
-#define pcm_call_notify(pcm, call) do {} while (0)
-#endif
-
static int snd_pcm_free(struct snd_pcm *pcm)
{
+ struct snd_pcm_notify *notify;
+
if (!pcm)
return 0;
- if (!pcm->internal)
- pcm_call_notify(pcm, n_unregister);
+ if (!pcm->internal) {
+ list_for_each_entry(notify, &snd_pcm_notify_list, list)
+ notify->n_unregister(pcm);
+ }
if (pcm->private_free)
pcm->private_free(pcm);
snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -1090,7 +1066,7 @@ static struct attribute *pcm_dev_attrs[] = {
NULL
};
-static const struct attribute_group pcm_dev_attr_group = {
+static struct attribute_group pcm_dev_attr_group = {
.attrs = pcm_dev_attrs,
};
@@ -1103,11 +1079,14 @@ static int snd_pcm_dev_register(struct snd_device *device)
{
int cidx, err;
struct snd_pcm_substream *substream;
+ struct snd_pcm_notify *notify;
struct snd_pcm *pcm;
if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO;
pcm = device->device_data;
+ if (pcm->internal)
+ return 0;
mutex_lock(&register_mutex);
err = snd_pcm_add(pcm);
@@ -1138,7 +1117,8 @@ static int snd_pcm_dev_register(struct snd_device *device)
snd_pcm_timer_init(substream);
}
- pcm_call_notify(pcm, n_register);
+ list_for_each_entry(notify, &snd_pcm_notify_list, list)
+ notify->n_register(pcm);
unlock:
mutex_unlock(&register_mutex);
@@ -1148,6 +1128,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
static int snd_pcm_dev_disconnect(struct snd_device *device)
{
struct snd_pcm *pcm = device->device_data;
+ struct snd_pcm_notify *notify;
struct snd_pcm_substream *substream;
int cidx;
@@ -1159,10 +1140,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
snd_pcm_stream_lock_irq(substream);
if (substream->runtime) {
- if (snd_pcm_running(substream))
- snd_pcm_stop(substream,
- SNDRV_PCM_STATE_DISCONNECTED);
- /* to be sure, set the state unconditionally */
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
wake_up(&substream->runtime->sleep);
wake_up(&substream->runtime->tsleep);
@@ -1170,10 +1147,13 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
snd_pcm_stream_unlock_irq(substream);
}
}
-
- pcm_call_notify(pcm, n_disconnect);
+ if (!pcm->internal) {
+ list_for_each_entry(notify, &snd_pcm_notify_list, list)
+ notify->n_disconnect(pcm);
+ }
for (cidx = 0; cidx < 2; cidx++) {
- snd_unregister_device(&pcm->streams[cidx].dev);
+ if (!pcm->internal)
+ snd_unregister_device(&pcm->streams[cidx].dev);
free_chmap(&pcm->streams[cidx]);
}
mutex_unlock(&pcm->open_mutex);
@@ -1181,7 +1161,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
return 0;
}
-#if IS_ENABLED(CONFIG_SND_PCM_OSS)
/**
* snd_pcm_notify - Add/remove the notify list
* @notify: PCM notify list
@@ -1214,7 +1193,6 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
return 0;
}
EXPORT_SYMBOL(snd_pcm_notify);
-#endif /* CONFIG_SND_PCM_OSS */
#ifdef CONFIG_SND_PROC_FS
/*
@@ -1247,8 +1225,7 @@ static void snd_pcm_proc_init(void)
{
struct snd_info_entry *entry;
- entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL);
- if (entry) {
+ if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 39d853bfa5ac..7ae080bae15c 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -27,14 +27,17 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
s32 __user *src)
{
snd_pcm_sframes_t delay;
+ mm_segment_t fs;
int err;
+ fs = snd_enter_user();
err = snd_pcm_delay(substream, &delay);
- if (err)
+ snd_leave_user(fs);
+ if (err < 0)
return err;
if (put_user(delay, src))
return -EFAULT;
- return 0;
+ return err;
}
static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
@@ -45,7 +48,10 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
- err = snd_pcm_rewind(substream, frames);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_playback_rewind(substream, frames);
+ else
+ err = snd_pcm_capture_rewind(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
@@ -59,7 +65,10 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
- err = snd_pcm_forward(substream, frames);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_playback_forward(substream, frames);
+ else
+ err = snd_pcm_capture_forward(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
@@ -544,7 +553,6 @@ struct snd_pcm_mmap_status_x32 {
u32 pad2; /* alignment */
struct timespec tstamp;
s32 suspended_state;
- s32 pad3;
struct timespec audio_tstamp;
} __packed;
@@ -674,7 +682,6 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
case SNDRV_PCM_IOCTL_INFO:
case SNDRV_PCM_IOCTL_TSTAMP:
case SNDRV_PCM_IOCTL_TTSTAMP:
- case SNDRV_PCM_IOCTL_USER_PVERSION:
case SNDRV_PCM_IOCTL_HWSYNC:
case SNDRV_PCM_IOCTL_PREPARE:
case SNDRV_PCM_IOCTL_RESET:
@@ -687,7 +694,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
case SNDRV_PCM_IOCTL_XRUN:
case SNDRV_PCM_IOCTL_LINK:
case SNDRV_PCM_IOCTL_UNLINK:
- return snd_pcm_common_ioctl(file, substream, cmd, argp);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
+ else
+ return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
case SNDRV_PCM_IOCTL_HW_REFINE32:
return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
case SNDRV_PCM_IOCTL_HW_PARAMS32:
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 9881d087756f..e70379fb63d0 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -29,13 +29,13 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_interval *r = hw_param_interval(params, rule->var);
- const struct snd_interval *c;
+ struct snd_interval *c;
unsigned int rate_mask = 7, i;
const u8 *sad, *eld = rule->private;
sad = drm_eld_sad(eld);
if (sad) {
- c = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
unsigned max_channels = sad_max_channels(sad);
@@ -57,7 +57,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_interval *c = hw_param_interval(params, rule->var);
- const struct snd_interval *r;
+ struct snd_interval *r;
struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
unsigned int i;
const u8 *sad, *eld = rule->private;
@@ -67,7 +67,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
unsigned int rate_mask = 0;
/* Convert the rate interval to a mask */
- r = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
+ r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
for (i = 0; i < ARRAY_SIZE(eld_rates); i++)
if (r->min <= eld_rates[i] && r->max >= eld_rates[i])
rate_mask |= BIT(i);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 40013b26f671..936b83970a0f 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -33,8 +33,6 @@
#include <sound/pcm_params.h>
#include <sound/timer.h>
-#include "pcm_local.h"
-
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
#define CREATE_TRACE_POINTS
#include "pcm_trace.h"
@@ -42,12 +40,8 @@
#define trace_hwptr(substream, pos, in_interrupt)
#define trace_xrun(substream)
#define trace_hw_ptr_error(substream, reason)
-#define trace_applptr(substream, prev, curr)
#endif
-static int fill_silence_frames(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
-
/*
* fill ring buffer with silence
* runtime->silence_start: starting pointer to silence area
@@ -61,7 +55,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
- int err;
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -115,8 +108,33 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
ofs = runtime->silence_start % runtime->buffer_size;
while (frames > 0) {
transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
- err = fill_silence_frames(substream, ofs, transfer);
- snd_BUG_ON(err < 0);
+ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+ runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
+ if (substream->ops->silence) {
+ int err;
+ err = substream->ops->silence(substream, -1, ofs, transfer);
+ snd_BUG_ON(err < 0);
+ } else {
+ char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
+ snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
+ }
+ } else {
+ unsigned int c;
+ unsigned int channels = runtime->channels;
+ if (substream->ops->silence) {
+ for (c = 0; c < channels; ++c) {
+ int err;
+ err = substream->ops->silence(substream, c, ofs, transfer);
+ snd_BUG_ON(err < 0);
+ }
+ } else {
+ size_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c) {
+ char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
+ snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
+ }
+ }
+ }
runtime->silence_filled += transfer;
frames -= transfer;
ofs = 0;
@@ -153,8 +171,7 @@ EXPORT_SYMBOL(snd_pcm_debug_name);
dump_stack(); \
} while (0)
-/* call with stream lock held */
-void __snd_pcm_xrun(struct snd_pcm_substream *substream)
+static void xrun(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -192,7 +209,10 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
{
snd_pcm_uframes_t avail;
- avail = snd_pcm_avail(substream);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ avail = snd_pcm_playback_avail(runtime);
+ else
+ avail = snd_pcm_capture_avail(runtime);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -202,7 +222,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
}
} else {
if (avail >= runtime->stop_threshold) {
- __snd_pcm_xrun(substream);
+ xrun(substream);
return -EPIPE;
}
}
@@ -298,7 +318,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
if (pos == SNDRV_PCM_POS_XRUN) {
- __snd_pcm_xrun(substream);
+ xrun(substream);
return -EPIPE;
}
if (pos >= runtime->buffer_size) {
@@ -491,6 +511,7 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction,
for (substream = stream->substream; substream != NULL; substream = substream->next)
substream->ops = ops;
}
+
EXPORT_SYMBOL(snd_pcm_set_ops);
/**
@@ -508,6 +529,7 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream)
runtime->sync.id32[2] = -1;
runtime->sync.id32[3] = -1;
}
+
EXPORT_SYMBOL(snd_pcm_set_sync);
/*
@@ -623,6 +645,7 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
}
return changed;
}
+
EXPORT_SYMBOL(snd_interval_refine);
static int snd_interval_refine_first(struct snd_interval *i)
@@ -891,6 +914,7 @@ int snd_interval_ratnum(struct snd_interval *i,
}
return err;
}
+
EXPORT_SYMBOL(snd_interval_ratnum);
/**
@@ -1028,6 +1052,7 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
}
return snd_interval_refine(i, &list_range);
}
+
EXPORT_SYMBOL(snd_interval_list);
/**
@@ -1133,12 +1158,16 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
if (constrs->rules_num >= constrs->rules_all) {
struct snd_pcm_hw_rule *new;
unsigned int new_rules = constrs->rules_all + 16;
- new = krealloc(constrs->rules, new_rules * sizeof(*c),
- GFP_KERNEL);
+ new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
if (!new) {
va_end(args);
return -ENOMEM;
}
+ if (constrs->rules) {
+ memcpy(new, constrs->rules,
+ constrs->rules_num * sizeof(*c));
+ kfree(constrs->rules);
+ }
constrs->rules = new;
constrs->rules_all = new_rules;
}
@@ -1162,6 +1191,7 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
va_end(args);
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_hw_rule_add);
/**
@@ -1225,6 +1255,7 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
return snd_interval_setinteger(constrs_interval(constrs, var));
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
/**
@@ -1250,6 +1281,7 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
t.integer = 0;
return snd_interval_refine(constrs_interval(constrs, var), &t);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
@@ -1280,6 +1312,7 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
snd_pcm_hw_rule_list, (void *)l,
var, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
@@ -1346,6 +1379,7 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
snd_pcm_hw_rule_ratnums, (void *)r,
var, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
@@ -1380,6 +1414,7 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
snd_pcm_hw_rule_ratdens, (void *)r,
var, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
@@ -1388,8 +1423,7 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
unsigned int l = (unsigned long) rule->private;
int width = l & 0xffff;
unsigned int msbits = l >> 16;
- const struct snd_interval *i =
- hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+ struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
if (!snd_interval_single(i))
return 0;
@@ -1426,6 +1460,7 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
(void*) l,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
@@ -1453,6 +1488,7 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
snd_pcm_hw_rule_step, (void *) step,
var, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
@@ -1483,6 +1519,7 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
snd_pcm_hw_rule_pow2, NULL,
var, -1);
}
+
EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
@@ -1541,6 +1578,7 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
_snd_pcm_hw_param_any(params, k);
params->info = ~0U;
}
+
EXPORT_SYMBOL(_snd_pcm_hw_params_any);
/**
@@ -1573,6 +1611,7 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
}
return -EINVAL;
}
+
EXPORT_SYMBOL(snd_pcm_hw_param_value);
void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
@@ -1590,6 +1629,7 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
snd_BUG();
}
}
+
EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
@@ -1602,7 +1642,7 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
changed = snd_interval_refine_first(hw_param_interval(params, var));
else
return -EINVAL;
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -1636,6 +1676,7 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
}
return snd_pcm_hw_param_value(params, var, dir);
}
+
EXPORT_SYMBOL(snd_pcm_hw_param_first);
static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
@@ -1648,7 +1689,7 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
changed = snd_interval_refine_last(hw_param_interval(params, var));
else
return -EINVAL;
- if (changed > 0) {
+ if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
@@ -1682,8 +1723,48 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
}
return snd_pcm_hw_param_value(params, var, dir);
}
+
EXPORT_SYMBOL(snd_pcm_hw_param_last);
+/**
+ * snd_pcm_hw_param_choose - choose a configuration defined by @params
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ *
+ * Choose one configuration from configuration space defined by @params.
+ * The configuration chosen is that obtained fixing in this order:
+ * first access, first format, first subformat, min channels,
+ * min rate, min period time, max buffer size, min tick time
+ *
+ * Return: Zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params)
+{
+ static int vars[] = {
+ SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_HW_PARAM_SUBFORMAT,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ SNDRV_PCM_HW_PARAM_RATE,
+ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ SNDRV_PCM_HW_PARAM_TICK_TIME,
+ -1
+ };
+ int err, *v;
+
+ for (v = vars; *v != -1; v++) {
+ if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+ err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+ else
+ err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+ if (snd_BUG_ON(err < 0))
+ return err;
+ }
+ return 0;
+}
+
static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
void *arg)
{
@@ -1770,6 +1851,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (cmd) {
+ case SNDRV_PCM_IOCTL1_INFO:
+ return 0;
case SNDRV_PCM_IOCTL1_RESET:
return snd_pcm_lib_ioctl_reset(substream, arg);
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
@@ -1779,6 +1862,7 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
}
return -ENXIO;
}
+
EXPORT_SYMBOL(snd_pcm_lib_ioctl);
/**
@@ -1814,6 +1898,7 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
snd_pcm_stream_unlock_irqrestore(substream, flags);
}
+
EXPORT_SYMBOL(snd_pcm_period_elapsed);
/*
@@ -1839,19 +1924,12 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
if (runtime->no_period_wakeup)
wait_time = MAX_SCHEDULE_TIMEOUT;
else {
- /* use wait time from substream if available */
- if (substream->wait_time) {
- wait_time = substream->wait_time;
- } else {
- wait_time = 10;
-
- if (runtime->rate) {
- long t = runtime->period_size * 2 /
- runtime->rate;
- wait_time = max(t, wait_time);
- }
- wait_time = msecs_to_jiffies(wait_time * 1000);
+ wait_time = 10;
+ if (runtime->rate) {
+ long t = runtime->period_size * 2 / runtime->rate;
+ wait_time = max(t, wait_time);
}
+ wait_time = msecs_to_jiffies(wait_time * 1000);
}
for (;;) {
@@ -1867,7 +1945,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
* This check must happen after been added to the waitqueue
* and having current state be INTERRUPTIBLE.
*/
- avail = snd_pcm_avail(substream);
+ if (is_playback)
+ avail = snd_pcm_playback_avail(runtime);
+ else
+ avail = snd_pcm_capture_avail(runtime);
if (avail >= runtime->twake)
break;
snd_pcm_stream_unlock_irq(substream);
@@ -1912,147 +1993,129 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
return err;
}
-typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
- int channel, unsigned long hwoff,
- void *buf, unsigned long bytes);
-
-typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
- snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
-
-/* calculate the target DMA-buffer position to be written/read */
-static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
- int channel, unsigned long hwoff)
-{
- return runtime->dma_area + hwoff +
- channel * (runtime->dma_bytes / runtime->channels);
-}
-
-/* default copy_user ops for write; used for both interleaved and non- modes */
-static int default_write_copy(struct snd_pcm_substream *substream,
- int channel, unsigned long hwoff,
- void *buf, unsigned long bytes)
-{
- if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
- (void __user *)buf, bytes))
- return -EFAULT;
- return 0;
-}
-
-/* default copy_kernel ops for write */
-static int default_write_copy_kernel(struct snd_pcm_substream *substream,
- int channel, unsigned long hwoff,
- void *buf, unsigned long bytes)
-{
- memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
- return 0;
-}
-
-/* fill silence instead of copy data; called as a transfer helper
- * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
- * a NULL buffer is passed
- */
-static int fill_silence(struct snd_pcm_substream *substream, int channel,
- unsigned long hwoff, void *buf, unsigned long bytes)
+static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- return 0;
- if (substream->ops->fill_silence)
- return substream->ops->fill_silence(substream, channel,
- hwoff, bytes);
-
- snd_pcm_format_set_silence(runtime->format,
- get_dma_ptr(runtime, channel, hwoff),
- bytes_to_samples(runtime, bytes));
- return 0;
-}
-
-/* default copy_user ops for read; used for both interleaved and non- modes */
-static int default_read_copy(struct snd_pcm_substream *substream,
- int channel, unsigned long hwoff,
- void *buf, unsigned long bytes)
-{
- if (copy_to_user((void __user *)buf,
- get_dma_ptr(substream->runtime, channel, hwoff),
- bytes))
- return -EFAULT;
- return 0;
-}
-
-/* default copy_kernel ops for read */
-static int default_read_copy_kernel(struct snd_pcm_substream *substream,
- int channel, unsigned long hwoff,
- void *buf, unsigned long bytes)
-{
- memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
+ int err;
+ char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+ if (substream->ops->copy) {
+ if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+ return err;
+ } else {
+ char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+ if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
+ return -EFAULT;
+ }
return 0;
}
+
+typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t size);
-/* call transfer function with the converted pointers and sizes;
- * for interleaved mode, it's one shot for all samples
- */
-static int interleaved_copy(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t hwoff, void *data,
- snd_pcm_uframes_t off,
- snd_pcm_uframes_t frames,
- pcm_transfer_f transfer)
+static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ unsigned long data,
+ snd_pcm_uframes_t size,
+ int nonblock,
+ transfer_f transfer)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+ int err = 0;
- /* convert to bytes */
- hwoff = frames_to_bytes(runtime, hwoff);
- off = frames_to_bytes(runtime, off);
- frames = frames_to_bytes(runtime, frames);
- return transfer(substream, 0, hwoff, data + off, frames);
-}
+ if (size == 0)
+ return 0;
-/* call transfer function with the converted pointers and sizes for each
- * non-interleaved channel; when buffer is NULL, silencing instead of copying
- */
-static int noninterleaved_copy(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t hwoff, void *data,
- snd_pcm_uframes_t off,
- snd_pcm_uframes_t frames,
- pcm_transfer_f transfer)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int channels = runtime->channels;
- void **bufs = data;
- int c, err;
+ snd_pcm_stream_lock_irq(substream);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PAUSED:
+ break;
+ case SNDRV_PCM_STATE_XRUN:
+ err = -EPIPE;
+ goto _end_unlock;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ err = -ESTRPIPE;
+ goto _end_unlock;
+ default:
+ err = -EBADFD;
+ goto _end_unlock;
+ }
- /* convert to bytes; note that it's not frames_to_bytes() here.
- * in non-interleaved mode, we copy for each channel, thus
- * each copy is n_samples bytes x channels = whole frames.
- */
- off = samples_to_bytes(runtime, off);
- frames = samples_to_bytes(runtime, frames);
- hwoff = samples_to_bytes(runtime, hwoff);
- for (c = 0; c < channels; ++c, ++bufs) {
- if (!data || !*bufs)
- err = fill_silence(substream, c, hwoff, NULL, frames);
- else
- err = transfer(substream, c, hwoff, *bufs + off,
- frames);
+ runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+ avail = snd_pcm_playback_avail(runtime);
+ while (size > 0) {
+ snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
+ snd_pcm_uframes_t cont;
+ if (!avail) {
+ if (nonblock) {
+ err = -EAGAIN;
+ goto _end_unlock;
+ }
+ runtime->twake = min_t(snd_pcm_uframes_t, size,
+ runtime->control->avail_min ? : 1);
+ err = wait_for_avail(substream, &avail);
+ if (err < 0)
+ goto _end_unlock;
+ }
+ frames = size > avail ? avail : size;
+ cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
+ if (frames > cont)
+ frames = cont;
+ if (snd_BUG_ON(!frames)) {
+ runtime->twake = 0;
+ snd_pcm_stream_unlock_irq(substream);
+ return -EINVAL;
+ }
+ appl_ptr = runtime->control->appl_ptr;
+ appl_ofs = appl_ptr % runtime->buffer_size;
+ snd_pcm_stream_unlock_irq(substream);
+ err = transfer(substream, appl_ofs, data, offset, frames);
+ snd_pcm_stream_lock_irq(substream);
if (err < 0)
- return err;
- }
- return 0;
-}
+ goto _end_unlock;
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_XRUN:
+ err = -EPIPE;
+ goto _end_unlock;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ err = -ESTRPIPE;
+ goto _end_unlock;
+ default:
+ break;
+ }
+ appl_ptr += frames;
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+ runtime->control->appl_ptr = appl_ptr;
+ if (substream->ops->ack)
+ substream->ops->ack(substream);
-/* fill silence on the given buffer position;
- * called from snd_pcm_playback_silence()
- */
-static int fill_silence_frames(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
-{
- if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
- substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
- return interleaved_copy(substream, off, NULL, 0, frames,
- fill_silence);
- else
- return noninterleaved_copy(substream, off, NULL, 0, frames,
- fill_silence);
+ offset += frames;
+ size -= frames;
+ xfer += frames;
+ avail -= frames;
+ if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+ snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
+ err = snd_pcm_start(substream);
+ if (err < 0)
+ goto _end_unlock;
+ }
+ }
+ _end_unlock:
+ runtime->twake = 0;
+ if (xfer > 0 && err >= 0)
+ snd_pcm_update_state(substream, runtime);
+ snd_pcm_stream_unlock_irq(substream);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
/* sanity-check for read/write methods */
@@ -2062,141 +2125,164 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
+ if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
return -EINVAL;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
return 0;
}
-static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
{
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PAUSED:
- return 0;
- case SNDRV_PCM_STATE_XRUN:
- return -EPIPE;
- case SNDRV_PCM_STATE_SUSPENDED:
- return -ESTRPIPE;
- default:
- return -EBADFD;
- }
+ struct snd_pcm_runtime *runtime;
+ int nonblock;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+ runtime = substream->runtime;
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
+
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ runtime->channels > 1)
+ return -EINVAL;
+ return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
+ snd_pcm_lib_write_transfer);
}
-/* update to the given appl_ptr and call ack callback if needed;
- * when an error is returned, take back to the original value
- */
-int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t appl_ptr)
+EXPORT_SYMBOL(snd_pcm_lib_write);
+
+static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
- int ret;
-
- if (old_appl_ptr == appl_ptr)
- return 0;
-
- runtime->control->appl_ptr = appl_ptr;
- if (substream->ops->ack) {
- ret = substream->ops->ack(substream);
- if (ret < 0) {
- runtime->control->appl_ptr = old_appl_ptr;
- return ret;
+ int err;
+ void __user **bufs = (void __user **)data;
+ int channels = runtime->channels;
+ int c;
+ if (substream->ops->copy) {
+ if (snd_BUG_ON(!substream->ops->silence))
+ return -EINVAL;
+ for (c = 0; c < channels; ++c, ++bufs) {
+ if (*bufs == NULL) {
+ if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
+ return err;
+ } else {
+ char __user *buf = *bufs + samples_to_bytes(runtime, off);
+ if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
+ return err;
+ }
+ }
+ } else {
+ /* default transfer behaviour */
+ size_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c, ++bufs) {
+ char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+ if (*bufs == NULL) {
+ snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
+ } else {
+ char __user *buf = *bufs + samples_to_bytes(runtime, off);
+ if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
+ return -EFAULT;
+ }
}
}
-
- trace_applptr(substream, old_appl_ptr, appl_ptr);
-
return 0;
}
-
-/* the common loop for read/write data */
-snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
- void *data, bool interleaved,
- snd_pcm_uframes_t size, bool in_kernel)
+
+snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+ void __user **bufs,
+ snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t xfer = 0;
- snd_pcm_uframes_t offset = 0;
- snd_pcm_uframes_t avail;
- pcm_copy_f writer;
- pcm_transfer_f transfer;
- bool nonblock;
- bool is_playback;
+ struct snd_pcm_runtime *runtime;
+ int nonblock;
int err;
err = pcm_sanity_check(substream);
if (err < 0)
return err;
+ runtime = substream->runtime;
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
- is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- if (interleaved) {
- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
- runtime->channels > 1)
- return -EINVAL;
- writer = interleaved_copy;
- } else {
- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- return -EINVAL;
- writer = noninterleaved_copy;
- }
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ return -EINVAL;
+ return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
+ nonblock, snd_pcm_lib_writev_transfer);
+}
- if (!data) {
- if (is_playback)
- transfer = fill_silence;
- else
- return -EINVAL;
- } else if (in_kernel) {
- if (substream->ops->copy_kernel)
- transfer = substream->ops->copy_kernel;
- else
- transfer = is_playback ?
- default_write_copy_kernel : default_read_copy_kernel;
+EXPORT_SYMBOL(snd_pcm_lib_writev);
+
+static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+ if (substream->ops->copy) {
+ if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+ return err;
} else {
- if (substream->ops->copy_user)
- transfer = (pcm_transfer_f)substream->ops->copy_user;
- else
- transfer = is_playback ?
- default_write_copy : default_read_copy;
+ char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+ if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
+ return -EFAULT;
}
+ return 0;
+}
+
+static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+ unsigned long data,
+ snd_pcm_uframes_t size,
+ int nonblock,
+ transfer_f transfer)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+ int err = 0;
if (size == 0)
return 0;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
-
snd_pcm_stream_lock_irq(substream);
- err = pcm_accessible_state(runtime);
- if (err < 0)
- goto _end_unlock;
-
- runtime->twake = runtime->control->avail_min ? : 1;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
-
- if (!is_playback &&
- runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_PREPARED:
if (size >= runtime->start_threshold) {
err = snd_pcm_start(substream);
if (err < 0)
goto _end_unlock;
- } else {
- /* nothing to do */
- err = 0;
- goto _end_unlock;
}
+ break;
+ case SNDRV_PCM_STATE_DRAINING:
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PAUSED:
+ break;
+ case SNDRV_PCM_STATE_XRUN:
+ err = -EPIPE;
+ goto _end_unlock;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ err = -ESTRPIPE;
+ goto _end_unlock;
+ default:
+ err = -EBADFD;
+ goto _end_unlock;
}
- avail = snd_pcm_avail(substream);
-
+ runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+ avail = snd_pcm_capture_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t cont;
if (!avail) {
- if (!is_playback &&
- runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ if (runtime->status->state ==
+ SNDRV_PCM_STATE_DRAINING) {
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
goto _end_unlock;
}
@@ -2224,32 +2310,31 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
return -EINVAL;
}
snd_pcm_stream_unlock_irq(substream);
- err = writer(substream, appl_ofs, data, offset, frames,
- transfer);
+ err = transfer(substream, appl_ofs, data, offset, frames);
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
- err = pcm_accessible_state(runtime);
- if (err < 0)
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_XRUN:
+ err = -EPIPE;
goto _end_unlock;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ err = -ESTRPIPE;
+ goto _end_unlock;
+ default:
+ break;
+ }
appl_ptr += frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
- err = pcm_lib_apply_appl_ptr(substream, appl_ptr);
- if (err < 0)
- goto _end_unlock;
+ runtime->control->appl_ptr = appl_ptr;
+ if (substream->ops->ack)
+ substream->ops->ack(substream);
offset += frames;
size -= frames;
xfer += frames;
avail -= frames;
- if (is_playback &&
- runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
- snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
- err = snd_pcm_start(substream);
- if (err < 0)
- goto _end_unlock;
- }
}
_end_unlock:
runtime->twake = 0;
@@ -2258,7 +2343,83 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
snd_pcm_stream_unlock_irq(substream);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
-EXPORT_SYMBOL(__snd_pcm_lib_xfer);
+
+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
+{
+ struct snd_pcm_runtime *runtime;
+ int nonblock;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+ runtime = substream->runtime;
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
+ return -EINVAL;
+ return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
+}
+
+EXPORT_SYMBOL(snd_pcm_lib_read);
+
+static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ void __user **bufs = (void __user **)data;
+ int channels = runtime->channels;
+ int c;
+ if (substream->ops->copy) {
+ for (c = 0; c < channels; ++c, ++bufs) {
+ char __user *buf;
+ if (*bufs == NULL)
+ continue;
+ buf = *bufs + samples_to_bytes(runtime, off);
+ if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
+ return err;
+ }
+ } else {
+ snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c, ++bufs) {
+ char *hwbuf;
+ char __user *buf;
+ if (*bufs == NULL)
+ continue;
+
+ hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+ buf = *bufs + samples_to_bytes(runtime, off);
+ if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
+ return -EFAULT;
+ }
+ }
+ return 0;
+}
+
+snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime;
+ int nonblock;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+ runtime = substream->runtime;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ return -EINVAL;
+ return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
+}
+
+EXPORT_SYMBOL(snd_pcm_lib_readv);
/*
* standard channel mapping helpers
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
deleted file mode 100644
index c515612969a4..000000000000
--- a/sound/core/pcm_local.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * pcm_local.h - a local header file for snd-pcm module.
- *
- * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp>
- *
- * Licensed under the terms of the GNU General Public License, version 2.
- */
-
-#ifndef __SOUND_CORE_PCM_LOCAL_H
-#define __SOUND_CORE_PCM_LOCAL_H
-
-extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
-
-void snd_interval_mul(const struct snd_interval *a,
- const struct snd_interval *b, struct snd_interval *c);
-void snd_interval_div(const struct snd_interval *a,
- const struct snd_interval *b, struct snd_interval *c);
-void snd_interval_muldivk(const struct snd_interval *a,
- const struct snd_interval *b,
- unsigned int k, struct snd_interval *c);
-void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
- const struct snd_interval *b, struct snd_interval *c);
-
-int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
-int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
-
-int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
- snd_pcm_hw_param_t var, u_int32_t mask);
-
-int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t appl_ptr);
-int snd_pcm_update_state(struct snd_pcm_substream *substream,
- struct snd_pcm_runtime *runtime);
-int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
-
-void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t new_hw_ptr);
-
-static inline snd_pcm_uframes_t
-snd_pcm_avail(struct snd_pcm_substream *substream)
-{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return snd_pcm_playback_avail(substream->runtime);
- else
- return snd_pcm_capture_avail(substream->runtime);
-}
-
-static inline snd_pcm_uframes_t
-snd_pcm_hw_avail(struct snd_pcm_substream *substream)
-{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return snd_pcm_playback_hw_avail(substream->runtime);
- else
- return snd_pcm_capture_hw_avail(substream->runtime);
-}
-
-#ifdef CONFIG_SND_PCM_TIMER
-void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
-void snd_pcm_timer_init(struct snd_pcm_substream *substream);
-void snd_pcm_timer_done(struct snd_pcm_substream *substream);
-#else
-static inline void
-snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
-static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
-static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
-#endif
-
-void __snd_pcm_xrun(struct snd_pcm_substream *substream);
-
-#endif /* __SOUND_CORE_PCM_LOCAL_H */
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ae33e456708c..b45f6aa32264 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -120,6 +120,7 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free(substream);
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
#ifdef CONFIG_SND_VERBOSE_PROCFS
@@ -262,6 +263,7 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
substream->dma_buffer.dev.dev = data;
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
+
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
/**
@@ -290,6 +292,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
return err;
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
#ifdef CONFIG_SND_DMA_SGBUF
@@ -311,6 +314,7 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
return NULL;
return sgbuf->page_table[idx];
}
+
EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
#endif /* CONFIG_SND_DMA_SGBUF */
@@ -366,6 +370,7 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
runtime->dma_bytes = size;
return 1; /* area was changed */
}
+
EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
/**
@@ -393,6 +398,7 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_lib_free_pages);
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index c4eb561d2008..53dc37357bca 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -23,9 +23,6 @@
#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
-
-#include "pcm_local.h"
-
#define SND_PCM_FORMAT_UNKNOWN (-1)
/* NOTE: "signed" prefix must be given below since the default char is
@@ -163,30 +160,13 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
.width = 32, .phys = 32, .le = 0, .signd = 0,
.silence = { 0x69, 0x69, 0x69, 0x69 },
},
- /* FIXME: the following two formats are not defined properly yet */
+ /* FIXME: the following three formats are not defined properly yet */
[SNDRV_PCM_FORMAT_MPEG] = {
.le = -1, .signd = -1,
},
[SNDRV_PCM_FORMAT_GSM] = {
.le = -1, .signd = -1,
},
- [SNDRV_PCM_FORMAT_S20_LE] = {
- .width = 20, .phys = 32, .le = 1, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_S20_BE] = {
- .width = 20, .phys = 32, .le = 0, .signd = 1,
- .silence = {},
- },
- [SNDRV_PCM_FORMAT_U20_LE] = {
- .width = 20, .phys = 32, .le = 1, .signd = 0,
- .silence = { 0x00, 0x00, 0x08, 0x00 },
- },
- [SNDRV_PCM_FORMAT_U20_BE] = {
- .width = 20, .phys = 32, .le = 0, .signd = 0,
- .silence = { 0x00, 0x08, 0x00, 0x00 },
- },
- /* FIXME: the following format is not defined properly yet */
[SNDRV_PCM_FORMAT_SPECIAL] = {
.le = -1, .signd = -1,
},
@@ -265,6 +245,7 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
return -EINVAL;
return val;
}
+
EXPORT_SYMBOL(snd_pcm_format_signed);
/**
@@ -283,6 +264,7 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format)
return val;
return !val;
}
+
EXPORT_SYMBOL(snd_pcm_format_unsigned);
/**
@@ -295,6 +277,7 @@ int snd_pcm_format_linear(snd_pcm_format_t format)
{
return snd_pcm_format_signed(format) >= 0;
}
+
EXPORT_SYMBOL(snd_pcm_format_linear);
/**
@@ -313,6 +296,7 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
return -EINVAL;
return val;
}
+
EXPORT_SYMBOL(snd_pcm_format_little_endian);
/**
@@ -331,6 +315,7 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
return val;
return !val;
}
+
EXPORT_SYMBOL(snd_pcm_format_big_endian);
/**
@@ -349,6 +334,7 @@ int snd_pcm_format_width(snd_pcm_format_t format)
return -EINVAL;
return val;
}
+
EXPORT_SYMBOL(snd_pcm_format_width);
/**
@@ -367,6 +353,7 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
return -EINVAL;
return val;
}
+
EXPORT_SYMBOL(snd_pcm_format_physical_width);
/**
@@ -384,6 +371,7 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
return -EINVAL;
return samples * phys_width / 8;
}
+
EXPORT_SYMBOL(snd_pcm_format_size);
/**
@@ -400,6 +388,7 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
return NULL;
return pcm_formats[(INT)format].silence;
}
+
EXPORT_SYMBOL(snd_pcm_format_silence_64);
/**
@@ -470,6 +459,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
#endif
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_format_set_silence);
/**
@@ -498,6 +488,7 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
}
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
/**
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 234963c5bd8b..5c58d1cfe959 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -38,18 +38,6 @@
#include <linux/uio.h>
#include <linux/delay.h>
-#include "pcm_local.h"
-
-#ifdef CONFIG_SND_DEBUG
-#define CREATE_TRACE_POINTS
-#include "pcm_param_trace.h"
-#else
-#define trace_hw_mask_param_enabled() 0
-#define trace_hw_interval_param_enabled() 0
-#define trace_hw_mask_param(substream, type, index, prev, curr)
-#define trace_hw_interval_param(substream, type, index, prev, curr)
-#endif
-
/*
* Compatibility
*/
@@ -100,57 +88,6 @@ static inline void down_write_nonfifo(struct rw_semaphore *lock)
msleep(1);
}
-#define PCM_LOCK_DEFAULT 0
-#define PCM_LOCK_IRQ 1
-#define PCM_LOCK_IRQSAVE 2
-
-static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
- unsigned int mode)
-{
- unsigned long flags = 0;
- if (substream->pcm->nonatomic) {
- down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
- mutex_lock(&substream->self_group.mutex);
- } else {
- switch (mode) {
- case PCM_LOCK_DEFAULT:
- read_lock(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQ:
- read_lock_irq(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQSAVE:
- read_lock_irqsave(&snd_pcm_link_rwlock, flags);
- break;
- }
- spin_lock(&substream->self_group.lock);
- }
- return flags;
-}
-
-static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
- unsigned int mode, unsigned long flags)
-{
- if (substream->pcm->nonatomic) {
- mutex_unlock(&substream->self_group.mutex);
- up_read(&snd_pcm_link_rwsem);
- } else {
- spin_unlock(&substream->self_group.lock);
-
- switch (mode) {
- case PCM_LOCK_DEFAULT:
- read_unlock(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQ:
- read_unlock_irq(&snd_pcm_link_rwlock);
- break;
- case PCM_LOCK_IRQSAVE:
- read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
- break;
- }
- }
-}
-
/**
* snd_pcm_stream_lock - Lock the PCM stream
* @substream: PCM substream
@@ -161,7 +98,13 @@ static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
*/
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
+ if (substream->pcm->nonatomic) {
+ down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
+ mutex_lock(&substream->self_group.mutex);
+ } else {
+ read_lock(&snd_pcm_link_rwlock);
+ spin_lock(&substream->self_group.lock);
+ }
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
@@ -173,7 +116,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
*/
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
+ if (substream->pcm->nonatomic) {
+ mutex_unlock(&substream->self_group.mutex);
+ up_read(&snd_pcm_link_rwsem);
+ } else {
+ spin_unlock(&substream->self_group.lock);
+ read_unlock(&snd_pcm_link_rwlock);
+ }
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
@@ -187,7 +136,9 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
*/
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
+ if (!substream->pcm->nonatomic)
+ local_irq_disable();
+ snd_pcm_stream_lock(substream);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
@@ -199,13 +150,19 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
*/
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
+ snd_pcm_stream_unlock(substream);
+ if (!substream->pcm->nonatomic)
+ local_irq_enable();
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
{
- return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
+ unsigned long flags = 0;
+ if (!substream->pcm->nonatomic)
+ local_irq_save(flags);
+ snd_pcm_stream_lock(substream);
+ return flags;
}
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
@@ -219,12 +176,29 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
unsigned long flags)
{
- __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
+ snd_pcm_stream_unlock(substream);
+ if (!substream->pcm->nonatomic)
+ local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
+static inline mm_segment_t snd_enter_user(void)
+{
+ mm_segment_t fs = get_fs();
+ set_fs(get_ds());
+ return fs;
+}
+
+static inline void snd_leave_user(mm_segment_t fs)
+{
+ set_fs(fs);
+}
+
+
+
int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
{
+ struct snd_pcm_runtime *runtime;
struct snd_pcm *pcm = substream->pcm;
struct snd_pcm_str *pstr = substream->pstr;
@@ -240,7 +214,12 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
info->subdevices_count = pstr->substream_count;
info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
strlcpy(info->subname, substream->name, sizeof(info->subname));
-
+ runtime = substream->runtime;
+ /* AB: FIXME!!! This is definitely nonsense */
+ if (runtime) {
+ info->sync = runtime->sync;
+ substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
+ }
return 0;
}
@@ -266,8 +245,10 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
{
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
return false;
- /* architecture supports dma_mmap_coherent()? */
-#if defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) || !defined(CONFIG_HAS_DMA)
+ /* check architectures that return -EINVAL from dma_mmap_coherent() */
+ /* FIXME: this should be some global flag */
+#if defined(CONFIG_C6X) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) ||\
+ defined(CONFIG_PARISC) || defined(CONFIG_XTENSA)
if (!substream->ops->mmap &&
substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
return false;
@@ -275,273 +256,205 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
return true;
}
-static int constrain_mask_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+#undef RULES_DEBUG
+
+#ifdef RULES_DEBUG
+#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
+static const char * const snd_pcm_hw_param_names[] = {
+ HW_PARAM(ACCESS),
+ HW_PARAM(FORMAT),
+ HW_PARAM(SUBFORMAT),
+ HW_PARAM(SAMPLE_BITS),
+ HW_PARAM(FRAME_BITS),
+ HW_PARAM(CHANNELS),
+ HW_PARAM(RATE),
+ HW_PARAM(PERIOD_TIME),
+ HW_PARAM(PERIOD_SIZE),
+ HW_PARAM(PERIOD_BYTES),
+ HW_PARAM(PERIODS),
+ HW_PARAM(BUFFER_TIME),
+ HW_PARAM(BUFFER_SIZE),
+ HW_PARAM(BUFFER_BYTES),
+ HW_PARAM(TICK_TIME),
+};
+#endif
+
+int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- struct snd_pcm_hw_constraints *constrs =
- &substream->runtime->hw_constraints;
- struct snd_mask *m;
unsigned int k;
- struct snd_mask old_mask;
- int changed;
+ struct snd_pcm_hardware *hw;
+ struct snd_interval *i = NULL;
+ struct snd_mask *m = NULL;
+ struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
+ unsigned int rstamps[constrs->rules_num];
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+ unsigned int stamp = 2;
+ int changed, again;
+
+ params->info = 0;
+ params->fifo_size = 0;
+ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
+ params->msbits = 0;
+ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
+ params->rate_num = 0;
+ params->rate_den = 0;
+ }
for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
m = hw_param_mask(params, k);
if (snd_mask_empty(m))
return -EINVAL;
-
- /* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k)))
continue;
-
- if (trace_hw_mask_param_enabled())
- old_mask = *m;
-
+#ifdef RULES_DEBUG
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+ pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+#endif
changed = snd_mask_refine(m, constrs_mask(constrs, k));
+#ifdef RULES_DEBUG
+ pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+#endif
+ if (changed)
+ params->cmask |= 1 << k;
if (changed < 0)
return changed;
- if (changed == 0)
- continue;
-
- /* Set corresponding flag so that the caller gets it. */
- trace_hw_mask_param(substream, k, 0, &old_mask, m);
- params->cmask |= 1 << k;
}
- return 0;
-}
-
-static int constrain_interval_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_hw_constraints *constrs =
- &substream->runtime->hw_constraints;
- struct snd_interval *i;
- unsigned int k;
- struct snd_interval old_interval;
- int changed;
-
for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
i = hw_param_interval(params, k);
if (snd_interval_empty(i))
return -EINVAL;
-
- /* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k)))
continue;
-
- if (trace_hw_interval_param_enabled())
- old_interval = *i;
-
+#ifdef RULES_DEBUG
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+ if (i->empty)
+ pr_cont("empty");
+ else
+ pr_cont("%c%u %u%c",
+ i->openmin ? '(' : '[', i->min,
+ i->max, i->openmax ? ')' : ']');
+ pr_cont(" -> ");
+#endif
changed = snd_interval_refine(i, constrs_interval(constrs, k));
+#ifdef RULES_DEBUG
+ if (i->empty)
+ pr_cont("empty\n");
+ else
+ pr_cont("%c%u %u%c\n",
+ i->openmin ? '(' : '[', i->min,
+ i->max, i->openmax ? ')' : ']');
+#endif
+ if (changed)
+ params->cmask |= 1 << k;
if (changed < 0)
return changed;
- if (changed == 0)
- continue;
-
- /* Set corresponding flag so that the caller gets it. */
- trace_hw_interval_param(substream, k, 0, &old_interval, i);
- params->cmask |= 1 << k;
}
- return 0;
-}
-
-static int constrain_params_by_rules(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_hw_constraints *constrs =
- &substream->runtime->hw_constraints;
- unsigned int k;
- unsigned int *rstamps;
- unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
- unsigned int stamp;
- struct snd_pcm_hw_rule *r;
- unsigned int d;
- struct snd_mask old_mask;
- struct snd_interval old_interval;
- bool again;
- int changed, err = 0;
-
- /*
- * Each application of rule has own sequence number.
- *
- * Each member of 'rstamps' array represents the sequence number of
- * recent application of corresponding rule.
- */
- rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
- if (!rstamps)
- return -ENOMEM;
-
- /*
- * Each member of 'vstamps' array represents the sequence number of
- * recent application of rule in which corresponding parameters were
- * changed.
- *
- * In initial state, elements corresponding to parameters requested by
- * a caller is 1. For unrequested parameters, corresponding members
- * have 0 so that the parameters are never changed anymore.
- */
- for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ for (k = 0; k < constrs->rules_num; k++)
+ rstamps[k] = 0;
+ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
-
- /* Due to the above design, actual sequence number starts at 2. */
- stamp = 2;
-retry:
- /* Apply all rules in order. */
- again = false;
- for (k = 0; k < constrs->rules_num; k++) {
- r = &constrs->rules[k];
-
- /*
- * Check condition bits of this rule. When the rule has
- * some condition bits, parameter without the bits is
- * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
- * is an example of the condition bits.
- */
- if (r->cond && !(r->cond & params->flags))
- continue;
-
- /*
- * The 'deps' array includes maximum three dependencies
- * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
- * member of this array is a sentinel and should be
- * negative value.
- *
- * This rule should be processed in this time when dependent
- * parameters were changed at former applications of the other
- * rules.
- */
- for (d = 0; r->deps[d] >= 0; d++) {
- if (vstamps[r->deps[d]] > rstamps[k])
- break;
- }
- if (r->deps[d] < 0)
- continue;
-
- if (trace_hw_mask_param_enabled()) {
- if (hw_is_mask(r->var))
- old_mask = *hw_param_mask(params, r->var);
- }
- if (trace_hw_interval_param_enabled()) {
- if (hw_is_interval(r->var))
- old_interval = *hw_param_interval(params, r->var);
- }
-
- changed = r->func(params, r);
- if (changed < 0) {
- err = changed;
- goto out;
- }
-
- /*
- * When the parameter is changed, notify it to the caller
- * by corresponding returned bit, then preparing for next
- * iteration.
- */
- if (changed && r->var >= 0) {
- if (hw_is_mask(r->var)) {
- trace_hw_mask_param(substream, r->var,
- k + 1, &old_mask,
- hw_param_mask(params, r->var));
+ do {
+ again = 0;
+ for (k = 0; k < constrs->rules_num; k++) {
+ struct snd_pcm_hw_rule *r = &constrs->rules[k];
+ unsigned int d;
+ int doit = 0;
+ if (r->cond && !(r->cond & params->flags))
+ continue;
+ for (d = 0; r->deps[d] >= 0; d++) {
+ if (vstamps[r->deps[d]] > rstamps[k]) {
+ doit = 1;
+ break;
+ }
}
- if (hw_is_interval(r->var)) {
- trace_hw_interval_param(substream, r->var,
- k + 1, &old_interval,
- hw_param_interval(params, r->var));
+ if (!doit)
+ continue;
+#ifdef RULES_DEBUG
+ pr_debug("Rule %d [%p]: ", k, r->func);
+ if (r->var >= 0) {
+ pr_cont("%s = ", snd_pcm_hw_param_names[r->var]);
+ if (hw_is_mask(r->var)) {
+ m = hw_param_mask(params, r->var);
+ pr_cont("%x", *m->bits);
+ } else {
+ i = hw_param_interval(params, r->var);
+ if (i->empty)
+ pr_cont("empty");
+ else
+ pr_cont("%c%u %u%c",
+ i->openmin ? '(' : '[', i->min,
+ i->max, i->openmax ? ')' : ']');
+ }
}
-
- params->cmask |= (1 << r->var);
- vstamps[r->var] = stamp;
- again = true;
+#endif
+ changed = r->func(params, r);
+#ifdef RULES_DEBUG
+ if (r->var >= 0) {
+ pr_cont(" -> ");
+ if (hw_is_mask(r->var))
+ pr_cont("%x", *m->bits);
+ else {
+ if (i->empty)
+ pr_cont("empty");
+ else
+ pr_cont("%c%u %u%c",
+ i->openmin ? '(' : '[', i->min,
+ i->max, i->openmax ? ')' : ']');
+ }
+ }
+ pr_cont("\n");
+#endif
+ rstamps[k] = stamp;
+ if (changed && r->var >= 0) {
+ params->cmask |= (1 << r->var);
+ vstamps[r->var] = stamp;
+ again = 1;
+ }
+ if (changed < 0)
+ return changed;
+ stamp++;
}
-
- rstamps[k] = stamp++;
- }
-
- /* Iterate to evaluate all rules till no parameters are changed. */
- if (again)
- goto retry;
-
- out:
- kfree(rstamps);
- return err;
-}
-
-static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- const struct snd_interval *i;
- const struct snd_mask *m;
- int err;
-
+ } while (again);
if (!params->msbits) {
- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
if (snd_interval_single(i))
params->msbits = snd_interval_value(i);
}
if (!params->rate_den) {
- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
+ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (snd_interval_single(i)) {
params->rate_num = snd_interval_value(i);
params->rate_den = 1;
}
}
- if (!params->fifo_size) {
- m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- if (snd_mask_single(m) && snd_interval_single(i)) {
- err = substream->ops->ioctl(substream,
- SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
- if (err < 0)
- return err;
- }
- }
-
+ hw = &substream->runtime->hw;
if (!params->info) {
- params->info = substream->runtime->hw.info;
- params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
- SNDRV_PCM_INFO_DRAIN_TRIGGER);
+ params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
+ SNDRV_PCM_INFO_DRAIN_TRIGGER);
if (!hw_support_mmap(substream))
params->info &= ~(SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID);
}
-
- return 0;
-}
-
-int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- int err;
-
- params->info = 0;
- params->fifo_size = 0;
- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
- params->msbits = 0;
- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
- params->rate_num = 0;
- params->rate_den = 0;
+ if (!params->fifo_size) {
+ m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ if (snd_mask_min(m) == snd_mask_max(m) &&
+ snd_interval_min(i) == snd_interval_max(i)) {
+ changed = substream->ops->ioctl(substream,
+ SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
+ if (changed < 0)
+ return changed;
+ }
}
-
- err = constrain_mask_params(substream, params);
- if (err < 0)
- return err;
-
- err = constrain_interval_params(substream, params);
- if (err < 0)
- return err;
-
- err = constrain_params_by_rules(substream, params);
- if (err < 0)
- return err;
-
params->rmask = 0;
-
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_hw_refine);
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
@@ -555,16 +468,11 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
return PTR_ERR(params);
err = snd_pcm_hw_refine(substream, params);
- if (err < 0)
- goto end;
-
- err = fixup_unreferenced_params(substream, params);
- if (err < 0)
- goto end;
+ if (copy_to_user(_params, params, sizeof(*params))) {
+ if (!err)
+ err = -EFAULT;
+ }
- if (copy_to_user(_params, params, sizeof(*params)))
- err = -EFAULT;
-end:
kfree(params);
return err;
}
@@ -602,70 +510,6 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
#endif
}
-/**
- * snd_pcm_hw_param_choose - choose a configuration defined by @params
- * @pcm: PCM instance
- * @params: the hw_params instance
- *
- * Choose one configuration from configuration space defined by @params.
- * The configuration chosen is that obtained fixing in this order:
- * first access, first format, first subformat, min channels,
- * min rate, min period time, max buffer size, min tick time
- *
- * Return: Zero if successful, or a negative error code on failure.
- */
-static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
- struct snd_pcm_hw_params *params)
-{
- static const int vars[] = {
- SNDRV_PCM_HW_PARAM_ACCESS,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_HW_PARAM_SUBFORMAT,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- SNDRV_PCM_HW_PARAM_RATE,
- SNDRV_PCM_HW_PARAM_PERIOD_TIME,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- SNDRV_PCM_HW_PARAM_TICK_TIME,
- -1
- };
- const int *v;
- struct snd_mask old_mask;
- struct snd_interval old_interval;
- int changed;
-
- for (v = vars; *v != -1; v++) {
- /* Keep old parameter to trace. */
- if (trace_hw_mask_param_enabled()) {
- if (hw_is_mask(*v))
- old_mask = *hw_param_mask(params, *v);
- }
- if (trace_hw_interval_param_enabled()) {
- if (hw_is_interval(*v))
- old_interval = *hw_param_interval(params, *v);
- }
- if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
- changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
- else
- changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
- if (changed < 0)
- return changed;
- if (changed == 0)
- continue;
-
- /* Trace the changed parameter. */
- if (hw_is_mask(*v)) {
- trace_hw_mask_param(pcm, *v, 0, &old_mask,
- hw_param_mask(params, *v));
- }
- if (hw_is_interval(*v)) {
- trace_hw_interval_param(pcm, *v, 0, &old_interval,
- hw_param_interval(params, *v));
- }
- }
-
- return 0;
-}
-
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -703,10 +547,6 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
goto _error;
- err = fixup_unreferenced_params(substream, params);
- if (err < 0)
- goto _error;
-
if (substream->ops->hw_params != NULL) {
err = substream->ops->hw_params(substream, params);
if (err < 0)
@@ -782,12 +622,11 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
return PTR_ERR(params);
err = snd_pcm_hw_params(substream, params);
- if (err < 0)
- goto end;
+ if (copy_to_user(_params, params, sizeof(*params))) {
+ if (!err)
+ err = -EFAULT;
+ }
- if (copy_to_user(_params, params, sizeof(*params)))
- err = -EFAULT;
-end:
kfree(params);
return err;
}
@@ -887,18 +726,6 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
return err;
}
-static inline snd_pcm_uframes_t
-snd_pcm_calc_delay(struct snd_pcm_substream *substream)
-{
- snd_pcm_uframes_t delay;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- delay = snd_pcm_playback_hw_avail(substream->runtime);
- else
- delay = snd_pcm_capture_avail(substream->runtime);
- return delay + substream->runtime->delay;
-}
-
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status)
{
@@ -950,9 +777,21 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
_tstamp_end:
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
- status->avail = snd_pcm_avail(substream);
- status->delay = snd_pcm_running(substream) ?
- snd_pcm_calc_delay(substream) : 0;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ status->avail = snd_pcm_playback_avail(runtime);
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ status->delay = runtime->buffer_size - status->avail;
+ status->delay += runtime->delay;
+ } else
+ status->delay = 0;
+ } else {
+ status->avail = snd_pcm_capture_avail(runtime);
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ status->delay = status->avail + runtime->delay;
+ else
+ status->delay = 0;
+ }
status->avail_max = runtime->avail_max;
status->overrange = runtime->overrange;
runtime->avail_max = 0;
@@ -1243,7 +1082,6 @@ static const struct action_ops snd_pcm_action_start = {
* @substream: the PCM substream instance
*
* Return: Zero if successful, or a negative error code.
- * The stream lock must be acquired before calling this function.
*/
int snd_pcm_start(struct snd_pcm_substream *substream)
{
@@ -1251,13 +1089,6 @@ int snd_pcm_start(struct snd_pcm_substream *substream)
SNDRV_PCM_STATE_RUNNING);
}
-/* take the stream lock and start the streams */
-static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
-{
- return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
- SNDRV_PCM_STATE_RUNNING);
-}
-
/*
* stop callbacks
*/
@@ -1309,6 +1140,7 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
{
return snd_pcm_action(&snd_pcm_action_stop, substream, state);
}
+
EXPORT_SYMBOL(snd_pcm_stop);
/**
@@ -1338,12 +1170,13 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream)
int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
{
unsigned long flags;
+ int ret = 0;
snd_pcm_stream_lock_irqsave(substream, flags);
- if (substream->runtime && snd_pcm_running(substream))
- __snd_pcm_xrun(substream);
+ if (snd_pcm_running(substream))
+ ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(substream, flags);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
@@ -1482,6 +1315,7 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
snd_pcm_stream_unlock_irqrestore(substream, flags);
return err;
}
+
EXPORT_SYMBOL(snd_pcm_suspend);
/**
@@ -1513,6 +1347,7 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
}
return 0;
}
+
EXPORT_SYMBOL(snd_pcm_suspend_all);
/* resume */
@@ -1563,7 +1398,14 @@ static const struct action_ops snd_pcm_action_resume = {
static int snd_pcm_resume(struct snd_pcm_substream *substream)
{
- return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+ struct snd_card *card = substream->pcm->card;
+ int res;
+
+ snd_power_lock(card);
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
+ res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+ snd_power_unlock(card);
+ return res;
}
#else
@@ -1582,22 +1424,31 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
*/
static int snd_pcm_xrun(struct snd_pcm_substream *substream)
{
+ struct snd_card *card = substream->pcm->card;
struct snd_pcm_runtime *runtime = substream->runtime;
int result;
+ snd_power_lock(card);
+ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+ if (result < 0)
+ goto _unlock;
+ }
+
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN:
result = 0; /* already there */
break;
case SNDRV_PCM_STATE_RUNNING:
- __snd_pcm_xrun(substream);
- result = 0;
+ result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
break;
default:
result = -EBADFD;
}
snd_pcm_stream_unlock_irq(substream);
+ _unlock:
+ snd_power_unlock(card);
return result;
}
@@ -1701,6 +1552,8 @@ static const struct action_ops snd_pcm_action_prepare = {
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
struct file *file)
{
+ int res;
+ struct snd_card *card = substream->pcm->card;
int f_flags;
if (file)
@@ -1708,19 +1561,12 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
else
f_flags = substream->f_flags;
- snd_pcm_stream_lock_irq(substream);
- switch (substream->runtime->status->state) {
- case SNDRV_PCM_STATE_PAUSED:
- snd_pcm_pause(substream, 0);
- /* fallthru */
- case SNDRV_PCM_STATE_SUSPENDED:
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- break;
- }
- snd_pcm_stream_unlock_irq(substream);
-
- return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
- substream, f_flags);
+ snd_power_lock(card);
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
+ res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
+ substream, f_flags);
+ snd_power_unlock(card);
+ return res;
}
/*
@@ -1817,6 +1663,15 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
+ snd_power_lock(card);
+ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+ if (result < 0) {
+ snd_power_unlock(card);
+ return result;
+ }
+ }
+
if (file) {
if (file->f_flags & O_NONBLOCK)
nonblock = 1;
@@ -1863,6 +1718,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
add_wait_queue(&to_check->sleep, &wait);
snd_pcm_stream_unlock_irq(substream);
up_read(&snd_pcm_link_rwsem);
+ snd_power_unlock(card);
if (runtime->no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
else {
@@ -1874,6 +1730,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
tout = msecs_to_jiffies(tout * 1000);
}
tout = schedule_timeout_interruptible(tout);
+ snd_power_lock(card);
down_read(&snd_pcm_link_rwsem);
snd_pcm_stream_lock_irq(substream);
remove_wait_queue(&to_check->sleep, &wait);
@@ -1897,6 +1754,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
unlock:
snd_pcm_stream_unlock_irq(substream);
up_read(&snd_pcm_link_rwsem);
+ snd_power_unlock(card);
return result;
}
@@ -1916,7 +1774,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
+ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
+ runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
return -EBADFD;
snd_pcm_stream_lock_irq(substream);
@@ -2082,8 +1941,7 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
unsigned int k;
- const struct snd_interval *i =
- hw_param_interval_c(params, rule->deps[0]);
+ struct snd_interval *i = hw_param_interval(params, rule->deps[0]);
struct snd_mask m;
struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_any(&m);
@@ -2129,10 +1987,8 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
#error "Change this table"
#endif
-static const unsigned int rates[] = {
- 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000
-};
+static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+ 48000, 64000, 88200, 96000, 176400, 192000 };
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
.count = ARRAY_SIZE(rates),
@@ -2396,6 +2252,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
}
snd_pcm_detach_substream(substream);
}
+
EXPORT_SYMBOL(snd_pcm_release_substream);
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
@@ -2437,6 +2294,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
snd_pcm_release_substream(substream);
return err;
}
+
EXPORT_SYMBOL(snd_pcm_open_substream);
static int snd_pcm_open_file(struct file *file,
@@ -2596,6 +2454,30 @@ static int do_pcm_hwsync(struct snd_pcm_substream *substream)
}
}
+/* update to the given appl_ptr and call ack callback if needed;
+ * when an error is returned, take back to the original value
+ */
+static int apply_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t appl_ptr)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
+ int ret;
+
+ if (old_appl_ptr == appl_ptr)
+ return 0;
+
+ runtime->control->appl_ptr = appl_ptr;
+ if (substream->ops->ack) {
+ ret = substream->ops->ack(substream);
+ if (ret < 0) {
+ runtime->control->appl_ptr = old_appl_ptr;
+ return ret;
+ }
+ }
+ return 0;
+}
+
/* increase the appl_ptr; returns the processed frames or a negative error */
static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames,
@@ -2612,7 +2494,7 @@ static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
appl_ptr = runtime->control->appl_ptr + frames;
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
appl_ptr -= runtime->boundary;
- ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
+ ret = apply_appl_ptr(substream, appl_ptr);
return ret < 0 ? ret : frames;
}
@@ -2632,7 +2514,7 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
appl_ptr = runtime->control->appl_ptr - frames;
if (appl_ptr < 0)
appl_ptr += runtime->boundary;
- ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
+ ret = apply_appl_ptr(substream, appl_ptr);
/* NOTE: we return zero for errors because PulseAudio gets depressed
* upon receiving an error from rewind ioctl and stops processing
* any longer. Returning zero means that no rewind is done, so
@@ -2641,9 +2523,10 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
return ret < 0 ? 0 : frames;
}
-static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@@ -2653,14 +2536,51 @@ static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
- snd_pcm_hw_avail(substream));
+ snd_pcm_playback_hw_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
-static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t ret;
+
+ if (frames == 0)
+ return 0;
+
+ snd_pcm_stream_lock_irq(substream);
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = rewind_appl_ptr(substream, frames,
+ snd_pcm_capture_hw_avail(runtime));
+ snd_pcm_stream_unlock_irq(substream);
+ return ret;
+}
+
+static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t ret;
+
+ if (frames == 0)
+ return 0;
+
+ snd_pcm_stream_lock_irq(substream);
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = forward_appl_ptr(substream, frames,
+ snd_pcm_playback_avail(runtime));
+ snd_pcm_stream_unlock_irq(substream);
+ return ret;
+}
+
+static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@@ -2670,7 +2590,7 @@ static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
- snd_pcm_avail(substream));
+ snd_pcm_capture_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@@ -2686,18 +2606,25 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
}
static int snd_pcm_delay(struct snd_pcm_substream *substream,
- snd_pcm_sframes_t *delay)
+ snd_pcm_sframes_t __user *res)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
snd_pcm_stream_lock_irq(substream);
err = do_pcm_hwsync(substream);
- if (!err)
- n = snd_pcm_calc_delay(substream);
+ if (!err) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ n = snd_pcm_playback_hw_avail(runtime);
+ else
+ n = snd_pcm_capture_avail(runtime);
+ n += runtime->delay;
+ }
snd_pcm_stream_unlock_irq(substream);
if (!err)
- *delay = n;
+ if (put_user(n, res))
+ err = -EFAULT;
return err;
}
@@ -2724,8 +2651,7 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
}
snd_pcm_stream_lock_irq(substream);
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
- err = pcm_lib_apply_appl_ptr(substream,
- sync_ptr.c.control.appl_ptr);
+ err = apply_appl_ptr(substream, sync_ptr.c.control.appl_ptr);
if (err < 0) {
snd_pcm_stream_unlock_irq(substream);
return err;
@@ -2760,101 +2686,11 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
runtime->tstamp_type = arg;
return 0;
}
-
-static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
- struct snd_xferi __user *_xferi)
-{
- struct snd_xferi xferi;
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t result;
-
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (put_user(0, &_xferi->result))
- return -EFAULT;
- if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
- return -EFAULT;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
- else
- result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
- __put_user(result, &_xferi->result);
- return result < 0 ? result : 0;
-}
-
-static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
- struct snd_xfern __user *_xfern)
-{
- struct snd_xfern xfern;
- struct snd_pcm_runtime *runtime = substream->runtime;
- void *bufs;
- snd_pcm_sframes_t result;
-
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- if (runtime->channels > 128)
- return -EINVAL;
- if (put_user(0, &_xfern->result))
- return -EFAULT;
- if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
- return -EFAULT;
-
- bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
- if (IS_ERR(bufs))
- return PTR_ERR(bufs);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
- else
- result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
- kfree(bufs);
- __put_user(result, &_xfern->result);
- return result < 0 ? result : 0;
-}
-
-static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t __user *_frames)
-{
- snd_pcm_uframes_t frames;
- snd_pcm_sframes_t result;
-
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_rewind(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
-}
-
-static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t __user *_frames)
-{
- snd_pcm_uframes_t frames;
- snd_pcm_sframes_t result;
-
- if (get_user(frames, _frames))
- return -EFAULT;
- if (put_user(0, _frames))
- return -EFAULT;
- result = snd_pcm_forward(substream, frames);
- __put_user(result, _frames);
- return result < 0 ? result : 0;
-}
-
-static int snd_pcm_common_ioctl(struct file *file,
+
+static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
- struct snd_pcm_file *pcm_file = file->private_data;
- int res;
-
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
-
- res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
- if (res < 0)
- return res;
-
switch (cmd) {
case SNDRV_PCM_IOCTL_PVERSION:
return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -2864,11 +2700,6 @@ static int snd_pcm_common_ioctl(struct file *file,
return 0;
case SNDRV_PCM_IOCTL_TTSTAMP:
return snd_pcm_tstamp(substream, arg);
- case SNDRV_PCM_IOCTL_USER_PVERSION:
- if (get_user(pcm_file->user_pversion,
- (unsigned int __user *)arg))
- return -EFAULT;
- return 0;
case SNDRV_PCM_IOCTL_HW_REFINE:
return snd_pcm_hw_refine_user(substream, arg);
case SNDRV_PCM_IOCTL_HW_PARAMS:
@@ -2888,7 +2719,7 @@ static int snd_pcm_common_ioctl(struct file *file,
case SNDRV_PCM_IOCTL_RESET:
return snd_pcm_reset(substream);
case SNDRV_PCM_IOCTL_START:
- return snd_pcm_start_lock_irq(substream);
+ return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
case SNDRV_PCM_IOCTL_LINK:
return snd_pcm_link(substream, (int)(unsigned long) arg);
case SNDRV_PCM_IOCTL_UNLINK:
@@ -2900,18 +2731,7 @@ static int snd_pcm_common_ioctl(struct file *file,
case SNDRV_PCM_IOCTL_HWSYNC:
return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY:
- {
- snd_pcm_sframes_t delay;
- snd_pcm_sframes_t __user *res = arg;
- int err;
-
- err = snd_pcm_delay(substream, &delay);
- if (err)
- return err;
- if (put_user(delay, res))
- return -EFAULT;
- return 0;
- }
+ return snd_pcm_delay(substream, arg);
case SNDRV_PCM_IOCTL_SYNC_PTR:
return snd_pcm_sync_ptr(substream, arg);
#ifdef CONFIG_SND_SUPPORT_OLD_API
@@ -2925,26 +2745,180 @@ static int snd_pcm_common_ioctl(struct file *file,
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream);
case SNDRV_PCM_IOCTL_PAUSE:
- return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
- substream,
- (int)(unsigned long)arg);
+ {
+ int res;
+ snd_pcm_stream_lock_irq(substream);
+ res = snd_pcm_pause(substream, (int)(unsigned long)arg);
+ snd_pcm_stream_unlock_irq(substream);
+ return res;
+ }
+ }
+ pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
+ return -ENOTTY;
+}
+
+static int snd_pcm_playback_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+{
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
+ return -EINVAL;
+ switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
- case SNDRV_PCM_IOCTL_READI_FRAMES:
- return snd_pcm_xferi_frames_ioctl(substream, arg);
+ {
+ struct snd_xferi xferi;
+ struct snd_xferi __user *_xferi = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t result;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ if (put_user(0, &_xferi->result))
+ return -EFAULT;
+ if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
+ return -EFAULT;
+ result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
+ __put_user(result, &_xferi->result);
+ return result < 0 ? result : 0;
+ }
case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+ {
+ struct snd_xfern xfern;
+ struct snd_xfern __user *_xfern = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ void __user **bufs;
+ snd_pcm_sframes_t result;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ if (runtime->channels > 128)
+ return -EINVAL;
+ if (put_user(0, &_xfern->result))
+ return -EFAULT;
+ if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
+ return -EFAULT;
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
+ result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
+ kfree(bufs);
+ __put_user(result, &_xfern->result);
+ return result < 0 ? result : 0;
+ }
+ case SNDRV_PCM_IOCTL_REWIND:
+ {
+ snd_pcm_uframes_t frames;
+ snd_pcm_uframes_t __user *_frames = arg;
+ snd_pcm_sframes_t result;
+ if (get_user(frames, _frames))
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+ result = snd_pcm_playback_rewind(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
+ }
+ case SNDRV_PCM_IOCTL_FORWARD:
+ {
+ snd_pcm_uframes_t frames;
+ snd_pcm_uframes_t __user *_frames = arg;
+ snd_pcm_sframes_t result;
+ if (get_user(frames, _frames))
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+ result = snd_pcm_playback_forward(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
+ }
+ }
+ return snd_pcm_common_ioctl1(file, substream, cmd, arg);
+}
+
+static int snd_pcm_capture_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+{
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
+ return -EINVAL;
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_READI_FRAMES:
+ {
+ struct snd_xferi xferi;
+ struct snd_xferi __user *_xferi = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t result;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ if (put_user(0, &_xferi->result))
+ return -EFAULT;
+ if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
+ return -EFAULT;
+ result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
+ __put_user(result, &_xferi->result);
+ return result < 0 ? result : 0;
+ }
case SNDRV_PCM_IOCTL_READN_FRAMES:
- return snd_pcm_xfern_frames_ioctl(substream, arg);
+ {
+ struct snd_xfern xfern;
+ struct snd_xfern __user *_xfern = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ void *bufs;
+ snd_pcm_sframes_t result;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ if (runtime->channels > 128)
+ return -EINVAL;
+ if (put_user(0, &_xfern->result))
+ return -EFAULT;
+ if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
+ return -EFAULT;
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
+ result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
+ kfree(bufs);
+ __put_user(result, &_xfern->result);
+ return result < 0 ? result : 0;
+ }
case SNDRV_PCM_IOCTL_REWIND:
- return snd_pcm_rewind_ioctl(substream, arg);
+ {
+ snd_pcm_uframes_t frames;
+ snd_pcm_uframes_t __user *_frames = arg;
+ snd_pcm_sframes_t result;
+ if (get_user(frames, _frames))
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+ result = snd_pcm_capture_rewind(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
+ }
case SNDRV_PCM_IOCTL_FORWARD:
- return snd_pcm_forward_ioctl(substream, arg);
+ {
+ snd_pcm_uframes_t frames;
+ snd_pcm_uframes_t __user *_frames = arg;
+ snd_pcm_sframes_t result;
+ if (get_user(frames, _frames))
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+ result = snd_pcm_capture_forward(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
}
- pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
- return -ENOTTY;
+ }
+ return snd_pcm_common_ioctl1(file, substream, cmd, arg);
}
-static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
+static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
struct snd_pcm_file *pcm_file;
@@ -2953,53 +2927,48 @@ static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
- return snd_pcm_common_ioctl(file, pcm_file->substream, cmd,
- (void __user *)arg);
+ return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
+ (void __user *)arg);
+}
+
+static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct snd_pcm_file *pcm_file;
+
+ pcm_file = file->private_data;
+
+ if (((cmd >> 8) & 0xff) != 'A')
+ return -ENOTTY;
+
+ return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
+ (void __user *)arg);
}
-/**
- * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
- * @substream: PCM substream
- * @cmd: IOCTL cmd
- * @arg: IOCTL argument
- *
- * The function is provided primarily for OSS layer and USB gadget drivers,
- * and it allows only the limited set of ioctls (hw_params, sw_params,
- * prepare, start, drain, drop, forward).
- */
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
- snd_pcm_uframes_t *frames = arg;
- snd_pcm_sframes_t result;
+ mm_segment_t fs;
+ int result;
- switch (cmd) {
- case SNDRV_PCM_IOCTL_FORWARD:
- {
- /* provided only for OSS; capture-only and no value returned */
- if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
- return -EINVAL;
- result = snd_pcm_forward(substream, *frames);
- return result < 0 ? result : 0;
- }
- case SNDRV_PCM_IOCTL_HW_PARAMS:
- return snd_pcm_hw_params(substream, arg);
- case SNDRV_PCM_IOCTL_SW_PARAMS:
- return snd_pcm_sw_params(substream, arg);
- case SNDRV_PCM_IOCTL_PREPARE:
- return snd_pcm_prepare(substream, NULL);
- case SNDRV_PCM_IOCTL_START:
- return snd_pcm_start_lock_irq(substream);
- case SNDRV_PCM_IOCTL_DRAIN:
- return snd_pcm_drain(substream, NULL);
- case SNDRV_PCM_IOCTL_DROP:
- return snd_pcm_drop(substream);
- case SNDRV_PCM_IOCTL_DELAY:
- return snd_pcm_delay(substream, frames);
+ fs = snd_enter_user();
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
+ (void __user *)arg);
+ break;
+ case SNDRV_PCM_STREAM_CAPTURE:
+ result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
+ (void __user *)arg);
+ break;
default:
- return -EINVAL;
+ result = -EINVAL;
+ break;
}
+ snd_leave_user(fs);
+ return result;
}
+
EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
@@ -3121,46 +3090,82 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
return result;
}
-static unsigned int snd_pcm_poll(struct file *file, poll_table *wait)
+static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
- unsigned int mask, ok;
+ unsigned int mask;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ok = POLLOUT | POLLWRNORM;
- else
- ok = POLLIN | POLLRDNORM;
if (PCM_RUNTIME_CHECK(substream))
- return ok | POLLERR;
+ return POLLOUT | POLLWRNORM | POLLERR;
+ runtime = substream->runtime;
+ poll_wait(file, &runtime->sleep, wait);
+
+ snd_pcm_stream_lock_irq(substream);
+ avail = snd_pcm_playback_avail(runtime);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
+ if (avail >= runtime->control->avail_min) {
+ mask = POLLOUT | POLLWRNORM;
+ break;
+ }
+ /* Fall through */
+ case SNDRV_PCM_STATE_DRAINING:
+ mask = 0;
+ break;
+ default:
+ mask = POLLOUT | POLLWRNORM | POLLERR;
+ break;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+ return mask;
+}
+
+static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
+{
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ unsigned int mask;
+ snd_pcm_uframes_t avail;
+
+ pcm_file = file->private_data;
+
+ substream = pcm_file->substream;
+ if (PCM_RUNTIME_CHECK(substream))
+ return POLLIN | POLLRDNORM | POLLERR;
runtime = substream->runtime;
+
poll_wait(file, &runtime->sleep, wait);
- mask = 0;
snd_pcm_stream_lock_irq(substream);
- avail = snd_pcm_avail(substream);
+ avail = snd_pcm_capture_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
- if (avail >= runtime->control->avail_min)
- mask = ok;
+ if (avail >= runtime->control->avail_min) {
+ mask = POLLIN | POLLRDNORM;
+ break;
+ }
+ mask = 0;
break;
case SNDRV_PCM_STATE_DRAINING:
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- mask = ok;
- if (!avail)
- mask |= POLLERR;
+ if (avail > 0) {
+ mask = POLLIN | POLLRDNORM;
+ break;
}
- break;
+ /* Fall through */
default:
- mask = ok | POLLERR;
+ mask = POLLIN | POLLRDNORM | POLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
@@ -3247,41 +3252,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
return 0;
}
-
-static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
-{
- if (pcm_file->no_compat_mmap)
- return false;
- /* See pcm_control_mmap_allowed() below.
- * Since older alsa-lib requires both status and control mmaps to be
- * coupled, we have to disable the status mmap for old alsa-lib, too.
- */
- if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
- (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
- return false;
- return true;
-}
-
-static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
-{
- if (pcm_file->no_compat_mmap)
- return false;
- /* Disallow the control mmap when SYNC_APPLPTR flag is set;
- * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
- * thus it effectively assures the manual update of appl_ptr.
- */
- if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
- return false;
- return true;
-}
-
#else /* ! coherent mmap */
/*
* don't support mmap for status and control records.
*/
-#define pcm_status_mmap_allowed(pcm_file) false
-#define pcm_control_mmap_allowed(pcm_file) false
-
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
@@ -3366,7 +3340,7 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
}
#endif /* CONFIG_GENERIC_ALLOCATOR */
#ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */
- if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page &&
+ if (!substream->ops->page &&
substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
return dma_mmap_coherent(substream->dma_buffer.dev.dev,
area,
@@ -3396,11 +3370,12 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;;
area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
}
+
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
#endif /* SNDRV_PCM_INFO_MMAP */
@@ -3449,6 +3424,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
atomic_inc(&substream->mmap_count);
return err;
}
+
EXPORT_SYMBOL(snd_pcm_mmap_data);
static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
@@ -3465,11 +3441,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
offset = area->vm_pgoff << PAGE_SHIFT;
switch (offset) {
case SNDRV_PCM_MMAP_OFFSET_STATUS:
- if (!pcm_status_mmap_allowed(pcm_file))
+ if (pcm_file->no_compat_mmap)
return -ENXIO;
return snd_pcm_mmap_status(substream, file, area);
case SNDRV_PCM_MMAP_OFFSET_CONTROL:
- if (!pcm_control_mmap_allowed(pcm_file))
+ if (pcm_file->no_compat_mmap)
return -ENXIO;
return snd_pcm_mmap_control(substream, file, area);
default:
@@ -3565,17 +3541,12 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
}
snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_refine(substream, params);
- if (err < 0)
- goto out_old;
-
- err = fixup_unreferenced_params(substream, params);
- if (err < 0)
- goto out_old;
-
snd_pcm_hw_convert_to_old_params(oparams, params);
- if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
- err = -EFAULT;
-out_old:
+ if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+ if (!err)
+ err = -EFAULT;
+ }
+
kfree(oparams);
out:
kfree(params);
@@ -3598,16 +3569,14 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
err = PTR_ERR(oparams);
goto out;
}
-
snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_params(substream, params);
- if (err < 0)
- goto out_old;
-
snd_pcm_hw_convert_to_old_params(oparams, params);
- if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
- err = -EFAULT;
-out_old:
+ if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+ if (!err)
+ err = -EFAULT;
+ }
+
kfree(oparams);
out:
kfree(params);
@@ -3652,8 +3621,8 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.llseek = no_llseek,
- .poll = snd_pcm_poll,
- .unlocked_ioctl = snd_pcm_ioctl,
+ .poll = snd_pcm_playback_poll,
+ .unlocked_ioctl = snd_pcm_playback_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
@@ -3666,8 +3635,8 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.llseek = no_llseek,
- .poll = snd_pcm_poll,
- .unlocked_ioctl = snd_pcm_ioctl,
+ .poll = snd_pcm_capture_poll,
+ .unlocked_ioctl = snd_pcm_capture_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h
deleted file mode 100644
index 86c8d658a25c..000000000000
--- a/sound/core/pcm_param_trace.h
+++ /dev/null
@@ -1,142 +0,0 @@
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM snd_pcm
-
-#if !defined(_PCM_PARAMS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _PCM_PARAMS_TRACE_H
-
-#include <linux/tracepoint.h>
-
-#define HW_PARAM_ENTRY(param) {SNDRV_PCM_HW_PARAM_##param, #param}
-#define hw_param_labels \
- HW_PARAM_ENTRY(ACCESS), \
- HW_PARAM_ENTRY(FORMAT), \
- HW_PARAM_ENTRY(SUBFORMAT), \
- HW_PARAM_ENTRY(SAMPLE_BITS), \
- HW_PARAM_ENTRY(FRAME_BITS), \
- HW_PARAM_ENTRY(CHANNELS), \
- HW_PARAM_ENTRY(RATE), \
- HW_PARAM_ENTRY(PERIOD_TIME), \
- HW_PARAM_ENTRY(PERIOD_SIZE), \
- HW_PARAM_ENTRY(PERIOD_BYTES), \
- HW_PARAM_ENTRY(PERIODS), \
- HW_PARAM_ENTRY(BUFFER_TIME), \
- HW_PARAM_ENTRY(BUFFER_SIZE), \
- HW_PARAM_ENTRY(BUFFER_BYTES), \
- HW_PARAM_ENTRY(TICK_TIME)
-
-TRACE_EVENT(hw_mask_param,
- TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_mask *prev, const struct snd_mask *curr),
- TP_ARGS(substream, type, index, prev, curr),
- TP_STRUCT__entry(
- __field(int, card)
- __field(int, device)
- __field(int, subdevice)
- __field(int, direction)
- __field(snd_pcm_hw_param_t, type)
- __field(int, index)
- __field(int, total)
- __array(__u32, prev_bits, 8)
- __array(__u32, curr_bits, 8)
- ),
- TP_fast_assign(
- __entry->card = substream->pcm->card->number;
- __entry->device = substream->pcm->device;
- __entry->subdevice = substream->number;
- __entry->direction = substream->stream;
- __entry->type = type;
- __entry->index = index;
- __entry->total = substream->runtime->hw_constraints.rules_num;
- memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8);
- memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8);
- ),
- TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x",
- __entry->card,
- __entry->device,
- __entry->direction ? "c" : "p",
- __entry->subdevice,
- __entry->index,
- __entry->total,
- __print_symbolic(__entry->type, hw_param_labels),
- __entry->prev_bits[3], __entry->prev_bits[2],
- __entry->prev_bits[1], __entry->prev_bits[0],
- __entry->curr_bits[3], __entry->curr_bits[2],
- __entry->curr_bits[1], __entry->curr_bits[0]
- )
-);
-
-TRACE_EVENT(hw_interval_param,
- TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_interval *prev, const struct snd_interval *curr),
- TP_ARGS(substream, type, index, prev, curr),
- TP_STRUCT__entry(
- __field(int, card)
- __field(int, device)
- __field(int, subdevice)
- __field(int, direction)
- __field(snd_pcm_hw_param_t, type)
- __field(int, index)
- __field(int, total)
- __field(unsigned int, prev_min)
- __field(unsigned int, prev_max)
- __field(unsigned int, prev_openmin)
- __field(unsigned int, prev_openmax)
- __field(unsigned int, prev_integer)
- __field(unsigned int, prev_empty)
- __field(unsigned int, curr_min)
- __field(unsigned int, curr_max)
- __field(unsigned int, curr_openmin)
- __field(unsigned int, curr_openmax)
- __field(unsigned int, curr_integer)
- __field(unsigned int, curr_empty)
- ),
- TP_fast_assign(
- __entry->card = substream->pcm->card->number;
- __entry->device = substream->pcm->device;
- __entry->subdevice = substream->number;
- __entry->direction = substream->stream;
- __entry->type = type;
- __entry->index = index;
- __entry->total = substream->runtime->hw_constraints.rules_num;
- __entry->prev_min = prev->min;
- __entry->prev_max = prev->max;
- __entry->prev_openmin = prev->openmin;
- __entry->prev_openmax = prev->openmax;
- __entry->prev_integer = prev->integer;
- __entry->prev_empty = prev->empty;
- __entry->curr_min = curr->min;
- __entry->curr_max = curr->max;
- __entry->curr_openmin = curr->openmin;
- __entry->curr_openmax = curr->openmax;
- __entry->curr_integer = curr->integer;
- __entry->curr_empty = curr->empty;
- ),
- TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s",
- __entry->card,
- __entry->device,
- __entry->direction ? "c" : "p",
- __entry->subdevice,
- __entry->index,
- __entry->total,
- __print_symbolic(__entry->type, hw_param_labels),
- __entry->prev_empty,
- __entry->prev_integer,
- __entry->prev_openmin ? "(" : "[",
- __entry->prev_min,
- __entry->prev_max,
- __entry->prev_openmax ? ")" : "]",
- __entry->curr_empty,
- __entry->curr_integer,
- __entry->curr_openmin ? "(" : "[",
- __entry->curr_min,
- __entry->curr_max,
- __entry->curr_openmax ? ")" : "]"
- )
-);
-
-#endif /* _PCM_PARAMS_TRACE_H */
-
-/* This part must be outside protection */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE pcm_param_trace
-#include <trace/define_trace.h>
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 11389f13de73..20ecd8f18080 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -25,8 +25,6 @@
#include <sound/pcm.h>
#include <sound/timer.h>
-#include "pcm_local.h"
-
/*
* Timer functions
*/
@@ -35,8 +33,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
{
unsigned long rate, mult, fsize, l, post;
struct snd_pcm_runtime *runtime = substream->runtime;
-
- mult = 1000000000;
+
+ mult = 1000000000;
rate = runtime->rate;
if (snd_BUG_ON(!rate))
return;
@@ -67,7 +65,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = timer->private_data;
return substream->runtime ? substream->runtime->timer_resolution : 0;
}
@@ -75,7 +73,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
static int snd_pcm_timer_start(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = snd_timer_chip(timer);
substream->timer_running = 1;
return 0;
@@ -84,7 +82,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer)
static int snd_pcm_timer_stop(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = snd_timer_chip(timer);
substream->timer_running = 0;
return 0;
@@ -114,7 +112,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream)
{
struct snd_timer_id tid;
struct snd_timer *timer;
-
+
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
tid.dev_class = SNDRV_TIMER_CLASS_PCM;
tid.card = substream->pcm->card->number;
diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h
index 3ddec1b8ae46..b63b654da5ff 100644
--- a/sound/core/pcm_trace.h
+++ b/sound/core/pcm_trace.h
@@ -34,9 +34,9 @@ TRACE_EVENT(hwptr,
__entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
__entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
),
- TP_printk("pcmC%dD%d%s/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu",
+ TP_printk("pcmC%dD%d%c/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu",
__entry->card, __entry->device,
- __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
+ __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
__entry->number,
__entry->in_interrupt ? "IRQ" : "POS",
(unsigned long)__entry->pos,
@@ -69,9 +69,9 @@ TRACE_EVENT(xrun,
__entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
__entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
),
- TP_printk("pcmC%dD%d%s/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu",
+ TP_printk("pcmC%dD%d%c/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu",
__entry->card, __entry->device,
- __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
+ __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
__entry->number,
(unsigned long)__entry->old_hw_ptr,
(unsigned long)__entry->hw_ptr_base,
@@ -96,50 +96,12 @@ TRACE_EVENT(hw_ptr_error,
__entry->stream = (substream)->stream;
__entry->reason = (why);
),
- TP_printk("pcmC%dD%d%s/sub%d: ERROR: %s",
+ TP_printk("pcmC%dD%d%c/sub%d: ERROR: %s",
__entry->card, __entry->device,
- __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c",
+ __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
__entry->number, __entry->reason)
);
-TRACE_EVENT(applptr,
- TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t prev, snd_pcm_uframes_t curr),
- TP_ARGS(substream, prev, curr),
- TP_STRUCT__entry(
- __field( unsigned int, card )
- __field( unsigned int, device )
- __field( unsigned int, number )
- __field( unsigned int, stream )
- __field( snd_pcm_uframes_t, prev )
- __field( snd_pcm_uframes_t, curr )
- __field( snd_pcm_uframes_t, avail )
- __field( snd_pcm_uframes_t, period_size )
- __field( snd_pcm_uframes_t, buffer_size )
- ),
- TP_fast_assign(
- __entry->card = (substream)->pcm->card->number;
- __entry->device = (substream)->pcm->device;
- __entry->number = (substream)->number;
- __entry->stream = (substream)->stream;
- __entry->prev = (prev);
- __entry->curr = (curr);
- __entry->avail = (substream)->stream ? snd_pcm_capture_avail(substream->runtime) : snd_pcm_playback_avail(substream->runtime);
- __entry->period_size = (substream)->runtime->period_size;
- __entry->buffer_size = (substream)->runtime->buffer_size;
- ),
- TP_printk("pcmC%dD%d%s/sub%d: prev=%lu, curr=%lu, avail=%lu, period=%lu, buf=%lu",
- __entry->card,
- __entry->device,
- __entry->stream ? "c" : "p",
- __entry->number,
- __entry->prev,
- __entry->curr,
- __entry->avail,
- __entry->period_size,
- __entry->buffer_size
- )
-);
-
#endif /* _PCM_TRACE_H */
/* This part must be outside protection */
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index e8197bbd12b8..ac39b3f591f4 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -29,7 +29,6 @@
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/mm.h>
#include <sound/rawmidi.h>
#include <sound/info.h>
#include <sound/control.h>
@@ -89,7 +88,6 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file)
static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
-
return runtime->avail >= runtime->avail_min;
}
@@ -97,7 +95,6 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre
size_t count)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
-
return runtime->avail >= runtime->avail_min &&
(!substream->append || runtime->avail >= count);
}
@@ -106,7 +103,6 @@ static void snd_rawmidi_input_event_work(struct work_struct *work)
{
struct snd_rawmidi_runtime *runtime =
container_of(work, struct snd_rawmidi_runtime, event_work);
-
if (runtime->event)
runtime->event(runtime->substream);
}
@@ -115,8 +111,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime;
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
- if (!runtime)
+ if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
return -ENOMEM;
runtime->substream = substream;
spin_lock_init(&runtime->lock);
@@ -129,8 +124,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
runtime->avail = 0;
else
runtime->avail = runtime->buffer_size;
- runtime->buffer = kvzalloc(runtime->buffer_size, GFP_KERNEL);
- if (!runtime->buffer) {
+ if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
kfree(runtime);
return -ENOMEM;
}
@@ -143,13 +137,13 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
- kvfree(runtime->buffer);
+ kfree(runtime->buffer);
kfree(runtime);
substream->runtime = NULL;
return 0;
}
-static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
+static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up)
{
if (!substream->opened)
return;
@@ -165,28 +159,17 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i
cancel_work_sync(&substream->runtime->event_work);
}
-static void __reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime,
- bool is_input)
-{
- runtime->drain = 0;
- runtime->appl_ptr = runtime->hw_ptr = 0;
- runtime->avail = is_input ? 0 : runtime->buffer_size;
-}
-
-static void reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime,
- bool is_input)
+int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ snd_rawmidi_output_trigger(substream, 0);
+ runtime->drain = 0;
spin_lock_irqsave(&runtime->lock, flags);
- __reset_runtime_ptrs(runtime, is_input);
+ runtime->appl_ptr = runtime->hw_ptr = 0;
+ runtime->avail = runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
-}
-
-int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
-{
- snd_rawmidi_output_trigger(substream, 0);
- reset_runtime_ptrs(substream->runtime, false);
return 0;
}
EXPORT_SYMBOL(snd_rawmidi_drop_output);
@@ -225,8 +208,15 @@ EXPORT_SYMBOL(snd_rawmidi_drain_output);
int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
{
+ unsigned long flags;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
snd_rawmidi_input_trigger(substream, 0);
- reset_runtime_ptrs(substream->runtime, true);
+ runtime->drain = 0;
+ spin_lock_irqsave(&runtime->lock, flags);
+ runtime->appl_ptr = runtime->hw_ptr = 0;
+ runtime->avail = 0;
+ spin_unlock_irqrestore(&runtime->lock, flags);
return 0;
}
EXPORT_SYMBOL(snd_rawmidi_drain_input);
@@ -340,23 +330,25 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
/* called from sound/core/seq/seq_midi.c */
int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
- int mode, struct snd_rawmidi_file *rfile)
+ int mode, struct snd_rawmidi_file * rfile)
{
struct snd_rawmidi *rmidi;
- int err = 0;
+ int err;
if (snd_BUG_ON(!rfile))
return -EINVAL;
mutex_lock(&register_mutex);
rmidi = snd_rawmidi_search(card, device);
- if (!rmidi)
- err = -ENODEV;
- else if (!try_module_get(rmidi->card->module))
- err = -ENXIO;
+ if (rmidi == NULL) {
+ mutex_unlock(&register_mutex);
+ return -ENODEV;
+ }
+ if (!try_module_get(rmidi->card->module)) {
+ mutex_unlock(&register_mutex);
+ return -ENXIO;
+ }
mutex_unlock(&register_mutex);
- if (err < 0)
- return err;
mutex_lock(&rmidi->open_mutex);
err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
@@ -378,7 +370,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
struct snd_rawmidi_file *rawmidi_file = NULL;
wait_queue_entry_t wait;
- if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
+ if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
return -EINVAL; /* invalid combination */
err = nonseekable_open(inode, file);
@@ -528,7 +520,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)
if (snd_BUG_ON(!rfile))
return -ENXIO;
-
+
rmidi = rfile->rmidi;
rawmidi_release_priv(rfile);
module_put(rmidi->card->module);
@@ -556,7 +548,7 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_info *info)
{
struct snd_rawmidi *rmidi;
-
+
if (substream == NULL)
return -ENODEV;
rmidi = substream->rmidi;
@@ -576,13 +568,11 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
}
static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_info __user *_info)
+ struct snd_rawmidi_info __user * _info)
{
struct snd_rawmidi_info info;
int err;
-
- err = snd_rawmidi_info(substream, &info);
- if (err < 0)
+ if ((err = snd_rawmidi_info(substream, &info)) < 0)
return err;
if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
return -EFAULT;
@@ -629,68 +619,85 @@ static int snd_rawmidi_info_select_user(struct snd_card *card,
{
int err;
struct snd_rawmidi_info info;
-
if (get_user(info.device, &_info->device))
return -EFAULT;
if (get_user(info.stream, &_info->stream))
return -EFAULT;
if (get_user(info.subdevice, &_info->subdevice))
return -EFAULT;
- err = snd_rawmidi_info_select(card, &info);
- if (err < 0)
+ if ((err = snd_rawmidi_info_select(card, &info)) < 0)
return err;
if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
return -EFAULT;
return 0;
}
-static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime,
- struct snd_rawmidi_params *params,
- bool is_input)
+int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_params * params)
{
char *newbuf, *oldbuf;
-
- if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L)
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+ if (substream->append && substream->use_count > 1)
+ return -EBUSY;
+ snd_rawmidi_drain_output(substream);
+ if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
return -EINVAL;
- if (params->avail_min < 1 || params->avail_min > params->buffer_size)
+ }
+ if (params->avail_min < 1 || params->avail_min > params->buffer_size) {
return -EINVAL;
+ }
if (params->buffer_size != runtime->buffer_size) {
- newbuf = kvzalloc(params->buffer_size, GFP_KERNEL);
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
if (!newbuf)
return -ENOMEM;
spin_lock_irq(&runtime->lock);
oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
- __reset_runtime_ptrs(runtime, is_input);
+ runtime->avail = runtime->buffer_size;
+ runtime->appl_ptr = runtime->hw_ptr = 0;
spin_unlock_irq(&runtime->lock);
- kvfree(oldbuf);
+ kfree(oldbuf);
}
runtime->avail_min = params->avail_min;
- return 0;
-}
-
-int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_params *params)
-{
- if (substream->append && substream->use_count > 1)
- return -EBUSY;
- snd_rawmidi_drain_output(substream);
substream->active_sensing = !params->no_active_sensing;
- return resize_runtime_buffer(substream->runtime, params, false);
+ return 0;
}
EXPORT_SYMBOL(snd_rawmidi_output_params);
int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_params *params)
+ struct snd_rawmidi_params * params)
{
+ char *newbuf, *oldbuf;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
snd_rawmidi_drain_input(substream);
- return resize_runtime_buffer(substream->runtime, params, true);
+ if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
+ return -EINVAL;
+ }
+ if (params->avail_min < 1 || params->avail_min > params->buffer_size) {
+ return -EINVAL;
+ }
+ if (params->buffer_size != runtime->buffer_size) {
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+ if (!newbuf)
+ return -ENOMEM;
+ spin_lock_irq(&runtime->lock);
+ oldbuf = runtime->buffer;
+ runtime->buffer = newbuf;
+ runtime->buffer_size = params->buffer_size;
+ runtime->appl_ptr = runtime->hw_ptr = 0;
+ spin_unlock_irq(&runtime->lock);
+ kfree(oldbuf);
+ }
+ runtime->avail_min = params->avail_min;
+ return 0;
}
EXPORT_SYMBOL(snd_rawmidi_input_params);
static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_status *status)
+ struct snd_rawmidi_status * status)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
@@ -703,7 +710,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
}
static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
- struct snd_rawmidi_status *status)
+ struct snd_rawmidi_status * status)
{
struct snd_rawmidi_runtime *runtime = substream->runtime;
@@ -732,7 +739,6 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
{
int stream;
struct snd_rawmidi_info __user *info = argp;
-
if (get_user(stream, &info->stream))
return -EFAULT;
switch (stream) {
@@ -747,7 +753,6 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
case SNDRV_RAWMIDI_IOCTL_PARAMS:
{
struct snd_rawmidi_params params;
-
if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
return -EFAULT;
switch (params.stream) {
@@ -767,7 +772,6 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
{
int err = 0;
struct snd_rawmidi_status status;
-
if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
return -EFAULT;
switch (status.stream) {
@@ -793,7 +797,6 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
case SNDRV_RAWMIDI_IOCTL_DROP:
{
int val;
-
if (get_user(val, (int __user *) argp))
return -EFAULT;
switch (val) {
@@ -808,7 +811,6 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
case SNDRV_RAWMIDI_IOCTL_DRAIN:
{
int val;
-
if (get_user(val, (int __user *) argp))
return -EFAULT;
switch (val) {
@@ -842,7 +844,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
{
int device;
-
+
if (get_user(device, (int __user *)argp))
return -EFAULT;
if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */
@@ -864,7 +866,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
{
int val;
-
+
if (get_user(val, (int __user *)argp))
return -EFAULT;
control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;
@@ -1018,7 +1020,6 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
spin_lock_irq(&runtime->lock);
while (!snd_rawmidi_ready(substream)) {
wait_queue_entry_t wait;
-
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
spin_unlock_irq(&runtime->lock);
return result > 0 ? result : -EAGAIN;
@@ -1071,7 +1072,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
spin_lock_irqsave(&runtime->lock, flags);
result = runtime->avail >= runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
- return result;
+ return result;
}
EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
@@ -1209,7 +1210,7 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
* @substream: the rawmidi substream
* @buffer: the buffer pointer
* @count: the data size to transfer
- *
+ *
* Copies data from the buffer to the device and advances the pointer.
*
* Return: The copied size if successful, or a negative error code on failure.
@@ -1236,28 +1237,6 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
}
EXPORT_SYMBOL(snd_rawmidi_transmit);
-/**
- * snd_rawmidi_proceed - Discard the all pending bytes and proceed
- * @substream: rawmidi substream
- *
- * Return: the number of discarded bytes
- */
-int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream)
-{
- struct snd_rawmidi_runtime *runtime = substream->runtime;
- unsigned long flags;
- int count = 0;
-
- spin_lock_irqsave(&runtime->lock, flags);
- if (runtime->avail < runtime->buffer_size) {
- count = runtime->buffer_size - runtime->avail;
- __snd_rawmidi_transmit_ack(substream, count);
- }
- spin_unlock_irqrestore(&runtime->lock, flags);
- return count;
-}
-EXPORT_SYMBOL(snd_rawmidi_proceed);
-
static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
const unsigned char __user *userbuf,
const unsigned char *kernelbuf,
@@ -1345,7 +1324,6 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
spin_lock_irq(&runtime->lock);
while (!snd_rawmidi_ready_append(substream, count)) {
wait_queue_entry_t wait;
-
if (file->f_flags & O_NONBLOCK) {
spin_unlock_irq(&runtime->lock);
return result > 0 ? result : -EAGAIN;
@@ -1379,7 +1357,6 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
while (runtime->avail != runtime->buffer_size) {
wait_queue_entry_t wait;
unsigned int last_avail = runtime->avail;
-
init_waitqueue_entry(&wait, current);
add_wait_queue(&runtime->sleep, &wait);
set_current_state(TASK_INTERRUPTIBLE);
@@ -1397,7 +1374,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
return result;
}
-static unsigned int snd_rawmidi_poll(struct file *file, poll_table *wait)
+static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
{
struct snd_rawmidi_file *rfile;
struct snd_rawmidi_runtime *runtime;
@@ -1434,6 +1411,7 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table *wait)
#endif
/*
+
*/
static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
@@ -1501,7 +1479,8 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
* Register functions
*/
-static const struct file_operations snd_rawmidi_f_ops = {
+static const struct file_operations snd_rawmidi_f_ops =
+{
.owner = THIS_MODULE,
.read = snd_rawmidi_read,
.write = snd_rawmidi_write,
@@ -1556,7 +1535,7 @@ static void release_rawmidi_device(struct device *dev)
*/
int snd_rawmidi_new(struct snd_card *card, char *id, int device,
int output_count, int input_count,
- struct snd_rawmidi **rrawmidi)
+ struct snd_rawmidi ** rrawmidi)
{
struct snd_rawmidi *rmidi;
int err;
@@ -1587,29 +1566,27 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
rmidi->dev.release = release_rawmidi_device;
dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device);
- err = snd_rawmidi_alloc_substreams(rmidi,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
- SNDRV_RAWMIDI_STREAM_INPUT,
- input_count);
- if (err < 0)
- goto error;
- err = snd_rawmidi_alloc_substreams(rmidi,
- &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
- SNDRV_RAWMIDI_STREAM_OUTPUT,
- output_count);
- if (err < 0)
- goto error;
- err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops);
- if (err < 0)
- goto error;
-
+ if ((err = snd_rawmidi_alloc_substreams(rmidi,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ input_count)) < 0) {
+ snd_rawmidi_free(rmidi);
+ return err;
+ }
+ if ((err = snd_rawmidi_alloc_substreams(rmidi,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
+ SNDRV_RAWMIDI_STREAM_OUTPUT,
+ output_count)) < 0) {
+ snd_rawmidi_free(rmidi);
+ return err;
+ }
+ if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) {
+ snd_rawmidi_free(rmidi);
+ return err;
+ }
if (rrawmidi)
*rrawmidi = rmidi;
return 0;
-
- error:
- snd_rawmidi_free(rmidi);
- return err;
}
EXPORT_SYMBOL(snd_rawmidi_new);
@@ -1647,15 +1624,13 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi)
static int snd_rawmidi_dev_free(struct snd_device *device)
{
struct snd_rawmidi *rmidi = device->device_data;
-
return snd_rawmidi_free(rmidi);
}
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
{
struct snd_rawmidi *rmidi = device->private_data;
-
rmidi->seq_dev = NULL;
}
#endif
@@ -1669,27 +1644,30 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
return -ENOMEM;
- err = 0;
mutex_lock(&register_mutex);
- if (snd_rawmidi_search(rmidi->card, rmidi->device))
- err = -EBUSY;
- else
- list_add_tail(&rmidi->list, &snd_rawmidi_devices);
+ if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
+ mutex_unlock(&register_mutex);
+ return -EBUSY;
+ }
+ list_add_tail(&rmidi->list, &snd_rawmidi_devices);
mutex_unlock(&register_mutex);
- if (err < 0)
- return err;
-
err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
rmidi->card, rmidi->device,
&snd_rawmidi_f_ops, rmidi, &rmidi->dev);
if (err < 0) {
rmidi_err(rmidi, "unable to register\n");
- goto error;
+ mutex_lock(&register_mutex);
+ list_del(&rmidi->list);
+ mutex_unlock(&register_mutex);
+ return err;
}
- if (rmidi->ops && rmidi->ops->dev_register) {
- err = rmidi->ops->dev_register(rmidi);
- if (err < 0)
- goto error_unregister;
+ if (rmidi->ops && rmidi->ops->dev_register &&
+ (err = rmidi->ops->dev_register(rmidi)) < 0) {
+ snd_unregister_device(&rmidi->dev);
+ mutex_lock(&register_mutex);
+ list_del(&rmidi->list);
+ mutex_unlock(&register_mutex);
+ return err;
}
#ifdef CONFIG_SND_OSSEMUL
rmidi->ossreg = 0;
@@ -1730,7 +1708,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
}
}
rmidi->proc_entry = entry;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */
if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {
rmidi->seq_dev->private_data = rmidi;
@@ -1741,14 +1719,6 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
}
#endif
return 0;
-
- error_unregister:
- snd_unregister_device(&rmidi->dev);
- error:
- mutex_lock(&register_mutex);
- list_del(&rmidi->list);
- mutex_unlock(&register_mutex);
- return err;
}
static int snd_rawmidi_dev_disconnect(struct snd_device *device)
@@ -1762,7 +1732,6 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
list_del_init(&rmidi->list);
for (dir = 0; dir < 2; dir++) {
struct snd_rawmidi_substream *s;
-
list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
if (s->runtime)
wake_up(&s->runtime->sleep);
@@ -1800,7 +1769,7 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
const struct snd_rawmidi_ops *ops)
{
struct snd_rawmidi_substream *substream;
-
+
list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)
substream->ops = ops;
}
diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig
index 45c1336c6597..b851fd890a89 100644
--- a/sound/core/seq/Kconfig
+++ b/sound/core/seq/Kconfig
@@ -1,62 +1,16 @@
-config SND_SEQUENCER
- tristate "Sequencer support"
- select SND_TIMER
- select SND_SEQ_DEVICE
- help
- Say Y or M to enable MIDI sequencer and router support. This
- feature allows routing and enqueueing of MIDI events. Events
- can be processed at a given time.
+# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX)
- Many programs require this feature, so you should enable it
- unless you know what you're doing.
+config SND_RAWMIDI_SEQ
+ def_tristate SND_SEQUENCER && SND_RAWMIDI
-if SND_SEQUENCER
+config SND_OPL3_LIB_SEQ
+ def_tristate SND_SEQUENCER && SND_OPL3_LIB
-config SND_SEQ_DUMMY
- tristate "Sequencer dummy client"
- help
- Say Y here to enable the dummy sequencer client. This client
- is a simple MIDI-through client: all normal input events are
- redirected to the output port immediately.
+config SND_OPL4_LIB_SEQ
+ def_tristate SND_SEQUENCER && SND_OPL4_LIB
- You don't need this unless you want to connect many MIDI
- devices or applications together.
+config SND_SBAWE_SEQ
+ def_tristate SND_SEQUENCER && SND_SBAWE
- To compile this driver as a module, choose M here: the module
- will be called snd-seq-dummy.
-
-config SND_SEQUENCER_OSS
- tristate "OSS Sequencer API"
- depends on SND_OSSEMUL
- select SND_SEQ_MIDI_EVENT
- help
- Say Y here to enable OSS sequencer emulation (both
- /dev/sequencer and /dev/music interfaces).
-
- Many programs still use the OSS API, so say Y.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-seq-oss.
-
-config SND_SEQ_HRTIMER_DEFAULT
- bool "Use HR-timer as default sequencer timer"
- depends on SND_HRTIMER
- default y
- help
- Say Y here to use the HR-timer backend as the default sequencer
- timer.
-
-config SND_SEQ_MIDI_EVENT
- tristate
-
-config SND_SEQ_MIDI
- def_tristate SND_RAWMIDI
- select SND_SEQ_MIDI_EVENT
-
-config SND_SEQ_MIDI_EMUL
- tristate
-
-config SND_SEQ_VIRMIDI
- tristate
-
-endif # SND_SEQUENCER
+config SND_EMU10K1_SEQ
+ def_tristate SND_SEQUENCER && SND_EMU10K1
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index 68fd367ac39c..b65fa5a1943b 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
#
+snd-seq-device-objs := seq_device.o
snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
seq_fifo.o seq_prioq.o seq_timer.o \
seq_system.o seq_ports.o
@@ -13,11 +14,17 @@ snd-seq-midi-event-objs := seq_midi_event.o
snd-seq-dummy-objs := seq_dummy.o
snd-seq-virmidi-objs := seq_virmidi.o
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o
-obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/
-
+obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
+ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
+ obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+ obj-$(CONFIG_SND_SEQUENCER) += oss/
+endif
obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
-obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o
-obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o
-obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o
-obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o
+
+# Toplevel Module Dependency
+obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
+obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o
+obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
+obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o
+obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o
diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile
index 4ea4e3eea6b7..b38406b8463c 100644
--- a/sound/core/seq/oss/Makefile
+++ b/sound/core/seq/oss/Makefile
@@ -7,4 +7,4 @@ snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \
seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \
seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o
-obj-$(CONFIG_SND_SEQUENCER_OSS) += snd-seq-oss.o
+obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 0c87502d0867..8cdf489df80e 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -203,7 +203,7 @@ odev_poll(struct file *file, poll_table * wait)
struct seq_oss_devinfo *dp;
dp = file->private_data;
if (snd_BUG_ON(!dp))
- return POLLERR;
+ return -ENXIO;
return snd_seq_oss_poll(dp, file, wait);
}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 0d5f8b16d057..9debd1b8fd28 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -637,7 +637,7 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
if ((mdev = get_mididev(dp, dev)) == NULL)
return -ENODEV;
- if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
+ if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) {
snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
snd_use_lock_free(&mdev->use_lock);
return 0;
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index 0778d28421da..4f24ea9fad93 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -92,7 +92,7 @@ snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev)
case TMR_WAIT_REL:
parm += rec->cur_tick;
rec->realtime = 0;
- /* fall through */
+ /* continue to next */
case TMR_WAIT_ABS:
if (parm == 0) {
rec->realtime = 1;
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 7de98d71f2aa..639544b4fb04 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -84,32 +84,30 @@ static int __init alsa_seq_init(void)
{
int err;
- err = client_init_data();
- if (err < 0)
+ if ((err = client_init_data()) < 0)
+ goto error;
+
+ /* init memory, room for selected events */
+ if ((err = snd_sequencer_memory_init()) < 0)
+ goto error;
+
+ /* init event queues */
+ if ((err = snd_seq_queues_init()) < 0)
goto error;
/* register sequencer device */
- err = snd_sequencer_device_init();
- if (err < 0)
+ if ((err = snd_sequencer_device_init()) < 0)
goto error;
/* register proc interface */
- err = snd_seq_info_init();
- if (err < 0)
- goto error_device;
+ if ((err = snd_seq_info_init()) < 0)
+ goto error;
/* register our internal client */
- err = snd_seq_system_client_init();
- if (err < 0)
- goto error_info;
+ if ((err = snd_seq_system_client_init()) < 0)
+ goto error;
snd_seq_autoload_init();
- return 0;
-
- error_info:
- snd_seq_info_done();
- error_device:
- snd_sequencer_device_done();
error:
return err;
}
@@ -128,6 +126,9 @@ static void __exit alsa_seq_exit(void)
/* unregister sequencer device */
snd_sequencer_device_done();
+ /* release event memory */
+ snd_sequencer_memory_done();
+
snd_seq_autoload_exit();
}
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 1cfb1a6a5d2a..f8070a3b1d8a 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -311,9 +311,10 @@ static int snd_seq_open(struct inode *inode, struct file *file)
if (err < 0)
return err;
- mutex_lock(&register_mutex);
+ if (mutex_lock_interruptible(&register_mutex))
+ return -ERESTARTSYS;
client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
- if (!client) {
+ if (client == NULL) {
mutex_unlock(&register_mutex);
return -ENOMEM; /* failure code */
}
@@ -802,10 +803,6 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
return -EMLINK;
}
- if (snd_seq_ev_is_variable(event) &&
- snd_BUG_ON(atomic && (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR)))
- return -EINVAL;
-
if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS ||
event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)
result = deliver_to_subscribers(client, event, atomic, hop);
@@ -1100,7 +1097,7 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
/* check client structures are in place */
if (snd_BUG_ON(!client))
- return POLLERR;
+ return -ENXIO;
if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) &&
client->data.user.fifo) {
@@ -1678,6 +1675,7 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
return -EPERM;
return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
}
+
EXPORT_SYMBOL(snd_seq_set_queue_tempo);
static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
@@ -1703,7 +1701,10 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
if (queue == NULL)
return -EINVAL;
- mutex_lock(&queue->timer_mutex);
+ if (mutex_lock_interruptible(&queue->timer_mutex)) {
+ queuefree(queue);
+ return -ERESTARTSYS;
+ }
tmr = queue->timer;
memset(timer, 0, sizeof(*timer));
timer->queue = queue->queue;
@@ -1737,7 +1738,10 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
q = queueptr(timer->queue);
if (q == NULL)
return -ENXIO;
- mutex_lock(&q->timer_mutex);
+ if (mutex_lock_interruptible(&q->timer_mutex)) {
+ queuefree(q);
+ return -ERESTARTSYS;
+ }
tmr = q->timer;
snd_seq_queue_timer_close(timer->queue);
tmr->type = timer->type;
@@ -2173,7 +2177,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)
return -EINVAL;
- mutex_lock(&register_mutex);
+ if (mutex_lock_interruptible(&register_mutex))
+ return -ERESTARTSYS;
if (card) {
client_index += SNDRV_SEQ_GLOBAL_CLIENTS
@@ -2207,6 +2212,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
/* return client number to caller */
return client->number;
}
+
EXPORT_SYMBOL(snd_seq_create_kernel_client);
/* exported to kernel modules */
@@ -2225,6 +2231,7 @@ int snd_seq_delete_kernel_client(int client)
kfree(ptr);
return 0;
}
+
EXPORT_SYMBOL(snd_seq_delete_kernel_client);
/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
@@ -2275,6 +2282,7 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
{
return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
}
+
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
/*
@@ -2288,6 +2296,7 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev
{
return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
}
+
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
/*
@@ -2325,6 +2334,7 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
snd_seq_client_unlock(cptr);
return result;
}
+
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
/**
@@ -2357,6 +2367,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
return -ENOTTY;
}
+
EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
/* exported (for OSS emulator) */
@@ -2374,6 +2385,7 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
return 1;
return 0;
}
+
EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
/*---------------------------------------------------------------------------*/
@@ -2514,15 +2526,19 @@ int __init snd_sequencer_device_init(void)
snd_device_initialize(&seq_dev, NULL);
dev_set_name(&seq_dev, "seq");
- mutex_lock(&register_mutex);
+ if (mutex_lock_interruptible(&register_mutex))
+ return -ERESTARTSYS;
+
err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
&snd_seq_f_ops, NULL, &seq_dev);
- mutex_unlock(&register_mutex);
if (err < 0) {
+ mutex_unlock(&register_mutex);
put_device(&seq_dev);
return err;
}
+ mutex_unlock(&register_mutex);
+
return 0;
}
@@ -2531,7 +2547,7 @@ int __init snd_sequencer_device_init(void)
/*
* unregister sequencer device
*/
-void snd_sequencer_device_done(void)
+void __exit snd_sequencer_device_done(void)
{
snd_unregister_device(&seq_dev);
put_device(&seq_dev);
diff --git a/sound/core/seq_device.c b/sound/core/seq/seq_device.c
index e40a2cba5002..e40a2cba5002 100644
--- a/sound/core/seq_device.c
+++ b/sound/core/seq/seq_device.c
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c
index b27fedd435b6..97015447b9b3 100644
--- a/sound/core/seq/seq_info.c
+++ b/sound/core/seq/seq_info.c
@@ -50,7 +50,7 @@ create_info_entry(char *name, void (*read)(struct snd_info_entry *,
return entry;
}
-void snd_seq_info_done(void)
+static void free_info_entries(void)
{
snd_info_free_entry(queues_entry);
snd_info_free_entry(clients_entry);
@@ -70,6 +70,12 @@ int __init snd_seq_info_init(void)
return 0;
error:
- snd_seq_info_done();
+ free_info_entries();
return -ENOMEM;
}
+
+int __exit snd_seq_info_done(void)
+{
+ free_info_entries();
+ return 0;
+}
diff --git a/sound/core/seq/seq_info.h b/sound/core/seq/seq_info.h
index 2cdf8f6e63f5..f8549f81a645 100644
--- a/sound/core/seq/seq_info.h
+++ b/sound/core/seq/seq_info.h
@@ -30,11 +30,11 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buff
#ifdef CONFIG_SND_PROC_FS
-int snd_seq_info_init(void);
-void snd_seq_info_done(void);
+int snd_seq_info_init( void );
+int snd_seq_info_done( void );
#else
static inline int snd_seq_info_init(void) { return 0; }
-static inline void snd_seq_info_done(void) {}
+static inline int snd_seq_info_done(void) { return 0; }
#endif
#endif
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index cda64b489e42..ba5752ee9af3 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -38,4 +38,5 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
schedule_timeout_uninterruptible(1);
}
}
+
EXPORT_SYMBOL(snd_use_lock_sync_helper);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index a45133f9f460..5e07f1428deb 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -118,6 +118,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
}
return 0;
}
+
EXPORT_SYMBOL(snd_seq_dump_var_event);
@@ -168,6 +169,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
&buf);
return err < 0 ? err : newlen;
}
+
EXPORT_SYMBOL(snd_seq_expand_var_event);
/*
@@ -503,6 +505,18 @@ int snd_seq_pool_delete(struct snd_seq_pool **ppool)
return 0;
}
+/* initialize sequencer memory */
+int __init snd_sequencer_memory_init(void)
+{
+ return 0;
+}
+
+/* release sequencer memory */
+void __exit snd_sequencer_memory_done(void)
+{
+}
+
+
/* exported to seq_clientmgr.c */
void snd_seq_info_pool(struct snd_info_buffer *buffer,
struct snd_seq_pool *pool, char *space)
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h
index 1292fe91f02e..3abe306c394a 100644
--- a/sound/core/seq/seq_memory.h
+++ b/sound/core/seq/seq_memory.h
@@ -94,6 +94,12 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize);
/* remove pool */
int snd_seq_pool_delete(struct snd_seq_pool **pool);
+/* init memory */
+int snd_sequencer_memory_init(void);
+
+/* release event memory */
+void snd_sequencer_memory_done(void);
+
/* polling */
int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 9e0dabd3ce5f..5dd0ee258359 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -78,7 +78,7 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
struct seq_midisynth *msynth;
struct snd_seq_event ev;
char buf[16], *pbuf;
- long res;
+ long res, count;
if (substream == NULL)
return;
@@ -94,15 +94,19 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
if (msynth->parser == NULL)
continue;
pbuf = buf;
- while (res-- > 0) {
- if (!snd_midi_event_encode_byte(msynth->parser,
- *pbuf++, &ev))
- continue;
- ev.source.port = msynth->seq_port;
- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0);
- /* clear event and reset header */
- memset(&ev, 0, sizeof(ev));
+ while (res > 0) {
+ count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev);
+ if (count < 0)
+ break;
+ pbuf += count;
+ res -= count;
+ if (ev.type != SNDRV_SEQ_EVENT_NONE) {
+ ev.source.port = msynth->seq_port;
+ ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
+ snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0);
+ /* clear event and reset header */
+ memset(&ev, 0, sizeof(ev));
+ }
}
}
}
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index ce780658bbcc..7ba937399ac7 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -236,7 +236,6 @@ snd_midi_process_event(struct snd_midi_op *ops,
break;
}
}
-EXPORT_SYMBOL(snd_midi_process_event);
/*
@@ -318,7 +317,7 @@ do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chse
break;
case MIDI_CTL_MSB_DATA_ENTRY:
chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0;
- /* fall through */
+ /* go through here */
case MIDI_CTL_LSB_DATA_ENTRY:
if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED)
rpn(ops, drv, chan, chset);
@@ -410,7 +409,6 @@ snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
chan->drum_channel = 0;
}
}
-EXPORT_SYMBOL(snd_midi_channel_set_clear);
/*
* Process a rpn message.
@@ -703,7 +701,6 @@ struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
}
return chset;
}
-EXPORT_SYMBOL(snd_midi_channel_alloc_set);
/*
* Reset the midi controllers on a particular channel to default values.
@@ -727,4 +724,20 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
kfree(chset->channels);
kfree(chset);
}
+
+static int __init alsa_seq_midi_emul_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_seq_midi_emul_exit(void)
+{
+}
+
+module_init(alsa_seq_midi_emul_init)
+module_exit(alsa_seq_midi_emul_exit)
+
+EXPORT_SYMBOL(snd_midi_process_event);
+EXPORT_SYMBOL(snd_midi_channel_set_clear);
+EXPORT_SYMBOL(snd_midi_channel_alloc_set);
EXPORT_SYMBOL(snd_midi_channel_free_set);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index b11419537062..37db7ba492a6 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -134,7 +134,6 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
*rdev = dev;
return 0;
}
-EXPORT_SYMBOL(snd_midi_event_new);
void snd_midi_event_free(struct snd_midi_event *dev)
{
@@ -143,7 +142,6 @@ void snd_midi_event_free(struct snd_midi_event *dev)
kfree(dev);
}
}
-EXPORT_SYMBOL(snd_midi_event_free);
/*
* initialize record
@@ -163,7 +161,6 @@ void snd_midi_event_reset_encode(struct snd_midi_event *dev)
reset_encode(dev);
spin_unlock_irqrestore(&dev->lock, flags);
}
-EXPORT_SYMBOL(snd_midi_event_reset_encode);
void snd_midi_event_reset_decode(struct snd_midi_event *dev)
{
@@ -173,25 +170,83 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev)
dev->lastcmd = 0xff;
spin_unlock_irqrestore(&dev->lock, flags);
}
-EXPORT_SYMBOL(snd_midi_event_reset_decode);
+
+#if 0
+void snd_midi_event_init(struct snd_midi_event *dev)
+{
+ snd_midi_event_reset_encode(dev);
+ snd_midi_event_reset_decode(dev);
+}
+#endif /* 0 */
void snd_midi_event_no_status(struct snd_midi_event *dev, int on)
{
dev->nostat = on ? 1 : 0;
}
-EXPORT_SYMBOL(snd_midi_event_no_status);
+
+/*
+ * resize buffer
+ */
+#if 0
+int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize)
+{
+ unsigned char *new_buf, *old_buf;
+ unsigned long flags;
+
+ if (bufsize == dev->bufsize)
+ return 0;
+ new_buf = kmalloc(bufsize, GFP_KERNEL);
+ if (new_buf == NULL)
+ return -ENOMEM;
+ spin_lock_irqsave(&dev->lock, flags);
+ old_buf = dev->buf;
+ dev->buf = new_buf;
+ dev->bufsize = bufsize;
+ reset_encode(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ kfree(old_buf);
+ return 0;
+}
+#endif /* 0 */
+
+/*
+ * read bytes and encode to sequencer event if finished
+ * return the size of encoded bytes
+ */
+long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev)
+{
+ long result = 0;
+ int rc;
+
+ ev->type = SNDRV_SEQ_EVENT_NONE;
+
+ while (count-- > 0) {
+ rc = snd_midi_event_encode_byte(dev, *buf++, ev);
+ result++;
+ if (rc < 0)
+ return rc;
+ else if (rc > 0)
+ return result;
+ }
+
+ return result;
+}
/*
* read one byte and encode to sequencer event:
- * return true if MIDI bytes are encoded to an event
- * false data is not finished
+ * return 1 if MIDI bytes are encoded to an event
+ * 0 data is not finished
+ * negative for error
*/
-bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c,
- struct snd_seq_event *ev)
+int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
+ struct snd_seq_event *ev)
{
- bool rc = false;
+ int rc = 0;
unsigned long flags;
+ c &= 0xff;
+
if (c >= MIDI_CMD_COMMON_CLOCK) {
/* real-time event */
ev->type = status_event[ST_SPECIAL + c - 0xf0].event;
@@ -232,7 +287,7 @@ bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c,
status_event[dev->type].encode(dev, ev);
if (dev->type >= ST_SPECIAL)
dev->type = ST_INVALID;
- rc = true;
+ rc = 1;
} else if (dev->type == ST_SYSEX) {
if (c == MIDI_CMD_COMMON_SYSEX_END ||
dev->read >= dev->bufsize) {
@@ -245,14 +300,13 @@ bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c,
dev->read = 0; /* continue to parse */
else
reset_encode(dev); /* all parsed */
- rc = true;
+ rc = 1;
}
}
spin_unlock_irqrestore(&dev->lock, flags);
return rc;
}
-EXPORT_SYMBOL(snd_midi_event_encode_byte);
/* encode note event */
static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
@@ -354,7 +408,6 @@ long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long
return qlen;
}
}
-EXPORT_SYMBOL(snd_midi_event_decode);
/* decode note event */
@@ -470,3 +523,28 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
}
return idx;
}
+
+/*
+ * exports
+ */
+
+EXPORT_SYMBOL(snd_midi_event_new);
+EXPORT_SYMBOL(snd_midi_event_free);
+EXPORT_SYMBOL(snd_midi_event_reset_encode);
+EXPORT_SYMBOL(snd_midi_event_reset_decode);
+EXPORT_SYMBOL(snd_midi_event_no_status);
+EXPORT_SYMBOL(snd_midi_event_encode);
+EXPORT_SYMBOL(snd_midi_event_encode_byte);
+EXPORT_SYMBOL(snd_midi_event_decode);
+
+static int __init alsa_seq_midi_event_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_seq_midi_event_exit(void)
+{
+}
+
+module_init(alsa_seq_midi_event_init)
+module_exit(alsa_seq_midi_event_exit)
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 24d90abfc64d..f04714d70bf7 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -669,7 +669,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */
memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client;
- strlcpy(portinfo.name, portname ? portname : "Unnamed port",
+ strlcpy(portinfo.name, portname ? portname : "Unamed port",
sizeof(portinfo.name));
portinfo.capability = cap;
@@ -688,6 +688,7 @@ int snd_seq_event_port_attach(int client,
return ret;
}
+
EXPORT_SYMBOL(snd_seq_event_port_attach);
/*
@@ -708,4 +709,5 @@ int snd_seq_event_port_detach(int client, int port)
return err;
}
+
EXPORT_SYMBOL(snd_seq_event_port_detach);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 3b3ac96f1f5f..1a6dc4ff44a6 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -159,8 +159,18 @@ static void queue_delete(struct snd_seq_queue *q)
/*----------------------------------------------------------------*/
+/* setup queues */
+int __init snd_seq_queues_init(void)
+{
+ /*
+ memset(queue_list, 0, sizeof(queue_list));
+ num_queues = 0;
+ */
+ return 0;
+}
+
/* delete all existing queues */
-void snd_seq_queues_delete(void)
+void __exit snd_seq_queues_delete(void)
{
int i;
@@ -477,7 +487,9 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
return -EPERM;
}
- result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq);
+ result = snd_seq_timer_set_tempo(q->timer, info->tempo);
+ if (result >= 0)
+ result = snd_seq_timer_set_ppq(q->timer, info->ppq);
if (result >= 0 && info->skew_base > 0)
result = snd_seq_timer_set_skew(q->timer, info->skew_value,
info->skew_base);
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index e006fc8e3a36..719093489a2c 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -63,6 +63,9 @@ struct snd_seq_queue {
/* get the number of current queues */
int snd_seq_queue_get_cur_queues(void);
+/* init queues structure */
+int snd_seq_queues_init(void);
+
/* delete queues */
void snd_seq_queues_delete(void);
@@ -109,4 +112,28 @@ int snd_seq_queue_is_used(int queueid, int client);
int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop);
+/*
+ * 64bit division - for sync stuff..
+ */
+#if defined(i386) || defined(i486)
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divl %4" \
+ : "=a" ((u32)(q)), \
+ "=d" ((u32)(r)) \
+ : "0" ((u32)(n0)), \
+ "1" ((u32)(n1)), \
+ "rm" ((u32)(d)))
+
+#define u64_div(x,y,q) do {u32 __tmp; udiv_qrnnd(q, __tmp, (x)>>32, x, y);} while (0)
+#define u64_mod(x,y,r) do {u32 __tmp; udiv_qrnnd(__tmp, q, (x)>>32, x, y);} while (0)
+#define u64_divmod(x,y,q,r) udiv_qrnnd(q, r, (x)>>32, x, y)
+
+#else
+#define u64_div(x,y,q) ((q) = (u32)((u64)(x) / (u64)(y)))
+#define u64_mod(x,y,r) ((r) = (u32)((u64)(x) % (u64)(y)))
+#define u64_divmod(x,y,q,r) (u64_div(x,y,q), u64_mod(x,y,r))
+#endif
+
+
#endif
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index 0dc5d5a45ecc..8ce1d0b40dce 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -123,7 +123,6 @@ int __init snd_seq_system_client_init(void)
{
struct snd_seq_port_callback pcallbacks;
struct snd_seq_port_info *port;
- int err;
port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
@@ -135,10 +134,6 @@ int __init snd_seq_system_client_init(void)
/* register client */
sysclient = snd_seq_create_kernel_client(NULL, 0, "System");
- if (sysclient < 0) {
- kfree(port);
- return sysclient;
- }
/* register timer */
strcpy(port->name, "Timer");
@@ -149,10 +144,7 @@ int __init snd_seq_system_client_init(void)
port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
port->addr.client = sysclient;
port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- err = snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT,
- port);
- if (err < 0)
- goto error_port;
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
/* register announcement port */
strcpy(port->name, "Announce");
@@ -162,24 +154,16 @@ int __init snd_seq_system_client_init(void)
port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
port->addr.client = sysclient;
port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- err = snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT,
- port);
- if (err < 0)
- goto error_port;
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
announce_port = port->addr.port;
kfree(port);
return 0;
-
- error_port:
- snd_seq_system_client_done();
- kfree(port);
- return err;
}
/* unregister our internal client */
-void snd_seq_system_client_done(void)
+void __exit snd_seq_system_client_done(void)
{
int oldsysclient = sysclient;
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index f587d0e27476..b80985fbc334 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -191,15 +191,14 @@ int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
return 0;
}
-/* set current tempo and ppq in a shot */
-int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq)
+/* set current ppq */
+int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
{
- int changed;
unsigned long flags;
if (snd_BUG_ON(!tmr))
return -EINVAL;
- if (tempo <= 0 || ppq <= 0)
+ if (ppq <= 0)
return -EINVAL;
spin_lock_irqsave(&tmr->lock, flags);
if (tmr->running && (ppq != tmr->ppq)) {
@@ -209,11 +208,9 @@ int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq)
pr_debug("ALSA: seq: cannot change ppq of a running timer\n");
return -EBUSY;
}
- changed = (tempo != tmr->tempo) || (ppq != tmr->ppq);
- tmr->tempo = tempo;
+
tmr->ppq = ppq;
- if (changed)
- snd_seq_timer_set_tick_resolution(tmr);
+ snd_seq_timer_set_tick_resolution(tmr);
spin_unlock_irqrestore(&tmr->lock, flags);
return 0;
}
@@ -371,7 +368,9 @@ static int initialize_timer(struct snd_seq_timer *tmr)
tmr->ticks = 1;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
- unsigned long r = snd_timer_resolution(tmr->timeri);
+ unsigned long r = t->hw.resolution;
+ if (! r && t->hw.c_resolution)
+ r = t->hw.c_resolution(t);
if (r) {
tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
if (! tmr->ticks)
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h
index 62f390671096..9506b661fe5b 100644
--- a/sound/core/seq/seq_timer.h
+++ b/sound/core/seq/seq_timer.h
@@ -131,7 +131,7 @@ int snd_seq_timer_stop(struct snd_seq_timer *tmr);
int snd_seq_timer_start(struct snd_seq_timer *tmr);
int snd_seq_timer_continue(struct snd_seq_timer *tmr);
int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
-int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
+int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq);
int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index e5a40795914a..c45375ff9d5c 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -89,7 +89,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
else
down_read(&rdev->filelist_sem);
list_for_each_entry(vmidi, &rdev->filelist, list) {
- if (!READ_ONCE(vmidi->trigger))
+ if (!vmidi->trigger)
continue;
if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
@@ -110,6 +110,23 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
}
/*
+ * receive an event from the remote virmidi port
+ *
+ * for rawmidi inputs, you can call this function from the event
+ * handler of a remote port which is attached to the virmidi via
+ * SNDRV_VIRMIDI_SEQ_ATTACH.
+ */
+#if 0
+int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev)
+{
+ struct snd_virmidi_dev *rdev;
+
+ rdev = rmidi->private_data;
+ return snd_virmidi_dev_receive_event(rdev, ev, true);
+}
+#endif /* 0 */
+
+/*
* event handler of virmidi port
*/
static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
@@ -130,45 +147,10 @@ static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, i
{
struct snd_virmidi *vmidi = substream->runtime->private_data;
- WRITE_ONCE(vmidi->trigger, !!up);
-}
-
-/* process rawmidi bytes and send events;
- * we need no lock here for vmidi->event since it's handled only in this work
- */
-static void snd_vmidi_output_work(struct work_struct *work)
-{
- struct snd_virmidi *vmidi;
- struct snd_rawmidi_substream *substream;
- unsigned char input;
- int ret;
-
- vmidi = container_of(work, struct snd_virmidi, output_work);
- substream = vmidi->substream;
-
- /* discard the outputs in dispatch mode unless subscribed */
- if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
- !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
- snd_rawmidi_proceed(substream);
- return;
- }
-
- while (READ_ONCE(vmidi->trigger)) {
- if (snd_rawmidi_transmit(substream, &input, 1) != 1)
- break;
- if (!snd_midi_event_encode_byte(vmidi->parser, input,
- &vmidi->event))
- continue;
- if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
- ret = snd_seq_kernel_client_dispatch(vmidi->client,
- &vmidi->event,
- false, 0);
- vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
- if (ret < 0)
- break;
- }
- /* rawmidi input might be huge, allow to have a break */
- cond_resched();
+ if (up) {
+ vmidi->trigger = 1;
+ } else {
+ vmidi->trigger = 0;
}
}
@@ -178,10 +160,62 @@ static void snd_vmidi_output_work(struct work_struct *work)
static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
struct snd_virmidi *vmidi = substream->runtime->private_data;
-
- WRITE_ONCE(vmidi->trigger, !!up);
- if (up)
- queue_work(system_highpri_wq, &vmidi->output_work);
+ int count, res;
+ unsigned char buf[32], *pbuf;
+ unsigned long flags;
+ bool check_resched = !in_atomic();
+
+ if (up) {
+ vmidi->trigger = 1;
+ if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
+ !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
+ while (snd_rawmidi_transmit(substream, buf,
+ sizeof(buf)) > 0) {
+ /* ignored */
+ }
+ return;
+ }
+ spin_lock_irqsave(&substream->runtime->lock, flags);
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+ goto out;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
+ while (1) {
+ count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+ if (count <= 0)
+ break;
+ pbuf = buf;
+ while (count > 0) {
+ res = snd_midi_event_encode(vmidi->parser, pbuf, count, &vmidi->event);
+ if (res < 0) {
+ snd_midi_event_reset_encode(vmidi->parser);
+ continue;
+ }
+ __snd_rawmidi_transmit_ack(substream, res);
+ pbuf += res;
+ count -= res;
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+ goto out;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
+ }
+ if (!check_resched)
+ continue;
+ /* do temporary unlock & cond_resched() for avoiding
+ * CPU soft lockup, which may happen via a write from
+ * a huge rawmidi buffer
+ */
+ spin_unlock_irqrestore(&substream->runtime->lock, flags);
+ cond_resched();
+ spin_lock_irqsave(&substream->runtime->lock, flags);
+ }
+ out:
+ spin_unlock_irqrestore(&substream->runtime->lock, flags);
+ } else {
+ vmidi->trigger = 0;
+ }
}
/*
@@ -236,7 +270,6 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
vmidi->port = rdev->port;
snd_virmidi_init_event(vmidi, &vmidi->event);
vmidi->rdev = rdev;
- INIT_WORK(&vmidi->output_work, snd_vmidi_output_work);
runtime->private_data = vmidi;
return 0;
}
@@ -266,9 +299,6 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream)
{
struct snd_virmidi *vmidi = substream->runtime->private_data;
-
- WRITE_ONCE(vmidi->trigger, false); /* to be sure */
- cancel_work_sync(&vmidi->output_work);
snd_midi_event_free(vmidi->parser);
substream->runtime->private_data = NULL;
kfree(vmidi);
@@ -525,4 +555,21 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
*rrmidi = rmidi;
return 0;
}
+
+/*
+ * ENTRY functions
+ */
+
+static int __init alsa_virmidi_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_virmidi_exit(void)
+{
+}
+
+module_init(alsa_virmidi_init)
+module_exit(alsa_virmidi_exit)
+
EXPORT_SYMBOL(snd_virmidi_new);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index b30f027eb0fe..175f9e4e01c8 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -74,6 +74,7 @@ void snd_request_card(int card)
return;
request_module("snd-card-%i", card);
}
+
EXPORT_SYMBOL(snd_request_card);
static void snd_request_other(int minor)
@@ -123,6 +124,7 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
mutex_unlock(&sound_mutex);
return private_data;
}
+
EXPORT_SYMBOL(snd_lookup_minor_data);
#ifdef CONFIG_MODULES
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 0a5c66229a22..0ca9d72b2273 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -55,6 +55,7 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
mutex_unlock(&sound_oss_mutex);
return private_data;
}
+
EXPORT_SYMBOL(snd_lookup_oss_minor_data);
static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
@@ -158,6 +159,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
kfree(preg);
return -EBUSY;
}
+
EXPORT_SYMBOL(snd_register_oss_device);
int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
@@ -198,6 +200,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
kfree(mptr);
return 0;
}
+
EXPORT_SYMBOL(snd_unregister_oss_device);
/*
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 50aad2bafdcc..a46a4089196d 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -345,7 +345,6 @@ int snd_timer_open(struct snd_timer_instance **ti,
*ti = timeri;
return err;
}
-EXPORT_SYMBOL(snd_timer_open);
/*
* close a timer instance
@@ -409,7 +408,6 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
return 0;
}
-EXPORT_SYMBOL(snd_timer_close);
/*
* close a timer instance
@@ -427,35 +425,23 @@ int snd_timer_close(struct snd_timer_instance *timeri)
return err;
}
-static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)
-{
- if (timer->hw.c_resolution)
- return timer->hw.c_resolution(timer);
- else
- return timer->hw.resolution;
-}
-
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
struct snd_timer * timer;
- unsigned long ret = 0;
- unsigned long flags;
if (timeri == NULL)
return 0;
- timer = timeri->timer;
- if (timer) {
- spin_lock_irqsave(&timer->lock, flags);
- ret = snd_timer_hw_resolution(timer);
- spin_unlock_irqrestore(&timer->lock, flags);
+ if ((timer = timeri->timer) != NULL) {
+ if (timer->hw.c_resolution)
+ return timer->hw.c_resolution(timer);
+ return timer->hw.resolution;
}
- return ret;
+ return 0;
}
-EXPORT_SYMBOL(snd_timer_resolution);
static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
- struct snd_timer *timer = ti->timer;
+ struct snd_timer *timer;
unsigned long resolution = 0;
struct snd_timer_instance *ts;
struct timespec tstamp;
@@ -467,14 +453,14 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
event > SNDRV_TIMER_EVENT_PAUSE))
return;
- if (timer &&
- (event == SNDRV_TIMER_EVENT_START ||
- event == SNDRV_TIMER_EVENT_CONTINUE))
- resolution = snd_timer_hw_resolution(timer);
+ if (event == SNDRV_TIMER_EVENT_START ||
+ event == SNDRV_TIMER_EVENT_CONTINUE)
+ resolution = snd_timer_resolution(ti);
if (ti->ccallback)
ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
+ timer = ti->timer;
if (timer == NULL)
return;
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
@@ -643,7 +629,6 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
else
return snd_timer_start1(timeri, true, ticks);
}
-EXPORT_SYMBOL(snd_timer_start);
/*
* stop the timer instance.
@@ -657,7 +642,6 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
else
return snd_timer_stop1(timeri, true);
}
-EXPORT_SYMBOL(snd_timer_stop);
/*
* start again.. the tick is kept.
@@ -673,7 +657,6 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
else
return snd_timer_start1(timeri, false, 0);
}
-EXPORT_SYMBOL(snd_timer_continue);
/*
* pause.. remember the ticks left
@@ -685,7 +668,6 @@ int snd_timer_pause(struct snd_timer_instance * timeri)
else
return snd_timer_stop1(timeri, false);
}
-EXPORT_SYMBOL(snd_timer_pause);
/*
* reschedule the timer
@@ -781,7 +763,10 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
- resolution = snd_timer_hw_resolution(timer);
+ if (timer->hw.c_resolution)
+ resolution = timer->hw.c_resolution(timer);
+ else
+ resolution = timer->hw.resolution;
/* loop for all active instances
* Here we cannot use list_for_each_entry because the active_list of a
@@ -864,7 +849,6 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
if (use_tasklet)
tasklet_schedule(&timer->task_queue);
}
-EXPORT_SYMBOL(snd_timer_interrupt);
/*
@@ -883,11 +867,6 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
if (snd_BUG_ON(!tid))
return -EINVAL;
- if (tid->dev_class == SNDRV_TIMER_CLASS_CARD ||
- tid->dev_class == SNDRV_TIMER_CLASS_PCM) {
- if (WARN_ON(!card))
- return -EINVAL;
- }
if (rtimer)
*rtimer = NULL;
timer = kzalloc(sizeof(*timer), GFP_KERNEL);
@@ -921,7 +900,6 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
*rtimer = timer;
return 0;
}
-EXPORT_SYMBOL(snd_timer_new);
static int snd_timer_free(struct snd_timer *timer)
{
@@ -1026,8 +1004,12 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
- event == SNDRV_TIMER_EVENT_MRESUME)
- resolution = snd_timer_hw_resolution(timer);
+ event == SNDRV_TIMER_EVENT_MRESUME) {
+ if (timer->hw.c_resolution)
+ resolution = timer->hw.c_resolution(timer);
+ else
+ resolution = timer->hw.resolution;
+ }
list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
@@ -1037,7 +1019,6 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
}
spin_unlock_irqrestore(&timer->lock, flags);
}
-EXPORT_SYMBOL(snd_timer_notify);
/*
* exported functions for global timers
@@ -1053,13 +1034,11 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
tid.subdevice = 0;
return snd_timer_new(NULL, id, &tid, rtimer);
}
-EXPORT_SYMBOL(snd_timer_global_new);
int snd_timer_global_free(struct snd_timer *timer)
{
return snd_timer_free(timer);
}
-EXPORT_SYMBOL(snd_timer_global_free);
int snd_timer_global_register(struct snd_timer *timer)
{
@@ -1069,7 +1048,6 @@ int snd_timer_global_register(struct snd_timer *timer)
dev.device_data = timer;
return snd_timer_dev_register(&dev);
}
-EXPORT_SYMBOL(snd_timer_global_register);
/*
* System timer
@@ -1077,17 +1055,15 @@ EXPORT_SYMBOL(snd_timer_global_register);
struct snd_timer_system_private {
struct timer_list tlist;
- struct snd_timer *snd_timer;
unsigned long last_expires;
unsigned long last_jiffies;
unsigned long correction;
};
-static void snd_timer_s_function(struct timer_list *t)
+static void snd_timer_s_function(unsigned long data)
{
- struct snd_timer_system_private *priv = from_timer(priv, t,
- tlist);
- struct snd_timer *timer = priv->snd_timer;
+ struct snd_timer *timer = (struct snd_timer *)data;
+ struct snd_timer_system_private *priv = timer->private_data;
unsigned long jiff = jiffies;
if (time_after(jiff, priv->last_expires))
priv->correction += (long)jiff - (long)priv->last_expires;
@@ -1169,8 +1145,7 @@ static int snd_timer_register_system(void)
snd_timer_free(timer);
return -ENOMEM;
}
- priv->snd_timer = timer;
- timer_setup(&priv->tlist, snd_timer_s_function, 0);
+ setup_timer(&priv->tlist, snd_timer_s_function, (unsigned long) timer);
timer->private_data = priv;
timer->private_free = snd_timer_free_system;
return snd_timer_global_register(timer);
@@ -1393,33 +1368,6 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
wake_up(&tu->qchange_sleep);
}
-static int realloc_user_queue(struct snd_timer_user *tu, int size)
-{
- struct snd_timer_read *queue = NULL;
- struct snd_timer_tread *tqueue = NULL;
-
- if (tu->tread) {
- tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
- if (!tqueue)
- return -ENOMEM;
- } else {
- queue = kcalloc(size, sizeof(*queue), GFP_KERNEL);
- if (!queue)
- return -ENOMEM;
- }
-
- spin_lock_irq(&tu->qlock);
- kfree(tu->queue);
- kfree(tu->tqueue);
- tu->queue_size = size;
- tu->queue = queue;
- tu->tqueue = tqueue;
- tu->qhead = tu->qtail = tu->qused = 0;
- spin_unlock_irq(&tu->qlock);
-
- return 0;
-}
-
static int snd_timer_user_open(struct inode *inode, struct file *file)
{
struct snd_timer_user *tu;
@@ -1436,7 +1384,10 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
init_waitqueue_head(&tu->qchange_sleep);
mutex_init(&tu->ioctl_lock);
tu->ticks = 1;
- if (realloc_user_queue(tu, 128) < 0) {
+ tu->queue_size = 128;
+ tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
+ GFP_KERNEL);
+ if (tu->queue == NULL) {
kfree(tu);
return -ENOMEM;
}
@@ -1664,8 +1615,10 @@ static int snd_timer_user_gstatus(struct file *file,
mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
- spin_lock_irq(&t->lock);
- gstatus.resolution = snd_timer_hw_resolution(t);
+ if (t->hw.c_resolution)
+ gstatus.resolution = t->hw.c_resolution(t);
+ else
+ gstatus.resolution = t->hw.resolution;
if (t->hw.precise_resolution) {
t->hw.precise_resolution(t, &gstatus.resolution_num,
&gstatus.resolution_den);
@@ -1673,7 +1626,6 @@ static int snd_timer_user_gstatus(struct file *file,
gstatus.resolution_num = gstatus.resolution;
gstatus.resolution_den = 1000000000uL;
}
- spin_unlock_irq(&t->lock);
} else {
err = -ENODEV;
}
@@ -1707,12 +1659,34 @@ static int snd_timer_user_tselect(struct file *file,
if (err < 0)
goto __err;
- tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
- tu->timeri->callback = tu->tread
+ tu->qhead = tu->qtail = tu->qused = 0;
+ kfree(tu->queue);
+ tu->queue = NULL;
+ kfree(tu->tqueue);
+ tu->tqueue = NULL;
+ if (tu->tread) {
+ tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
+ GFP_KERNEL);
+ if (tu->tqueue == NULL)
+ err = -ENOMEM;
+ } else {
+ tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
+ GFP_KERNEL);
+ if (tu->queue == NULL)
+ err = -ENOMEM;
+ }
+
+ if (err < 0) {
+ snd_timer_close(tu->timeri);
+ tu->timeri = NULL;
+ } else {
+ tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
+ tu->timeri->callback = tu->tread
? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
- tu->timeri->ccallback = snd_timer_user_ccallback;
- tu->timeri->callback_data = (void *)tu;
- tu->timeri->disconnect = snd_timer_user_disconnect;
+ tu->timeri->ccallback = snd_timer_user_ccallback;
+ tu->timeri->callback_data = (void *)tu;
+ tu->timeri->disconnect = snd_timer_user_disconnect;
+ }
__err:
return err;
@@ -1754,6 +1728,8 @@ static int snd_timer_user_params(struct file *file,
struct snd_timer_user *tu;
struct snd_timer_params params;
struct snd_timer *t;
+ struct snd_timer_read *tr;
+ struct snd_timer_tread *ttr;
int err;
tu = file->private_data;
@@ -1816,11 +1792,24 @@ static int snd_timer_user_params(struct file *file,
spin_unlock_irq(&t->lock);
if (params.queue_size > 0 &&
(unsigned int)tu->queue_size != params.queue_size) {
- err = realloc_user_queue(tu, params.queue_size);
- if (err < 0)
- goto _end;
+ if (tu->tread) {
+ ttr = kmalloc(params.queue_size * sizeof(*ttr),
+ GFP_KERNEL);
+ if (ttr) {
+ kfree(tu->tqueue);
+ tu->queue_size = params.queue_size;
+ tu->tqueue = ttr;
+ }
+ } else {
+ tr = kmalloc(params.queue_size * sizeof(*tr),
+ GFP_KERNEL);
+ if (tr) {
+ kfree(tu->queue);
+ tu->queue_size = params.queue_size;
+ tu->queue = tr;
+ }
+ }
}
- spin_lock_irq(&tu->qlock);
tu->qhead = tu->qtail = tu->qused = 0;
if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
if (tu->tread) {
@@ -1841,7 +1830,6 @@ static int snd_timer_user_params(struct file *file,
}
tu->filter = params.filter;
tu->ticks = params.ticks;
- spin_unlock_irq(&tu->qlock);
err = 0;
_end:
if (copy_to_user(_params, &params, sizeof(params)))
@@ -1944,19 +1932,13 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
return snd_timer_user_next_device(argp);
case SNDRV_TIMER_IOCTL_TREAD:
{
- int xarg, old_tread;
+ int xarg;
if (tu->timeri) /* too late */
return -EBUSY;
if (get_user(xarg, p))
return -EFAULT;
- old_tread = tu->tread;
tu->tread = xarg ? 1 : 0;
- if (tu->tread != old_tread &&
- realloc_user_queue(tu, tu->queue_size) < 0) {
- tu->tread = old_tread;
- return -ENOMEM;
- }
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
@@ -2089,12 +2071,10 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
poll_wait(file, &tu->qchange_sleep, wait);
mask = 0;
- spin_lock_irq(&tu->qlock);
if (tu->qused)
mask |= POLLIN | POLLRDNORM;
if (tu->disconnected)
mask |= POLLERR;
- spin_unlock_irq(&tu->qlock);
return mask;
}
@@ -2148,7 +2128,8 @@ static int __init alsa_timer_init(void)
err = snd_timer_register_system();
if (err < 0) {
pr_err("ALSA: unable to register system timer (%i)\n", err);
- goto put_timer;
+ put_device(&timer_dev);
+ return err;
}
err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
@@ -2156,15 +2137,12 @@ static int __init alsa_timer_init(void)
if (err < 0) {
pr_err("ALSA: unable to register timer device (%i)\n", err);
snd_timer_free_all();
- goto put_timer;
+ put_device(&timer_dev);
+ return err;
}
snd_timer_proc_init();
return 0;
-
-put_timer:
- put_device(&timer_dev);
- return err;
}
static void __exit alsa_timer_exit(void)
@@ -2180,3 +2158,17 @@ static void __exit alsa_timer_exit(void)
module_init(alsa_timer_init)
module_exit(alsa_timer_exit)
+
+EXPORT_SYMBOL(snd_timer_open);
+EXPORT_SYMBOL(snd_timer_close);
+EXPORT_SYMBOL(snd_timer_resolution);
+EXPORT_SYMBOL(snd_timer_start);
+EXPORT_SYMBOL(snd_timer_stop);
+EXPORT_SYMBOL(snd_timer_continue);
+EXPORT_SYMBOL(snd_timer_pause);
+EXPORT_SYMBOL(snd_timer_new);
+EXPORT_SYMBOL(snd_timer_notify);
+EXPORT_SYMBOL(snd_timer_global_new);
+EXPORT_SYMBOL(snd_timer_global_free);
+EXPORT_SYMBOL(snd_timer_global_register);
+EXPORT_SYMBOL(snd_timer_interrupt);
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 58fa3f94722a..b67de2bb06a2 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -63,7 +63,7 @@ static int slave_update(struct link_slave *slave)
struct snd_ctl_elem_value *uctl;
int err, ch;
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return -ENOMEM;
uctl->id = slave->slave.id;
@@ -421,15 +421,13 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
kctl->private_free = master_free;
/* additional (constant) TLV read */
- if (tlv) {
- unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE];
- if (type == SNDRV_CTL_TLVT_DB_SCALE ||
- type == SNDRV_CTL_TLVT_DB_MINMAX ||
- type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) {
- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- memcpy(master->tlv, tlv, sizeof(master->tlv));
- kctl->tlv.p = master->tlv;
- }
+ if (tlv &&
+ (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
+ tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
+ tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+ memcpy(master->tlv, tlv, sizeof(master->tlv));
+ kctl->tlv.p = master->tlv;
}
return kctl;
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7144cc36e8ae..8545da99b183 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -6,24 +6,11 @@ config SND_OPL3_LIB
tristate
select SND_TIMER
select SND_HWDEP
- select SND_SEQ_DEVICE if SND_SEQUENCER != n
config SND_OPL4_LIB
tristate
select SND_TIMER
select SND_HWDEP
- select SND_SEQ_DEVICE if SND_SEQUENCER != n
-
-# select SEQ stuff to min(SND_SEQUENCER,SND_XXX)
-config SND_OPL3_LIB_SEQ
- def_tristate SND_SEQUENCER && SND_OPL3_LIB
- select SND_SEQ_MIDI_EMUL
- select SND_SEQ_MIDI_EVENT
-
-config SND_OPL4_LIB_SEQ
- def_tristate SND_SEQUENCER && SND_OPL4_LIB
- select SND_SEQ_MIDI_EMUL
- select SND_SEQ_MIDI_EVENT
config SND_VX_LIB
tristate
@@ -112,8 +99,6 @@ config SND_VIRMIDI
depends on SND_SEQUENCER
select SND_TIMER
select SND_RAWMIDI
- select SND_SEQ_VIRMIDI
- select SND_SEQ_MIDI_EVENT
help
Say Y here to include the virtual MIDI driver. This driver
allows to connect applications using raw MIDI devices to
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index d5e5b4657b4b..cd9e9f31720f 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -528,7 +528,7 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
opl3->hwdep = hw;
opl3->seq_dev_num = seq_device;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
strcpy(opl3->seq_dev->name, hw->name);
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index d3e91be8b23a..fdae5d7f421f 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -252,7 +252,7 @@ static int snd_opl3_seq_probe(struct device *_dev)
spin_lock_init(&opl3->sys_timer_lock);
opl3->sys_timer_status = 0;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
snd_opl3_init_seq_oss(opl3, name);
#endif
return 0;
@@ -267,7 +267,7 @@ static int snd_opl3_seq_remove(struct device *_dev)
if (opl3 == NULL)
return -EINVAL;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
snd_opl3_free_seq_oss(opl3);
#endif
if (opl3->seq_client >= 0) {
diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h
index eaef435e0528..a371c075ac87 100644
--- a/sound/drivers/opl3/opl3_voice.h
+++ b/sound/drivers/opl3/opl3_voice.h
@@ -44,12 +44,9 @@ void snd_opl3_load_drums(struct snd_opl3 *opl3);
void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan);
/* Prototypes for opl3_oss.c */
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name);
void snd_opl3_free_seq_oss(struct snd_opl3 *opl3);
-#else
-#define snd_opl3_init_seq_oss(opl3, name) /* NOP */
-#define snd_opl3_free_seq_oss(opl3) /* NOP */
#endif
#endif
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index bc345d564f8d..89c7aa04b3bc 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -153,7 +153,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4)
return 0;
}
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
{
struct snd_opl4 *opl4 = seq_dev->private_data;
@@ -249,7 +249,7 @@ int snd_opl4_create(struct snd_card *card,
snd_opl4_create_mixer(opl4);
snd_opl4_create_proc(opl4);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
opl4->seq_client = -1;
if (opl4->hardware < OPL3_HW_OPL4_ML)
snd_opl4_create_seq_dev(opl4, seq_device);
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
index a16b4677c1e9..9a41bdebce6b 100644
--- a/sound/drivers/opl4/opl4_local.h
+++ b/sound/drivers/opl4/opl4_local.h
@@ -184,7 +184,7 @@ struct snd_opl4 {
#endif
struct mutex access_mutex;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
int used;
int seq_dev_num;
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 98a41ac40b60..be9477e30739 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -455,7 +455,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
return 0;
}
-static const struct snd_kcontrol_new vx_control_output_level = {
+static struct snd_kcontrol_new vx_control_output_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -514,7 +514,7 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
return 0;
}
-static const struct snd_kcontrol_new vx_control_audio_src = {
+static struct snd_kcontrol_new vx_control_audio_src = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = vx_audio_src_info,
@@ -558,7 +558,7 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return 0;
}
-static const struct snd_kcontrol_new vx_control_clock_mode = {
+static struct snd_kcontrol_new vx_control_clock_mode = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Clock Mode",
.info = vx_clock_mode_info,
@@ -717,7 +717,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
-static const struct snd_kcontrol_new vx_control_audio_gain = {
+static struct snd_kcontrol_new vx_control_audio_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -727,14 +727,14 @@ static const struct snd_kcontrol_new vx_control_audio_gain = {
.put = vx_audio_gain_put,
.tlv = { .p = db_scale_audio_gain },
};
-static const struct snd_kcontrol_new vx_control_output_switch = {
+static struct snd_kcontrol_new vx_control_output_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.info = vx_audio_sw_info,
.get = vx_audio_sw_get,
.put = vx_audio_sw_put
};
-static const struct snd_kcontrol_new vx_control_monitor_gain = {
+static struct snd_kcontrol_new vx_control_monitor_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Volume",
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -744,7 +744,7 @@ static const struct snd_kcontrol_new vx_control_monitor_gain = {
.put = vx_audio_monitor_put,
.tlv = { .p = db_scale_audio_gain },
};
-static const struct snd_kcontrol_new vx_control_monitor_switch = {
+static struct snd_kcontrol_new vx_control_monitor_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Switch",
.info = vx_audio_sw_info, /* shared */
@@ -805,7 +805,7 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
return 0;
}
-static const struct snd_kcontrol_new vx_control_iec958_mask = {
+static struct snd_kcontrol_new vx_control_iec958_mask = {
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
@@ -813,7 +813,7 @@ static const struct snd_kcontrol_new vx_control_iec958_mask = {
.get = vx_iec958_mask_get,
};
-static const struct snd_kcontrol_new vx_control_iec958 = {
+static struct snd_kcontrol_new vx_control_iec958 = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.info = vx_iec958_info,
@@ -878,7 +878,7 @@ static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return 0;
}
-static const struct snd_kcontrol_new vx_control_vu_meter = {
+static struct snd_kcontrol_new vx_control_vu_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -886,7 +886,7 @@ static const struct snd_kcontrol_new vx_control_vu_meter = {
.get = vx_vu_meter_get,
};
-static const struct snd_kcontrol_new vx_control_peak_meter = {
+static struct snd_kcontrol_new vx_control_peak_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -894,7 +894,7 @@ static const struct snd_kcontrol_new vx_control_peak_meter = {
.get = vx_peak_meter_get,
};
-static const struct snd_kcontrol_new vx_control_saturation = {
+static struct snd_kcontrol_new vx_control_saturation = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Saturation",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c
index d3fb5022a65a..6dbf047d4f75 100644
--- a/sound/firewire/bebob/bebob_maudio.c
+++ b/sound/firewire/bebob/bebob_maudio.c
@@ -396,7 +396,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl,
return err;
}
-static const struct snd_kcontrol_new special_clk_ctl = {
+static struct snd_kcontrol_new special_clk_ctl = {
.name = "Clock Source",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -429,7 +429,7 @@ static int special_sync_ctl_get(struct snd_kcontrol *kctl,
return 0;
}
-static const struct snd_kcontrol_new special_sync_ctl = {
+static struct snd_kcontrol_new special_sync_ctl = {
.name = "Sync Status",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -521,7 +521,7 @@ end:
mutex_unlock(&bebob->mutex);
return err;
}
-static const struct snd_kcontrol_new special_dig_in_iface_ctl = {
+static struct snd_kcontrol_new special_dig_in_iface_ctl = {
.name = "Digital Input Interface",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -577,7 +577,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl,
mutex_unlock(&bebob->mutex);
return err;
}
-static const struct snd_kcontrol_new special_dig_out_iface_ctl = {
+static struct snd_kcontrol_new special_dig_out_iface_ctl = {
.name = "Digital Output Interface",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index b7a75b0a382a..37adcc6cbe6b 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -377,7 +377,6 @@ config SND_SBAWE
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_SB16_DSP
- select SND_SEQ_DEVICE if SND_SEQUENCER != n
help
Say Y here to include support for Sound Blaster AWE soundcards
(including the Plug and Play version).
@@ -385,12 +384,6 @@ config SND_SBAWE
To compile this driver as a module, choose M here: the module
will be called snd-sbawe.
-# select SEQ stuff to min(SND_SEQUENCER,SND_XXX)
-config SND_SBAWE_SEQ
- def_tristate SND_SEQUENCER && SND_SBAWE
- select SND_SEQ_MIDI_EMUL
- select SND_SEQ_VIRMIDI
-
config SND_SB16_CSP
bool "Sound Blaster 16/AWE CSP support"
depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index d56973b770c7..ec180708f160 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1138,7 +1138,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
snd_emu8000_free(hw);
return err;
}
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(struct snd_emu8000*), &awe) >= 0) {
strcpy(awe->name, "EMU-8000");
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
index d28d712f99f4..72a9ac5efb40 100644
--- a/sound/isa/sb/emu8000_callback.c
+++ b/sound/isa/sb/emu8000_callback.c
@@ -36,7 +36,7 @@ static void reset_voice(struct snd_emux *emu, int ch);
static void terminate_voice(struct snd_emux_voice *vp);
static void sysex(struct snd_emux *emu, char *buf, int len, int parsed,
struct snd_midi_channel_set *chset);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2);
#endif
static int load_fx(struct snd_emux *emu, int type, int mode,
@@ -76,7 +76,7 @@ static struct snd_emux_operators emu8000_ops = {
.sample_reset = snd_emu8000_sample_reset,
.load_fx = load_fx,
.sysex = sysex,
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
.oss_ioctl = oss_ioctl,
#endif
};
@@ -477,7 +477,7 @@ sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_chan
}
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
/*
* OSS ioctl callback
*/
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 917a93d696c3..3b2e4f405ff2 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -62,7 +62,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
#define SNDRV_DEBUG_IRQ
#endif
-#if defined(SNDRV_SBAWE) && IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)))
#define SNDRV_SBAWE_EMU8000
#endif
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index 6505deb8c06b..684dc4ddef41 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -264,7 +264,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
return old != new;
}
-static const struct snd_kcontrol_new hal2_ctrl_headphone = {
+static struct snd_kcontrol_new hal2_ctrl_headphone = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -274,7 +274,7 @@ static const struct snd_kcontrol_new hal2_ctrl_headphone = {
.put = hal2_gain_put,
};
-static const struct snd_kcontrol_new hal2_ctrl_mic = {
+static struct snd_kcontrol_new hal2_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index 0ebc1c3727df..f07aa3993f83 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -230,7 +230,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
}
/* dac1/pcm0 mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -242,7 +242,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
};
/* dac2/pcm1 mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 1,
@@ -254,7 +254,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
};
/* record level mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
+static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -265,7 +265,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
};
/* record level source control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
+static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -275,7 +275,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
};
/* line mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_line = {
+static struct snd_kcontrol_new sgio2audio_ctrl_line = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 0,
@@ -287,7 +287,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_line = {
};
/* cd mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_cd = {
+static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 1,
@@ -299,7 +299,7 @@ static const struct snd_kcontrol_new sgio2audio_ctrl_cd = {
};
/* mic mixer control */
-static const struct snd_kcontrol_new sgio2audio_ctrl_mic = {
+static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 914b859770f8..32151d8c6bb8 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -465,7 +465,6 @@ config SND_EMU10K1
select SND_RAWMIDI
select SND_AC97_CODEC
select SND_TIMER
- select SND_SEQ_DEVICE if SND_SEQUENCER != n
depends on ZONE_DMA
help
Say Y to include support for Sound Blaster PCI 512, Live!,
@@ -478,12 +477,6 @@ config SND_EMU10K1
To compile this driver as a module, choose M here: the module
will be called snd-emu10k1.
-# select SEQ stuff to min(SND_SEQUENCER,SND_XXX)
-config SND_EMU10K1_SEQ
- def_tristate SND_SEQUENCER && SND_EMU10K1
- select SND_SEQ_MIDI_EMUL
- select SND_SEQ_VIRMIDI
-
config SND_EMU10K1X
tristate "Emu10k1X (Dell OEM Version)"
select SND_AC97_CODEC
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index d3203df50a1a..6a0e49ac5273 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
"{Creative Labs,SB Audigy}}");
-#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
#define ENABLE_SYNTH
#include <sound/emu10k1_synth.h>
#endif
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index 425315cf60e2..a4a664259f0d 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -69,7 +69,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
-static const struct snd_kcontrol_new vx_control_mic_level = {
+static struct snd_kcontrol_new vx_control_mic_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -109,7 +109,7 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
return 0;
}
-static const struct snd_kcontrol_new vx_control_mic_boost = {
+static struct snd_kcontrol_new vx_control_mic_boost = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost",
.info = vx_mic_boost_info,
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index d1e4ef1c5c30..1468e4b7bf93 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
},
};
-static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -523,7 +523,7 @@ static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
.private_value = AMP_CH_HD,
};
-static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_stereo_info,
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index f19eb3e39937..d3524f9fa05d 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -206,7 +206,7 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
return oval != chip->beep->volume;
}
-static const struct snd_kcontrol_new snd_pmac_beep_mixer = {
+static struct snd_kcontrol_new snd_pmac_beep_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Beep Playback Volume",
.info = snd_pmac_info_beep,
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 0779a2912237..58ee8089bbf9 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -897,7 +897,7 @@ static struct snd_kcontrol_new snapper_mixers[] = {
},
};
-static const struct snd_kcontrol_new tumbler_hp_sw = {
+static struct snd_kcontrol_new tumbler_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -905,7 +905,7 @@ static const struct snd_kcontrol_new tumbler_hp_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_HP,
};
-static const struct snd_kcontrol_new tumbler_speaker_sw = {
+static struct snd_kcontrol_new tumbler_speaker_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -913,7 +913,7 @@ static const struct snd_kcontrol_new tumbler_speaker_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_AMP,
};
-static const struct snd_kcontrol_new tumbler_lineout_sw = {
+static struct snd_kcontrol_new tumbler_lineout_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Out Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -921,7 +921,7 @@ static const struct snd_kcontrol_new tumbler_lineout_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_LINE,
};
-static const struct snd_kcontrol_new tumbler_drc_sw = {
+static struct snd_kcontrol_new tumbler_drc_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Switch",
.info = snd_pmac_boolean_mono_info,
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index ab4802df62e1..fbbc25279559 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -535,7 +535,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
+static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -544,7 +544,7 @@ static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
.put = aica_pcmswitch_put
};
-static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
+static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 4a22aadac294..76b2ab8c2b4a 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -441,7 +441,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
return 0;
}
-static const struct snd_kcontrol_new playback_controls = {
+static struct snd_kcontrol_new playback_controls = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -451,7 +451,7 @@ static const struct snd_kcontrol_new playback_controls = {
.private_value = VOLUME_PLAYBACK,
};
-static const struct snd_kcontrol_new capture_controls = {
+static struct snd_kcontrol_new capture_controls = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Capture Volume",
.index = 0,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6e460bdb2b3e..8a64a1b22705 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -638,7 +638,9 @@ int snd_soc_suspend(struct device *dev)
/* Due to the resume being scheduled into a workqueue we could
* suspend before that's finished - wait for it to complete.
*/
+ snd_power_lock(card->snd_card);
snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
+ snd_power_unlock(card->snd_card);
/* we're going to block userspace touching us until resume completes */
snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 5eeca313bd9a..914cb99a6ed2 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2744,9 +2744,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (platform->driver->ops) {
rtd->ops.ack = platform->driver->ops->ack;
- rtd->ops.copy_user = platform->driver->ops->copy_user;
- rtd->ops.copy_kernel = platform->driver->ops->copy_kernel;
- rtd->ops.fill_silence = platform->driver->ops->fill_silence;
+ rtd->ops.copy = platform->driver->ops->copy;
+ rtd->ops.silence = platform->driver->ops->silence;
rtd->ops.page = platform->driver->ops->page;
rtd->ops.mmap = platform->driver->ops->mmap;
}
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index b9981e8c0027..9312cd8a6fdd 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -47,7 +47,7 @@ int snd_emux_new(struct snd_emux **remu)
mutex_init(&emu->register_mutex);
emu->client = -1;
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
emu->oss_synth = NULL;
#endif
emu->max_voices = 0;
@@ -123,7 +123,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
snd_emux_init_voices(emu);
snd_emux_init_seq(emu, card, index);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
snd_emux_init_seq_oss(emu);
#endif
snd_emux_init_virmidi(emu, card);
@@ -150,7 +150,7 @@ int snd_emux_free(struct snd_emux *emu)
snd_emux_proc_free(emu);
snd_emux_delete_virmidi(emu);
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
snd_emux_detach_seq_oss(emu);
#endif
snd_emux_detach_seq(emu);
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
index 9ac0bf531b4b..a447218b6160 100644
--- a/sound/synth/emux/emux_effect.c
+++ b/sound/synth/emux/emux_effect.c
@@ -150,7 +150,7 @@ effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode)
return addr;
}
-#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
+#ifdef CONFIG_SND_SEQUENCER_OSS
/* change effects - for OSS sequencer compatibility */
void
snd_emux_send_effect_oss(struct snd_emux_port *port,
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index de19e108974a..850fab4a8f3b 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -23,6 +23,8 @@
*/
+#ifdef CONFIG_SND_SEQUENCER_OSS
+
#include <linux/export.h>
#include <linux/uaccess.h>
#include <sound/core.h>
@@ -503,3 +505,5 @@ fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param,
ev.data.control.value = val;
snd_emux_event_input(&ev, 0, port, atomic, hop);
}
+
+#endif /* CONFIG_SND_SEQUENCER_OSS */
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 17d5e3ee6d73..dcddfc354ba6 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -143,40 +143,47 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
chip->card = card;
ret = usb6fire_comm_init(chip);
- if (ret < 0)
- goto destroy_chip;
+ if (ret < 0) {
+ usb6fire_chip_destroy(chip);
+ return ret;
+ }
ret = usb6fire_midi_init(chip);
- if (ret < 0)
- goto destroy_chip;
+ if (ret < 0) {
+ usb6fire_chip_destroy(chip);
+ return ret;
+ }
ret = usb6fire_pcm_init(chip);
- if (ret < 0)
- goto destroy_chip;
+ if (ret < 0) {
+ usb6fire_chip_destroy(chip);
+ return ret;
+ }
ret = usb6fire_control_init(chip);
- if (ret < 0)
- goto destroy_chip;
+ if (ret < 0) {
+ usb6fire_chip_destroy(chip);
+ return ret;
+ }
ret = snd_card_register(card);
if (ret < 0) {
dev_err(&intf->dev, "cannot register card.");
- goto destroy_chip;
+ usb6fire_chip_destroy(chip);
+ return ret;
}
usb_set_intfdata(intf, chip);
return 0;
-
-destroy_chip:
- usb6fire_chip_destroy(chip);
- return ret;
}
static void usb6fire_chip_disconnect(struct usb_interface *intf)
{
struct sfire_chip *chip;
+ struct snd_card *card;
chip = usb_get_intfdata(intf);
if (chip) { /* if !chip, fw upload has been performed */
+ card = chip->card;
chip->intf_count--;
if (!chip->intf_count) {
mutex_lock(&register_mutex);
@@ -191,7 +198,7 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
}
}
-static const struct usb_device_id device_table[] = {
+static struct usb_device_id device_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0ccd,
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index a3ee9dba21b0..42cb33b94f6a 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -12,7 +12,6 @@ snd-usb-audio-objs := card.o \
mixer_scarlett.o \
mixer_us16x08.o \
pcm.o \
- power.o \
proc.o \
quirks.o \
stream.o
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
index d6c8b29fe430..7ca44be0fb58 100644
--- a/sound/usb/bcd2000/bcd2000.c
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -29,7 +29,7 @@
#define PREFIX "snd-bcd2000: "
#define BUFSIZE 64
-static const struct usb_device_id id_table[] = {
+static struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1397, 0x00bd) },
{ },
};
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 60dac0587e04..8f66ba730d69 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -636,7 +636,6 @@ static void read_completed(struct urb *urb)
struct device *dev;
struct urb *out = NULL;
int i, frame, len, send_it = 0, outframe = 0;
- unsigned long flags;
size_t offset = 0;
if (urb->status || !info)
@@ -673,10 +672,10 @@ static void read_completed(struct urb *urb)
offset += len;
if (len > 0) {
- spin_lock_irqsave(&cdev->spinlock, flags);
+ spin_lock(&cdev->spinlock);
fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]);
read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]);
- spin_unlock_irqrestore(&cdev->spinlock, flags);
+ spin_unlock(&cdev->spinlock);
check_for_elapsed_periods(cdev, cdev->sub_playback);
check_for_elapsed_periods(cdev, cdev->sub_capture);
send_it = 1;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index f4a72e39ffa9..ca692b8b3690 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -81,7 +81,7 @@ enum {
DEPTH_32 = 3
};
-static const struct usb_device_id snd_usb_id_table[] = {
+static struct usb_device_id snd_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = USB_VID_NATIVEINSTRUMENTS,
@@ -200,7 +200,6 @@ static void usb_ep1_command_reply_dispatch (struct urb* urb)
break;
}
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
- /* fall through */
case EP1_CMD_READ_ERP:
case EP1_CMD_READ_ANALOG:
snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length);
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a105947eaf55..c505b1f8e263 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -7,7 +7,6 @@
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
- * Audio Class 3.0 support by Ruslan Bilovol <ruslan.bilovol@gmail.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
@@ -45,7 +44,6 @@
#include <linux/mutex.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
#include <linux/module.h>
#include <sound/control.h>
@@ -86,8 +84,6 @@ static bool ignore_ctl_error;
static bool autoclock = true;
static char *quirk_alias[SNDRV_CARDS];
-bool snd_usb_use_vmalloc = true;
-
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
module_param_array(id, charp, NULL, 0444);
@@ -107,8 +103,6 @@ module_param(autoclock, bool, 0444);
MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
module_param_array(quirk_alias, charp, NULL, 0444);
MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
-module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
-MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
/*
* we keep the snd_usb_audio_t instances by ourselves for merging
@@ -225,13 +219,32 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
struct usb_device *dev = chip->dev;
struct usb_host_interface *host_iface;
struct usb_interface_descriptor *altsd;
+ void *control_header;
int i, protocol;
+ int rest_bytes;
/* find audiocontrol interface */
host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
+ control_header = snd_usb_find_csint_desc(host_iface->extra,
+ host_iface->extralen,
+ NULL, UAC_HEADER);
altsd = get_iface_desc(host_iface);
protocol = altsd->bInterfaceProtocol;
+ if (!control_header) {
+ dev_err(&dev->dev, "cannot find UAC_HEADER\n");
+ return -EINVAL;
+ }
+
+ rest_bytes = (void *)(host_iface->extra + host_iface->extralen) -
+ control_header;
+
+ /* just to be sure -- this shouldn't hit at all */
+ if (rest_bytes <= 0) {
+ dev_err(&dev->dev, "invalid control header\n");
+ return -EINVAL;
+ }
+
switch (protocol) {
default:
dev_warn(&dev->dev,
@@ -240,25 +253,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
/* fall through */
case UAC_VERSION_1: {
- struct uac1_ac_header_descriptor *h1;
- int rest_bytes;
-
- h1 = snd_usb_find_csint_desc(host_iface->extra,
- host_iface->extralen,
- NULL, UAC_HEADER);
- if (!h1) {
- dev_err(&dev->dev, "cannot find UAC_HEADER\n");
- return -EINVAL;
- }
-
- rest_bytes = (void *)(host_iface->extra +
- host_iface->extralen) - (void *)h1;
-
- /* just to be sure -- this shouldn't hit at all */
- if (rest_bytes <= 0) {
- dev_err(&dev->dev, "invalid control header\n");
- return -EINVAL;
- }
+ struct uac1_ac_header_descriptor *h1 = control_header;
if (rest_bytes < sizeof(*h1)) {
dev_err(&dev->dev, "too short v1 buffer descriptor\n");
@@ -286,8 +281,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
break;
}
- case UAC_VERSION_2:
- case UAC_VERSION_3: {
+ case UAC_VERSION_2: {
struct usb_interface_assoc_descriptor *assoc =
usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
@@ -307,24 +301,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
}
if (!assoc) {
- dev_err(&dev->dev, "Audio class v2/v3 interfaces need an interface association\n");
+ dev_err(&dev->dev, "Audio class v2 interfaces need an interface association\n");
return -EINVAL;
}
- if (protocol == UAC_VERSION_3) {
- int badd = assoc->bFunctionSubClass;
-
- if (badd != UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 &&
- (badd < UAC3_FUNCTION_SUBCLASS_GENERIC_IO ||
- badd > UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE)) {
- dev_err(&dev->dev,
- "Unsupported UAC3 BADD profile\n");
- return -EINVAL;
- }
-
- chip->badd_profile = badd;
- }
-
for (i = 0; i < assoc->bInterfaceCount; i++) {
int intf = assoc->bFirstInterface + i;
@@ -346,9 +326,8 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
*
*/
-static void snd_usb_audio_free(struct snd_card *card)
+static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
- struct snd_usb_audio *chip = card->private_data;
struct snd_usb_endpoint *ep, *n;
list_for_each_entry_safe(ep, n, &chip->ep_list, list)
@@ -357,6 +336,14 @@ static void snd_usb_audio_free(struct snd_card *card)
mutex_destroy(&chip->mutex);
if (!atomic_read(&chip->shutdown))
dev_set_drvdata(&chip->dev->dev, NULL);
+ kfree(chip);
+ return 0;
+}
+
+static int snd_usb_audio_dev_free(struct snd_device *device)
+{
+ struct snd_usb_audio *chip = device->device_data;
+ return snd_usb_audio_free(chip);
}
static void usb_audio_make_shortname(struct usb_device *dev,
@@ -456,6 +443,9 @@ static int snd_usb_audio_create(struct usb_interface *intf,
struct snd_usb_audio *chip;
int err;
char component[14];
+ static struct snd_device_ops ops = {
+ .dev_free = snd_usb_audio_dev_free,
+ };
*rchip = NULL;
@@ -473,13 +463,18 @@ static int snd_usb_audio_create(struct usb_interface *intf,
}
err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
- sizeof(*chip), &card);
+ 0, &card);
if (err < 0) {
dev_err(&dev->dev, "cannot create card instance %d\n", idx);
return err;
}
- chip = card->private_data;
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (! chip) {
+ snd_card_free(card);
+ return -ENOMEM;
+ }
+
mutex_init(&chip->mutex);
init_waitqueue_head(&chip->shutdown_wait);
chip->index = idx;
@@ -497,7 +492,11 @@ static int snd_usb_audio_create(struct usb_interface *intf,
INIT_LIST_HEAD(&chip->midi_list);
INIT_LIST_HEAD(&chip->mixer_list);
- card->private_free = snd_usb_audio_free;
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ snd_usb_audio_free(chip);
+ snd_card_free(card);
+ return err;
+ }
strcpy(card->driver, "USB-Audio");
sprintf(component, "USB%04x:%04x",
@@ -535,7 +534,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id)
return false;
}
-static const struct usb_device_id usb_audio_ids[]; /* defined below */
+static struct usb_device_id usb_audio_ids[]; /* defined below */
/* look for the corresponding quirk */
static const struct snd_usb_audio_quirk *
@@ -812,7 +811,6 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
if (!chip->num_suspended_intf++) {
list_for_each_entry(as, &chip->pcm_list, list) {
snd_pcm_suspend_all(as->pcm);
- snd_usb_pcm_suspend(as);
as->substream[0].need_setup_ep =
as->substream[1].need_setup_ep = true;
}
@@ -828,7 +826,6 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
- struct snd_usb_stream *as;
struct usb_mixer_interface *mixer;
struct list_head *p;
int err = 0;
@@ -839,13 +836,6 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
return 0;
atomic_inc(&chip->active); /* avoid autopm */
-
- list_for_each_entry(as, &chip->pcm_list, list) {
- err = snd_usb_pcm_resume(as);
- if (err < 0)
- goto err_out;
- }
-
/*
* ALSA leaves material resumption to user space
* we just notify and restart the mixers
@@ -884,7 +874,7 @@ static int usb_audio_reset_resume(struct usb_interface *intf)
#define usb_audio_reset_resume NULL
#endif /* CONFIG_PM */
-static const struct usb_device_id usb_audio_ids [] = {
+static struct usb_device_id usb_audio_ids [] = {
#include "quirks-table.h"
{ .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
.bInterfaceClass = USB_CLASS_AUDIO,
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5dc808e41f2a..cbcf2158e61d 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -21,7 +21,7 @@ struct audioformat {
unsigned char endpoint; /* endpoint */
unsigned char ep_attr; /* endpoint attributes */
unsigned char datainterval; /* log_2 of data packet interval */
- unsigned char protocol; /* UAC_VERSION_1/2/3 */
+ unsigned char protocol; /* UAC_VERSION_1/2 */
unsigned int maxpacksize; /* max. packet size */
unsigned int rates; /* rate bitmasks */
unsigned int rate_min, rate_max; /* min/max rates */
@@ -36,7 +36,6 @@ struct audioformat {
struct snd_usb_substream;
struct snd_usb_endpoint;
-struct snd_usb_power_domain;
struct snd_urb_ctx {
struct urb *urb;
@@ -115,7 +114,6 @@ struct snd_usb_substream {
int interface; /* current interface */
int endpoint; /* assigned endpoint */
struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */
- struct snd_usb_power_domain *str_pd; /* UAC3 Power Domain for streaming path */
snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */
unsigned int channels; /* current number of channels (for hw_params callback) */
unsigned int channels_max; /* max channels in the all audiofmts */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index db5e39d67a90..eb3396ffba4c 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -23,7 +23,6 @@
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -35,85 +34,57 @@
#include "clock.h"
#include "quirks.h"
-static void *find_uac_clock_desc(struct usb_host_interface *iface, int id,
- bool (*validator)(void *, int), u8 type)
+static struct uac_clock_source_descriptor *
+ snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
+ int clock_id)
{
- void *cs = NULL;
+ struct uac_clock_source_descriptor *cs = NULL;
- while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen,
- cs, type))) {
- if (validator(cs, id))
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_SOURCE))) {
+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id)
return cs;
}
return NULL;
}
-static bool validate_clock_source_v2(void *p, int id)
+static struct uac_clock_selector_descriptor *
+ snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
+ int clock_id)
{
- struct uac_clock_source_descriptor *cs = p;
- return cs->bLength == sizeof(*cs) && cs->bClockID == id;
-}
-
-static bool validate_clock_source_v3(void *p, int id)
-{
- struct uac3_clock_source_descriptor *cs = p;
- return cs->bLength == sizeof(*cs) && cs->bClockID == id;
-}
-
-static bool validate_clock_selector_v2(void *p, int id)
-{
- struct uac_clock_selector_descriptor *cs = p;
- return cs->bLength >= sizeof(*cs) && cs->bClockID == id &&
- cs->bLength == 7 + cs->bNrInPins;
-}
+ struct uac_clock_selector_descriptor *cs = NULL;
+
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_SELECTOR))) {
+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id) {
+ if (cs->bLength < 5 + cs->bNrInPins)
+ return NULL;
+ return cs;
+ }
+ }
-static bool validate_clock_selector_v3(void *p, int id)
-{
- struct uac3_clock_selector_descriptor *cs = p;
- return cs->bLength >= sizeof(*cs) && cs->bClockID == id &&
- cs->bLength == 11 + cs->bNrInPins;
+ return NULL;
}
-static bool validate_clock_multiplier_v2(void *p, int id)
+static struct uac_clock_multiplier_descriptor *
+ snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
+ int clock_id)
{
- struct uac_clock_multiplier_descriptor *cs = p;
- return cs->bLength == sizeof(*cs) && cs->bClockID == id;
-}
+ struct uac_clock_multiplier_descriptor *cs = NULL;
-static bool validate_clock_multiplier_v3(void *p, int id)
-{
- struct uac3_clock_multiplier_descriptor *cs = p;
- return cs->bLength == sizeof(*cs) && cs->bClockID == id;
-}
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_MULTIPLIER))) {
+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id)
+ return cs;
+ }
-#define DEFINE_FIND_HELPER(name, obj, validator, type) \
-static obj *name(struct usb_host_interface *iface, int id) \
-{ \
- return find_uac_clock_desc(iface, id, validator, type); \
+ return NULL;
}
-DEFINE_FIND_HELPER(snd_usb_find_clock_source,
- struct uac_clock_source_descriptor,
- validate_clock_source_v2, UAC2_CLOCK_SOURCE);
-DEFINE_FIND_HELPER(snd_usb_find_clock_source_v3,
- struct uac3_clock_source_descriptor,
- validate_clock_source_v3, UAC3_CLOCK_SOURCE);
-
-DEFINE_FIND_HELPER(snd_usb_find_clock_selector,
- struct uac_clock_selector_descriptor,
- validate_clock_selector_v2, UAC2_CLOCK_SELECTOR);
-DEFINE_FIND_HELPER(snd_usb_find_clock_selector_v3,
- struct uac3_clock_selector_descriptor,
- validate_clock_selector_v3, UAC3_CLOCK_SELECTOR);
-
-DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
- struct uac_clock_multiplier_descriptor,
- validate_clock_multiplier_v2, UAC2_CLOCK_MULTIPLIER);
-DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier_v3,
- struct uac3_clock_multiplier_descriptor,
- validate_clock_multiplier_v3, UAC3_CLOCK_MULTIPLIER);
-
static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
{
unsigned char buf;
@@ -167,34 +138,20 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
return ret;
}
-static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
- int protocol,
- int source_id)
+static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
{
int err;
unsigned char data;
struct usb_device *dev = chip->dev;
- u32 bmControls;
-
- if (protocol == UAC_VERSION_3) {
- struct uac3_clock_source_descriptor *cs_desc =
- snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id);
-
- if (!cs_desc)
- return 0;
- bmControls = le32_to_cpu(cs_desc->bmControls);
- } else { /* UAC_VERSION_1/2 */
- struct uac_clock_source_descriptor *cs_desc =
- snd_usb_find_clock_source(chip->ctrl_intf, source_id);
-
- if (!cs_desc)
- return 0;
- bmControls = cs_desc->bmControls;
- }
+ struct uac_clock_source_descriptor *cs_desc =
+ snd_usb_find_clock_source(chip->ctrl_intf, source_id);
+
+ if (!cs_desc)
+ return 0;
/* If a clock source can't tell us whether it's valid, we assume it is */
- if (!uac_v2v3_control_is_readable(bmControls,
- UAC2_CS_CONTROL_CLOCK_VALID))
+ if (!uac2_control_is_readable(cs_desc->bmControls,
+ UAC2_CS_CONTROL_CLOCK_VALID - 1))
return 1;
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
@@ -213,8 +170,9 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
return !!data;
}
-static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
- unsigned long *visited, bool validate)
+static int __uac_clock_find_source(struct snd_usb_audio *chip,
+ int entity_id, unsigned long *visited,
+ bool validate)
{
struct uac_clock_source_descriptor *source;
struct uac_clock_selector_descriptor *selector;
@@ -233,8 +191,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
if (source) {
entity_id = source->bClockID;
- if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_2,
- entity_id)) {
+ if (validate && !uac_clock_source_is_valid(chip, entity_id)) {
usb_audio_err(chip,
"clock source %d is not valid, cannot use\n",
entity_id);
@@ -303,97 +260,6 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
return -EINVAL;
}
-static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
- unsigned long *visited, bool validate)
-{
- struct uac3_clock_source_descriptor *source;
- struct uac3_clock_selector_descriptor *selector;
- struct uac3_clock_multiplier_descriptor *multiplier;
-
- entity_id &= 0xff;
-
- if (test_and_set_bit(entity_id, visited)) {
- usb_audio_warn(chip,
- "%s(): recursive clock topology detected, id %d.\n",
- __func__, entity_id);
- return -EINVAL;
- }
-
- /* first, see if the ID we're looking for is a clock source already */
- source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id);
- if (source) {
- entity_id = source->bClockID;
- if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_3,
- entity_id)) {
- usb_audio_err(chip,
- "clock source %d is not valid, cannot use\n",
- entity_id);
- return -ENXIO;
- }
- return entity_id;
- }
-
- selector = snd_usb_find_clock_selector_v3(chip->ctrl_intf, entity_id);
- if (selector) {
- int ret, i, cur;
-
- /* the entity ID we are looking for is a selector.
- * find out what it currently selects */
- ret = uac_clock_selector_get_val(chip, selector->bClockID);
- if (ret < 0)
- return ret;
-
- /* Selector values are one-based */
-
- if (ret > selector->bNrInPins || ret < 1) {
- usb_audio_err(chip,
- "%s(): selector reported illegal value, id %d, ret %d\n",
- __func__, selector->bClockID, ret);
-
- return -EINVAL;
- }
-
- cur = ret;
- ret = __uac3_clock_find_source(chip, selector->baCSourceID[ret - 1],
- visited, validate);
- if (!validate || ret > 0 || !chip->autoclock)
- return ret;
-
- /* The current clock source is invalid, try others. */
- for (i = 1; i <= selector->bNrInPins; i++) {
- int err;
-
- if (i == cur)
- continue;
-
- ret = __uac3_clock_find_source(chip, selector->baCSourceID[i - 1],
- visited, true);
- if (ret < 0)
- continue;
-
- err = uac_clock_selector_set_val(chip, entity_id, i);
- if (err < 0)
- continue;
-
- usb_audio_info(chip,
- "found and selected valid clock source %d\n",
- ret);
- return ret;
- }
-
- return -ENXIO;
- }
-
- /* FIXME: multipliers only act as pass-thru element for now */
- multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf,
- entity_id);
- if (multiplier)
- return __uac3_clock_find_source(chip, multiplier->bCSourceID,
- visited, validate);
-
- return -EINVAL;
-}
-
/*
* For all kinds of sample rate settings and other device queries,
* the clock source (end-leaf) must be used. However, clock selectors,
@@ -405,22 +271,12 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
*
* Returns the clock source UnitID (>=0) on success, or an error.
*/
-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol,
- int entity_id, bool validate)
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id,
+ bool validate)
{
DECLARE_BITMAP(visited, 256);
memset(visited, 0, sizeof(visited));
-
- switch (protocol) {
- case UAC_VERSION_2:
- return __uac_clock_find_source(chip, entity_id, visited,
- validate);
- case UAC_VERSION_3:
- return __uac3_clock_find_source(chip, entity_id, visited,
- validate);
- default:
- return -EINVAL;
- }
+ return __uac_clock_find_source(chip, entity_id, visited, validate);
}
static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
@@ -443,11 +299,10 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
data[0] = rate;
data[1] = rate >> 8;
data[2] = rate >> 16;
- err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data));
- if (err < 0) {
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data))) < 0) {
dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
iface, fmt->altsetting, rate, ep);
return err;
@@ -461,11 +316,10 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
if (chip->sample_rate_read_error > 2)
return 0;
- err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data));
- if (err < 0) {
+ if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data))) < 0) {
dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
iface, fmt->altsetting, ep);
chip->sample_rate_read_error++;
@@ -481,7 +335,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
return 0;
}
-static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
+static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface,
int altsetting, int clock)
{
struct usb_device *dev = chip->dev;
@@ -494,7 +348,7 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
snd_usb_ctrl_intf(chip) | (clock << 8),
&data, sizeof(data));
if (err < 0) {
- dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
+ dev_warn(&dev->dev, "%d:%d: cannot get freq (v2): err %d\n",
iface, altsetting, err);
return 0;
}
@@ -502,7 +356,7 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
return le32_to_cpu(data);
}
-static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
+static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt, int rate)
{
@@ -511,45 +365,18 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
int err, cur_rate, prev_rate;
int clock;
bool writeable;
- u32 bmControls;
-
- /* First, try to find a valid clock. This may trigger
- * automatic clock selection if the current clock is not
- * valid.
- */
- clock = snd_usb_clock_find_source(chip, fmt->protocol,
- fmt->clock, true);
- if (clock < 0) {
- /* We did not find a valid clock, but that might be
- * because the current sample rate does not match an
- * external clock source. Try again without validation
- * and we will do another validation after setting the
- * rate.
- */
- clock = snd_usb_clock_find_source(chip, fmt->protocol,
- fmt->clock, false);
- if (clock < 0)
- return clock;
- }
-
- prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock);
- if (prev_rate == rate)
- goto validation;
+ struct uac_clock_source_descriptor *cs_desc;
- if (fmt->protocol == UAC_VERSION_3) {
- struct uac3_clock_source_descriptor *cs_desc;
+ clock = snd_usb_clock_find_source(chip, fmt->clock, true);
+ if (clock < 0)
+ return clock;
- cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock);
- bmControls = le32_to_cpu(cs_desc->bmControls);
- } else {
- struct uac_clock_source_descriptor *cs_desc;
-
- cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
- bmControls = cs_desc->bmControls;
- }
+ prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
+ if (prev_rate == rate)
+ return 0;
- writeable = uac_v2v3_control_is_writeable(bmControls,
- UAC2_CS_CONTROL_SAM_FREQ);
+ cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
+ writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
if (writeable) {
data = cpu_to_le32(rate);
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
@@ -559,13 +386,12 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
&data, sizeof(data));
if (err < 0) {
usb_audio_err(chip,
- "%d:%d: cannot set freq %d (v2/v3): err %d\n",
+ "%d:%d: cannot set freq %d (v2): err %d\n",
iface, fmt->altsetting, rate, err);
return err;
}
- cur_rate = get_sample_rate_v2v3(chip, iface,
- fmt->altsetting, clock);
+ cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
} else {
cur_rate = prev_rate;
}
@@ -591,10 +417,6 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
snd_usb_set_interface_quirk(dev);
}
-validation:
- /* validate clock after rate change */
- if (!uac_clock_source_is_valid(chip, fmt->protocol, clock))
- return -ENXIO;
return 0;
}
@@ -607,16 +429,8 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
default:
return set_sample_rate_v1(chip, iface, alts, fmt, rate);
- case UAC_VERSION_3:
- if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
- if (rate != UAC3_BADD_SAMPLING_RATE)
- return -ENXIO;
- else
- return 0;
- }
- /* fall through */
case UAC_VERSION_2:
- return set_sample_rate_v2v3(chip, iface, alts, fmt, rate);
+ return set_sample_rate_v2(chip, iface, alts, fmt, rate);
}
}
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index e465ff58653b..d592e4a29856 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -5,7 +5,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt, int rate);
-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol,
- int entity_id, bool validate);
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id,
+ bool validate);
#endif /* __USBAUDIO_CLOCK_H */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index d86be8bfe412..c90607ebe155 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -325,6 +325,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
unsigned long flags;
struct snd_usb_packet_info *uninitialized_var(packet);
struct snd_urb_ctx *ctx = NULL;
+ struct urb *urb;
int err, i;
spin_lock_irqsave(&ep->lock, flags);
@@ -344,6 +345,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
return;
list_del_init(&ctx->ready_list);
+ urb = ctx->urb;
/* copy over the length information */
for (i = 0; i < packet->packets; i++)
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 0a2a27f2854d..916ff842c437 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -20,7 +20,6 @@
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -40,11 +39,11 @@
* @dev: usb device
* @fp: audioformat record
* @format: the format tag (wFormatTag)
- * @fmt: the format type descriptor (v1/v2) or AudioStreaming descriptor (v3)
+ * @fmt: the format type descriptor
*/
static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
struct audioformat *fp,
- u64 format, void *_fmt)
+ unsigned int format, void *_fmt)
{
int sample_width, sample_bytes;
u64 pcm_formats = 0;
@@ -55,7 +54,7 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
sample_width = fmt->bBitResolution;
sample_bytes = fmt->bSubframeSize;
- format = 1ULL << format;
+ format = 1 << format;
break;
}
@@ -73,18 +72,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
format <<= 1;
break;
}
- case UAC_VERSION_3: {
- struct uac3_as_header_descriptor *as = _fmt;
-
- sample_width = as->bBitResolution;
- sample_bytes = as->bSubslotSize;
-
- if (format & UAC3_FORMAT_TYPE_I_RAW_DATA)
- pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
-
- format <<= 1;
- break;
- }
}
if ((pcm_formats == 0) &&
@@ -153,7 +140,7 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
}
if (format & ~0x3f) {
usb_audio_info(chip,
- "%u:%d : unsupported format bits %#llx\n",
+ "%u:%d : unsupported format bits %#x\n",
fp->iface, fp->altsetting, format);
}
@@ -297,16 +284,15 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
/*
* parse the format descriptor and stores the possible sample rates
- * on the audioformat table (audio class v2 and v3).
+ * on the audioformat table (audio class v2).
*/
-static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
+static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
struct audioformat *fp)
{
struct usb_device *dev = chip->dev;
unsigned char tmp[2], *data;
int nr_triplets, data_size, ret = 0;
- int clock = snd_usb_clock_find_source(chip, fp->protocol,
- fp->clock, false);
+ int clock = snd_usb_clock_find_source(chip, fp->clock, false);
if (clock < 0) {
dev_err(&dev->dev,
@@ -385,30 +371,13 @@ err:
* parse the format type I and III descriptors
*/
static int parse_audio_format_i(struct snd_usb_audio *chip,
- struct audioformat *fp, u64 format,
- void *_fmt)
+ struct audioformat *fp, unsigned int format,
+ struct uac_format_type_i_continuous_descriptor *fmt)
{
snd_pcm_format_t pcm_format;
- unsigned int fmt_type;
int ret;
- switch (fp->protocol) {
- default:
- case UAC_VERSION_1:
- case UAC_VERSION_2: {
- struct uac_format_type_i_continuous_descriptor *fmt = _fmt;
-
- fmt_type = fmt->bFormatType;
- break;
- }
- case UAC_VERSION_3: {
- /* fp->fmt_type is already set in this case */
- fmt_type = fp->fmt_type;
- break;
- }
- }
-
- if (fmt_type == UAC_FORMAT_TYPE_III) {
+ if (fmt->bFormatType == UAC_FORMAT_TYPE_III) {
/* FIXME: the format type is really IECxxx
* but we give normal PCM format to get the existing
* apps working...
@@ -427,7 +396,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
}
fp->formats = pcm_format_to_bits(pcm_format);
} else {
- fp->formats = parse_audio_format_i_type(chip, fp, format, _fmt);
+ fp->formats = parse_audio_format_i_type(chip, fp, format, fmt);
if (!fp->formats)
return -EINVAL;
}
@@ -439,20 +408,15 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
*/
switch (fp->protocol) {
default:
- case UAC_VERSION_1: {
- struct uac_format_type_i_continuous_descriptor *fmt = _fmt;
-
+ case UAC_VERSION_1:
fp->channels = fmt->bNrChannels;
ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
break;
- }
case UAC_VERSION_2:
- case UAC_VERSION_3: {
/* fp->channels is already set in this case */
- ret = parse_audio_format_rates_v2v3(chip, fp);
+ ret = parse_audio_format_rates_v2(chip, fp);
break;
}
- }
if (fp->channels < 1) {
usb_audio_err(chip,
@@ -469,7 +433,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
*/
static int parse_audio_format_ii(struct snd_usb_audio *chip,
struct audioformat *fp,
- u64 format, void *_fmt)
+ int format, void *_fmt)
{
int brate, framesize, ret;
@@ -484,7 +448,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
break;
default:
usb_audio_info(chip,
- "%u:%d : unknown format tag %#llx is detected. processed as MPEG.\n",
+ "%u:%d : unknown format tag %#x is detected. processed as MPEG.\n",
fp->iface, fp->altsetting, format);
fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
@@ -509,7 +473,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
framesize = le16_to_cpu(fmt->wSamplesPerFrame);
usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
fp->frame_size = framesize;
- ret = parse_audio_format_rates_v2v3(chip, fp);
+ ret = parse_audio_format_rates_v2(chip, fp);
break;
}
}
@@ -518,7 +482,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
}
int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
- struct audioformat *fp, u64 format,
+ struct audioformat *fp, unsigned int format,
struct uac_format_type_i_continuous_descriptor *fmt,
int stream)
{
@@ -559,26 +523,3 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
return 0;
}
-int snd_usb_parse_audio_format_v3(struct snd_usb_audio *chip,
- struct audioformat *fp,
- struct uac3_as_header_descriptor *as,
- int stream)
-{
- u64 format = le64_to_cpu(as->bmFormats);
- int err;
-
- /*
- * Type I format bits are D0..D6
- * This test works because type IV is not supported
- */
- if (format & 0x7f)
- fp->fmt_type = UAC_FORMAT_TYPE_I;
- else
- fp->fmt_type = UAC_FORMAT_TYPE_III;
-
- err = parse_audio_format_i(chip, fp, format, as);
- if (err < 0)
- return err;
-
- return 0;
-}
diff --git a/sound/usb/format.h b/sound/usb/format.h
index 46c9de714f83..4b8a01129f24 100644
--- a/sound/usb/format.h
+++ b/sound/usb/format.h
@@ -2,12 +2,8 @@
#define __USBAUDIO_FORMAT_H
int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
- struct audioformat *fp, u64 format,
+ struct audioformat *fp, unsigned int format,
struct uac_format_type_i_continuous_descriptor *fmt,
int stream);
-int snd_usb_parse_audio_format_v3(struct snd_usb_audio *chip,
- struct audioformat *fp,
- struct uac3_as_header_descriptor *as,
- int stream);
#endif /* __USBAUDIO_FORMAT_H */
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index 693f247de197..805c300dd004 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -17,12 +17,16 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
*/
+#ifndef get_iface_desc
#define get_iface_desc(iface) (&(iface)->desc)
#define get_endpoint(alt,ep) (&(alt)->endpoint[ep].desc)
#define get_ep_desc(ep) (&(ep)->desc)
#define get_cfg_desc(cfg) (&(cfg)->desc)
+#endif
+#ifndef snd_usb_get_speed
#define snd_usb_get_speed(dev) ((dev)->speed)
+#endif
static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
{
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 947d6168f24a..7c812565f90d 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -248,7 +248,7 @@ static int snd_line6_capture_close(struct snd_pcm_substream *substream)
}
/* capture operators */
-const struct snd_pcm_ops snd_line6_capture_ops = {
+struct snd_pcm_ops snd_line6_capture_ops = {
.open = snd_line6_capture_open,
.close = snd_line6_capture_close,
.ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
index b67ccc39fd25..890b21bff18c 100644
--- a/sound/usb/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -17,7 +17,7 @@
#include "driver.h"
#include "pcm.h"
-extern const struct snd_pcm_ops snd_line6_capture_ops;
+extern struct snd_pcm_ops snd_line6_capture_ops;
extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
int fsize);
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 4f9613e5fc9e..8d5a454842f4 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -199,9 +199,9 @@ static int line6_send_raw_message_async_part(struct message *msg,
Setup and start timer.
*/
void line6_start_timer(struct timer_list *timer, unsigned long msecs,
- void (*function)(struct timer_list *t))
+ void (*function)(unsigned long), unsigned long data)
{
- timer->function = (TIMER_FUNC_TYPE)function;
+ setup_timer(timer, function, data);
mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
}
EXPORT_SYMBOL_GPL(line6_start_timer);
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index 61425597eb61..dc97895547be 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -198,7 +198,8 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
- void (*function)(struct timer_list *t));
+ void (*function)(unsigned long),
+ unsigned long data);
extern int line6_version_request_async(struct usb_line6 *line6);
extern int line6_write_data(struct usb_line6 *line6, unsigned address,
void *data, unsigned datalen);
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 819e9b2d1d6e..812d18191e01 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -393,7 +393,7 @@ static int snd_line6_playback_close(struct snd_pcm_substream *substream)
}
/* playback operators */
-const struct snd_pcm_ops snd_line6_playback_ops = {
+struct snd_pcm_ops snd_line6_playback_ops = {
.open = snd_line6_playback_open,
.close = snd_line6_playback_close,
.ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
index d8d3b8a07a72..51fce29e8726 100644
--- a/sound/usb/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -27,7 +27,7 @@
*/
#define USE_CLEAR_BUFFER_WORKAROUND 1
-extern const struct snd_pcm_ops snd_line6_playback_ops;
+extern struct snd_pcm_ops snd_line6_playback_ops;
extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index 020c81818951..358224cc5638 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -174,7 +174,7 @@ static const char pod_version_header[] = {
};
/* forward declarations: */
-static void pod_startup2(struct timer_list *t);
+static void pod_startup2(unsigned long data);
static void pod_startup3(struct usb_line6_pod *pod);
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
@@ -286,12 +286,13 @@ static void pod_startup1(struct usb_line6_pod *pod)
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
/* delay startup procedure: */
- line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2);
+ line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
+ (unsigned long)pod);
}
-static void pod_startup2(struct timer_list *t)
+static void pod_startup2(unsigned long data)
{
- struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
+ struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
struct usb_line6 *line6 = &pod->line6;
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
@@ -412,7 +413,7 @@ static int pod_init(struct usb_line6 *line6,
line6->process_message = line6_pod_process_message;
line6->disconnect = line6_pod_disconnect;
- timer_setup(&pod->startup_timer, NULL, 0);
+ init_timer(&pod->startup_timer);
INIT_WORK(&pod->startup_work, pod_startup4);
/* create sysfs entries: */
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 36ed9c85c0eb..46fa8c046cb5 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -158,7 +158,7 @@ static struct line6_pcm_properties podx3_pcm_properties = {
};
static struct usb_driver podhd_driver;
-static void podhd_startup_start_workqueue(struct timer_list *t);
+static void podhd_startup_start_workqueue(unsigned long data);
static void podhd_startup_workqueue(struct work_struct *work);
static int podhd_startup_finalize(struct usb_line6_podhd *pod);
@@ -208,12 +208,12 @@ static void podhd_startup(struct usb_line6_podhd *pod)
/* delay startup procedure: */
line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
- podhd_startup_start_workqueue);
+ podhd_startup_start_workqueue, (unsigned long)pod);
}
-static void podhd_startup_start_workqueue(struct timer_list *t)
+static void podhd_startup_start_workqueue(unsigned long data)
{
- struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer);
+ struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data;
CHECK_STARTUP_PROGRESS(pod->startup_progress,
PODHD_STARTUP_SCHEDULE_WORKQUEUE);
@@ -319,7 +319,7 @@ static int podhd_init(struct usb_line6 *line6,
line6->disconnect = podhd_disconnect;
- timer_setup(&pod->startup_timer, NULL, 0);
+ init_timer(&pod->startup_timer);
INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index f47ba94e6f4a..ba7975c0d03d 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -241,9 +241,9 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static void toneport_start_pcm(struct timer_list *t)
+static void toneport_start_pcm(unsigned long arg)
{
- struct usb_line6_toneport *toneport = from_timer(toneport, t, timer);
+ struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
struct usb_line6 *line6 = &toneport->line6;
line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
@@ -367,13 +367,12 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
*/
static void toneport_setup(struct usb_line6_toneport *toneport)
{
- u32 ticks;
+ int ticks;
struct usb_line6 *line6 = &toneport->line6;
struct usb_device *usbdev = line6->usbdev;
/* sync time on device with host: */
- /* note: 32-bit timestamps overflow in year 2106 */
- ticks = (u32)ktime_get_real_seconds();
+ ticks = (int)get_seconds();
line6_write_data(line6, 0x80c6, &ticks, 4);
/* enable device: */
@@ -416,7 +415,8 @@ static int toneport_init(struct usb_line6 *line6,
struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
toneport->type = id->driver_info;
- timer_setup(&toneport->timer, toneport_start_pcm, 0);
+ setup_timer(&toneport->timer, toneport_start_pcm,
+ (unsigned long)toneport);
line6->disconnect = line6_toneport_disconnect;
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
index e8c852b2ce35..0c4512d0382e 100644
--- a/sound/usb/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -82,9 +82,9 @@ static const char variax_activate[] = {
};
/* forward declarations: */
-static void variax_startup2(struct timer_list *t);
-static void variax_startup4(struct timer_list *t);
-static void variax_startup5(struct timer_list *t);
+static void variax_startup2(unsigned long data);
+static void variax_startup4(unsigned long data);
+static void variax_startup5(unsigned long data);
static void variax_activate_async(struct usb_line6_variax *variax, int a)
{
@@ -106,12 +106,12 @@ static void variax_startup1(struct usb_line6_variax *variax)
/* delay startup procedure: */
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
- variax_startup2);
+ variax_startup2, (unsigned long)variax);
}
-static void variax_startup2(struct timer_list *t)
+static void variax_startup2(unsigned long data)
{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1);
+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
struct usb_line6 *line6 = &variax->line6;
/* schedule another startup procedure until startup is complete: */
@@ -120,7 +120,7 @@ static void variax_startup2(struct timer_list *t)
variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
- variax_startup2);
+ variax_startup2, (unsigned long)variax);
/* request firmware version: */
line6_version_request_async(line6);
@@ -132,12 +132,12 @@ static void variax_startup3(struct usb_line6_variax *variax)
/* delay startup procedure: */
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
- variax_startup4);
+ variax_startup4, (unsigned long)variax);
}
-static void variax_startup4(struct timer_list *t)
+static void variax_startup4(unsigned long data)
{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
CHECK_STARTUP_PROGRESS(variax->startup_progress,
VARIAX_STARTUP_ACTIVATE);
@@ -145,12 +145,12 @@ static void variax_startup4(struct timer_list *t)
/* activate device: */
variax_activate_async(variax, 1);
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
- variax_startup5);
+ variax_startup5, (unsigned long)variax);
}
-static void variax_startup5(struct timer_list *t)
+static void variax_startup5(unsigned long data)
{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
CHECK_STARTUP_PROGRESS(variax->startup_progress,
VARIAX_STARTUP_WORKQUEUE);
@@ -190,7 +190,7 @@ static void line6_variax_process_message(struct usb_line6 *line6)
} else if (memcmp(buf + 1, variax_init_done + 1,
sizeof(variax_init_done) - 1) == 0) {
/* notify of complete initialization: */
- variax_startup4(&variax->startup_timer2);
+ variax_startup4((unsigned long)variax);
}
break;
}
@@ -222,8 +222,8 @@ static int variax_init(struct usb_line6 *line6,
line6->process_message = line6_variax_process_message;
line6->disconnect = line6_variax_disconnect;
- timer_setup(&variax->startup_timer1, NULL, 0);
- timer_setup(&variax->startup_timer2, NULL, 0);
+ init_timer(&variax->startup_timer1);
+ init_timer(&variax->startup_timer2);
INIT_WORK(&variax->startup_work, variax_startup6);
/* initialize USB buffers: */
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index c62ae8c7393e..66c36c100177 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -281,16 +281,15 @@ static void snd_usbmidi_out_urb_complete(struct urb *urb)
struct out_urb_context *context = urb->context;
struct snd_usb_midi_out_endpoint *ep = context->ep;
unsigned int urb_index;
- unsigned long flags;
- spin_lock_irqsave(&ep->buffer_lock, flags);
+ spin_lock(&ep->buffer_lock);
urb_index = context - ep->urbs;
ep->active_urbs &= ~(1 << urb_index);
if (unlikely(ep->drain_urbs)) {
ep->drain_urbs &= ~(1 << urb_index);
wake_up(&ep->drain_wait);
}
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
+ spin_unlock(&ep->buffer_lock);
if (urb->status < 0) {
int err = snd_usbmidi_urb_error(urb);
if (err < 0) {
@@ -353,9 +352,9 @@ static void snd_usbmidi_out_tasklet(unsigned long data)
}
/* called after transfers had been interrupted due to some USB error */
-static void snd_usbmidi_error_timer(struct timer_list *t)
+static void snd_usbmidi_error_timer(unsigned long data)
{
- struct snd_usb_midi *umidi = from_timer(umidi, t, error_timer);
+ struct snd_usb_midi *umidi = (struct snd_usb_midi *)data;
unsigned int i, j;
spin_lock(&umidi->disc_lock);
@@ -1175,7 +1174,8 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
if (port->ep->umidi->disconnected) {
/* gobble up remaining bytes to prevent wait in
* snd_rawmidi_drain_output */
- snd_rawmidi_proceed(substream);
+ while (!snd_rawmidi_transmit_empty(substream))
+ snd_rawmidi_transmit_ack(substream, 1);
return;
}
tasklet_schedule(&port->ep->tasklet);
@@ -2369,7 +2369,8 @@ int __snd_usbmidi_create(struct snd_card *card,
usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
le16_to_cpu(umidi->dev->descriptor.idProduct));
umidi->usb_id = usb_id;
- timer_setup(&umidi->error_timer, snd_usbmidi_error_timer, 0);
+ setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
+ (unsigned long)umidi);
/* detect the endpoint(s) to use */
memset(endpoints, 0, sizeof(endpoints));
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index b05cd38400ff..c19a5dd05631 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -1366,7 +1366,7 @@ static void ua101_disconnect(struct usb_interface *interface)
mutex_unlock(&devices_mutex);
}
-static const struct usb_device_id ua101_ids[] = {
+static struct usb_device_id ua101_ids[] = {
{ USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
{ USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
{ USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index c3712af100f0..20c008191eeb 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -51,7 +51,6 @@
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -112,12 +111,14 @@ enum {
#include "mixer_maps.c"
static const struct usbmix_name_map *
-find_map(const struct usbmix_name_map *p, int unitid, int control)
+find_map(struct mixer_build *state, int unitid, int control)
{
+ const struct usbmix_name_map *p = state->map;
+
if (!p)
return NULL;
- for (; p->id; p++) {
+ for (p = state->map; p->id; p++) {
if (p->id == unitid &&
(!control || !p->control || control == p->control))
return p;
@@ -188,7 +189,7 @@ static void *find_audio_control_unit(struct mixer_build *state,
USB_DT_CS_INTERFACE)) != NULL) {
if (hdr->bLength >= 4 &&
hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL &&
- hdr->bDescriptorSubtype <= UAC3_SAMPLE_RATE_CONVERTER &&
+ hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER &&
hdr->bUnitID == unit)
return hdr;
}
@@ -199,10 +200,10 @@ static void *find_audio_control_unit(struct mixer_build *state,
/*
* copy a string with the given id
*/
-static int snd_usb_copy_string_desc(struct snd_usb_audio *chip,
+static int snd_usb_copy_string_desc(struct mixer_build *state,
int index, char *buf, int maxlen)
{
- int len = usb_string(chip->dev, index, buf, maxlen - 1);
+ int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
if (len < 0)
return 0;
@@ -464,10 +465,9 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
validx += cval->idx_off;
-
if (cval->head.mixer->protocol == UAC_VERSION_1) {
val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
- } else { /* UAC_VERSION_2/3 */
+ } else { /* UAC_VERSION_2 */
val_len = uac2_ctl_value_size(cval->val_type);
/* FIXME */
@@ -592,8 +592,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
kctl->id.index++;
- err = snd_ctl_add(mixer->chip->card, kctl);
- if (err < 0) {
+ if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n",
err);
return err;
@@ -651,34 +650,30 @@ static struct iterm_name_combo {
{ 0 },
};
-static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iterm,
+static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm,
unsigned char *name, int maxlen, int term_only)
{
struct iterm_name_combo *names;
- int len;
- if (iterm->name) {
- len = snd_usb_copy_string_desc(chip, iterm->name,
+ if (iterm->name)
+ return snd_usb_copy_string_desc(state, iterm->name,
name, maxlen);
- if (len)
- return len;
- }
/* virtual type - not a real terminal */
if (iterm->type >> 16) {
if (term_only)
return 0;
switch (iterm->type >> 16) {
- case UAC3_SELECTOR_UNIT:
+ case UAC_SELECTOR_UNIT:
strcpy(name, "Selector");
return 8;
- case UAC3_PROCESSING_UNIT:
+ case UAC1_PROCESSING_UNIT:
strcpy(name, "Process Unit");
return 12;
- case UAC3_EXTENSION_UNIT:
+ case UAC1_EXTENSION_UNIT:
strcpy(name, "Ext Unit");
return 8;
- case UAC3_MIXER_UNIT:
+ case UAC_MIXER_UNIT:
strcpy(name, "Mixer");
return 5;
default:
@@ -712,73 +707,12 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter
}
/*
- * Get logical cluster information for UAC3 devices.
- */
-static int get_cluster_channels_v3(struct mixer_build *state, unsigned int cluster_id)
-{
- struct uac3_cluster_header_descriptor c_header;
- int err;
-
- err = snd_usb_ctl_msg(state->chip->dev,
- usb_rcvctrlpipe(state->chip->dev, 0),
- UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- cluster_id,
- snd_usb_ctrl_intf(state->chip),
- &c_header, sizeof(c_header));
- if (err < 0)
- goto error;
- if (err != sizeof(c_header)) {
- err = -EIO;
- goto error;
- }
-
- return c_header.bNrChannels;
-
-error:
- usb_audio_err(state->chip, "cannot request logical cluster ID: %d (err: %d)\n", cluster_id, err);
- return err;
-}
-
-/*
- * Get number of channels for a Mixer Unit.
- */
-static int uac_mixer_unit_get_channels(struct mixer_build *state,
- struct uac_mixer_unit_descriptor *desc)
-{
- int mu_channels;
-
- if (desc->bLength < 11)
- return -EINVAL;
- if (!desc->bNrInPins)
- return -EINVAL;
-
- switch (state->mixer->protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
- mu_channels = uac_mixer_unit_bNrChannels(desc);
- break;
- case UAC_VERSION_3:
- mu_channels = get_cluster_channels_v3(state,
- uac3_mixer_unit_wClusterDescrID(desc));
- break;
- }
-
- if (!mu_channels)
- return -EINVAL;
-
- return mu_channels;
-}
-
-/*
* parse the source unit recursively until it reaches to a terminal
* or a branched unit.
*/
static int check_input_term(struct mixer_build *state, int id,
struct usb_audio_term *term)
{
- int protocol = state->mixer->protocol;
int err;
void *p1;
@@ -786,116 +720,16 @@ static int check_input_term(struct mixer_build *state, int id,
while ((p1 = find_audio_control_unit(state, id)) != NULL) {
unsigned char *hdr = p1;
term->id = id;
-
- if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
- switch (hdr[2]) {
- case UAC_INPUT_TERMINAL:
- if (protocol == UAC_VERSION_1) {
- struct uac_input_terminal_descriptor *d = p1;
-
- term->type = le16_to_cpu(d->wTerminalType);
- term->channels = d->bNrChannels;
- term->chconfig = le16_to_cpu(d->wChannelConfig);
- term->name = d->iTerminal;
- } else { /* UAC_VERSION_2 */
- struct uac2_input_terminal_descriptor *d = p1;
-
- /* call recursively to verify that the
- * referenced clock entity is valid */
- err = check_input_term(state, d->bCSourceID, term);
- if (err < 0)
- return err;
-
- /* save input term properties after recursion,
- * to ensure they are not overriden by the
- * recursion calls */
- term->id = id;
- term->type = le16_to_cpu(d->wTerminalType);
- term->channels = d->bNrChannels;
- term->chconfig = le32_to_cpu(d->bmChannelConfig);
- term->name = d->iTerminal;
- }
- return 0;
- case UAC_FEATURE_UNIT: {
- /* the header is the same for v1 and v2 */
- struct uac_feature_unit_descriptor *d = p1;
-
- id = d->bSourceID;
- break; /* continue to parse */
- }
- case UAC_MIXER_UNIT: {
- struct uac_mixer_unit_descriptor *d = p1;
-
- term->type = UAC3_MIXER_UNIT << 16; /* virtual type */
- term->channels = uac_mixer_unit_bNrChannels(d);
- term->chconfig = uac_mixer_unit_wChannelConfig(d, protocol);
- term->name = uac_mixer_unit_iMixer(d);
- return 0;
- }
- case UAC_SELECTOR_UNIT:
- case UAC2_CLOCK_SELECTOR: {
- struct uac_selector_unit_descriptor *d = p1;
- /* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
- if (err < 0)
- return err;
- term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
- term->id = id;
- term->name = uac_selector_unit_iSelector(d);
- return 0;
- }
- case UAC1_PROCESSING_UNIT:
- /* UAC2_EFFECT_UNIT */
- if (protocol == UAC_VERSION_1)
- term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
- else /* UAC_VERSION_2 */
- term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */
- /* fall through */
- case UAC1_EXTENSION_UNIT:
- /* UAC2_PROCESSING_UNIT_V2 */
- if (protocol == UAC_VERSION_1 && !term->type)
- term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */
- else if (protocol == UAC_VERSION_2 && !term->type)
- term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
- /* fall through */
- case UAC2_EXTENSION_UNIT_V2: {
- struct uac_processing_unit_descriptor *d = p1;
-
- if (protocol == UAC_VERSION_2 &&
- hdr[2] == UAC2_EFFECT_UNIT) {
- /* UAC2/UAC1 unit IDs overlap here in an
- * uncompatible way. Ignore this unit for now.
- */
- return 0;
- }
-
- if (d->bNrInPins) {
- id = d->baSourceID[0];
- break; /* continue to parse */
- }
- if (!term->type)
- term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */
-
- term->channels = uac_processing_unit_bNrChannels(d);
- term->chconfig = uac_processing_unit_wChannelConfig(d, protocol);
- term->name = uac_processing_unit_iProcessing(d, protocol);
- return 0;
- }
- case UAC2_CLOCK_SOURCE: {
- struct uac_clock_source_descriptor *d = p1;
-
- term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */
- term->id = id;
- term->name = d->iClockSource;
- return 0;
- }
- default:
- return -ENODEV;
- }
- } else { /* UAC_VERSION_3 */
- switch (hdr[2]) {
- case UAC_INPUT_TERMINAL: {
- struct uac3_input_terminal_descriptor *d = p1;
+ switch (hdr[2]) {
+ case UAC_INPUT_TERMINAL:
+ if (state->mixer->protocol == UAC_VERSION_1) {
+ struct uac_input_terminal_descriptor *d = p1;
+ term->type = le16_to_cpu(d->wTerminalType);
+ term->channels = d->bNrChannels;
+ term->chconfig = le16_to_cpu(d->wChannelConfig);
+ term->name = d->iTerminal;
+ } else { /* UAC_VERSION_2 */
+ struct uac2_input_terminal_descriptor *d = p1;
/* call recursively to verify that the
* referenced clock entity is valid */
@@ -908,77 +742,71 @@ static int check_input_term(struct mixer_build *state, int id,
* recursion calls */
term->id = id;
term->type = le16_to_cpu(d->wTerminalType);
-
- err = get_cluster_channels_v3(state, le16_to_cpu(d->wClusterDescrID));
- if (err < 0)
- return err;
- term->channels = err;
-
- /* REVISIT: UAC3 IT doesn't have channels cfg */
- term->chconfig = 0;
-
- term->name = le16_to_cpu(d->wTerminalDescrStr);
- return 0;
- }
- case UAC3_FEATURE_UNIT: {
- struct uac3_feature_unit_descriptor *d = p1;
-
- id = d->bSourceID;
- break; /* continue to parse */
+ term->channels = d->bNrChannels;
+ term->chconfig = le32_to_cpu(d->bmChannelConfig);
+ term->name = d->iTerminal;
}
- case UAC3_CLOCK_SOURCE: {
- struct uac3_clock_source_descriptor *d = p1;
-
- term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */
- term->id = id;
- term->name = le16_to_cpu(d->wClockSourceStr);
- return 0;
- }
- case UAC3_MIXER_UNIT: {
- struct uac_mixer_unit_descriptor *d = p1;
-
- err = uac_mixer_unit_get_channels(state, d);
- if (err < 0)
- return err;
-
- term->channels = err;
- term->type = UAC3_MIXER_UNIT << 16; /* virtual type */
-
- return 0;
- }
- case UAC3_SELECTOR_UNIT:
- case UAC3_CLOCK_SELECTOR: {
- struct uac_selector_unit_descriptor *d = p1;
- /* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
- if (err < 0)
- return err;
- term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
- term->id = id;
- term->name = 0; /* TODO: UAC3 Class-specific strings */
-
+ return 0;
+ case UAC_FEATURE_UNIT: {
+ /* the header is the same for v1 and v2 */
+ struct uac_feature_unit_descriptor *d = p1;
+ id = d->bSourceID;
+ break; /* continue to parse */
+ }
+ case UAC_MIXER_UNIT: {
+ struct uac_mixer_unit_descriptor *d = p1;
+ term->type = d->bDescriptorSubtype << 16; /* virtual type */
+ term->channels = uac_mixer_unit_bNrChannels(d);
+ term->chconfig = uac_mixer_unit_wChannelConfig(d, state->mixer->protocol);
+ term->name = uac_mixer_unit_iMixer(d);
+ return 0;
+ }
+ case UAC_SELECTOR_UNIT:
+ case UAC2_CLOCK_SELECTOR: {
+ struct uac_selector_unit_descriptor *d = p1;
+ /* call recursively to retrieve the channel info */
+ err = check_input_term(state, d->baSourceID[0], term);
+ if (err < 0)
+ return err;
+ term->type = d->bDescriptorSubtype << 16; /* virtual type */
+ term->id = id;
+ term->name = uac_selector_unit_iSelector(d);
+ return 0;
+ }
+ case UAC1_PROCESSING_UNIT:
+ case UAC1_EXTENSION_UNIT:
+ /* UAC2_PROCESSING_UNIT_V2 */
+ /* UAC2_EFFECT_UNIT */
+ case UAC2_EXTENSION_UNIT_V2: {
+ struct uac_processing_unit_descriptor *d = p1;
+
+ if (state->mixer->protocol == UAC_VERSION_2 &&
+ hdr[2] == UAC2_EFFECT_UNIT) {
+ /* UAC2/UAC1 unit IDs overlap here in an
+ * uncompatible way. Ignore this unit for now.
+ */
return 0;
}
- case UAC3_PROCESSING_UNIT: {
- struct uac_processing_unit_descriptor *d = p1;
-
- if (!d->bNrInPins)
- return -EINVAL;
-
- /* call recursively to retrieve the channel info */
- err = check_input_term(state, d->baSourceID[0], term);
- if (err < 0)
- return err;
- term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
- term->id = id;
- term->name = 0; /* TODO: UAC3 Class-specific strings */
-
- return 0;
- }
- default:
- return -ENODEV;
+ if (d->bNrInPins) {
+ id = d->baSourceID[0];
+ break; /* continue to parse */
}
+ term->type = d->bDescriptorSubtype << 16; /* virtual type */
+ term->channels = uac_processing_unit_bNrChannels(d);
+ term->chconfig = uac_processing_unit_wChannelConfig(d, state->mixer->protocol);
+ term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol);
+ return 0;
+ }
+ case UAC2_CLOCK_SOURCE: {
+ struct uac_clock_source_descriptor *d = p1;
+ term->type = d->bDescriptorSubtype << 16; /* virtual type */
+ term->id = id;
+ term->name = d->iClockSource;
+ return 0;
+ }
+ default:
+ return -ENODEV;
}
}
return -ENODEV;
@@ -990,27 +818,26 @@ static int check_input_term(struct mixer_build *state, int id,
/* feature unit control information */
struct usb_feature_control_info {
- int control;
const char *name;
int type; /* data type for uac1 */
int type_uac2; /* data type for uac2 if different from uac1, else -1 */
};
static struct usb_feature_control_info audio_feature_info[] = {
- { UAC_FU_MUTE, "Mute", USB_MIXER_INV_BOOLEAN, -1 },
- { UAC_FU_VOLUME, "Volume", USB_MIXER_S16, -1 },
- { UAC_FU_BASS, "Tone Control - Bass", USB_MIXER_S8, -1 },
- { UAC_FU_MID, "Tone Control - Mid", USB_MIXER_S8, -1 },
- { UAC_FU_TREBLE, "Tone Control - Treble", USB_MIXER_S8, -1 },
- { UAC_FU_GRAPHIC_EQUALIZER, "Graphic Equalizer", USB_MIXER_S8, -1 }, /* FIXME: not implemented yet */
- { UAC_FU_AUTOMATIC_GAIN, "Auto Gain Control", USB_MIXER_BOOLEAN, -1 },
- { UAC_FU_DELAY, "Delay Control", USB_MIXER_U16, USB_MIXER_U32 },
- { UAC_FU_BASS_BOOST, "Bass Boost", USB_MIXER_BOOLEAN, -1 },
- { UAC_FU_LOUDNESS, "Loudness", USB_MIXER_BOOLEAN, -1 },
+ { "Mute", USB_MIXER_INV_BOOLEAN, -1 },
+ { "Volume", USB_MIXER_S16, -1 },
+ { "Tone Control - Bass", USB_MIXER_S8, -1 },
+ { "Tone Control - Mid", USB_MIXER_S8, -1 },
+ { "Tone Control - Treble", USB_MIXER_S8, -1 },
+ { "Graphic Equalizer", USB_MIXER_S8, -1 }, /* FIXME: not implemeted yet */
+ { "Auto Gain Control", USB_MIXER_BOOLEAN, -1 },
+ { "Delay Control", USB_MIXER_U16, USB_MIXER_U32 },
+ { "Bass Boost", USB_MIXER_BOOLEAN, -1 },
+ { "Loudness", USB_MIXER_BOOLEAN, -1 },
/* UAC2 specific */
- { UAC2_FU_INPUT_GAIN, "Input Gain Control", USB_MIXER_S16, -1 },
- { UAC2_FU_INPUT_GAIN_PAD, "Input Gain Pad Control", USB_MIXER_S16, -1 },
- { UAC2_FU_PHASE_INVERTER, "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 },
+ { "Input Gain Control", USB_MIXER_S16, -1 },
+ { "Input Gain Pad Control", USB_MIXER_S16, -1 },
+ { "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 },
};
/* private_free callback */
@@ -1354,66 +1181,6 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
return changed;
}
-/* get the boolean value from the master channel of a UAC control */
-static int mixer_ctl_master_bool_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
- int val, err;
-
- err = snd_usb_get_cur_mix_value(cval, 0, 0, &val);
- if (err < 0)
- return filter_error(cval, err);
- val = (val != 0);
- ucontrol->value.integer.value[0] = val;
- return 0;
-}
-
-/* get the connectors status and report it as boolean type */
-static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
- struct snd_usb_audio *chip = cval->head.mixer->chip;
- int idx = 0, validx, ret, val;
-
- validx = cval->control << 8 | 0;
-
- ret = snd_usb_lock_shutdown(chip) ? -EIO : 0;
- if (ret)
- goto error;
-
- idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
- if (cval->head.mixer->protocol == UAC_VERSION_2) {
- struct uac2_connectors_ctl_blk uac2_conn;
-
- ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- validx, idx, &uac2_conn, sizeof(uac2_conn));
- val = !!uac2_conn.bNrChannels;
- } else { /* UAC_VERSION_3 */
- struct uac3_insertion_ctl_blk uac3_conn;
-
- ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- validx, idx, &uac3_conn, sizeof(uac3_conn));
- val = !!uac3_conn.bmConInserted;
- }
-
- snd_usb_unlock_shutdown(chip);
-
- if (ret < 0) {
-error:
- usb_audio_err(chip,
- "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
- UAC_GET_CUR, validx, idx, cval->val_type);
- return ret;
- }
-
- ucontrol->value.integer.value[0] = val;
- return 0;
-}
-
static struct snd_kcontrol_new usb_feature_unit_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later manually */
@@ -1432,28 +1199,6 @@ static const struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
};
/*
- * A control which shows the boolean value from reading a UAC control on
- * the master channel.
- */
-static struct snd_kcontrol_new usb_bool_master_control_ctl_ro = {
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .name = "", /* will be filled later manually */
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .info = snd_ctl_boolean_mono_info,
- .get = mixer_ctl_master_bool_get,
- .put = NULL,
-};
-
-static const struct snd_kcontrol_new usb_connector_ctl_ro = {
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .name = "", /* will be filled later manually */
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .info = snd_ctl_boolean_mono_info,
- .get = mixer_ctl_connector_get,
- .put = NULL,
-};
-
-/*
* This symbol is exported in order to allow the mixer quirks to
* hook up to the standard feature unit control mechanism
*/
@@ -1495,54 +1240,40 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
}
-static struct usb_feature_control_info *get_feature_control_info(int control)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(audio_feature_info); ++i) {
- if (audio_feature_info[i].control == control)
- return &audio_feature_info[i];
- }
- return NULL;
-}
-
-static void __build_feature_ctl(struct usb_mixer_interface *mixer,
- const struct usbmix_name_map *imap,
- unsigned int ctl_mask, int control,
- struct usb_audio_term *iterm,
- struct usb_audio_term *oterm,
- int unitid, int nameid, int readonly_mask)
+static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
+ unsigned int ctl_mask, int control,
+ struct usb_audio_term *iterm, int unitid,
+ int readonly_mask)
{
+ struct uac_feature_unit_descriptor *desc = raw_desc;
struct usb_feature_control_info *ctl_info;
unsigned int len = 0;
int mapped_name = 0;
+ int nameid = uac_feature_unit_iFeature(desc);
struct snd_kcontrol *kctl;
struct usb_mixer_elem_info *cval;
const struct usbmix_name_map *map;
unsigned int range;
+ control++; /* change from zero-based to 1-based value */
+
if (control == UAC_FU_GRAPHIC_EQUALIZER) {
/* FIXME: not supported yet */
return;
}
- map = find_map(imap, unitid, control);
+ map = find_map(state, unitid, control);
if (check_ignored_ctl(map))
return;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
return;
- snd_usb_mixer_elem_init_std(&cval->head, mixer, unitid);
+ snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
cval->control = control;
cval->cmask = ctl_mask;
-
- ctl_info = get_feature_control_info(control);
- if (!ctl_info) {
- kfree(cval);
- return;
- }
- if (mixer->protocol == UAC_VERSION_1)
+ ctl_info = &audio_feature_info[control-1];
+ if (state->mixer->protocol == UAC_VERSION_1)
cval->val_type = ctl_info->type;
else /* UAC_VERSION_2 */
cval->val_type = ctl_info->type_uac2 >= 0 ?
@@ -1571,7 +1302,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
if (!kctl) {
- usb_audio_err(mixer->chip, "cannot malloc kcontrol\n");
+ usb_audio_err(state->chip, "cannot malloc kcontrol\n");
kfree(cval);
return;
}
@@ -1580,7 +1311,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
mapped_name = len != 0;
if (!len && nameid)
- len = snd_usb_copy_string_desc(mixer->chip, nameid,
+ len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
switch (control) {
@@ -1595,12 +1326,10 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
* - otherwise, anonymous name.
*/
if (!len) {
- if (iterm)
- len = get_term_name(mixer->chip, iterm,
- kctl->id.name,
- sizeof(kctl->id.name), 1);
- if (!len && oterm)
- len = get_term_name(mixer->chip, oterm,
+ len = get_term_name(state, iterm, kctl->id.name,
+ sizeof(kctl->id.name), 1);
+ if (!len)
+ len = get_term_name(state, &state->oterm,
kctl->id.name,
sizeof(kctl->id.name), 1);
if (!len)
@@ -1609,15 +1338,15 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
}
if (!mapped_name)
- check_no_speaker_on_headset(kctl, mixer->chip->card);
+ check_no_speaker_on_headset(kctl, state->mixer->chip->card);
/*
* determine the stream direction:
* if the connected output is USB stream, then it's likely a
* capture stream. otherwise it should be playback (hopefully :)
*/
- if (!mapped_name && oterm && !(oterm->type >> 16)) {
- if ((oterm->type & 0xff00) == 0x0100)
+ if (!mapped_name && !(state->oterm.type >> 16)) {
+ if ((state->oterm.type & 0xff00) == 0x0100)
append_ctl_name(kctl, " Capture");
else
append_ctl_name(kctl, " Playback");
@@ -1645,7 +1374,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
}
}
- snd_usb_mixer_fu_apply_quirk(mixer, cval, unitid, kctl);
+ snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl);
range = (cval->max - cval->min) / cval->res;
/*
@@ -1654,103 +1383,21 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
* devices. It will definitively catch all buggy Logitech devices.
*/
if (range > 384) {
- usb_audio_warn(mixer->chip,
+ usb_audio_warn(state->chip,
"Warning! Unlikely big volume range (=%u), cval->res is probably wrong.",
range);
- usb_audio_warn(mixer->chip,
+ usb_audio_warn(state->chip,
"[%d] FU [%s] ch = %d, val = %d/%d/%d",
cval->head.id, kctl->id.name, cval->channels,
cval->min, cval->max, cval->res);
}
- usb_audio_dbg(mixer->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
+ usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
cval->head.id, kctl->id.name, cval->channels,
cval->min, cval->max, cval->res);
snd_usb_mixer_add_control(&cval->head, kctl);
}
-static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
- unsigned int ctl_mask, int control,
- struct usb_audio_term *iterm, int unitid,
- int readonly_mask)
-{
- struct uac_feature_unit_descriptor *desc = raw_desc;
- int nameid = uac_feature_unit_iFeature(desc);
-
- __build_feature_ctl(state->mixer, state->map, ctl_mask, control,
- iterm, &state->oterm, unitid, nameid, readonly_mask);
-}
-
-static void build_feature_ctl_badd(struct usb_mixer_interface *mixer,
- unsigned int ctl_mask, int control, int unitid,
- const struct usbmix_name_map *badd_map)
-{
- __build_feature_ctl(mixer, badd_map, ctl_mask, control,
- NULL, NULL, unitid, 0, 0);
-}
-
-static void get_connector_control_name(struct usb_mixer_interface *mixer,
- struct usb_audio_term *term,
- bool is_input, char *name, int name_size)
-{
- int name_len = get_term_name(mixer->chip, term, name, name_size, 0);
-
- if (name_len == 0)
- strlcpy(name, "Unknown", name_size);
-
- /*
- * sound/core/ctljack.c has a convention of naming jack controls
- * by ending in " Jack". Make it slightly more useful by
- * indicating Input or Output after the terminal name.
- */
- if (is_input)
- strlcat(name, " - Input Jack", name_size);
- else
- strlcat(name, " - Output Jack", name_size);
-}
-
-/* Build a mixer control for a UAC connector control (jack-detect) */
-static void build_connector_control(struct usb_mixer_interface *mixer,
- struct usb_audio_term *term, bool is_input)
-{
- struct snd_kcontrol *kctl;
- struct usb_mixer_elem_info *cval;
-
- cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (!cval)
- return;
- snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id);
- /*
- * UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
- * number of channels connected.
- *
- * UAC3: The first byte specifies size of bitmap for the inserted controls. The
- * following byte(s) specifies which connectors are inserted.
- *
- * This boolean ctl will simply report if any channels are connected
- * or not.
- */
- if (mixer->protocol == UAC_VERSION_2)
- cval->control = UAC2_TE_CONNECTOR;
- else /* UAC_VERSION_3 */
- cval->control = UAC3_TE_INSERTION;
-
- cval->val_type = USB_MIXER_BOOLEAN;
- cval->channels = 1; /* report true if any channel is connected */
- cval->min = 0;
- cval->max = 1;
- kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);
- if (!kctl) {
- usb_audio_err(mixer->chip, "cannot malloc kcontrol\n");
- kfree(cval);
- return;
- }
- get_connector_control_name(mixer, term, is_input, kctl->id.name,
- sizeof(kctl->id.name));
- kctl->private_free = snd_usb_mixer_elem_free;
- snd_usb_mixer_add_control(&cval->head, kctl);
-}
-
static int parse_clock_source_unit(struct mixer_build *state, int unitid,
void *_ftr)
{
@@ -1774,8 +1421,8 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
* The only property of this unit we are interested in is the
* clock source validity. If that isn't readable, just bail out.
*/
- if (!uac_v2v3_control_is_readable(hdr->bmControls,
- UAC2_CS_CONTROL_CLOCK_VALID))
+ if (!uac2_control_is_readable(hdr->bmControls,
+ ilog2(UAC2_CS_CONTROL_CLOCK_VALID)))
return 0;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -1790,9 +1437,13 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
cval->val_type = USB_MIXER_BOOLEAN;
cval->control = UAC2_CS_CONTROL_CLOCK_VALID;
- cval->master_readonly = 1;
- /* From UAC2 5.2.5.1.2 "Only the get request is supported." */
- kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval);
+ if (uac2_control_is_writeable(hdr->bmControls,
+ ilog2(UAC2_CS_CONTROL_CLOCK_VALID)))
+ kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
+ else {
+ cval->master_readonly = 1;
+ kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
+ }
if (!kctl) {
kfree(cval);
@@ -1800,7 +1451,7 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
}
kctl->private_free = snd_usb_mixer_elem_free;
- ret = snd_usb_copy_string_desc(state->chip, hdr->iClockSource,
+ ret = snd_usb_copy_string_desc(state, hdr->iClockSource,
name, sizeof(name));
if (ret > 0)
snprintf(kctl->id.name, sizeof(kctl->id.name),
@@ -1849,7 +1500,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
unitid);
return -EINVAL;
}
- } else if (state->mixer->protocol == UAC_VERSION_2) {
+ } else {
struct uac2_feature_unit_descriptor *ftr = _ftr;
if (hdr->bLength < 6) {
usb_audio_err(state->chip,
@@ -1866,29 +1517,10 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
unitid);
return -EINVAL;
}
- } else { /* UAC_VERSION_3 */
- struct uac3_feature_unit_descriptor *ftr = _ftr;
-
- if (hdr->bLength < 7) {
- usb_audio_err(state->chip,
- "unit %u: invalid UAC3_FEATURE_UNIT descriptor\n",
- unitid);
- return -EINVAL;
- }
- csize = 4;
- channels = (ftr->bLength - 7) / 4 - 1;
- bmaControls = ftr->bmaControls;
- if (hdr->bLength < 7 + csize) {
- usb_audio_err(state->chip,
- "unit %u: invalid UAC3_FEATURE_UNIT descriptor\n",
- unitid);
- return -EINVAL;
- }
}
/* parse the source unit */
- err = parse_audio_unit(state, hdr->bSourceID);
- if (err < 0)
+ if ((err = parse_audio_unit(state, hdr->bSourceID)) < 0)
return err;
/* determine the input source type and name */
@@ -1922,8 +1554,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
/* check all control types */
for (i = 0; i < 10; i++) {
unsigned int ch_bits = 0;
- int control = audio_feature_info[i].control;
-
for (j = 0; j < channels; j++) {
unsigned int mask;
@@ -1939,26 +1569,25 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
* (for ease of programming).
*/
if (ch_bits & 1)
- build_feature_ctl(state, _ftr, ch_bits, control,
+ build_feature_ctl(state, _ftr, ch_bits, i,
&iterm, unitid, 0);
if (master_bits & (1 << i))
- build_feature_ctl(state, _ftr, 0, control,
- &iterm, unitid, 0);
+ build_feature_ctl(state, _ftr, 0, i, &iterm,
+ unitid, 0);
}
- } else { /* UAC_VERSION_2/3 */
+ } else { /* UAC_VERSION_2 */
for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
unsigned int ch_bits = 0;
unsigned int ch_read_only = 0;
- int control = audio_feature_info[i].control;
for (j = 0; j < channels; j++) {
unsigned int mask;
mask = snd_usb_combine_bytes(bmaControls +
csize * (j+1), csize);
- if (uac_v2v3_control_is_readable(mask, control)) {
+ if (uac2_control_is_readable(mask, i)) {
ch_bits |= (1 << j);
- if (!uac_v2v3_control_is_writeable(mask, control))
+ if (!uac2_control_is_writeable(mask, i))
ch_read_only |= (1 << j);
}
}
@@ -1977,13 +1606,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
* (for ease of programming).
*/
if (ch_bits & 1)
- build_feature_ctl(state, _ftr, ch_bits, control,
+ build_feature_ctl(state, _ftr, ch_bits, i,
&iterm, unitid, ch_read_only);
- if (uac_v2v3_control_is_readable(master_bits, control))
- build_feature_ctl(state, _ftr, 0, control,
- &iterm, unitid,
- !uac_v2v3_control_is_writeable(master_bits,
- control));
+ if (uac2_control_is_readable(master_bits, i))
+ build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
+ !uac2_control_is_writeable(master_bits, i));
}
}
@@ -2002,15 +1629,16 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
*/
static void build_mixer_unit_ctl(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc,
- int in_pin, int in_ch, int num_outs,
- int unitid, struct usb_audio_term *iterm)
+ int in_pin, int in_ch, int unitid,
+ struct usb_audio_term *iterm)
{
struct usb_mixer_elem_info *cval;
+ unsigned int num_outs = uac_mixer_unit_bNrChannels(desc);
unsigned int i, len;
struct snd_kcontrol *kctl;
const struct usbmix_name_map *map;
- map = find_map(state->map, unitid, 0);
+ map = find_map(state, unitid, 0);
if (check_ignored_ctl(map))
return;
@@ -2043,7 +1671,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
if (!len)
- len = get_term_name(state->chip, iterm, kctl->id.name,
+ len = get_term_name(state, iterm, kctl->id.name,
sizeof(kctl->id.name), 0);
if (!len)
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
@@ -2054,35 +1682,6 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
snd_usb_mixer_add_control(&cval->head, kctl);
}
-static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
- void *raw_desc)
-{
- struct usb_audio_term iterm;
- unsigned int control, bmctls, term_id;
-
- if (state->mixer->protocol == UAC_VERSION_2) {
- struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
- control = UAC2_TE_CONNECTOR;
- term_id = d_v2->bTerminalID;
- bmctls = le16_to_cpu(d_v2->bmControls);
- } else if (state->mixer->protocol == UAC_VERSION_3) {
- struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
- control = UAC3_TE_INSERTION;
- term_id = d_v3->bTerminalID;
- bmctls = le32_to_cpu(d_v3->bmControls);
- } else {
- return 0; /* UAC1. No Insertion control */
- }
-
- check_input_term(state, term_id, &iterm);
-
- /* Check for jack detection. */
- if (uac_v2v3_control_is_readable(bmctls, control))
- build_connector_control(state->mixer, &iterm, true);
-
- return 0;
-}
-
/*
* parse a mixer unit
*/
@@ -2094,17 +1693,14 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
int input_pins, num_ins, num_outs;
int pin, ich, err;
- err = uac_mixer_unit_get_channels(state, desc);
- if (err < 0) {
+ if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) ||
+ !(num_outs = uac_mixer_unit_bNrChannels(desc))) {
usb_audio_err(state->chip,
"invalid MIXER UNIT descriptor %d\n",
unitid);
- return err;
+ return -EINVAL;
}
- num_outs = err;
- input_pins = desc->bNrInPins;
-
num_ins = 0;
ich = 0;
for (pin = 0; pin < input_pins; pin++) {
@@ -2131,7 +1727,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
}
}
if (ich_has_controls)
- build_mixer_unit_ctl(state, desc, pin, ich, num_outs,
+ build_mixer_unit_ctl(state, desc, pin, ich,
unitid, &iterm);
}
}
@@ -2203,11 +1799,6 @@ struct procunit_info {
struct procunit_value_info *values;
};
-static struct procunit_value_info undefined_proc_info[] = {
- { 0x00, "Control Undefined", 0 },
- { 0 }
-};
-
static struct procunit_value_info updown_proc_info[] = {
{ UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
@@ -2256,23 +1847,6 @@ static struct procunit_info procunits[] = {
{ UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info },
{ 0 },
};
-
-static struct procunit_value_info uac3_updown_proc_info[] = {
- { UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
- { 0 }
-};
-static struct procunit_value_info uac3_stereo_ext_proc_info[] = {
- { UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 },
- { 0 }
-};
-
-static struct procunit_info uac3_procunits[] = {
- { UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info },
- { UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info },
- { UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info },
- { 0 },
-};
-
/*
* predefined data for extension units
*/
@@ -2330,8 +1904,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
}
for (i = 0; i < num_ins; i++) {
- err = parse_audio_unit(state, desc->baSourceID[i]);
- if (err < 0)
+ if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)
return err;
}
@@ -2345,17 +1918,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
for (valinfo = info->values; valinfo->control; valinfo++) {
__u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol);
- if (state->mixer->protocol == UAC_VERSION_1) {
- if (!(controls[valinfo->control / 8] &
- (1 << ((valinfo->control % 8) - 1))))
- continue;
- } else { /* UAC_VERSION_2/3 */
- if (!uac_v2v3_control_is_readable(controls[valinfo->control / 8],
- valinfo->control))
- continue;
- }
-
- map = find_map(state->map, unitid, valinfo->control);
+ if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
+ continue;
+ map = find_map(state, unitid, valinfo->control);
if (check_ignored_ctl(map))
continue;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -2366,55 +1931,26 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
cval->val_type = valinfo->val_type;
cval->channels = 1;
- if (state->mixer->protocol > UAC_VERSION_1 &&
- !uac_v2v3_control_is_writeable(controls[valinfo->control / 8],
- valinfo->control))
- cval->master_readonly = 1;
-
/* get min/max values */
- switch (type) {
- case UAC_PROCESS_UP_DOWNMIX: {
- bool mode_sel = false;
-
- switch (state->mixer->protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
- if (cval->control == UAC_UD_MODE_SELECT)
- mode_sel = true;
- break;
- case UAC_VERSION_3:
- if (cval->control == UAC3_UD_MODE_SELECT)
- mode_sel = true;
- break;
- }
-
- if (mode_sel) {
- __u8 *control_spec = uac_processing_unit_specific(desc,
- state->mixer->protocol);
- cval->min = 1;
- cval->max = control_spec[0];
- cval->res = 1;
- cval->initialized = 1;
- break;
- }
-
- get_min_max(cval, valinfo->min_value);
- break;
- }
- case USB_XU_CLOCK_RATE:
- /*
- * E-Mu USB 0404/0202/TrackerPre/0204
- * samplerate control quirk
- */
- cval->min = 0;
- cval->max = 5;
+ if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) {
+ __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol);
+ /* FIXME: hard-coded */
+ cval->min = 1;
+ cval->max = control_spec[0];
cval->res = 1;
cval->initialized = 1;
- break;
- default:
- get_min_max(cval, valinfo->min_value);
- break;
+ } else {
+ if (type == USB_XU_CLOCK_RATE) {
+ /*
+ * E-Mu USB 0404/0202/TrackerPre/0204
+ * samplerate control quirk
+ */
+ cval->min = 0;
+ cval->max = 5;
+ cval->res = 1;
+ cval->initialized = 1;
+ } else
+ get_min_max(cval, valinfo->min_value);
}
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
@@ -2432,8 +1968,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);
len = 0;
if (nameid)
- len = snd_usb_copy_string_desc(state->chip,
- nameid,
+ len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name,
sizeof(kctl->id.name));
if (!len)
@@ -2457,16 +1992,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
static int parse_audio_processing_unit(struct mixer_build *state, int unitid,
void *raw_desc)
{
- switch (state->mixer->protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
- return build_audio_procunit(state, unitid, raw_desc,
- procunits, "Processing Unit");
- case UAC_VERSION_3:
- return build_audio_procunit(state, unitid, raw_desc,
- uac3_procunits, "Processing Unit");
- }
+ return build_audio_procunit(state, unitid, raw_desc,
+ procunits, "Processing Unit");
}
static int parse_audio_extension_unit(struct mixer_build *state, int unitid,
@@ -2589,15 +2116,14 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
}
for (i = 0; i < desc->bNrInPins; i++) {
- err = parse_audio_unit(state, desc->baSourceID[i]);
- if (err < 0)
+ if ((err = parse_audio_unit(state, desc->baSourceID[i])) < 0)
return err;
}
if (desc->bNrInPins == 1) /* only one ? nonsense! */
return 0;
- map = find_map(state->map, unitid, 0);
+ map = find_map(state, unitid, 0);
if (check_ignored_ctl(map))
return 0;
@@ -2612,20 +2138,11 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
cval->res = 1;
cval->initialized = 1;
- switch (state->mixer->protocol) {
- case UAC_VERSION_1:
- default:
+ if (state->mixer->protocol == UAC_VERSION_1)
cval->control = 0;
- break;
- case UAC_VERSION_2:
- case UAC_VERSION_3:
- if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
- desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR)
- cval->control = UAC2_CX_CLOCK_SELECTOR;
- else /* UAC2/3_SELECTOR_UNIT */
- cval->control = UAC2_SU_SELECTOR;
- break;
- }
+ else /* UAC_VERSION_2 */
+ cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ?
+ UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR;
namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
if (!namelist) {
@@ -2647,8 +2164,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
len = check_mapped_selector_name(state, unitid, i, namelist[i],
MAX_ITEM_NAME_LEN);
if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0)
- len = get_term_name(state->chip, &iterm, namelist[i],
- MAX_ITEM_NAME_LEN, 0);
+ len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
if (! len)
sprintf(namelist[i], "Input %u", i);
}
@@ -2667,33 +2183,22 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
if (!len) {
/* no mapping ? */
- switch (state->mixer->protocol) {
- case UAC_VERSION_1:
- case UAC_VERSION_2:
- default:
/* if iSelector is given, use it */
- nameid = uac_selector_unit_iSelector(desc);
- if (nameid)
- len = snd_usb_copy_string_desc(state->chip,
- nameid, kctl->id.name,
- sizeof(kctl->id.name));
- break;
- case UAC_VERSION_3:
- /* TODO: Class-Specific strings not yet supported */
- break;
- }
-
+ nameid = uac_selector_unit_iSelector(desc);
+ if (nameid)
+ len = snd_usb_copy_string_desc(state, nameid,
+ kctl->id.name,
+ sizeof(kctl->id.name));
/* ... or pick up the terminal name at next */
if (!len)
- len = get_term_name(state->chip, &state->oterm,
+ len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 0);
/* ... or use the fixed string "USB" as the last resort */
if (!len)
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
/* and add the proper suffix */
- if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
- desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR)
+ if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
append_ctl_name(kctl, " Clock Source");
else if ((state->oterm.type & 0xff00) == 0x0100)
append_ctl_name(kctl, " Capture Source");
@@ -2713,7 +2218,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
static int parse_audio_unit(struct mixer_build *state, int unitid)
{
unsigned char *p1;
- int protocol = state->mixer->protocol;
if (test_and_set_bit(unitid, state->unitbitmap))
return 0; /* the unit already visited */
@@ -2724,62 +2228,36 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
return -EINVAL;
}
- if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
- switch (p1[2]) {
- case UAC_INPUT_TERMINAL:
- return parse_audio_input_terminal(state, unitid, p1);
- case UAC_MIXER_UNIT:
- return parse_audio_mixer_unit(state, unitid, p1);
- case UAC2_CLOCK_SOURCE:
- return parse_clock_source_unit(state, unitid, p1);
- case UAC_SELECTOR_UNIT:
- case UAC2_CLOCK_SELECTOR:
- return parse_audio_selector_unit(state, unitid, p1);
- case UAC_FEATURE_UNIT:
- return parse_audio_feature_unit(state, unitid, p1);
- case UAC1_PROCESSING_UNIT:
- /* UAC2_EFFECT_UNIT has the same value */
- if (protocol == UAC_VERSION_1)
- return parse_audio_processing_unit(state, unitid, p1);
- else
- return 0; /* FIXME - effect units not implemented yet */
- case UAC1_EXTENSION_UNIT:
- /* UAC2_PROCESSING_UNIT_V2 has the same value */
- if (protocol == UAC_VERSION_1)
- return parse_audio_extension_unit(state, unitid, p1);
- else /* UAC_VERSION_2 */
- return parse_audio_processing_unit(state, unitid, p1);
- case UAC2_EXTENSION_UNIT_V2:
- return parse_audio_extension_unit(state, unitid, p1);
- default:
- usb_audio_err(state->chip,
- "unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
- return -EINVAL;
- }
- } else { /* UAC_VERSION_3 */
- switch (p1[2]) {
- case UAC_INPUT_TERMINAL:
- return parse_audio_input_terminal(state, unitid, p1);
- case UAC3_MIXER_UNIT:
- return parse_audio_mixer_unit(state, unitid, p1);
- case UAC3_CLOCK_SOURCE:
- return parse_clock_source_unit(state, unitid, p1);
- case UAC3_SELECTOR_UNIT:
- case UAC3_CLOCK_SELECTOR:
- return parse_audio_selector_unit(state, unitid, p1);
- case UAC3_FEATURE_UNIT:
- return parse_audio_feature_unit(state, unitid, p1);
- case UAC3_EFFECT_UNIT:
- return 0; /* FIXME - effect units not implemented yet */
- case UAC3_PROCESSING_UNIT:
+ switch (p1[2]) {
+ case UAC_INPUT_TERMINAL:
+ return 0; /* NOP */
+ case UAC_MIXER_UNIT:
+ return parse_audio_mixer_unit(state, unitid, p1);
+ case UAC2_CLOCK_SOURCE:
+ return parse_clock_source_unit(state, unitid, p1);
+ case UAC_SELECTOR_UNIT:
+ case UAC2_CLOCK_SELECTOR:
+ return parse_audio_selector_unit(state, unitid, p1);
+ case UAC_FEATURE_UNIT:
+ return parse_audio_feature_unit(state, unitid, p1);
+ case UAC1_PROCESSING_UNIT:
+ /* UAC2_EFFECT_UNIT has the same value */
+ if (state->mixer->protocol == UAC_VERSION_1)
return parse_audio_processing_unit(state, unitid, p1);
- case UAC3_EXTENSION_UNIT:
+ else
+ return 0; /* FIXME - effect units not implemented yet */
+ case UAC1_EXTENSION_UNIT:
+ /* UAC2_PROCESSING_UNIT_V2 has the same value */
+ if (state->mixer->protocol == UAC_VERSION_1)
return parse_audio_extension_unit(state, unitid, p1);
- default:
- usb_audio_err(state->chip,
- "unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
- return -EINVAL;
- }
+ else /* UAC_VERSION_2 */
+ return parse_audio_processing_unit(state, unitid, p1);
+ case UAC2_EXTENSION_UNIT_V2:
+ return parse_audio_extension_unit(state, unitid, p1);
+ default:
+ usb_audio_err(state->chip,
+ "unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
+ return -EINVAL;
}
}
@@ -2805,263 +2283,6 @@ static int snd_usb_mixer_dev_free(struct snd_device *device)
return 0;
}
-/* UAC3 predefined channels configuration */
-struct uac3_badd_profile {
- int subclass;
- const char *name;
- int c_chmask; /* capture channels mask */
- int p_chmask; /* playback channels mask */
- int st_chmask; /* side tone mixing channel mask */
-};
-
-static struct uac3_badd_profile uac3_badd_profiles[] = {
- {
- /*
- * BAIF, BAOF or combination of both
- * IN: Mono or Stereo cfg, Mono alt possible
- * OUT: Mono or Stereo cfg, Mono alt possible
- */
- .subclass = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
- .name = "GENERIC IO",
- .c_chmask = -1, /* dynamic channels */
- .p_chmask = -1, /* dynamic channels */
- },
- {
- /* BAOF; Stereo only cfg, Mono alt possible */
- .subclass = UAC3_FUNCTION_SUBCLASS_HEADPHONE,
- .name = "HEADPHONE",
- .p_chmask = 3,
- },
- {
- /* BAOF; Mono or Stereo cfg, Mono alt possible */
- .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKER,
- .name = "SPEAKER",
- .p_chmask = -1, /* dynamic channels */
- },
- {
- /* BAIF; Mono or Stereo cfg, Mono alt possible */
- .subclass = UAC3_FUNCTION_SUBCLASS_MICROPHONE,
- .name = "MICROPHONE",
- .c_chmask = -1, /* dynamic channels */
- },
- {
- /*
- * BAIOF topology
- * IN: Mono only
- * OUT: Mono or Stereo cfg, Mono alt possible
- */
- .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET,
- .name = "HEADSET",
- .c_chmask = 1,
- .p_chmask = -1, /* dynamic channels */
- .st_chmask = 1,
- },
- {
- /* BAIOF; IN: Mono only; OUT: Stereo only, Mono alt possible */
- .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER,
- .name = "HEADSET ADAPTER",
- .c_chmask = 1,
- .p_chmask = 3,
- .st_chmask = 1,
- },
- {
- /* BAIF + BAOF; IN: Mono only; OUT: Mono only */
- .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,
- .name = "SPEAKERPHONE",
- .c_chmask = 1,
- .p_chmask = 1,
- },
- { 0 } /* terminator */
-};
-
-static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,
- struct uac3_badd_profile *f,
- int c_chmask, int p_chmask)
-{
- /*
- * If both playback/capture channels are dynamic, make sure
- * at least one channel is present
- */
- if (f->c_chmask < 0 && f->p_chmask < 0) {
- if (!c_chmask && !p_chmask) {
- usb_audio_warn(mixer->chip, "BAAD %s: no channels?",
- f->name);
- return false;
- }
- return true;
- }
-
- if ((f->c_chmask < 0 && !c_chmask) ||
- (f->c_chmask >= 0 && f->c_chmask != c_chmask)) {
- usb_audio_warn(mixer->chip, "BAAD %s c_chmask mismatch",
- f->name);
- return false;
- }
- if ((f->p_chmask < 0 && !p_chmask) ||
- (f->p_chmask >= 0 && f->p_chmask != p_chmask)) {
- usb_audio_warn(mixer->chip, "BAAD %s p_chmask mismatch",
- f->name);
- return false;
- }
- return true;
-}
-
-/*
- * create mixer controls for UAC3 BADD profiles
- *
- * UAC3 BADD device doesn't contain CS descriptors thus we will guess everything
- *
- * BADD device may contain Mixer Unit, which doesn't have any controls, skip it
- */
-static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
- int ctrlif)
-{
- struct usb_device *dev = mixer->chip->dev;
- struct usb_interface_assoc_descriptor *assoc;
- int badd_profile = mixer->chip->badd_profile;
- struct uac3_badd_profile *f;
- const struct usbmix_ctl_map *map;
- int p_chmask = 0, c_chmask = 0, st_chmask = 0;
- int i;
-
- assoc = usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
-
- /* Detect BADD capture/playback channels from AS EP descriptors */
- for (i = 0; i < assoc->bInterfaceCount; i++) {
- int intf = assoc->bFirstInterface + i;
-
- struct usb_interface *iface;
- struct usb_host_interface *alts;
- struct usb_interface_descriptor *altsd;
- unsigned int maxpacksize;
- char dir_in;
- int chmask, num;
-
- if (intf == ctrlif)
- continue;
-
- iface = usb_ifnum_to_if(dev, intf);
- num = iface->num_altsetting;
-
- if (num < 2)
- return -EINVAL;
-
- /*
- * The number of Channels in an AudioStreaming interface
- * and the audio sample bit resolution (16 bits or 24
- * bits) can be derived from the wMaxPacketSize field in
- * the Standard AS Audio Data Endpoint descriptor in
- * Alternate Setting 1
- */
- alts = &iface->altsetting[1];
- altsd = get_iface_desc(alts);
-
- if (altsd->bNumEndpoints < 1)
- return -EINVAL;
-
- /* check direction */
- dir_in = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
- maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-
- switch (maxpacksize) {
- default:
- usb_audio_err(mixer->chip,
- "incorrect wMaxPacketSize 0x%x for BADD profile\n",
- maxpacksize);
- return -EINVAL;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
- case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
- chmask = 1;
- break;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
- case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
- chmask = 3;
- break;
- }
-
- if (dir_in)
- c_chmask = chmask;
- else
- p_chmask = chmask;
- }
-
- usb_audio_dbg(mixer->chip,
- "UAC3 BADD profile 0x%x: detected c_chmask=%d p_chmask=%d\n",
- badd_profile, c_chmask, p_chmask);
-
- /* check the mapping table */
- for (map = uac3_badd_usbmix_ctl_maps; map->id; map++) {
- if (map->id == badd_profile)
- break;
- }
-
- if (!map->id)
- return -EINVAL;
-
- for (f = uac3_badd_profiles; f->name; f++) {
- if (badd_profile == f->subclass)
- break;
- }
- if (!f->name)
- return -EINVAL;
- if (!uac3_badd_func_has_valid_channels(mixer, f, c_chmask, p_chmask))
- return -EINVAL;
- st_chmask = f->st_chmask;
-
- /* Playback */
- if (p_chmask) {
- /* Master channel, always writable */
- build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
- UAC3_BADD_FU_ID2, map->map);
- /* Mono/Stereo volume channels, always writable */
- build_feature_ctl_badd(mixer, p_chmask, UAC_FU_VOLUME,
- UAC3_BADD_FU_ID2, map->map);
- }
-
- /* Capture */
- if (c_chmask) {
- /* Master channel, always writable */
- build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
- UAC3_BADD_FU_ID5, map->map);
- /* Mono/Stereo volume channels, always writable */
- build_feature_ctl_badd(mixer, c_chmask, UAC_FU_VOLUME,
- UAC3_BADD_FU_ID5, map->map);
- }
-
- /* Side tone-mixing */
- if (st_chmask) {
- /* Master channel, always writable */
- build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
- UAC3_BADD_FU_ID7, map->map);
- /* Mono volume channel, always writable */
- build_feature_ctl_badd(mixer, 1, UAC_FU_VOLUME,
- UAC3_BADD_FU_ID7, map->map);
- }
-
- /* Insertion Control */
- if (f->subclass == UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER) {
- struct usb_audio_term iterm, oterm;
-
- /* Input Term - Insertion control */
- memset(&iterm, 0, sizeof(iterm));
- iterm.id = UAC3_BADD_IT_ID4;
- iterm.type = UAC_BIDIR_TERMINAL_HEADSET;
- build_connector_control(mixer, &iterm, true);
-
- /* Output Term - Insertion control */
- memset(&oterm, 0, sizeof(oterm));
- oterm.id = UAC3_BADD_OT_ID3;
- oterm.type = UAC_BIDIR_TERMINAL_HEADSET;
- build_connector_control(mixer, &oterm, false);
- }
-
- return 0;
-}
-
/*
* create mixer controls
*
@@ -3107,7 +2328,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
err = parse_audio_unit(&state, desc->bSourceID);
if (err < 0 && err != -EINVAL)
return err;
- } else if (mixer->protocol == UAC_VERSION_2) {
+ } else { /* UAC_VERSION_2 */
struct uac2_output_terminal_descriptor *desc = p;
if (desc->bLength < sizeof(*desc))
@@ -3128,39 +2349,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
err = parse_audio_unit(&state, desc->bCSourceID);
if (err < 0 && err != -EINVAL)
return err;
-
- if (uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
- UAC2_TE_CONNECTOR)) {
- build_connector_control(state.mixer, &state.oterm,
- false);
- }
- } else { /* UAC_VERSION_3 */
- struct uac3_output_terminal_descriptor *desc = p;
-
- if (desc->bLength < sizeof(*desc))
- continue; /* invalid descriptor? */
- /* mark terminal ID as visited */
- set_bit(desc->bTerminalID, state.unitbitmap);
- state.oterm.id = desc->bTerminalID;
- state.oterm.type = le16_to_cpu(desc->wTerminalType);
- state.oterm.name = le16_to_cpu(desc->wTerminalDescrStr);
- err = parse_audio_unit(&state, desc->bSourceID);
- if (err < 0 && err != -EINVAL)
- return err;
-
- /*
- * For UAC3, use the same approach to also add the
- * clock selectors
- */
- err = parse_audio_unit(&state, desc->bCSourceID);
- if (err < 0 && err != -EINVAL)
- return err;
-
- if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
- UAC3_TE_INSERTION)) {
- build_connector_control(state.mixer, &state.oterm,
- false);
- }
}
}
@@ -3171,9 +2359,9 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
{
struct usb_mixer_elem_list *list;
- for_each_mixer_elem(list, mixer, unitid) {
+ for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
struct usb_mixer_elem_info *info =
- mixer_elem_list_to_info(list);
+ (struct usb_mixer_elem_info *)list;
/* invalidate cache, so the value is read from the device */
info->cached = 0;
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -3184,7 +2372,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
struct usb_mixer_elem_list *list)
{
- struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+ struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
"S8", "U8", "S16", "U16"};
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
@@ -3210,7 +2398,8 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
mixer->ignore_ctl_error);
snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
- for_each_mixer_elem(list, mixer, unitid) {
+ for (list = mixer->id_elems[unitid]; list;
+ list = list->next_id_elem) {
snd_iprintf(buffer, " Unit: %i\n", list->id);
if (list->kctl)
snd_iprintf(buffer,
@@ -3240,19 +2429,19 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
return;
}
- for_each_mixer_elem(list, mixer, unitid)
+ for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
count++;
if (count == 0)
return;
- for_each_mixer_elem(list, mixer, unitid) {
+ for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
struct usb_mixer_elem_info *info;
if (!list->kctl)
continue;
- info = mixer_elem_list_to_info(list);
+ info = (struct usb_mixer_elem_info *)list;
if (count > 1 && info->control != control)
continue;
@@ -3448,26 +2637,11 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
case UAC_VERSION_2:
mixer->protocol = UAC_VERSION_2;
break;
- case UAC_VERSION_3:
- mixer->protocol = UAC_VERSION_3;
- break;
}
- if (mixer->protocol == UAC_VERSION_3 &&
- chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
- err = snd_usb_mixer_controls_badd(mixer, ctrlif);
- if (err < 0)
- goto _error;
- } else {
- err = snd_usb_mixer_controls(mixer);
- if (err < 0)
- goto _error;
- }
-
- err = snd_usb_mixer_status_create(mixer);
- if (err < 0)
+ if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
+ (err = snd_usb_mixer_status_create(mixer)) < 0)
goto _error;
-
err = create_keep_iface_ctl(mixer);
if (err < 0)
goto _error;
@@ -3530,7 +2704,7 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
static int restore_mixer_value(struct usb_mixer_elem_list *list)
{
- struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+ struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
int c, err, idx;
if (cval->cmask) {
@@ -3566,7 +2740,8 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
if (reset_resume) {
/* restore cached mixer values */
for (id = 0; id < MAX_ID_ELEMS; id++) {
- for_each_mixer_elem(list, mixer, id) {
+ for (list = mixer->id_elems[id]; list;
+ list = list->next_id_elem) {
if (list->resume) {
err = list->resume(list);
if (err < 0)
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 1ebaaac2ab90..545d99b09706 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -52,12 +52,6 @@ struct usb_mixer_elem_list {
usb_mixer_elem_resume_func_t resume;
};
-/* iterate over mixer element list of the given unit id */
-#define for_each_mixer_elem(list, mixer, id) \
- for ((list) = (mixer)->id_elems[id]; (list); (list) = (list)->next_id_elem)
-#define mixer_elem_list_to_info(list) \
- container_of(list, struct usb_mixer_elem_info, head)
-
struct usb_mixer_elem_info {
struct usb_mixer_elem_list head;
unsigned int control; /* CS or ICN (high byte) */
@@ -108,6 +102,4 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl);
-extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
-
#endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 71069e110897..eaa03acd4686 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -485,68 +485,3 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ 0 } /* terminator */
};
-/*
- * Control map entries for UAC3 BADD profiles
- */
-
-static struct usbmix_name_map uac3_badd_generic_io_map[] = {
- { UAC3_BADD_FU_ID2, "Generic Out Playback" },
- { UAC3_BADD_FU_ID5, "Generic In Capture" },
- { 0 } /* terminator */
-};
-static struct usbmix_name_map uac3_badd_headphone_map[] = {
- { UAC3_BADD_FU_ID2, "Headphone Playback" },
- { 0 } /* terminator */
-};
-static struct usbmix_name_map uac3_badd_speaker_map[] = {
- { UAC3_BADD_FU_ID2, "Speaker Playback" },
- { 0 } /* terminator */
-};
-static struct usbmix_name_map uac3_badd_microphone_map[] = {
- { UAC3_BADD_FU_ID5, "Mic Capture" },
- { 0 } /* terminator */
-};
-/* Covers also 'headset adapter' profile */
-static struct usbmix_name_map uac3_badd_headset_map[] = {
- { UAC3_BADD_FU_ID2, "Headset Playback" },
- { UAC3_BADD_FU_ID5, "Headset Capture" },
- { UAC3_BADD_FU_ID7, "Sidetone Mixing" },
- { 0 } /* terminator */
-};
-static struct usbmix_name_map uac3_badd_speakerphone_map[] = {
- { UAC3_BADD_FU_ID2, "Speaker Playback" },
- { UAC3_BADD_FU_ID5, "Mic Capture" },
- { 0 } /* terminator */
-};
-
-static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
- {
- .id = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
- .map = uac3_badd_generic_io_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_HEADPHONE,
- .map = uac3_badd_headphone_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_SPEAKER,
- .map = uac3_badd_speaker_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_MICROPHONE,
- .map = uac3_badd_microphone_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_HEADSET,
- .map = uac3_badd_headset_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER,
- .map = uac3_badd_headset_map,
- },
- {
- .id = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,
- .map = uac3_badd_speakerphone_map,
- },
- { 0 } /* terminator */
-};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index f02bf158022a..4ba21e9ca2d1 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -29,7 +29,6 @@
#include <linux/hid.h>
#include <linux/init.h>
-#include <linux/math64.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
@@ -48,6 +47,8 @@
#include "mixer_us16x08.h"
#include "helper.h"
+extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+
struct std_mono_table {
unsigned int unitid, control, cmask;
int val_type;
@@ -362,7 +363,7 @@ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list)
}
/* name and private_value are set dynamically */
-static const struct snd_kcontrol_new snd_audigy2nx_control = {
+static struct snd_kcontrol_new snd_audigy2nx_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_audigy2nx_led_info,
.get = snd_audigy2nx_led_get,
@@ -1171,7 +1172,7 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
int unitid = 12; /* SamleRate ExtensionUnit ID */
list_for_each_entry(mixer, &chip->mixer_list, list) {
- cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
+ cval = (struct usb_mixer_elem_info *)mixer->id_elems[unitid];
if (cval) {
snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
cval->control << 8,
@@ -1818,387 +1819,12 @@ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
return 0;
}
-/* RME Class Compliant device quirks */
-
-#define SND_RME_GET_STATUS1 23
-#define SND_RME_GET_CURRENT_FREQ 17
-#define SND_RME_CLK_SYSTEM_SHIFT 16
-#define SND_RME_CLK_SYSTEM_MASK 0x1f
-#define SND_RME_CLK_AES_SHIFT 8
-#define SND_RME_CLK_SPDIF_SHIFT 12
-#define SND_RME_CLK_AES_SPDIF_MASK 0xf
-#define SND_RME_CLK_SYNC_SHIFT 6
-#define SND_RME_CLK_SYNC_MASK 0x3
-#define SND_RME_CLK_FREQMUL_SHIFT 18
-#define SND_RME_CLK_FREQMUL_MASK 0x7
-#define SND_RME_CLK_SYSTEM(x) \
- ((x >> SND_RME_CLK_SYSTEM_SHIFT) & SND_RME_CLK_SYSTEM_MASK)
-#define SND_RME_CLK_AES(x) \
- ((x >> SND_RME_CLK_AES_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK)
-#define SND_RME_CLK_SPDIF(x) \
- ((x >> SND_RME_CLK_SPDIF_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK)
-#define SND_RME_CLK_SYNC(x) \
- ((x >> SND_RME_CLK_SYNC_SHIFT) & SND_RME_CLK_SYNC_MASK)
-#define SND_RME_CLK_FREQMUL(x) \
- ((x >> SND_RME_CLK_FREQMUL_SHIFT) & SND_RME_CLK_FREQMUL_MASK)
-#define SND_RME_CLK_AES_LOCK 0x1
-#define SND_RME_CLK_AES_SYNC 0x4
-#define SND_RME_CLK_SPDIF_LOCK 0x2
-#define SND_RME_CLK_SPDIF_SYNC 0x8
-#define SND_RME_SPDIF_IF_SHIFT 4
-#define SND_RME_SPDIF_FORMAT_SHIFT 5
-#define SND_RME_BINARY_MASK 0x1
-#define SND_RME_SPDIF_IF(x) \
- ((x >> SND_RME_SPDIF_IF_SHIFT) & SND_RME_BINARY_MASK)
-#define SND_RME_SPDIF_FORMAT(x) \
- ((x >> SND_RME_SPDIF_FORMAT_SHIFT) & SND_RME_BINARY_MASK)
-
-static const u32 snd_rme_rate_table[] = {
- 32000, 44100, 48000, 50000,
- 64000, 88200, 96000, 100000,
- 128000, 176400, 192000, 200000,
- 256000, 352800, 384000, 400000,
- 512000, 705600, 768000, 800000
-};
-/* maximum number of items for AES and S/PDIF rates for above table */
-#define SND_RME_RATE_IDX_AES_SPDIF_NUM 12
-
-enum snd_rme_domain {
- SND_RME_DOMAIN_SYSTEM,
- SND_RME_DOMAIN_AES,
- SND_RME_DOMAIN_SPDIF
-};
-
-enum snd_rme_clock_status {
- SND_RME_CLOCK_NOLOCK,
- SND_RME_CLOCK_LOCK,
- SND_RME_CLOCK_SYNC
-};
-
-static int snd_rme_read_value(struct snd_usb_audio *chip,
- unsigned int item,
- u32 *value)
-{
- struct usb_device *dev = chip->dev;
- int err;
-
- err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
- item,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, 0,
- value, sizeof(*value));
- if (err < 0)
- dev_err(&dev->dev,
- "unable to issue vendor read request %d (ret = %d)",
- item, err);
- return err;
-}
-
-static int snd_rme_get_status1(struct snd_kcontrol *kcontrol,
- u32 *status1)
-{
- struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
- struct snd_usb_audio *chip = list->mixer->chip;
- int err;
-
- err = snd_usb_lock_shutdown(chip);
- if (err < 0)
- return err;
- err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, status1);
- snd_usb_unlock_shutdown(chip);
- return err;
-}
-
-static int snd_rme_rate_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- u32 status1;
- u32 rate = 0;
- int idx;
- int err;
-
- err = snd_rme_get_status1(kcontrol, &status1);
- if (err < 0)
- return err;
- switch (kcontrol->private_value) {
- case SND_RME_DOMAIN_SYSTEM:
- idx = SND_RME_CLK_SYSTEM(status1);
- if (idx < ARRAY_SIZE(snd_rme_rate_table))
- rate = snd_rme_rate_table[idx];
- break;
- case SND_RME_DOMAIN_AES:
- idx = SND_RME_CLK_AES(status1);
- if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM)
- rate = snd_rme_rate_table[idx];
- break;
- case SND_RME_DOMAIN_SPDIF:
- idx = SND_RME_CLK_SPDIF(status1);
- if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM)
- rate = snd_rme_rate_table[idx];
- break;
- default:
- return -EINVAL;
- }
- ucontrol->value.integer.value[0] = rate;
- return 0;
-}
-
-static int snd_rme_sync_state_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- u32 status1;
- int idx = SND_RME_CLOCK_NOLOCK;
- int err;
-
- err = snd_rme_get_status1(kcontrol, &status1);
- if (err < 0)
- return err;
- switch (kcontrol->private_value) {
- case SND_RME_DOMAIN_AES: /* AES */
- if (status1 & SND_RME_CLK_AES_SYNC)
- idx = SND_RME_CLOCK_SYNC;
- else if (status1 & SND_RME_CLK_AES_LOCK)
- idx = SND_RME_CLOCK_LOCK;
- break;
- case SND_RME_DOMAIN_SPDIF: /* SPDIF */
- if (status1 & SND_RME_CLK_SPDIF_SYNC)
- idx = SND_RME_CLOCK_SYNC;
- else if (status1 & SND_RME_CLK_SPDIF_LOCK)
- idx = SND_RME_CLOCK_LOCK;
- break;
- default:
- return -EINVAL;
- }
- ucontrol->value.enumerated.item[0] = idx;
- return 0;
-}
-
-static int snd_rme_spdif_if_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- u32 status1;
- int err;
-
- err = snd_rme_get_status1(kcontrol, &status1);
- if (err < 0)
- return err;
- ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_IF(status1);
- return 0;
-}
-
-static int snd_rme_spdif_format_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- u32 status1;
- int err;
-
- err = snd_rme_get_status1(kcontrol, &status1);
- if (err < 0)
- return err;
- ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_FORMAT(status1);
- return 0;
-}
-
-static int snd_rme_sync_source_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- u32 status1;
- int err;
-
- err = snd_rme_get_status1(kcontrol, &status1);
- if (err < 0)
- return err;
- ucontrol->value.enumerated.item[0] = SND_RME_CLK_SYNC(status1);
- return 0;
-}
-
-static int snd_rme_current_freq_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
- struct snd_usb_audio *chip = list->mixer->chip;
- u32 status1;
- const u64 num = 104857600000000ULL;
- u32 den;
- unsigned int freq;
- int err;
-
- err = snd_usb_lock_shutdown(chip);
- if (err < 0)
- return err;
- err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, &status1);
- if (err < 0)
- goto end;
- err = snd_rme_read_value(chip, SND_RME_GET_CURRENT_FREQ, &den);
- if (err < 0)
- goto end;
- freq = (den == 0) ? 0 : div64_u64(num, den);
- freq <<= SND_RME_CLK_FREQMUL(status1);
- ucontrol->value.integer.value[0] = freq;
-
-end:
- snd_usb_unlock_shutdown(chip);
- return err;
-}
-
-static int snd_rme_rate_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- switch (kcontrol->private_value) {
- case SND_RME_DOMAIN_SYSTEM:
- uinfo->value.integer.min = 32000;
- uinfo->value.integer.max = 800000;
- break;
- case SND_RME_DOMAIN_AES:
- case SND_RME_DOMAIN_SPDIF:
- default:
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 200000;
- }
- uinfo->value.integer.step = 0;
- return 0;
-}
-
-static int snd_rme_sync_state_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char *const sync_states[] = {
- "No Lock", "Lock", "Sync"
- };
-
- return snd_ctl_enum_info(uinfo, 1,
- ARRAY_SIZE(sync_states), sync_states);
-}
-
-static int snd_rme_spdif_if_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char *const spdif_if[] = {
- "Coaxial", "Optical"
- };
-
- return snd_ctl_enum_info(uinfo, 1,
- ARRAY_SIZE(spdif_if), spdif_if);
-}
-
-static int snd_rme_spdif_format_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char *const optical_type[] = {
- "Consumer", "Professional"
- };
-
- return snd_ctl_enum_info(uinfo, 1,
- ARRAY_SIZE(optical_type), optical_type);
-}
-
-static int snd_rme_sync_source_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char *const sync_sources[] = {
- "Internal", "AES", "SPDIF", "Internal"
- };
-
- return snd_ctl_enum_info(uinfo, 1,
- ARRAY_SIZE(sync_sources), sync_sources);
-}
-
-static struct snd_kcontrol_new snd_rme_controls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "AES Rate",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_rate_info,
- .get = snd_rme_rate_get,
- .private_value = SND_RME_DOMAIN_AES
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "AES Sync",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_sync_state_info,
- .get = snd_rme_sync_state_get,
- .private_value = SND_RME_DOMAIN_AES
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Rate",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_rate_info,
- .get = snd_rme_rate_get,
- .private_value = SND_RME_DOMAIN_SPDIF
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Sync",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_sync_state_info,
- .get = snd_rme_sync_state_get,
- .private_value = SND_RME_DOMAIN_SPDIF
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Interface",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_spdif_if_info,
- .get = snd_rme_spdif_if_get,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Format",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_spdif_format_info,
- .get = snd_rme_spdif_format_get,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Sync Source",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_sync_source_info,
- .get = snd_rme_sync_source_get
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "System Rate",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_rate_info,
- .get = snd_rme_rate_get,
- .private_value = SND_RME_DOMAIN_SYSTEM
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Current Frequency",
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = snd_rme_rate_info,
- .get = snd_rme_current_freq_get
- }
-};
-
-static int snd_rme_controls_create(struct usb_mixer_interface *mixer)
-{
- int err, i;
-
- for (i = 0; i < ARRAY_SIZE(snd_rme_controls); ++i) {
- err = add_single_ctl_with_resume(mixer, 0,
- NULL,
- &snd_rme_controls[i],
- NULL);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
{
int err = 0;
struct snd_info_entry *entry;
- err = snd_usb_soundblaster_remote_init(mixer);
- if (err < 0)
+ if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
return err;
switch (mixer->chip->usb_id) {
@@ -2222,6 +1848,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
/* EMU0204 */
case USB_ID(0x041e, 0x3f19):
err = snd_emu0204_controls_create(mixer);
+ if (err < 0)
+ break;
break;
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
@@ -2279,12 +1907,6 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x0bda, 0x4014): /* Dell WD15 dock */
err = dell_dock_mixer_init(mixer);
break;
-
- case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */
- case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */
- case USB_ID(0x2a39, 0x3fd4): /* RME */
- err = snd_rme_controls_create(mixer);
- break;
}
return err;
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
index 4aeb9488a0c9..c33e2378089d 100644
--- a/sound/usb/mixer_scarlett.c
+++ b/sound/usb/mixer_scarlett.c
@@ -287,7 +287,8 @@ static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl,
static int scarlett_ctl_resume(struct usb_mixer_elem_list *list)
{
- struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);
+ struct usb_mixer_elem_info *elem =
+ container_of(list, struct usb_mixer_elem_info, head);
int i;
for (i = 0; i < elem->channels; i++)
@@ -446,7 +447,8 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl,
static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list)
{
- struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);
+ struct usb_mixer_elem_info *elem =
+ container_of(list, struct usb_mixer_elem_info, head);
if (elem->cached)
snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 6c15a474b10b..ca26f1dfa52f 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -76,9 +76,10 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
*/
static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
{
- struct snd_usb_substream *subs = substream->runtime->private_data;
+ struct snd_usb_substream *subs;
unsigned int hwptr_done;
+ subs = (struct snd_usb_substream *)substream->runtime->private_data;
if (atomic_read(&subs->stream->chip->shutdown))
return SNDRV_PCM_POS_XRUN;
spin_lock(&subs->lock);
@@ -163,11 +164,10 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
ep = get_endpoint(alts, 0)->bEndpointAddress;
data[0] = 1;
- err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
- data, sizeof(data));
- if (err < 0) {
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
+ UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
+ data, sizeof(data))) < 0) {
usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n",
iface, ep);
return err;
@@ -185,11 +185,10 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
int err;
data[0] = 1;
- err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- UAC2_EP_CS_PITCH << 8, 0,
- data, sizeof(data));
- if (err < 0) {
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ UAC2_EP_CS_PITCH << 8, 0,
+ data, sizeof(data))) < 0) {
usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n",
iface, fmt->altsetting);
return err;
@@ -343,10 +342,6 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
ep = 0x86;
ifnum = 2;
goto add_sync_ep_from_ifnum;
- case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx III */
- ep = 0x81;
- ifnum = 2;
- goto add_sync_ep_from_ifnum;
case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
ep = 0x81;
ifnum = 1;
@@ -711,54 +706,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
return ret;
}
-static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state)
-{
- int ret;
-
- if (!subs->str_pd)
- return 0;
-
- ret = snd_usb_power_domain_set(subs->stream->chip, subs->str_pd, state);
- if (ret < 0) {
- dev_err(&subs->dev->dev,
- "Cannot change Power Domain ID: %d to state: %d. Err: %d\n",
- subs->str_pd->pd_id, state, ret);
- return ret;
- }
-
- return 0;
-}
-
-int snd_usb_pcm_suspend(struct snd_usb_stream *as)
-{
- int ret;
-
- ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D2);
- if (ret < 0)
- return ret;
-
- ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D2);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int snd_usb_pcm_resume(struct snd_usb_stream *as)
-{
- int ret;
-
- ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D1);
- if (ret < 0)
- return ret;
-
- ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D1);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
/*
* hw_params callback
*
@@ -776,11 +723,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
struct audioformat *fmt;
int ret;
- if (snd_usb_use_vmalloc)
- ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
- else
- ret = snd_pcm_lib_malloc_pages(substream,
+ ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
return ret;
@@ -803,22 +746,16 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
ret = snd_usb_lock_shutdown(subs->stream->chip);
if (ret < 0)
return ret;
-
- ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
- if (ret < 0)
- goto unlock;
-
ret = set_format(subs, fmt);
+ snd_usb_unlock_shutdown(subs->stream->chip);
if (ret < 0)
- goto unlock;
+ return ret;
subs->interface = fmt->iface;
subs->altset_idx = fmt->altset_idx;
subs->need_setup_ep = true;
- unlock:
- snd_usb_unlock_shutdown(subs->stream->chip);
- return ret;
+ return 0;
}
/*
@@ -839,11 +776,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
snd_usb_endpoint_deactivate(subs->data_endpoint);
snd_usb_unlock_shutdown(subs->stream->chip);
}
-
- if (snd_usb_use_vmalloc)
- return snd_pcm_lib_free_vmalloc_buffer(substream);
- else
- return snd_pcm_lib_free_pages(substream);
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
}
/*
@@ -875,10 +808,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
- ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
- if (ret < 0)
- goto unlock;
-
ret = set_format(subs, subs->cur_audiofmt);
if (ret < 0)
goto unlock;
@@ -1239,6 +1168,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
pt = 125 * (1 << fp->datainterval);
ptmin = min(ptmin, pt);
}
+ err = snd_usb_autoresume(subs->stream->chip);
+ if (err < 0)
+ return err;
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
if (subs->speed == USB_SPEED_FULL)
@@ -1247,37 +1179,30 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
if (ptmin == 1000)
/* if period time doesn't go below 1 ms, no rules needed */
param_period_time_if_needed = -1;
-
- err = snd_pcm_hw_constraint_minmax(runtime,
- SNDRV_PCM_HW_PARAM_PERIOD_TIME,
- ptmin, UINT_MAX);
- if (err < 0)
- return err;
-
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- hw_rule_rate, subs,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- param_period_time_if_needed,
- -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- hw_rule_channels, subs,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_HW_PARAM_RATE,
- param_period_time_if_needed,
- -1);
- if (err < 0)
- return err;
- err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
- hw_rule_format, subs,
- SNDRV_PCM_HW_PARAM_RATE,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- param_period_time_if_needed,
- -1);
- if (err < 0)
- return err;
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+ ptmin, UINT_MAX);
+
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ hw_rule_rate, subs,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ param_period_time_if_needed,
+ -1)) < 0)
+ goto rep_err;
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ hw_rule_channels, subs,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_HW_PARAM_RATE,
+ param_period_time_if_needed,
+ -1)) < 0)
+ goto rep_err;
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+ hw_rule_format, subs,
+ SNDRV_PCM_HW_PARAM_RATE,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ param_period_time_if_needed,
+ -1)) < 0)
+ goto rep_err;
if (param_period_time_if_needed >= 0) {
err = snd_pcm_hw_rule_add(runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -1287,18 +1212,19 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
SNDRV_PCM_HW_PARAM_RATE,
-1);
if (err < 0)
- return err;
+ goto rep_err;
}
- err = snd_usb_pcm_check_knot(runtime, subs);
- if (err < 0)
- return err;
+ if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
+ goto rep_err;
+ return 0;
- return snd_usb_autoresume(subs->stream->chip);
+rep_err:
+ snd_usb_autosuspend(subs->stream->chip);
+ return err;
}
-static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
+static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
{
- int direction = substream->stream;
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usb_substream *subs = &as->substream[direction];
@@ -1318,12 +1244,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
return setup_hw_info(runtime, subs);
}
-static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
+static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
{
- int direction = substream->stream;
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction];
- int ret;
stop_endpoints(subs, true);
@@ -1332,10 +1256,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
!snd_usb_lock_shutdown(subs->stream->chip)) {
usb_set_interface(subs->dev, subs->interface, 0);
subs->interface = -1;
- ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
snd_usb_unlock_shutdown(subs->stream->chip);
- if (ret < 0)
- return ret;
}
subs->pcm_substream = NULL;
@@ -1686,6 +1607,26 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
spin_unlock_irqrestore(&subs->lock, flags);
}
+static int snd_usb_playback_open(struct snd_pcm_substream *substream)
+{
+ return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+static int snd_usb_playback_close(struct snd_pcm_substream *substream)
+{
+ return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+static int snd_usb_capture_open(struct snd_pcm_substream *substream)
+{
+ return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE);
+}
+
+static int snd_usb_capture_close(struct snd_pcm_substream *substream)
+{
+ return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE);
+}
+
static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
@@ -1694,7 +1635,6 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
subs->trigger_tstamp_pending_update = true;
- /* fall through */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
subs->data_endpoint->retire_data_urb = retire_playback_urb;
@@ -1747,9 +1687,9 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
return -EINVAL;
}
-static const struct snd_pcm_ops snd_usb_playback_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
+static struct snd_pcm_ops snd_usb_playback_ops = {
+ .open = snd_usb_playback_open,
+ .close = snd_usb_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_usb_hw_params,
.hw_free = snd_usb_hw_free,
@@ -1760,9 +1700,9 @@ static const struct snd_pcm_ops snd_usb_playback_ops = {
.mmap = snd_pcm_lib_mmap_vmalloc,
};
-static const struct snd_pcm_ops snd_usb_capture_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
+static struct snd_pcm_ops snd_usb_capture_ops = {
+ .open = snd_usb_capture_open,
+ .close = snd_usb_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_usb_hw_params,
.hw_free = snd_usb_hw_free,
@@ -1773,50 +1713,9 @@ static const struct snd_pcm_ops snd_usb_capture_ops = {
.mmap = snd_pcm_lib_mmap_vmalloc,
};
-static const struct snd_pcm_ops snd_usb_playback_dev_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_usb_hw_params,
- .hw_free = snd_usb_hw_free,
- .prepare = snd_usb_pcm_prepare,
- .trigger = snd_usb_substream_playback_trigger,
- .pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_sgbuf_ops_page,
-};
-
-static const struct snd_pcm_ops snd_usb_capture_dev_ops = {
- .open = snd_usb_pcm_open,
- .close = snd_usb_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_usb_hw_params,
- .hw_free = snd_usb_hw_free,
- .prepare = snd_usb_pcm_prepare,
- .trigger = snd_usb_substream_capture_trigger,
- .pointer = snd_usb_pcm_pointer,
- .page = snd_pcm_sgbuf_ops_page,
-};
-
void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream)
{
- const struct snd_pcm_ops *ops;
-
- if (snd_usb_use_vmalloc)
- ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &snd_usb_playback_ops : &snd_usb_capture_ops;
- else
- ops = stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &snd_usb_playback_dev_ops : &snd_usb_capture_dev_ops;
- snd_pcm_set_ops(pcm, stream, ops);
-}
-
-void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
-{
- struct snd_pcm *pcm = subs->stream->pcm;
- struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
- struct device *dev = subs->dev->bus->controller;
-
- if (!snd_usb_use_vmalloc)
- snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG,
- dev, 64*1024, 512*1024);
+ snd_pcm_set_ops(pcm, stream,
+ stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ &snd_usb_playback_ops : &snd_usb_capture_ops);
}
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index ec89a93ab1f9..df7a003682ad 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -5,13 +5,10 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
unsigned int rate);
void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
-int snd_usb_pcm_suspend(struct snd_usb_stream *as);
-int snd_usb_pcm_resume(struct snd_usb_stream *as);
int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt);
-void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
#endif /* __USBAUDIO_PCM_H */
diff --git a/sound/usb/power.c b/sound/usb/power.c
deleted file mode 100644
index bd303a1ba1b7..000000000000
--- a/sound/usb/power.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * UAC3 Power Domain state management functions
- */
-
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/usb/audio.h>
-#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
-
-#include "usbaudio.h"
-#include "helper.h"
-#include "power.h"
-
-struct snd_usb_power_domain *
-snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
- unsigned char id)
-{
- struct snd_usb_power_domain *pd;
- void *p;
-
- pd = kzalloc(sizeof(*pd), GFP_KERNEL);
- if (!pd)
- return NULL;
-
- p = NULL;
- while ((p = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- p, UAC3_POWER_DOMAIN)) != NULL) {
- struct uac3_power_domain_descriptor *pd_desc = p;
- int i;
-
- for (i = 0; i < pd_desc->bNrEntities; i++) {
- if (pd_desc->baEntityID[i] == id) {
- pd->pd_id = pd_desc->bPowerDomainID;
- pd->pd_d1d0_rec =
- le16_to_cpu(pd_desc->waRecoveryTime1);
- pd->pd_d2d0_rec =
- le16_to_cpu(pd_desc->waRecoveryTime2);
- return pd;
- }
- }
- }
-
- kfree(pd);
- return NULL;
-}
-
-int snd_usb_power_domain_set(struct snd_usb_audio *chip,
- struct snd_usb_power_domain *pd,
- unsigned char state)
-{
- struct usb_device *dev = chip->dev;
- unsigned char current_state;
- int err, idx;
-
- idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
-
- err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
- UAC2_CS_CUR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- UAC3_AC_POWER_DOMAIN_CONTROL << 8, idx,
- &current_state, sizeof(current_state));
- if (err < 0) {
- dev_err(&dev->dev, "Can't get UAC3 power state for id %d\n",
- pd->pd_id);
- return err;
- }
-
- if (current_state == state) {
- dev_dbg(&dev->dev, "UAC3 power domain id %d already in state %d\n",
- pd->pd_id, state);
- return 0;
- }
-
- err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- UAC3_AC_POWER_DOMAIN_CONTROL << 8, idx,
- &state, sizeof(state));
- if (err < 0) {
- dev_err(&dev->dev, "Can't set UAC3 power state to %d for id %d\n",
- state, pd->pd_id);
- return err;
- }
-
- if (state == UAC3_PD_STATE_D0) {
- switch (current_state) {
- case UAC3_PD_STATE_D2:
- udelay(pd->pd_d2d0_rec * 50);
- break;
- case UAC3_PD_STATE_D1:
- udelay(pd->pd_d1d0_rec * 50);
- break;
- default:
- return -EINVAL;
- }
- }
-
- dev_dbg(&dev->dev, "UAC3 power domain id %d change to state %d\n",
- pd->pd_id, state);
-
- return 0;
-}
diff --git a/sound/usb/power.h b/sound/usb/power.h
index bbd549691e69..48ee51dcb71e 100644
--- a/sound/usb/power.h
+++ b/sound/usb/power.h
@@ -1,25 +1,6 @@
#ifndef __USBAUDIO_POWER_H
#define __USBAUDIO_POWER_H
-struct snd_usb_power_domain {
- int pd_id; /* UAC3 Power Domain ID */
- int pd_d1d0_rec; /* D1 to D0 recovery time */
- int pd_d2d0_rec; /* D2 to D0 recovery time */
-};
-
-enum {
- UAC3_PD_STATE_D0,
- UAC3_PD_STATE_D1,
- UAC3_PD_STATE_D2,
-};
-
-int snd_usb_power_domain_set(struct snd_usb_audio *chip,
- struct snd_usb_power_domain *pd,
- unsigned char state);
-struct snd_usb_power_domain *
-snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
- unsigned char id);
-
#ifdef CONFIG_PM
int snd_usb_autoresume(struct snd_usb_audio *chip);
void snd_usb_autosuspend(struct snd_usb_audio *chip);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index c50e86fe9bcc..fffd7cccce2c 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -19,7 +19,6 @@
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
-#include <linux/bits.h>
#include <sound/control.h>
#include <sound/core.h>
@@ -670,133 +669,15 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
}
/*
- * CM6206 registers from the CM6206 datasheet rev 2.1
+ * C-Media CM6206 is based on CM106 with two additional
+ * registers that are not documented in the data sheet.
+ * Values here are chosen based on sniffing USB traffic
+ * under Windows.
*/
-#define CM6206_REG0_DMA_MASTER BIT(15)
-#define CM6206_REG0_SPDIFO_RATE_48K (2 << 12)
-#define CM6206_REG0_SPDIFO_RATE_96K (7 << 12)
-/* Bit 4 thru 11 is the S/PDIF category code */
-#define CM6206_REG0_SPDIFO_CAT_CODE_GENERAL (0 << 4)
-#define CM6206_REG0_SPDIFO_EMPHASIS_CD BIT(3)
-#define CM6206_REG0_SPDIFO_COPYRIGHT_NA BIT(2)
-#define CM6206_REG0_SPDIFO_NON_AUDIO BIT(1)
-#define CM6206_REG0_SPDIFO_PRO_FORMAT BIT(0)
-
-#define CM6206_REG1_TEST_SEL_CLK BIT(14)
-#define CM6206_REG1_PLLBIN_EN BIT(13)
-#define CM6206_REG1_SOFT_MUTE_EN BIT(12)
-#define CM6206_REG1_GPIO4_OUT BIT(11)
-#define CM6206_REG1_GPIO4_OE BIT(10)
-#define CM6206_REG1_GPIO3_OUT BIT(9)
-#define CM6206_REG1_GPIO3_OE BIT(8)
-#define CM6206_REG1_GPIO2_OUT BIT(7)
-#define CM6206_REG1_GPIO2_OE BIT(6)
-#define CM6206_REG1_GPIO1_OUT BIT(5)
-#define CM6206_REG1_GPIO1_OE BIT(4)
-#define CM6206_REG1_SPDIFO_INVALID BIT(3)
-#define CM6206_REG1_SPDIF_LOOP_EN BIT(2)
-#define CM6206_REG1_SPDIFO_DIS BIT(1)
-#define CM6206_REG1_SPDIFI_MIX BIT(0)
-
-#define CM6206_REG2_DRIVER_ON BIT(15)
-#define CM6206_REG2_HEADP_SEL_SIDE_CHANNELS (0 << 13)
-#define CM6206_REG2_HEADP_SEL_SURROUND_CHANNELS (1 << 13)
-#define CM6206_REG2_HEADP_SEL_CENTER_SUBW (2 << 13)
-#define CM6206_REG2_HEADP_SEL_FRONT_CHANNELS (3 << 13)
-#define CM6206_REG2_MUTE_HEADPHONE_RIGHT BIT(12)
-#define CM6206_REG2_MUTE_HEADPHONE_LEFT BIT(11)
-#define CM6206_REG2_MUTE_REAR_SURROUND_RIGHT BIT(10)
-#define CM6206_REG2_MUTE_REAR_SURROUND_LEFT BIT(9)
-#define CM6206_REG2_MUTE_SIDE_SURROUND_RIGHT BIT(8)
-#define CM6206_REG2_MUTE_SIDE_SURROUND_LEFT BIT(7)
-#define CM6206_REG2_MUTE_SUBWOOFER BIT(6)
-#define CM6206_REG2_MUTE_CENTER BIT(5)
-#define CM6206_REG2_MUTE_RIGHT_FRONT BIT(3)
-#define CM6206_REG2_MUTE_LEFT_FRONT BIT(3)
-#define CM6206_REG2_EN_BTL BIT(2)
-#define CM6206_REG2_MCUCLKSEL_1_5_MHZ (0)
-#define CM6206_REG2_MCUCLKSEL_3_MHZ (1)
-#define CM6206_REG2_MCUCLKSEL_6_MHZ (2)
-#define CM6206_REG2_MCUCLKSEL_12_MHZ (3)
-
-/* Bit 11..13 sets the sensitivity to FLY tuner volume control VP/VD signal */
-#define CM6206_REG3_FLYSPEED_DEFAULT (2 << 11)
-#define CM6206_REG3_VRAP25EN BIT(10)
-#define CM6206_REG3_MSEL1 BIT(9)
-#define CM6206_REG3_SPDIFI_RATE_44_1K BIT(0 << 7)
-#define CM6206_REG3_SPDIFI_RATE_48K BIT(2 << 7)
-#define CM6206_REG3_SPDIFI_RATE_32K BIT(3 << 7)
-#define CM6206_REG3_PINSEL BIT(6)
-#define CM6206_REG3_FOE BIT(5)
-#define CM6206_REG3_ROE BIT(4)
-#define CM6206_REG3_CBOE BIT(3)
-#define CM6206_REG3_LOSE BIT(2)
-#define CM6206_REG3_HPOE BIT(1)
-#define CM6206_REG3_SPDIFI_CANREC BIT(0)
-
-#define CM6206_REG5_DA_RSTN BIT(13)
-#define CM6206_REG5_AD_RSTN BIT(12)
-#define CM6206_REG5_SPDIFO_AD2SPDO BIT(12)
-#define CM6206_REG5_SPDIFO_SEL_FRONT (0 << 9)
-#define CM6206_REG5_SPDIFO_SEL_SIDE_SUR (1 << 9)
-#define CM6206_REG5_SPDIFO_SEL_CEN_LFE (2 << 9)
-#define CM6206_REG5_SPDIFO_SEL_REAR_SUR (3 << 9)
-#define CM6206_REG5_CODECM BIT(8)
-#define CM6206_REG5_EN_HPF BIT(7)
-#define CM6206_REG5_T_SEL_DSDA4 BIT(6)
-#define CM6206_REG5_T_SEL_DSDA3 BIT(5)
-#define CM6206_REG5_T_SEL_DSDA2 BIT(4)
-#define CM6206_REG5_T_SEL_DSDA1 BIT(3)
-#define CM6206_REG5_T_SEL_DSDAD_NORMAL 0
-#define CM6206_REG5_T_SEL_DSDAD_FRONT 4
-#define CM6206_REG5_T_SEL_DSDAD_S_SURROUND 5
-#define CM6206_REG5_T_SEL_DSDAD_CEN_LFE 6
-#define CM6206_REG5_T_SEL_DSDAD_R_SURROUND 7
-
static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
{
int err = 0, reg;
- int val[] = {
- /*
- * Values here are chosen based on sniffing USB traffic
- * under Windows.
- *
- * REG0: DAC is master, sample rate 48kHz, no copyright
- */
- CM6206_REG0_SPDIFO_RATE_48K |
- CM6206_REG0_SPDIFO_COPYRIGHT_NA,
- /*
- * REG1: PLL binary search enable, soft mute enable.
- */
- CM6206_REG1_PLLBIN_EN |
- CM6206_REG1_SOFT_MUTE_EN |
- /*
- * REG2: enable output drivers,
- * select front channels to the headphone output,
- * then mute the headphone channels, run the MCU
- * at 1.5 MHz.
- */
- CM6206_REG2_DRIVER_ON |
- CM6206_REG2_HEADP_SEL_FRONT_CHANNELS |
- CM6206_REG2_MUTE_HEADPHONE_RIGHT |
- CM6206_REG2_MUTE_HEADPHONE_LEFT,
- /*
- * REG3: default flyspeed, set 2.5V mic bias
- * enable all line out ports and enable SPDIF
- */
- CM6206_REG3_FLYSPEED_DEFAULT |
- CM6206_REG3_VRAP25EN |
- CM6206_REG3_FOE |
- CM6206_REG3_ROE |
- CM6206_REG3_CBOE |
- CM6206_REG3_LOSE |
- CM6206_REG3_HPOE |
- CM6206_REG3_SPDIFI_CANREC,
- /* REG4 is just a bunch of GPIO lines */
- 0x0000,
- /* REG5: de-assert AD/DA reset signals */
- CM6206_REG5_DA_RSTN |
- CM6206_REG5_AD_RSTN };
+ int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]);
@@ -1333,7 +1214,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
if (err < 0)
return err;
- msleep(20); /* Delay needed after setting the interface */
+ mdelay(20); /* Delay needed after setting the interface */
/* Vendor mode switch cmd is required. */
if (fmt->formats & SNDRV_PCM_FMTBIT_DSD_U32_BE) {
@@ -1354,7 +1235,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
return err;
}
- msleep(20);
+ mdelay(20);
}
return 0;
}
@@ -1401,7 +1282,7 @@ void snd_usb_set_interface_quirk(struct usb_device *dev)
switch (USB_ID_VENDOR(chip->usb_id)) {
case 0x23ba: /* Playback Design */
case 0x0644: /* TEAC Corp. */
- msleep(50);
+ mdelay(50);
break;
}
}
@@ -1421,7 +1302,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
*/
if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
+ mdelay(20);
/*
* "TEAC Corp." products need a 20ms delay after each
@@ -1429,14 +1310,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
*/
if (USB_ID_VENDOR(chip->usb_id) == 0x0644 &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
+ mdelay(20);
/* ITF-USB DSD based DACs functionality need a delay
* after each class compliant request
*/
if (is_itf_usb_dsd_dac(chip->usb_id)
&& (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
+ mdelay(20);
/* Zoom R16/24, Logitech H650e, Jabra 550a needs a tiny delay here,
* otherwise requests like get/set frequency return as failed despite
@@ -1446,7 +1327,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
chip->usb_id == USB_ID(0x046d, 0x0a46) ||
chip->usb_id == USB_ID(0x0b0e, 0x0349)) &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- usleep_range(1000, 2000);
+ mdelay(1);
}
/*
@@ -1565,7 +1446,6 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
*/
switch (USB_ID_VENDOR(chip->usb_id)) {
case 0x20b1: /* XMOS based devices */
- case 0x152a: /* Thesycon devices */
case 0x25ce: /* Mytek devices */
if (fp->dsd_raw)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
@@ -1577,37 +1457,3 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
return 0;
}
-
-void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
- struct audioformat *fp,
- int stream)
-{
- switch (chip->usb_id) {
- case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
- /* Optoplay sets the sample rate attribute although
- * it seems not supporting it in fact.
- */
- fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
- case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
- /* doesn't set the sample rate attribute, but supports it */
- fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
- case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
- case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
- case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
- an older model 77d:223) */
- /*
- * plantronics headset and Griffin iMic have set adaptive-in
- * although it's really not...
- */
- fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
- else
- fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
- break;
- }
-}
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 283ee46ff43c..192ff5ce9452 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -41,8 +41,4 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
struct audioformat *fp,
unsigned int sample_bytes);
-void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
- struct audioformat *fp,
- int stream);
-
#endif /* __USBAUDIO_QUIRKS_H */
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 67cf849aa16b..8e9548bc1f1a 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -20,7 +20,6 @@
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/usb/audio-v3.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -37,7 +36,6 @@
#include "format.h"
#include "clock.h"
#include "stream.h"
-#include "power.h"
/*
* free a substream
@@ -54,7 +52,6 @@ static void free_substream(struct snd_usb_substream *subs)
kfree(fp);
}
kfree(subs->rate_list.list);
- kfree(subs->str_pd);
}
@@ -84,8 +81,7 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
static void snd_usb_init_substream(struct snd_usb_stream *as,
int stream,
- struct audioformat *fp,
- struct snd_usb_power_domain *pd)
+ struct audioformat *fp)
{
struct snd_usb_substream *subs = &as->substream[stream];
@@ -109,15 +105,6 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
subs->ep_num = fp->endpoint;
if (fp->channels > subs->channels_max)
subs->channels_max = fp->channels;
-
- if (pd) {
- subs->str_pd = pd;
- /* Initialize Power Domain to idle status D1 */
- snd_usb_power_domain_set(subs->stream->chip, pd,
- UAC3_PD_STATE_D1);
- }
-
- snd_usb_preallocate_buffer(subs);
}
/* kctl callbacks for usb-audio channel maps */
@@ -324,153 +311,6 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
return chmap;
}
-/* UAC3 device stores channels information in Cluster Descriptors */
-static struct
-snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
- *cluster)
-{
- unsigned int channels = cluster->bNrChannels;
- struct snd_pcm_chmap_elem *chmap;
- void *p = cluster;
- int len, c;
-
- if (channels > ARRAY_SIZE(chmap->map))
- return NULL;
-
- chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
- if (!chmap)
- return NULL;
-
- len = le16_to_cpu(cluster->wLength);
- c = 0;
- p += sizeof(struct uac3_cluster_header_descriptor);
-
- while (((p - (void *)cluster) < len) && (c < channels)) {
- struct uac3_cluster_segment_descriptor *cs_desc = p;
- u16 cs_len;
- u8 cs_type;
-
- cs_len = le16_to_cpu(cs_desc->wLength);
- cs_type = cs_desc->bSegmentType;
-
- if (cs_type == UAC3_CHANNEL_INFORMATION) {
- struct uac3_cluster_information_segment_descriptor *is = p;
- unsigned char map;
-
- /*
- * TODO: this conversion is not complete, update it
- * after adding UAC3 values to asound.h
- */
- switch (is->bChRelationship) {
- case UAC3_CH_MONO:
- map = SNDRV_CHMAP_MONO;
- break;
- case UAC3_CH_LEFT:
- case UAC3_CH_FRONT_LEFT:
- case UAC3_CH_HEADPHONE_LEFT:
- map = SNDRV_CHMAP_FL;
- break;
- case UAC3_CH_RIGHT:
- case UAC3_CH_FRONT_RIGHT:
- case UAC3_CH_HEADPHONE_RIGHT:
- map = SNDRV_CHMAP_FR;
- break;
- case UAC3_CH_FRONT_CENTER:
- map = SNDRV_CHMAP_FC;
- break;
- case UAC3_CH_FRONT_LEFT_OF_CENTER:
- map = SNDRV_CHMAP_FLC;
- break;
- case UAC3_CH_FRONT_RIGHT_OF_CENTER:
- map = SNDRV_CHMAP_FRC;
- break;
- case UAC3_CH_SIDE_LEFT:
- map = SNDRV_CHMAP_SL;
- break;
- case UAC3_CH_SIDE_RIGHT:
- map = SNDRV_CHMAP_SR;
- break;
- case UAC3_CH_BACK_LEFT:
- map = SNDRV_CHMAP_RL;
- break;
- case UAC3_CH_BACK_RIGHT:
- map = SNDRV_CHMAP_RR;
- break;
- case UAC3_CH_BACK_CENTER:
- map = SNDRV_CHMAP_RC;
- break;
- case UAC3_CH_BACK_LEFT_OF_CENTER:
- map = SNDRV_CHMAP_RLC;
- break;
- case UAC3_CH_BACK_RIGHT_OF_CENTER:
- map = SNDRV_CHMAP_RRC;
- break;
- case UAC3_CH_TOP_CENTER:
- map = SNDRV_CHMAP_TC;
- break;
- case UAC3_CH_TOP_FRONT_LEFT:
- map = SNDRV_CHMAP_TFL;
- break;
- case UAC3_CH_TOP_FRONT_RIGHT:
- map = SNDRV_CHMAP_TFR;
- break;
- case UAC3_CH_TOP_FRONT_CENTER:
- map = SNDRV_CHMAP_TFC;
- break;
- case UAC3_CH_TOP_FRONT_LOC:
- map = SNDRV_CHMAP_TFLC;
- break;
- case UAC3_CH_TOP_FRONT_ROC:
- map = SNDRV_CHMAP_TFRC;
- break;
- case UAC3_CH_TOP_SIDE_LEFT:
- map = SNDRV_CHMAP_TSL;
- break;
- case UAC3_CH_TOP_SIDE_RIGHT:
- map = SNDRV_CHMAP_TSR;
- break;
- case UAC3_CH_TOP_BACK_LEFT:
- map = SNDRV_CHMAP_TRL;
- break;
- case UAC3_CH_TOP_BACK_RIGHT:
- map = SNDRV_CHMAP_TRR;
- break;
- case UAC3_CH_TOP_BACK_CENTER:
- map = SNDRV_CHMAP_TRC;
- break;
- case UAC3_CH_BOTTOM_CENTER:
- map = SNDRV_CHMAP_BC;
- break;
- case UAC3_CH_LOW_FREQUENCY_EFFECTS:
- map = SNDRV_CHMAP_LFE;
- break;
- case UAC3_CH_LFE_LEFT:
- map = SNDRV_CHMAP_LLFE;
- break;
- case UAC3_CH_LFE_RIGHT:
- map = SNDRV_CHMAP_RLFE;
- break;
- case UAC3_CH_RELATIONSHIP_UNDEFINED:
- default:
- map = SNDRV_CHMAP_UNKNOWN;
- break;
- }
- chmap->map[c++] = map;
- }
- p += cs_len;
- }
-
- if (channels < c)
- pr_err("%s: channel number mismatch\n", __func__);
-
- chmap->channels = channels;
-
- for (; c < channels; c++)
- chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
-
- return chmap;
-}
-
/*
* add this endpoint to the chip instance.
* if a stream with the same endpoint already exists, append to it.
@@ -478,11 +318,9 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
* fmt_list and will be freed on the chip instance release. do not free
* fp or do remove it from the substream fmt_list to avoid double-free.
*/
-static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
- int stream,
- struct audioformat *fp,
- struct snd_usb_power_domain *pd)
-
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+ int stream,
+ struct audioformat *fp)
{
struct snd_usb_stream *as;
struct snd_usb_substream *subs;
@@ -510,7 +348,7 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
err = snd_pcm_new_stream(as->pcm, stream, 1);
if (err < 0)
return err;
- snd_usb_init_substream(as, stream, fp, pd);
+ snd_usb_init_substream(as, stream, fp);
return add_chmap(as->pcm, stream, subs);
}
@@ -538,7 +376,7 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
else
strcpy(pcm->name, "USB Audio");
- snd_usb_init_substream(as, stream, fp, pd);
+ snd_usb_init_substream(as, stream, fp);
/*
* Keep using head insertion for M-Audio Audiophile USB (tm) which has a
@@ -556,21 +394,6 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
return add_chmap(pcm, stream, &as->substream[stream]);
}
-int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
- int stream,
- struct audioformat *fp)
-{
- return __snd_usb_add_audio_stream(chip, stream, fp, NULL);
-}
-
-static int snd_usb_add_audio_stream_v3(struct snd_usb_audio *chip,
- int stream,
- struct audioformat *fp,
- struct snd_usb_power_domain *pd)
-{
- return __snd_usb_add_audio_stream(chip, stream, fp, pd);
-}
-
static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
struct usb_host_interface *alts,
int protocol, int iface_no)
@@ -605,7 +428,7 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
if (protocol == UAC_VERSION_1) {
attributes = csep->bmAttributes;
- } else if (protocol == UAC_VERSION_2) {
+ } else {
struct uac2_iso_endpoint_descriptor *csep2 =
(struct uac2_iso_endpoint_descriptor *) csep;
@@ -614,13 +437,6 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
/* emulate the endpoint attributes of a v1 device */
if (csep2->bmControls & UAC2_CONTROL_PITCH)
attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
- } else { /* UAC_VERSION_3 */
- struct uac3_iso_endpoint_descriptor *csep3 =
- (struct uac3_iso_endpoint_descriptor *) csep;
-
- /* emulate the endpoint attributes of a v1 device */
- if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
- attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
}
return attributes;
@@ -645,11 +461,10 @@ snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
return NULL;
}
-static void *
-snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
- int terminal_id)
+static struct uac2_output_terminal_descriptor *
+ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+ int terminal_id)
{
- /* OK to use with both UAC2 and UAC3 */
struct uac2_output_terminal_descriptor *term = NULL;
while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
@@ -662,416 +477,6 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
return NULL;
}
-static struct audioformat *
-audio_format_alloc_init(struct snd_usb_audio *chip,
- struct usb_host_interface *alts,
- int protocol, int iface_no, int altset_idx,
- int altno, int num_channels, int clock)
-{
- struct audioformat *fp;
-
- fp = kzalloc(sizeof(*fp), GFP_KERNEL);
- if (!fp)
- return NULL;
-
- fp->iface = iface_no;
- fp->altsetting = altno;
- fp->altset_idx = altset_idx;
- fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
- fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
- fp->datainterval = snd_usb_parse_datainterval(chip, alts);
- fp->protocol = protocol;
- fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
- fp->channels = num_channels;
- if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH)
- fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
- * (fp->maxpacksize & 0x7ff);
- fp->clock = clock;
- INIT_LIST_HEAD(&fp->list);
-
- return fp;
-}
-
-static struct audioformat *
-snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
- struct usb_host_interface *alts,
- int protocol, int iface_no, int altset_idx,
- int altno, int stream, int bm_quirk)
-{
- struct usb_device *dev = chip->dev;
- struct uac_format_type_i_continuous_descriptor *fmt;
- unsigned int num_channels = 0, chconfig = 0;
- struct audioformat *fp;
- int clock = 0;
- u64 format;
-
- /* get audio formats */
- if (protocol == UAC_VERSION_1) {
- struct uac1_as_header_descriptor *as =
- snd_usb_find_csint_desc(alts->extra, alts->extralen,
- NULL, UAC_AS_GENERAL);
- struct uac_input_terminal_descriptor *iterm;
-
- if (!as) {
- dev_err(&dev->dev,
- "%u:%d : UAC_AS_GENERAL descriptor not found\n",
- iface_no, altno);
- return NULL;
- }
-
- if (as->bLength < sizeof(*as)) {
- dev_err(&dev->dev,
- "%u:%d : invalid UAC_AS_GENERAL desc\n",
- iface_no, altno);
- return NULL;
- }
-
- format = le16_to_cpu(as->wFormatTag); /* remember the format value */
-
- iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (iterm) {
- num_channels = iterm->bNrChannels;
- chconfig = le16_to_cpu(iterm->wChannelConfig);
- }
- } else { /* UAC_VERSION_2 */
- struct uac2_input_terminal_descriptor *input_term;
- struct uac2_output_terminal_descriptor *output_term;
- struct uac2_as_header_descriptor *as =
- snd_usb_find_csint_desc(alts->extra, alts->extralen,
- NULL, UAC_AS_GENERAL);
-
- if (!as) {
- dev_err(&dev->dev,
- "%u:%d : UAC_AS_GENERAL descriptor not found\n",
- iface_no, altno);
- return NULL;
- }
-
- if (as->bLength < sizeof(*as)) {
- dev_err(&dev->dev,
- "%u:%d : invalid UAC_AS_GENERAL desc\n",
- iface_no, altno);
- return NULL;
- }
-
- num_channels = as->bNrChannels;
- format = le32_to_cpu(as->bmFormats);
- chconfig = le32_to_cpu(as->bmChannelConfig);
-
- /*
- * lookup the terminal associated to this interface
- * to extract the clock
- */
- input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (input_term) {
- clock = input_term->bCSourceID;
- if (!chconfig && (num_channels == input_term->bNrChannels))
- chconfig = le32_to_cpu(input_term->bmChannelConfig);
- goto found_clock;
- }
-
- output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (output_term) {
- clock = output_term->bCSourceID;
- goto found_clock;
- }
-
- dev_err(&dev->dev,
- "%u:%d : bogus bTerminalLink %d\n",
- iface_no, altno, as->bTerminalLink);
- return NULL;
- }
-
-found_clock:
- /* get format type */
- fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen,
- NULL, UAC_FORMAT_TYPE);
- if (!fmt) {
- dev_err(&dev->dev,
- "%u:%d : no UAC_FORMAT_TYPE desc\n",
- iface_no, altno);
- return NULL;
- }
- if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8))
- || ((protocol == UAC_VERSION_2) &&
- (fmt->bLength < 6))) {
- dev_err(&dev->dev,
- "%u:%d : invalid UAC_FORMAT_TYPE desc\n",
- iface_no, altno);
- return NULL;
- }
-
- /*
- * Blue Microphones workaround: The last altsetting is
- * identical with the previous one, except for a larger
- * packet size, but is actually a mislabeled two-channel
- * setting; ignore it.
- *
- * Part 2: analyze quirk flag and format
- */
- if (bm_quirk && fmt->bNrChannels == 1 && fmt->bSubframeSize == 2)
- return NULL;
-
- fp = audio_format_alloc_init(chip, alts, protocol, iface_no,
- altset_idx, altno, num_channels, clock);
- if (!fp)
- return ERR_PTR(-ENOMEM);
-
- fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol,
- iface_no);
-
- /* some quirks for attributes here */
- snd_usb_audioformat_attributes_quirk(chip, fp, stream);
-
- /* ok, let's parse further... */
- if (snd_usb_parse_audio_format(chip, fp, format,
- fmt, stream) < 0) {
- kfree(fp->rate_table);
- kfree(fp);
- return NULL;
- }
-
- /* Create chmap */
- if (fp->channels != num_channels)
- chconfig = 0;
-
- fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
-
- return fp;
-}
-
-static struct audioformat *
-snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
- struct usb_host_interface *alts,
- struct snd_usb_power_domain **pd_out,
- int iface_no, int altset_idx,
- int altno, int stream)
-{
- struct usb_device *dev = chip->dev;
- struct uac3_input_terminal_descriptor *input_term;
- struct uac3_output_terminal_descriptor *output_term;
- struct uac3_cluster_header_descriptor *cluster;
- struct uac3_as_header_descriptor *as = NULL;
- struct uac3_hc_descriptor_header hc_header;
- struct snd_pcm_chmap_elem *chmap;
- struct snd_usb_power_domain *pd;
- unsigned char badd_profile;
- u64 badd_formats = 0;
- unsigned int num_channels;
- struct audioformat *fp;
- u16 cluster_id, wLength;
- int clock = 0;
- int err;
-
- badd_profile = chip->badd_profile;
-
- if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
- unsigned int maxpacksize =
- le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-
- switch (maxpacksize) {
- default:
- dev_err(&dev->dev,
- "%u:%d : incorrect wMaxPacketSize for BADD profile\n",
- iface_no, altno);
- return NULL;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
- badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
- num_channels = 1;
- break;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
- badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
- num_channels = 1;
- break;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
- badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
- num_channels = 2;
- break;
- case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
- case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
- badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
- num_channels = 2;
- break;
- }
-
- chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
- if (!chmap)
- return ERR_PTR(-ENOMEM);
-
- if (num_channels == 1) {
- chmap->map[0] = SNDRV_CHMAP_MONO;
- } else {
- chmap->map[0] = SNDRV_CHMAP_FL;
- chmap->map[1] = SNDRV_CHMAP_FR;
- }
-
- chmap->channels = num_channels;
- clock = UAC3_BADD_CS_ID9;
- goto found_clock;
- }
-
- as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
- NULL, UAC_AS_GENERAL);
- if (!as) {
- dev_err(&dev->dev,
- "%u:%d : UAC_AS_GENERAL descriptor not found\n",
- iface_no, altno);
- return NULL;
- }
-
- if (as->bLength < sizeof(*as)) {
- dev_err(&dev->dev,
- "%u:%d : invalid UAC_AS_GENERAL desc\n",
- iface_no, altno);
- return NULL;
- }
-
- cluster_id = le16_to_cpu(as->wClusterDescrID);
- if (!cluster_id) {
- dev_err(&dev->dev,
- "%u:%d : no cluster descriptor\n",
- iface_no, altno);
- return NULL;
- }
-
- /*
- * Get number of channels and channel map through
- * High Capability Cluster Descriptor
- *
- * First step: get High Capability header and
- * read size of Cluster Descriptor
- */
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0),
- UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- cluster_id,
- snd_usb_ctrl_intf(chip),
- &hc_header, sizeof(hc_header));
- if (err < 0)
- return ERR_PTR(err);
- else if (err != sizeof(hc_header)) {
- dev_err(&dev->dev,
- "%u:%d : can't get High Capability descriptor\n",
- iface_no, altno);
- return ERR_PTR(-EIO);
- }
-
- /*
- * Second step: allocate needed amount of memory
- * and request Cluster Descriptor
- */
- wLength = le16_to_cpu(hc_header.wLength);
- cluster = kzalloc(wLength, GFP_KERNEL);
- if (!cluster)
- return ERR_PTR(-ENOMEM);
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0),
- UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- cluster_id,
- snd_usb_ctrl_intf(chip),
- cluster, wLength);
- if (err < 0) {
- kfree(cluster);
- return ERR_PTR(err);
- } else if (err != wLength) {
- dev_err(&dev->dev,
- "%u:%d : can't get Cluster Descriptor\n",
- iface_no, altno);
- kfree(cluster);
- return ERR_PTR(-EIO);
- }
-
- num_channels = cluster->bNrChannels;
- chmap = convert_chmap_v3(cluster);
- kfree(cluster);
-
- /*
- * lookup the terminal associated to this interface
- * to extract the clock
- */
- input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (input_term) {
- clock = input_term->bCSourceID;
- goto found_clock;
- }
-
- output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (output_term) {
- clock = output_term->bCSourceID;
- goto found_clock;
- }
-
- dev_err(&dev->dev, "%u:%d : bogus bTerminalLink %d\n",
- iface_no, altno, as->bTerminalLink);
- kfree(chmap);
- return NULL;
-
-found_clock:
- fp = audio_format_alloc_init(chip, alts, UAC_VERSION_3, iface_no,
- altset_idx, altno, num_channels, clock);
- if (!fp) {
- kfree(chmap);
- return ERR_PTR(-ENOMEM);
- }
-
- fp->chmap = chmap;
-
- if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
- fp->attributes = 0; /* No attributes */
-
- fp->fmt_type = UAC_FORMAT_TYPE_I;
- fp->formats = badd_formats;
-
- fp->nr_rates = 0; /* SNDRV_PCM_RATE_CONTINUOUS */
- fp->rate_min = UAC3_BADD_SAMPLING_RATE;
- fp->rate_max = UAC3_BADD_SAMPLING_RATE;
- fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
-
- pd = kzalloc(sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- kfree(fp->rate_table);
- kfree(fp);
- return NULL;
- }
- pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11;
- pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0;
- pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0;
-
- } else {
- fp->attributes = parse_uac_endpoint_attributes(chip, alts,
- UAC_VERSION_3,
- iface_no);
-
- pd = snd_usb_find_power_domain(chip->ctrl_intf,
- as->bTerminalLink);
-
- /* ok, let's parse further... */
- if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
- kfree(pd);
- kfree(fp->chmap);
- kfree(fp->rate_table);
- kfree(fp);
- return NULL;
- }
- }
-
- if (pd)
- *pd_out = pd;
-
- return fp;
-}
-
int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
{
struct usb_device *dev;
@@ -1079,9 +484,11 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
int i, altno, err, stream;
+ unsigned int format = 0, num_channels = 0;
struct audioformat *fp = NULL;
- struct snd_usb_power_domain *pd = NULL;
- int num, protocol;
+ int num, protocol, clock = 0;
+ struct uac_format_type_i_continuous_descriptor *fmt;
+ unsigned int chconfig;
dev = chip->dev;
@@ -1130,58 +537,196 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
protocol <= 2)
protocol = UAC_VERSION_1;
+ chconfig = 0;
+ /* get audio formats */
switch (protocol) {
default:
dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
iface_no, altno, protocol);
protocol = UAC_VERSION_1;
/* fall through */
- case UAC_VERSION_1:
- /* fall through */
+
+ case UAC_VERSION_1: {
+ struct uac1_as_header_descriptor *as =
+ snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+ struct uac_input_terminal_descriptor *iterm;
+
+ if (!as) {
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
+ continue;
+ }
+
+ if (as->bLength < sizeof(*as)) {
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
+ continue;
+ }
+
+ format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+
+ iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (iterm) {
+ num_channels = iterm->bNrChannels;
+ chconfig = le16_to_cpu(iterm->wChannelConfig);
+ }
+
+ break;
+ }
+
case UAC_VERSION_2: {
- int bm_quirk = 0;
-
- /*
- * Blue Microphones workaround: The last altsetting is
- * identical with the previous one, except for a larger
- * packet size, but is actually a mislabeled two-channel
- * setting; ignore it.
- *
- * Part 1: prepare quirk flag
- */
- if (altno == 2 && num == 3 &&
- fp && fp->altsetting == 1 && fp->channels == 1 &&
- fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
- protocol == UAC_VERSION_1 &&
- le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+ struct uac2_input_terminal_descriptor *input_term;
+ struct uac2_output_terminal_descriptor *output_term;
+ struct uac2_as_header_descriptor *as =
+ snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+ if (!as) {
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
+ continue;
+ }
+
+ if (as->bLength < sizeof(*as)) {
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
+ continue;
+ }
+
+ num_channels = as->bNrChannels;
+ format = le32_to_cpu(as->bmFormats);
+ chconfig = le32_to_cpu(as->bmChannelConfig);
+
+ /* lookup the terminal associated to this interface
+ * to extract the clock */
+ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (input_term) {
+ clock = input_term->bCSourceID;
+ if (!chconfig && (num_channels == input_term->bNrChannels))
+ chconfig = le32_to_cpu(input_term->bmChannelConfig);
+ break;
+ }
+
+ output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (output_term) {
+ clock = output_term->bCSourceID;
+ break;
+ }
+
+ dev_err(&dev->dev,
+ "%u:%d : bogus bTerminalLink %d\n",
+ iface_no, altno, as->bTerminalLink);
+ continue;
+ }
+ }
+
+ /* get format type */
+ fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
+ if (!fmt) {
+ dev_err(&dev->dev,
+ "%u:%d : no UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
+ continue;
+ }
+ if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
+ ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
+ continue;
+ }
+
+ /*
+ * Blue Microphones workaround: The last altsetting is identical
+ * with the previous one, except for a larger packet size, but
+ * is actually a mislabeled two-channel setting; ignore it.
+ */
+ if (fmt->bNrChannels == 1 &&
+ fmt->bSubframeSize == 2 &&
+ altno == 2 && num == 3 &&
+ fp && fp->altsetting == 1 && fp->channels == 1 &&
+ fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
+ protocol == UAC_VERSION_1 &&
+ le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
fp->maxpacksize * 2)
- bm_quirk = 1;
+ continue;
- fp = snd_usb_get_audioformat_uac12(chip, alts, protocol,
- iface_no, i, altno,
- stream, bm_quirk);
- break;
+ fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+ if (! fp) {
+ dev_err(&dev->dev, "cannot malloc\n");
+ return -ENOMEM;
}
- case UAC_VERSION_3:
- fp = snd_usb_get_audioformat_uac3(chip, alts, &pd,
- iface_no, i, altno, stream);
+
+ fp->iface = iface_no;
+ fp->altsetting = altno;
+ fp->altset_idx = i;
+ fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+ fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+ fp->datainterval = snd_usb_parse_datainterval(chip, alts);
+ fp->protocol = protocol;
+ fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+ fp->channels = num_channels;
+ if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
+ fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
+ * (fp->maxpacksize & 0x7ff);
+ fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+ fp->clock = clock;
+ INIT_LIST_HEAD(&fp->list);
+
+ /* some quirks for attributes here */
+
+ switch (chip->usb_id) {
+ case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
+ /* Optoplay sets the sample rate attribute although
+ * it seems not supporting it in fact.
+ */
+ fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
+ break;
+ case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+ /* doesn't set the sample rate attribute, but supports it */
+ fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
+ break;
+ case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
+ case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
+ case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+ case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+ an older model 77d:223) */
+ /*
+ * plantronics headset and Griffin iMic have set adaptive-in
+ * although it's really not...
+ */
+ fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
+ else
+ fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
break;
}
- if (!fp)
+ /* ok, let's parse further... */
+ if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) {
+ kfree(fp->rate_table);
+ kfree(fp);
+ fp = NULL;
continue;
- else if (IS_ERR(fp))
- return PTR_ERR(fp);
+ }
- dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
- if (protocol == UAC_VERSION_3)
- err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd);
- else
- err = snd_usb_add_audio_stream(chip, stream, fp);
+ /* Create chmap */
+ if (fp->channels != num_channels)
+ chconfig = 0;
+ fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
+ dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
+ err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
list_del(&fp->list); /* unlink for avoiding double-free */
- kfree(pd);
kfree(fp->rate_table);
kfree(fp->chmap);
kfree(fp);
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b9faeca645fd..1cb6b3e9483c 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -49,8 +49,6 @@ struct snd_usb_audio {
int num_suspended_intf;
int sample_rate_read_error;
- int badd_profile; /* UAC3 BADD profile */
-
struct list_head pcm_list; /* list of pcm streams */
struct list_head ep_list; /* list of audio-related endpoints */
int pcm_devs;
@@ -127,6 +125,4 @@ struct snd_usb_audio_quirk {
int snd_usb_lock_shutdown(struct snd_usb_audio *chip);
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
-extern bool snd_usb_use_vmalloc;
-
#endif /* __USBAUDIO_H */
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 8c394178a385..e118bdca983d 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -46,11 +46,9 @@ MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
-/* driver_info flags */
-#define US122L_FLAG_US144 BIT(0)
-
static int snd_us122l_card_used[SNDRV_CARDS];
+
static int us122l_create_usbmidi(struct snd_card *card)
{
static struct snd_usb_midi_endpoint_info quirk_data = {
@@ -200,7 +198,8 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
if (!us122l->first)
us122l->first = file;
- if (us122l->is_us144) {
+ if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
+ us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
iface = usb_ifnum_to_if(us122l->dev, 0);
usb_autopm_get_interface(iface);
}
@@ -215,7 +214,8 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
struct usb_interface *iface;
snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
- if (us122l->is_us144) {
+ if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
+ us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
iface = usb_ifnum_to_if(us122l->dev, 0);
usb_autopm_put_interface(iface);
}
@@ -378,7 +378,7 @@ out:
static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
unsigned cmd, unsigned long arg)
{
- struct usb_stream_config cfg;
+ struct usb_stream_config *cfg;
struct us122l *us122l = hw->private_data;
struct usb_stream *s;
unsigned min_period_frames;
@@ -388,21 +388,24 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS)
return -ENOTTY;
- if (copy_from_user(&cfg, (void __user *)arg, sizeof(cfg)))
- return -EFAULT;
-
- if (cfg.version != USB_STREAM_INTERFACE_VERSION)
- return -ENXIO;
+ cfg = memdup_user((void *)arg, sizeof(*cfg));
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+ if (cfg->version != USB_STREAM_INTERFACE_VERSION) {
+ err = -ENXIO;
+ goto free;
+ }
high_speed = us122l->dev->speed == USB_SPEED_HIGH;
- if ((cfg.sample_rate != 44100 && cfg.sample_rate != 48000 &&
+ if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000 &&
(!high_speed ||
- (cfg.sample_rate != 88200 && cfg.sample_rate != 96000))) ||
- cfg.frame_size != 6 ||
- cfg.period_frames > 0x3000)
- return -EINVAL;
-
- switch (cfg.sample_rate) {
+ (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) ||
+ cfg->frame_size != 6 ||
+ cfg->period_frames > 0x3000) {
+ err = -EINVAL;
+ goto free;
+ }
+ switch (cfg->sample_rate) {
case 44100:
min_period_frames = 48;
break;
@@ -415,8 +418,10 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
}
if (!high_speed)
min_period_frames <<= 1;
- if (cfg.period_frames < min_period_frames)
- return -EINVAL;
+ if (cfg->period_frames < min_period_frames) {
+ err = -EINVAL;
+ goto free;
+ }
snd_power_wait(hw->card, SNDRV_CTL_POWER_D0);
@@ -425,22 +430,24 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
if (!us122l->master)
us122l->master = file;
else if (us122l->master != file) {
- if (!s || memcmp(&cfg, &s->cfg, sizeof(cfg))) {
+ if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg))) {
err = -EIO;
goto unlock;
}
us122l->slave = file;
}
- if (!s || memcmp(&cfg, &s->cfg, sizeof(cfg)) ||
+ if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg)) ||
s->state == usb_stream_xrun) {
us122l_stop(us122l);
- if (!us122l_start(us122l, cfg.sample_rate, cfg.period_frames))
+ if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames))
err = -EIO;
else
err = 1;
}
unlock:
mutex_unlock(&us122l->mutex);
+free:
+ kfree(cfg);
wake_up_all(&us122l->sk.sleep);
return err;
}
@@ -476,7 +483,8 @@ static bool us122l_create_card(struct snd_card *card)
int err;
struct us122l *us122l = US122L(card);
- if (us122l->is_us144) {
+ if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
+ us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
err = usb_set_interface(us122l->dev, 0, 1);
if (err) {
snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -495,13 +503,15 @@ static bool us122l_create_card(struct snd_card *card)
if (!us122l_start(us122l, 44100, 256))
return false;
- if (us122l->is_us144)
+ if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
+ us122l->dev->descriptor.idProduct == USB_ID_US144MKII)
err = us144_create_usbmidi(card);
else
err = us122l_create_usbmidi(card);
if (err < 0) {
snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err);
- goto stop;
+ us122l_stop(us122l);
+ return false;
}
err = usb_stream_hwdep_new(card);
if (err < 0) {
@@ -510,13 +520,10 @@ static bool us122l_create_card(struct snd_card *card)
list_for_each(p, &us122l->midi_list)
snd_usbmidi_disconnect(p);
- goto stop;
+ us122l_stop(us122l);
+ return false;
}
return true;
-
-stop:
- us122l_stop(us122l);
- return false;
}
static void snd_us122l_free(struct snd_card *card)
@@ -529,8 +536,7 @@ static void snd_us122l_free(struct snd_card *card)
static int usx2y_create_card(struct usb_device *device,
struct usb_interface *intf,
- struct snd_card **cardp,
- unsigned long flags)
+ struct snd_card **cardp)
{
int dev;
struct snd_card *card;
@@ -550,7 +556,6 @@ static int usx2y_create_card(struct usb_device *device,
US122L(card)->dev = device;
mutex_init(&US122L(card)->mutex);
init_waitqueue_head(&US122L(card)->sk.sleep);
- US122L(card)->is_us144 = flags & US122L_FLAG_US144;
INIT_LIST_HEAD(&US122L(card)->midi_list);
strcpy(card->driver, "USB "NAME_ALLCAPS"");
sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
@@ -574,7 +579,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
struct snd_card *card;
int err;
- err = usx2y_create_card(device, intf, &card, device_id->driver_info);
+ err = usx2y_create_card(device, intf, &card);
if (err < 0)
return err;
@@ -602,8 +607,9 @@ static int snd_us122l_probe(struct usb_interface *intf,
struct snd_card *card;
int err;
- if (id->driver_info & US122L_FLAG_US144 &&
- device->speed == USB_SPEED_HIGH) {
+ if ((device->descriptor.idProduct == USB_ID_US144 ||
+ device->descriptor.idProduct == USB_ID_US144MKII)
+ && device->speed == USB_SPEED_HIGH) {
snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
return -ENODEV;
}
@@ -697,7 +703,8 @@ static int snd_us122l_resume(struct usb_interface *intf)
mutex_lock(&us122l->mutex);
/* needed, doesn't restart without: */
- if (us122l->is_us144) {
+ if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
+ us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
err = usb_set_interface(us122l->dev, 0, 1);
if (err) {
snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -731,7 +738,7 @@ unlock:
return err;
}
-static const struct usb_device_id snd_us122l_usb_id_table[] = {
+static struct usb_device_id snd_us122l_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
@@ -740,8 +747,7 @@ static const struct usb_device_id snd_us122l_usb_id_table[] = {
{ /* US-144 only works at USB1.1! Disable module ehci-hcd. */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
- .idProduct = USB_ID_US144,
- .driver_info = US122L_FLAG_US144
+ .idProduct = USB_ID_US144
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
@@ -751,8 +757,7 @@ static const struct usb_device_id snd_us122l_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
- .idProduct = USB_ID_US144MKII,
- .driver_info = US122L_FLAG_US144
+ .idProduct = USB_ID_US144MKII
},
{ /* terminator */ }
};
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index 3e2a2d0041ee..f263b3f96c86 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -16,8 +16,6 @@ struct us122l {
struct list_head midi_list;
atomic_t mmap_count;
-
- bool is_us144;
};
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 2bbcf4af06dd..f4b3cda412fc 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -198,22 +198,24 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw,
struct snd_hwdep_dsp_image *dsp)
{
struct usX2Ydev *priv = hw->private_data;
- struct usb_device* dev = priv->dev;
- int lret, err;
- char *buf;
-
+ int lret, err = -EINVAL;
snd_printdd( "dsp_load %s\n", dsp->name);
- buf = memdup_user(dsp->image, dsp->length);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
+ if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
+ struct usb_device* dev = priv->dev;
+ char *buf;
- err = usb_set_interface(dev, 0, 1);
- if (err)
- snd_printk(KERN_ERR "usb_set_interface error \n");
- else
- err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000);
- kfree(buf);
+ buf = memdup_user(dsp->image, dsp->length);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ err = usb_set_interface(dev, 0, 1);
+ if (err)
+ snd_printk(KERN_ERR "usb_set_interface error \n");
+ else
+ err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000);
+ kfree(buf);
+ }
if (err)
return err;
if (dsp->index == 1) {
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 56d06566b30c..36812f77ee92 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -365,22 +365,20 @@ static int submit_urbs(struct usb_stream_kernel *sk,
int err;
prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb);
err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC);
- if (err < 0)
- goto report_failure;
-
+ if (err < 0) {
+ snd_printk(KERN_ERR "%i\n", err);
+ return err;
+ }
sk->idle_inurb = sk->completed_inurb;
sk->completed_inurb = inurb;
err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC);
- if (err < 0)
- goto report_failure;
-
+ if (err < 0) {
+ snd_printk(KERN_ERR "%i\n", err);
+ return err;
+ }
sk->idle_outurb = sk->completed_outurb;
sk->completed_outurb = outurb;
return 0;
-
-report_failure:
- snd_printk(KERN_ERR "%i\n", err);
- return err;
}
#ifdef DEBUG_LOOP_BACK