mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
sound updates for v3.10-rc1
Mostly many small changes spread as seen in diffstat in sound/* directory by this update. A significant change in the subsystem level is the introduction of snd_soc_component, which will help more generic handling of SoC and off-SoC components. Also, snd_BUG_ON() macro is enabled unconditionally now due to its misuses, so people might hit kernel warnings (it's a good thing for us). - compress-offload: support for capture by Charles Keepax - HD-audio: codec delay support by Dylan Reid - HD-audio: improvements/fixes in generic parser: better headphone mic and headset mic support, jack_modes hint consolidation, proper beep attach/detachment, generalized power filter controls by David Henningsson, et al - HD-audio: Improved management of HDMI codec pins/converters - HD-audio: Better pin/DAC assignment for VIA codecs - HD-audio: Haswell HDMI workarounds - HD-audio: ALC268 codec support, a few new quirks for Chromebooks - USB: regression fixes: USB-MIDI autopm fix, the recent ISO latency fix by Clemens Ladisch - USB: support for DSD formats by Daniel Mack - USB: A few UAC2 device endian/cock fixes by Eldad Zack - USB: quirks for Emu 192kHz support, Novation Twitch DJ controller, Yamaha THRxx devices - HDSPM: updates for TCO controls by Adrian Knoth - ASoC: Add a snd_soc_component object type for generic handling of SoC and off-SoC components by Kuninori Morimoto, - dmaengine: a large set of cleanups and conversions by Lars-Peter Clausen - ASoC DAPM: performance optimizations from Ryo Tsutsui - ASoC DAPM: support for mixer control sharing by Stephen Warren - ASoC: multiplatform ARM cleanups from Arnd Bergmann - ASoC: new codec drivers for AK5385 and TAS5086 from Daniel Mack -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRg2bUAAoJEGwxgFQ9KSmksasQAIq1ypbylrLA3vf7PUXmL7Jb hMtC5tzasZqJsIZ2fyhiZL8J5yQ78Z5dhjehFWlCbJEaKhsjZVyb67RpuK597b6K Ypa30OghbWuCoKjmaXK9AFTuijTxdefmewIJfgwVMYtgA5rBU70qt96NC/b/UQXk gEPI740i7EFJL2wfcqRpGoKGO1o80yMuKzIj3gHUZMFHYYhPgvVuGt9cCe3cXwLV IBT77PjMoGt1Q7iJQkX4DGlB5n526l1G8a6VptdCou0qyEWfhgSik5I3msNuAXte 1KYE4zj0Rq4xqN28/D/eAF1o3q+X9aiLttGpG0sJLiwGagdWVFaXLyJDMhZxCbwz 1F4k+B8UCucojw3HtNzoIQJezoRX2aHMjlAZ50b416hITkg5VQe5+sJBxpjIJo4I GSmizUiNahDk9jtI/PEGo7yr8CdRTY3v38mdZRGYxyWgJ1a8sNwQwqUdH6A0D/w6 3wMp4Y9Zt8AK/kiWLLWvsDVvwRptqplrXistTvv4v2xVJgvU+klDsDpa5Lz7kG7Z q43RA4o+yWdG6d1hTgMXp7FGwUkcer7WKWEmAZsQmX03Q0zjZqMhfUwVUtaHIx9c 6YipHdVMAJ0sz/dYrKnZ92hbZcXNj/A9zfqYWeFlA/18FCO6u4BXODBup8BLwyUm hfOv+M/q6haNA98GDHS9 =sYiI -----END PGP SIGNATURE----- Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "Mostly many small changes spread as seen in diffstat in sound/* directory by this update. A significant change in the subsystem level is the introduction of snd_soc_component, which will help more generic handling of SoC and off-SoC components. Also, snd_BUG_ON() macro is enabled unconditionally now due to its misuses, so people might hit kernel warnings (it's a good thing for us). - compress-offload: support for capture by Charles Keepax - HD-audio: codec delay support by Dylan Reid - HD-audio: improvements/fixes in generic parser: better headphone mic and headset mic support, jack_modes hint consolidation, proper beep attach/detachment, generalized power filter controls by David Henningsson, et al - HD-audio: Improved management of HDMI codec pins/converters - HD-audio: Better pin/DAC assignment for VIA codecs - HD-audio: Haswell HDMI workarounds - HD-audio: ALC268 codec support, a few new quirks for Chromebooks - USB: regression fixes: USB-MIDI autopm fix, the recent ISO latency fix by Clemens Ladisch - USB: support for DSD formats by Daniel Mack - USB: A few UAC2 device endian/cock fixes by Eldad Zack - USB: quirks for Emu 192kHz support, Novation Twitch DJ controller, Yamaha THRxx devices - HDSPM: updates for TCO controls by Adrian Knoth - ASoC: Add a snd_soc_component object type for generic handling of SoC and off-SoC components by Kuninori Morimoto, - dmaengine: a large set of cleanups and conversions by Lars-Peter Clausen - ASoC DAPM: performance optimizations from Ryo Tsutsui - ASoC DAPM: support for mixer control sharing by Stephen Warren - ASoC: multiplatform ARM cleanups from Arnd Bergmann - ASoC: new codec drivers for AK5385 and TAS5086 from Daniel Mack" * tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (315 commits) ALSA: usb-audio: caiaq: fix endianness bug in snd_usb_caiaq_maschine_dispatch ALSA: asihpi: add format support check in snd_card_asihpi_capture_formats ALSA: pcm_format_to_bits strong-typed conversion ALSA: compress: fix the states to check for allowing read ALSA: hda - Move Thinkpad X220 to use auto parser ALSA: USB: adjust for changed 3.8 USB API ALSA: usb - Avoid unnecessary sample rate changes on USB 2.0 clock sources sound: oss/dmabuf: use dma_map_single ALSA: ali5451: use mdelay instead of large udelay constants ALSA: hda - Add the support for ALC286 codec ALSA: usb-audio: USB quirk for Yamaha THR10C ALSA: usb-audio: USB quirk for Yamaha THR5A ALSA: usb-audio: USB quirk for Yamaha THR10 ALSA: usb-audio: Fix autopm error during probing ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT ALSA: sound kconfig typo ALSA: emu10k1: Fix dock firmware loading ASoC: ux500: forward declare msp_i2s_platform_data ASoC: davinci-mcasp: Add Support BCLK-to-LRCLK ratio for TDM modes ASoC: davinci-pcm, davinci-mcasp: Clean up active_serializers ...
This commit is contained in:
commit
9992ba7232
@ -6164,14 +6164,12 @@ struct _snd_pcm_runtime {
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The macro takes an conditional expression to evaluate.
|
The macro takes an conditional expression to evaluate.
|
||||||
When <constant>CONFIG_SND_DEBUG</constant>, is set, the
|
When <constant>CONFIG_SND_DEBUG</constant>, is set, if the
|
||||||
expression is actually evaluated. If it's non-zero, it shows
|
expression is non-zero, it shows the warning message such as
|
||||||
the warning message such as
|
|
||||||
<computeroutput>BUG? (xxx)</computeroutput>
|
<computeroutput>BUG? (xxx)</computeroutput>
|
||||||
normally followed by stack trace. It returns the evaluated
|
normally followed by stack trace.
|
||||||
value.
|
|
||||||
When no <constant>CONFIG_SND_DEBUG</constant> is set, this
|
In both cases it returns the evaluated value.
|
||||||
macro always returns zero.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
19
Documentation/devicetree/bindings/sound/ak5386.txt
Normal file
19
Documentation/devicetree/bindings/sound/ak5386.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC
|
||||||
|
|
||||||
|
This device has no control interface.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible : "asahi-kasei,ak5386"
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- reset-gpio : a GPIO spec for the reset/power down pin.
|
||||||
|
If specified, it will be deasserted at probe time.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
spdif: ak5386@0 {
|
||||||
|
compatible = "asahi-kasei,ak5386";
|
||||||
|
reset-gpio = <&gpio0 23>;
|
||||||
|
};
|
@ -1,12 +1,22 @@
|
|||||||
NVIDIA Tegra30 AHUB (Audio Hub)
|
NVIDIA Tegra30 AHUB (Audio Hub)
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra30-ahub"
|
- compatible : "nvidia,tegra30-ahub", "nvidia,tegra114-ahub", etc.
|
||||||
- reg : Should contain the register physical address and length for each of
|
- reg : Should contain the register physical address and length for each of
|
||||||
the AHUB's APBIF registers and the AHUB's own registers.
|
the AHUB's register blocks.
|
||||||
|
- Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
|
||||||
|
- Tegra114 requires an additional entry, for the APBIF2 register block.
|
||||||
- interrupts : Should contain AHUB interrupt
|
- interrupts : Should contain AHUB interrupt
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- nvidia,dma-request-selector : A list of the DMA channel specifiers. Each
|
||||||
request selector for the first APBIF channel.
|
entry contains the Tegra DMA controller's phandle and request selector.
|
||||||
|
If a single entry is present, the request selectors for the channels are
|
||||||
|
assumed to be contiguous, and increment from this value.
|
||||||
|
If multiple values are given, one value must be given per channel.
|
||||||
|
- clocks : Must contain an entry for each required entry in clock-names.
|
||||||
|
- clock-names : Must include the following entries:
|
||||||
|
- Tegra30: Requires d_audio, apbif, i2s0, i2s1, i2s2, i2s3, i2s4, dam0,
|
||||||
|
dam1, dam2, spdif_in.
|
||||||
|
- Tegra114: Additionally requires amx, adx.
|
||||||
- ranges : The bus address mapping for the configlink register bus.
|
- ranges : The bus address mapping for the configlink register bus.
|
||||||
Can be empty since the mapping is 1:1.
|
Can be empty since the mapping is 1:1.
|
||||||
- #address-cells : For the configlink bus. Should be <1>;
|
- #address-cells : For the configlink bus. Should be <1>;
|
||||||
@ -25,7 +35,13 @@ ahub@70080000 {
|
|||||||
reg = <0x70080000 0x200 0x70080200 0x100>;
|
reg = <0x70080000 0x200 0x70080200 0x100>;
|
||||||
interrupts = < 0 103 0x04 >;
|
interrupts = < 0 103 0x04 >;
|
||||||
nvidia,dma-request-selector = <&apbdma 1>;
|
nvidia,dma-request-selector = <&apbdma 1>;
|
||||||
|
clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
|
||||||
|
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
|
||||||
|
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
|
||||||
|
<&tegra_car 110>, <&tegra_car 162>;
|
||||||
|
clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||||
|
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||||
|
"spdif_in";
|
||||||
ranges;
|
ranges;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
32
Documentation/devicetree/bindings/sound/ti,tas5086.txt
Normal file
32
Documentation/devicetree/bindings/sound/ti,tas5086.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Texas Instruments TAS5086 6-channel PWM Processor
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible: Should contain "ti,tas5086".
|
||||||
|
- reg: The i2c address. Should contain <0x1b>.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- reset-gpio: A GPIO spec to define which pin is connected to the
|
||||||
|
chip's !RESET pin. If specified, the driver will
|
||||||
|
assert a hardware reset at probe time.
|
||||||
|
|
||||||
|
- ti,charge-period: This property should contain the time in microseconds
|
||||||
|
that closely matches the external single-ended
|
||||||
|
split-capacitor charge period. The hardware chip
|
||||||
|
waits for this period of time before starting the
|
||||||
|
PWM signals. This helps reduce pops and clicks.
|
||||||
|
|
||||||
|
When not specified, the hardware default of 1300ms
|
||||||
|
is retained.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
i2c_bus {
|
||||||
|
tas5086@1b {
|
||||||
|
compatible = "ti,tas5086";
|
||||||
|
reg = <0x1b>;
|
||||||
|
reset-gpio = <&gpio 23 0>;
|
||||||
|
ti,charge-period = <156000>;
|
||||||
|
};
|
||||||
|
};
|
@ -461,11 +461,13 @@ The generic parser supports the following hints:
|
|||||||
the corresponding mixer control, if available
|
the corresponding mixer control, if available
|
||||||
- add_stereo_mix_input (bool): add the stereo mix (analog-loopback
|
- add_stereo_mix_input (bool): add the stereo mix (analog-loopback
|
||||||
mix) to the input mux if available
|
mix) to the input mux if available
|
||||||
- add_out_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
- add_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
||||||
output jack for allowing to change the headphone amp capability
|
I/O jack for allowing to change the headphone amp and mic bias VREF
|
||||||
- add_in_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
capabilities
|
||||||
input jack for allowing to change the mic bias vref
|
|
||||||
- power_down_unused (bool): power down the unused widgets
|
- power_down_unused (bool): power down the unused widgets
|
||||||
|
- add_hp_mic (bool): add the headphone to capture source if possible
|
||||||
|
- hp_mic_detect (bool): enable/disable the hp/mic shared input for a
|
||||||
|
single built-in mic case; default true
|
||||||
- mixer_nid (int): specifies the widget NID of the analog-loopback
|
- mixer_nid (int): specifies the widget NID of the analog-loopback
|
||||||
mixer
|
mixer
|
||||||
|
|
||||||
|
@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
#include <mach/regs-gpio.h>
|
#include <mach/regs-gpio.h>
|
||||||
#include <plat/regs-ac97.h>
|
|
||||||
#include <plat/regs-dma.h>
|
#include <plat/regs-dma.h>
|
||||||
#include <mach/regs-lcd.h>
|
#include <mach/regs-lcd.h>
|
||||||
#include <plat/regs-iis.h>
|
|
||||||
#include <plat/regs-spi.h>
|
#include <plat/regs-spi.h>
|
||||||
|
|
||||||
static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
|
static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
|
||||||
|
@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
#include <mach/regs-gpio.h>
|
#include <mach/regs-gpio.h>
|
||||||
#include <plat/regs-ac97.h>
|
|
||||||
#include <plat/regs-dma.h>
|
#include <plat/regs-dma.h>
|
||||||
#include <mach/regs-lcd.h>
|
#include <mach/regs-lcd.h>
|
||||||
#include <plat/regs-iis.h>
|
|
||||||
#include <plat/regs-spi.h>
|
#include <plat/regs-spi.h>
|
||||||
|
|
||||||
#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
|
#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
|
||||||
|
@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
#include <mach/regs-gpio.h>
|
#include <mach/regs-gpio.h>
|
||||||
#include <plat/regs-ac97.h>
|
|
||||||
#include <plat/regs-dma.h>
|
#include <plat/regs-dma.h>
|
||||||
#include <mach/regs-lcd.h>
|
#include <mach/regs-lcd.h>
|
||||||
#include <plat/regs-iis.h>
|
|
||||||
#include <plat/regs-spi.h>
|
#include <plat/regs-spi.h>
|
||||||
|
|
||||||
static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
|
static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
|
||||||
|
@ -25,10 +25,8 @@
|
|||||||
|
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
#include <mach/regs-gpio.h>
|
#include <mach/regs-gpio.h>
|
||||||
#include <plat/regs-ac97.h>
|
|
||||||
#include <plat/regs-dma.h>
|
#include <plat/regs-dma.h>
|
||||||
#include <mach/regs-lcd.h>
|
#include <mach/regs-lcd.h>
|
||||||
#include <plat/regs-iis.h>
|
|
||||||
#include <plat/regs-spi.h>
|
#include <plat/regs-spi.h>
|
||||||
|
|
||||||
#define MAP(x) { \
|
#define MAP(x) { \
|
||||||
|
@ -146,14 +146,20 @@ struct platform_device s3c_device_camif = {
|
|||||||
|
|
||||||
/* ASOC DMA */
|
/* ASOC DMA */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PLAT_S5P
|
||||||
|
static struct resource samsung_asoc_idma_resource = DEFINE_RES_IRQ(IRQ_I2S0);
|
||||||
|
|
||||||
struct platform_device samsung_asoc_idma = {
|
struct platform_device samsung_asoc_idma = {
|
||||||
.name = "samsung-idma",
|
.name = "samsung-idma",
|
||||||
.id = -1,
|
.id = -1,
|
||||||
|
.num_resources = 1,
|
||||||
|
.resource = &samsung_asoc_idma_resource,
|
||||||
.dev = {
|
.dev = {
|
||||||
.dma_mask = &samsung_device_dma_mask,
|
.dma_mask = &samsung_device_dma_mask,
|
||||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FB */
|
/* FB */
|
||||||
|
|
||||||
|
@ -290,12 +290,14 @@ static const struct reg_default wm5102_reg_default[] = {
|
|||||||
{ 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
|
{ 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
|
||||||
{ 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */
|
{ 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */
|
||||||
{ 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
|
{ 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
|
||||||
|
{ 0x00000179, 0x0000 }, /* R377 - FLL1 Control 7 */
|
||||||
{ 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
|
{ 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
|
||||||
{ 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
|
{ 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
|
||||||
{ 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
|
{ 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
|
||||||
{ 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
|
{ 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
|
||||||
{ 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
|
{ 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
|
||||||
{ 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
|
{ 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
|
||||||
|
{ 0x00000187, 0x0001 }, /* R391 - FLL1 Synchroniser 7 */
|
||||||
{ 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
|
{ 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
|
||||||
{ 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */
|
{ 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */
|
||||||
{ 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */
|
{ 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */
|
||||||
@ -306,12 +308,14 @@ static const struct reg_default wm5102_reg_default[] = {
|
|||||||
{ 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
|
{ 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
|
||||||
{ 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
|
{ 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
|
||||||
{ 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
|
{ 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
|
||||||
|
{ 0x00000199, 0x0000 }, /* R409 - FLL2 Control 7 */
|
||||||
{ 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
|
{ 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
|
||||||
{ 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
|
{ 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
|
||||||
{ 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
|
{ 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
|
||||||
{ 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
|
{ 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
|
||||||
{ 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
|
{ 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
|
||||||
{ 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
|
{ 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
|
||||||
|
{ 0x000001A7, 0x0001 }, /* R423 - FLL2 Synchroniser 7 */
|
||||||
{ 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
|
{ 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
|
||||||
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
|
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
|
||||||
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
|
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
|
||||||
@ -1055,12 +1059,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
|||||||
case ARIZONA_FLL1_CONTROL_6:
|
case ARIZONA_FLL1_CONTROL_6:
|
||||||
case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
|
case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
|
||||||
case ARIZONA_FLL1_NCO_TEST_0:
|
case ARIZONA_FLL1_NCO_TEST_0:
|
||||||
|
case ARIZONA_FLL1_CONTROL_7:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_1:
|
case ARIZONA_FLL1_SYNCHRONISER_1:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_2:
|
case ARIZONA_FLL1_SYNCHRONISER_2:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_3:
|
case ARIZONA_FLL1_SYNCHRONISER_3:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_4:
|
case ARIZONA_FLL1_SYNCHRONISER_4:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_5:
|
case ARIZONA_FLL1_SYNCHRONISER_5:
|
||||||
case ARIZONA_FLL1_SYNCHRONISER_6:
|
case ARIZONA_FLL1_SYNCHRONISER_6:
|
||||||
|
case ARIZONA_FLL1_SYNCHRONISER_7:
|
||||||
case ARIZONA_FLL1_SPREAD_SPECTRUM:
|
case ARIZONA_FLL1_SPREAD_SPECTRUM:
|
||||||
case ARIZONA_FLL1_GPIO_CLOCK:
|
case ARIZONA_FLL1_GPIO_CLOCK:
|
||||||
case ARIZONA_FLL2_CONTROL_1:
|
case ARIZONA_FLL2_CONTROL_1:
|
||||||
@ -1071,12 +1077,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
|||||||
case ARIZONA_FLL2_CONTROL_6:
|
case ARIZONA_FLL2_CONTROL_6:
|
||||||
case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
|
case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
|
||||||
case ARIZONA_FLL2_NCO_TEST_0:
|
case ARIZONA_FLL2_NCO_TEST_0:
|
||||||
|
case ARIZONA_FLL2_CONTROL_7:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_1:
|
case ARIZONA_FLL2_SYNCHRONISER_1:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_2:
|
case ARIZONA_FLL2_SYNCHRONISER_2:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_3:
|
case ARIZONA_FLL2_SYNCHRONISER_3:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_4:
|
case ARIZONA_FLL2_SYNCHRONISER_4:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_5:
|
case ARIZONA_FLL2_SYNCHRONISER_5:
|
||||||
case ARIZONA_FLL2_SYNCHRONISER_6:
|
case ARIZONA_FLL2_SYNCHRONISER_6:
|
||||||
|
case ARIZONA_FLL2_SYNCHRONISER_7:
|
||||||
case ARIZONA_FLL2_SPREAD_SPECTRUM:
|
case ARIZONA_FLL2_SPREAD_SPECTRUM:
|
||||||
case ARIZONA_FLL2_GPIO_CLOCK:
|
case ARIZONA_FLL2_GPIO_CLOCK:
|
||||||
case ARIZONA_MIC_CHARGE_PUMP_1:
|
case ARIZONA_MIC_CHARGE_PUMP_1:
|
||||||
@ -1169,6 +1177,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
|||||||
case ARIZONA_NOISE_GATE_CONTROL:
|
case ARIZONA_NOISE_GATE_CONTROL:
|
||||||
case ARIZONA_PDM_SPK1_CTRL_1:
|
case ARIZONA_PDM_SPK1_CTRL_1:
|
||||||
case ARIZONA_PDM_SPK1_CTRL_2:
|
case ARIZONA_PDM_SPK1_CTRL_2:
|
||||||
|
case ARIZONA_SPK_CTRL_2:
|
||||||
|
case ARIZONA_SPK_CTRL_3:
|
||||||
case ARIZONA_DAC_COMP_1:
|
case ARIZONA_DAC_COMP_1:
|
||||||
case ARIZONA_DAC_COMP_2:
|
case ARIZONA_DAC_COMP_2:
|
||||||
case ARIZONA_DAC_COMP_3:
|
case ARIZONA_DAC_COMP_3:
|
||||||
|
@ -85,12 +85,14 @@
|
|||||||
#define ARIZONA_FLL1_CONTROL_6 0x176
|
#define ARIZONA_FLL1_CONTROL_6 0x176
|
||||||
#define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177
|
#define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177
|
||||||
#define ARIZONA_FLL1_NCO_TEST_0 0x178
|
#define ARIZONA_FLL1_NCO_TEST_0 0x178
|
||||||
|
#define ARIZONA_FLL1_CONTROL_7 0x179
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_1 0x181
|
#define ARIZONA_FLL1_SYNCHRONISER_1 0x181
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_2 0x182
|
#define ARIZONA_FLL1_SYNCHRONISER_2 0x182
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_3 0x183
|
#define ARIZONA_FLL1_SYNCHRONISER_3 0x183
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_4 0x184
|
#define ARIZONA_FLL1_SYNCHRONISER_4 0x184
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_5 0x185
|
#define ARIZONA_FLL1_SYNCHRONISER_5 0x185
|
||||||
#define ARIZONA_FLL1_SYNCHRONISER_6 0x186
|
#define ARIZONA_FLL1_SYNCHRONISER_6 0x186
|
||||||
|
#define ARIZONA_FLL1_SYNCHRONISER_7 0x187
|
||||||
#define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189
|
#define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189
|
||||||
#define ARIZONA_FLL1_GPIO_CLOCK 0x18A
|
#define ARIZONA_FLL1_GPIO_CLOCK 0x18A
|
||||||
#define ARIZONA_FLL2_CONTROL_1 0x191
|
#define ARIZONA_FLL2_CONTROL_1 0x191
|
||||||
@ -101,12 +103,14 @@
|
|||||||
#define ARIZONA_FLL2_CONTROL_6 0x196
|
#define ARIZONA_FLL2_CONTROL_6 0x196
|
||||||
#define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197
|
#define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197
|
||||||
#define ARIZONA_FLL2_NCO_TEST_0 0x198
|
#define ARIZONA_FLL2_NCO_TEST_0 0x198
|
||||||
|
#define ARIZONA_FLL2_CONTROL_7 0x199
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1
|
#define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2
|
#define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3
|
#define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4
|
#define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5
|
#define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5
|
||||||
#define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6
|
#define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6
|
||||||
|
#define ARIZONA_FLL2_SYNCHRONISER_7 0x1A7
|
||||||
#define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9
|
#define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9
|
||||||
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
|
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
|
||||||
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200
|
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200
|
||||||
@ -217,6 +221,8 @@
|
|||||||
#define ARIZONA_PDM_SPK1_CTRL_2 0x491
|
#define ARIZONA_PDM_SPK1_CTRL_2 0x491
|
||||||
#define ARIZONA_PDM_SPK2_CTRL_1 0x492
|
#define ARIZONA_PDM_SPK2_CTRL_1 0x492
|
||||||
#define ARIZONA_PDM_SPK2_CTRL_2 0x493
|
#define ARIZONA_PDM_SPK2_CTRL_2 0x493
|
||||||
|
#define ARIZONA_SPK_CTRL_2 0x4B5
|
||||||
|
#define ARIZONA_SPK_CTRL_3 0x4B6
|
||||||
#define ARIZONA_DAC_COMP_1 0x4DC
|
#define ARIZONA_DAC_COMP_1 0x4DC
|
||||||
#define ARIZONA_DAC_COMP_2 0x4DD
|
#define ARIZONA_DAC_COMP_2 0x4DD
|
||||||
#define ARIZONA_DAC_COMP_3 0x4DE
|
#define ARIZONA_DAC_COMP_3 0x4DE
|
||||||
@ -1681,6 +1687,13 @@
|
|||||||
#define ARIZONA_FLL1_FRC_INTEG_VAL_SHIFT 0 /* FLL1_FRC_INTEG_VAL - [11:0] */
|
#define ARIZONA_FLL1_FRC_INTEG_VAL_SHIFT 0 /* FLL1_FRC_INTEG_VAL - [11:0] */
|
||||||
#define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH 12 /* FLL1_FRC_INTEG_VAL - [11:0] */
|
#define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH 12 /* FLL1_FRC_INTEG_VAL - [11:0] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R377 (0x179) - FLL1 Control 7
|
||||||
|
*/
|
||||||
|
#define ARIZONA_FLL1_GAIN_MASK 0x003c /* FLL1_GAIN */
|
||||||
|
#define ARIZONA_FLL1_GAIN_SHIFT 2 /* FLL1_GAIN */
|
||||||
|
#define ARIZONA_FLL1_GAIN_WIDTH 4 /* FLL1_GAIN */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R385 (0x181) - FLL1 Synchroniser 1
|
* R385 (0x181) - FLL1 Synchroniser 1
|
||||||
*/
|
*/
|
||||||
@ -1727,6 +1740,17 @@
|
|||||||
#define ARIZONA_FLL1_CLK_SYNC_SRC_SHIFT 0 /* FLL1_CLK_SYNC_SRC - [3:0] */
|
#define ARIZONA_FLL1_CLK_SYNC_SRC_SHIFT 0 /* FLL1_CLK_SYNC_SRC - [3:0] */
|
||||||
#define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH 4 /* FLL1_CLK_SYNC_SRC - [3:0] */
|
#define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH 4 /* FLL1_CLK_SYNC_SRC - [3:0] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R391 (0x187) - FLL1 Synchroniser 7
|
||||||
|
*/
|
||||||
|
#define ARIZONA_FLL1_SYNC_GAIN_MASK 0x003c /* FLL1_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL1_SYNC_GAIN_SHIFT 2 /* FLL1_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL1_SYNC_GAIN_WIDTH 4 /* FLL1_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL1_SYNC_BW 0x0001 /* FLL1_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL1_SYNC_BW_MASK 0x0001 /* FLL1_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL1_SYNC_BW_SHIFT 0 /* FLL1_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL1_SYNC_BW_WIDTH 1 /* FLL1_SYNC_BW */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R393 (0x189) - FLL1 Spread Spectrum
|
* R393 (0x189) - FLL1 Spread Spectrum
|
||||||
*/
|
*/
|
||||||
@ -1819,6 +1843,13 @@
|
|||||||
#define ARIZONA_FLL2_FRC_INTEG_VAL_SHIFT 0 /* FLL2_FRC_INTEG_VAL - [11:0] */
|
#define ARIZONA_FLL2_FRC_INTEG_VAL_SHIFT 0 /* FLL2_FRC_INTEG_VAL - [11:0] */
|
||||||
#define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH 12 /* FLL2_FRC_INTEG_VAL - [11:0] */
|
#define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH 12 /* FLL2_FRC_INTEG_VAL - [11:0] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R409 (0x199) - FLL2 Control 7
|
||||||
|
*/
|
||||||
|
#define ARIZONA_FLL2_GAIN_MASK 0x003c /* FLL2_GAIN */
|
||||||
|
#define ARIZONA_FLL2_GAIN_SHIFT 2 /* FLL2_GAIN */
|
||||||
|
#define ARIZONA_FLL2_GAIN_WIDTH 4 /* FLL2_GAIN */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R417 (0x1A1) - FLL2 Synchroniser 1
|
* R417 (0x1A1) - FLL2 Synchroniser 1
|
||||||
*/
|
*/
|
||||||
@ -1865,6 +1896,17 @@
|
|||||||
#define ARIZONA_FLL2_CLK_SYNC_SRC_SHIFT 0 /* FLL2_CLK_SYNC_SRC - [3:0] */
|
#define ARIZONA_FLL2_CLK_SYNC_SRC_SHIFT 0 /* FLL2_CLK_SYNC_SRC - [3:0] */
|
||||||
#define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH 4 /* FLL2_CLK_SYNC_SRC - [3:0] */
|
#define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH 4 /* FLL2_CLK_SYNC_SRC - [3:0] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R423 (0x1A7) - FLL2 Synchroniser 7
|
||||||
|
*/
|
||||||
|
#define ARIZONA_FLL2_SYNC_GAIN_MASK 0x003c /* FLL2_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL2_SYNC_GAIN_SHIFT 2 /* FLL2_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL2_SYNC_GAIN_WIDTH 4 /* FLL2_SYNC_GAIN */
|
||||||
|
#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL2_SYNC_BW_SHIFT 0 /* FLL2_SYNC_BW */
|
||||||
|
#define ARIZONA_FLL2_SYNC_BW_WIDTH 1 /* FLL2_SYNC_BW */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R425 (0x1A9) - FLL2 Spread Spectrum
|
* R425 (0x1A9) - FLL2 Spread Spectrum
|
||||||
*/
|
*/
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#define WM8994_NUM_LDO 2
|
#define WM8994_NUM_LDO 2
|
||||||
#define WM8994_NUM_GPIO 11
|
#define WM8994_NUM_GPIO 11
|
||||||
|
#define WM8994_NUM_AIF 3
|
||||||
|
|
||||||
struct wm8994_ldo_pdata {
|
struct wm8994_ldo_pdata {
|
||||||
/** GPIOs to enable regulator, 0 or less if not available */
|
/** GPIOs to enable regulator, 0 or less if not available */
|
||||||
@ -215,6 +216,13 @@ struct wm8994_pdata {
|
|||||||
* system.
|
* system.
|
||||||
*/
|
*/
|
||||||
bool spkmode_pu;
|
bool spkmode_pu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of channels clocks will be generated for,
|
||||||
|
* useful for systems where and I2S bus with multiple data
|
||||||
|
* lines is mastered.
|
||||||
|
*/
|
||||||
|
int max_channels_clocked[WM8994_NUM_AIF];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -170,6 +170,8 @@ struct uac2_as_header_descriptor {
|
|||||||
__u8 iChannelNames;
|
__u8 iChannelNames;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define UAC2_FORMAT_TYPE_I_RAW_DATA (1 << 31)
|
||||||
|
|
||||||
/* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
|
/* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
|
||||||
|
|
||||||
struct uac2_iso_endpoint_descriptor {
|
struct uac2_iso_endpoint_descriptor {
|
||||||
|
@ -56,8 +56,6 @@ struct snd_compr_runtime {
|
|||||||
u64 buffer_size;
|
u64 buffer_size;
|
||||||
u32 fragment_size;
|
u32 fragment_size;
|
||||||
u32 fragments;
|
u32 fragments;
|
||||||
u64 hw_pointer;
|
|
||||||
u64 app_pointer;
|
|
||||||
u64 total_bytes_available;
|
u64 total_bytes_available;
|
||||||
u64 total_bytes_transferred;
|
u64 total_bytes_transferred;
|
||||||
wait_queue_head_t sleep;
|
wait_queue_head_t sleep;
|
||||||
@ -121,7 +119,7 @@ struct snd_compr_ops {
|
|||||||
int (*trigger)(struct snd_compr_stream *stream, int cmd);
|
int (*trigger)(struct snd_compr_stream *stream, int cmd);
|
||||||
int (*pointer)(struct snd_compr_stream *stream,
|
int (*pointer)(struct snd_compr_stream *stream,
|
||||||
struct snd_compr_tstamp *tstamp);
|
struct snd_compr_tstamp *tstamp);
|
||||||
int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
|
int (*copy)(struct snd_compr_stream *stream, char __user *buf,
|
||||||
size_t count);
|
size_t count);
|
||||||
int (*mmap)(struct snd_compr_stream *stream,
|
int (*mmap)(struct snd_compr_stream *stream,
|
||||||
struct vm_area_struct *vma);
|
struct vm_area_struct *vma);
|
||||||
|
@ -189,7 +189,6 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
|
|||||||
*
|
*
|
||||||
* Add a virtual slave control to the given master element created via
|
* Add a virtual slave control to the given master element created via
|
||||||
* snd_ctl_create_virtual_master() beforehand.
|
* snd_ctl_create_virtual_master() beforehand.
|
||||||
* Returns zero if successful or a negative error code.
|
|
||||||
*
|
*
|
||||||
* All slaves must be the same type (returning the same information
|
* All slaves must be the same type (returning the same information
|
||||||
* via info callback). The function doesn't check it, so it's your
|
* via info callback). The function doesn't check it, so it's your
|
||||||
@ -199,6 +198,8 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
|
|||||||
* at most two channels,
|
* at most two channels,
|
||||||
* logarithmic volume control (dB level) thus no linear volume,
|
* logarithmic volume control (dB level) thus no linear volume,
|
||||||
* master can only attenuate the volume without gain
|
* master can only attenuate the volume without gain
|
||||||
|
*
|
||||||
|
* Return: Zero if successful or a negative error code.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
|
snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
|
||||||
@ -219,6 +220,8 @@ snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
|
|||||||
* When the control peeks the hardware values directly and the value
|
* When the control peeks the hardware values directly and the value
|
||||||
* can be changed by other means than the put callback of the element,
|
* can be changed by other means than the put callback of the element,
|
||||||
* this function should be used to keep the value always up-to-date.
|
* this function should be used to keep the value always up-to-date.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful or a negative error code.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
|
snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
|
||||||
|
@ -229,7 +229,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card,
|
|||||||
* This function uses the card's device pointer to link to the
|
* This function uses the card's device pointer to link to the
|
||||||
* correct &struct device.
|
* correct &struct device.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
static inline int snd_register_device(int type, struct snd_card *card, int dev,
|
static inline int snd_register_device(int type, struct snd_card *card, int dev,
|
||||||
const struct file_operations *f_ops,
|
const struct file_operations *f_ops,
|
||||||
@ -379,18 +379,10 @@ void __snd_printk(unsigned int level, const char *file, int line,
|
|||||||
* snd_BUG_ON - debugging check macro
|
* snd_BUG_ON - debugging check macro
|
||||||
* @cond: condition to evaluate
|
* @cond: condition to evaluate
|
||||||
*
|
*
|
||||||
* When CONFIG_SND_DEBUG is set, this macro evaluates the given condition,
|
* Has the same behavior as WARN_ON when CONFIG_SND_DEBUG is set,
|
||||||
* and call WARN() and returns the value if it's non-zero.
|
* otherwise just evaluates the conditional and returns the value.
|
||||||
*
|
|
||||||
* When CONFIG_SND_DEBUG is not set, this just returns zero, and the given
|
|
||||||
* condition is ignored.
|
|
||||||
*
|
|
||||||
* NOTE: the argument won't be evaluated at all when CONFIG_SND_DEBUG=n.
|
|
||||||
* Thus, don't put any statement that influences on the code behavior,
|
|
||||||
* such as pre/post increment, to the argument of this macro.
|
|
||||||
* If you want to evaluate and give a warning, use standard WARN_ON().
|
|
||||||
*/
|
*/
|
||||||
#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond))
|
#define snd_BUG_ON(cond) WARN_ON((cond))
|
||||||
|
|
||||||
#else /* !CONFIG_SND_DEBUG */
|
#else /* !CONFIG_SND_DEBUG */
|
||||||
|
|
||||||
@ -400,11 +392,11 @@ __printf(2, 3)
|
|||||||
static inline void _snd_printd(int level, const char *format, ...) {}
|
static inline void _snd_printd(int level, const char *format, ...) {}
|
||||||
|
|
||||||
#define snd_BUG() do { } while (0)
|
#define snd_BUG() do { } while (0)
|
||||||
static inline int __snd_bug_on(int cond)
|
|
||||||
{
|
#define snd_BUG_ON(condition) ({ \
|
||||||
return 0;
|
int __ret_warn_on = !!(condition); \
|
||||||
}
|
unlikely(__ret_warn_on); \
|
||||||
#define snd_BUG_ON(cond) __snd_bug_on(0 && (cond)) /* always false */
|
})
|
||||||
|
|
||||||
#endif /* CONFIG_SND_DEBUG */
|
#endif /* CONFIG_SND_DEBUG */
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#define __SOUND_DMAENGINE_PCM_H__
|
#define __SOUND_DMAENGINE_PCM_H__
|
||||||
|
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
#include <linux/dmaengine.h>
|
#include <linux/dmaengine.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,9 +33,6 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
|
|||||||
return DMA_DEV_TO_MEM;
|
return DMA_DEV_TO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data);
|
|
||||||
void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream);
|
|
||||||
|
|
||||||
int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
|
int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
|
||||||
const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
|
const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
|
||||||
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
|
int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||||
@ -42,9 +40,100 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
|
|||||||
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
|
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
|
int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
|
||||||
dma_filter_fn filter_fn, void *filter_data);
|
struct dma_chan *chan);
|
||||||
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
|
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
|
||||||
|
dma_filter_fn filter_fn, void *filter_data);
|
||||||
|
int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
|
||||||
|
void *filter_data);
|
||||||
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
|
struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
|
||||||
|
* @addr: Address of the DAI data source or destination register.
|
||||||
|
* @addr_width: Width of the DAI data source or destination register.
|
||||||
|
* @maxburst: Maximum number of words(note: words, as in units of the
|
||||||
|
* src_addr_width member, not bytes) that can be send to or received from the
|
||||||
|
* DAI in one burst.
|
||||||
|
* @slave_id: Slave requester id for the DMA channel.
|
||||||
|
* @filter_data: Custom DMA channel filter data, this will usually be used when
|
||||||
|
* requesting the DMA channel.
|
||||||
|
*/
|
||||||
|
struct snd_dmaengine_dai_dma_data {
|
||||||
|
dma_addr_t addr;
|
||||||
|
enum dma_slave_buswidth addr_width;
|
||||||
|
u32 maxburst;
|
||||||
|
unsigned int slave_id;
|
||||||
|
void *filter_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void snd_dmaengine_pcm_set_config_from_dai_data(
|
||||||
|
const struct snd_pcm_substream *substream,
|
||||||
|
const struct snd_dmaengine_dai_dma_data *dma_data,
|
||||||
|
struct dma_slave_config *config);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to request the DMA channel using compat_request_channel or
|
||||||
|
* compat_filter_fn if it couldn't be requested through devicetree.
|
||||||
|
*/
|
||||||
|
#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0)
|
||||||
|
/*
|
||||||
|
* Don't try to request the DMA channels through devicetree. This flag only
|
||||||
|
* makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well.
|
||||||
|
*/
|
||||||
|
#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1)
|
||||||
|
/*
|
||||||
|
* The platforms dmaengine driver does not support reporting the amount of
|
||||||
|
* bytes that are still left to transfer.
|
||||||
|
*/
|
||||||
|
#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2)
|
||||||
|
/*
|
||||||
|
* The PCM is half duplex and the DMA channel is shared between capture and
|
||||||
|
* playback.
|
||||||
|
*/
|
||||||
|
#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM
|
||||||
|
* @prepare_slave_config: Callback used to fill in the DMA slave_config for a
|
||||||
|
* PCM substream. Will be called from the PCM drivers hwparams callback.
|
||||||
|
* @compat_request_channel: Callback to request a DMA channel for platforms
|
||||||
|
* which do not use devicetree.
|
||||||
|
* @compat_filter_fn: Will be used as the filter function when requesting a
|
||||||
|
* channel for platforms which do not use devicetree. The filter parameter
|
||||||
|
* will be the DAI's DMA data.
|
||||||
|
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
|
||||||
|
* @prealloc_buffer_size: Size of the preallocated audio buffer.
|
||||||
|
*
|
||||||
|
* Note: If both compat_request_channel and compat_filter_fn are set
|
||||||
|
* compat_request_channel will be used to request the channel and
|
||||||
|
* compat_filter_fn will be ignored. Otherwise the channel will be requested
|
||||||
|
* using dma_request_channel with compat_filter_fn as the filter function.
|
||||||
|
*/
|
||||||
|
struct snd_dmaengine_pcm_config {
|
||||||
|
int (*prepare_slave_config)(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct dma_slave_config *slave_config);
|
||||||
|
struct dma_chan *(*compat_request_channel)(
|
||||||
|
struct snd_soc_pcm_runtime *rtd,
|
||||||
|
struct snd_pcm_substream *substream);
|
||||||
|
dma_filter_fn compat_filter_fn;
|
||||||
|
|
||||||
|
const struct snd_pcm_hardware *pcm_hardware;
|
||||||
|
unsigned int prealloc_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
int snd_dmaengine_pcm_register(struct device *dev,
|
||||||
|
const struct snd_dmaengine_pcm_config *config,
|
||||||
|
unsigned int flags);
|
||||||
|
void snd_dmaengine_pcm_unregister(struct device *dev);
|
||||||
|
|
||||||
|
int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct dma_slave_config *slave_config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1787,6 +1787,7 @@ struct snd_emu10k1 {
|
|||||||
unsigned int next_free_voice;
|
unsigned int next_free_voice;
|
||||||
|
|
||||||
const struct firmware *firmware;
|
const struct firmware *firmware;
|
||||||
|
const struct firmware *dock_fw;
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
unsigned int *saved_ptr;
|
unsigned int *saved_ptr;
|
||||||
|
@ -181,6 +181,8 @@ struct snd_pcm_ops {
|
|||||||
#define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B)
|
#define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B)
|
||||||
#define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40)
|
#define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40)
|
||||||
#define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B)
|
#define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B)
|
||||||
|
#define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8)
|
||||||
|
#define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE)
|
||||||
|
|
||||||
#ifdef SNDRV_LITTLE_ENDIAN
|
#ifdef SNDRV_LITTLE_ENDIAN
|
||||||
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
|
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
|
||||||
@ -659,7 +661,7 @@ static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime
|
|||||||
*
|
*
|
||||||
* Checks whether enough free space is available on the playback buffer.
|
* Checks whether enough free space is available on the playback buffer.
|
||||||
*
|
*
|
||||||
* Returns non-zero if available, or zero if not.
|
* Return: Non-zero if available, or zero if not.
|
||||||
*/
|
*/
|
||||||
static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
|
static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -673,7 +675,7 @@ static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
|
|||||||
*
|
*
|
||||||
* Checks whether enough capture data is available on the capture buffer.
|
* Checks whether enough capture data is available on the capture buffer.
|
||||||
*
|
*
|
||||||
* Returns non-zero if available, or zero if not.
|
* Return: Non-zero if available, or zero if not.
|
||||||
*/
|
*/
|
||||||
static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
|
static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -685,10 +687,10 @@ static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
|
|||||||
* snd_pcm_playback_data - check whether any data exists on the playback buffer
|
* snd_pcm_playback_data - check whether any data exists on the playback buffer
|
||||||
* @substream: the pcm substream instance
|
* @substream: the pcm substream instance
|
||||||
*
|
*
|
||||||
* Checks whether any data exists on the playback buffer. If stop_threshold
|
* Checks whether any data exists on the playback buffer.
|
||||||
* is bigger or equal to boundary, then this function returns always non-zero.
|
|
||||||
*
|
*
|
||||||
* Returns non-zero if exists, or zero if not.
|
* Return: Non-zero if any data exists, or zero if not. If stop_threshold
|
||||||
|
* is bigger or equal to boundary, then this function returns always non-zero.
|
||||||
*/
|
*/
|
||||||
static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
|
static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -705,7 +707,7 @@ static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
|
|||||||
*
|
*
|
||||||
* Checks whether the playback buffer is empty.
|
* Checks whether the playback buffer is empty.
|
||||||
*
|
*
|
||||||
* Returns non-zero if empty, or zero if not.
|
* Return: Non-zero if empty, or zero if not.
|
||||||
*/
|
*/
|
||||||
static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
|
static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -719,7 +721,7 @@ static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
|
|||||||
*
|
*
|
||||||
* Checks whether the capture buffer is empty.
|
* Checks whether the capture buffer is empty.
|
||||||
*
|
*
|
||||||
* Returns non-zero if empty, or zero if not.
|
* Return: Non-zero if empty, or zero if not.
|
||||||
*/
|
*/
|
||||||
static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream)
|
static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -852,7 +854,7 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format);
|
|||||||
* snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
|
* snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is CPU-endian, 0 if
|
* Return: 1 if the given PCM format is CPU-endian, 0 if
|
||||||
* opposite, or a negative error code if endian not specified.
|
* opposite, or a negative error code if endian not specified.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
|
int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
|
||||||
@ -963,7 +965,7 @@ struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
|||||||
* contiguous in kernel virtual space, but not in physical memory. Use this
|
* contiguous in kernel virtual space, but not in physical memory. Use this
|
||||||
* if the buffer is accessed by kernel code but not by device DMA.
|
* if the buffer is accessed by kernel code but not by device DMA.
|
||||||
*
|
*
|
||||||
* Returns 1 if the buffer was changed, 0 if not changed, or a negative error
|
* Return: 1 if the buffer was changed, 0 if not changed, or a negative error
|
||||||
* code.
|
* code.
|
||||||
*/
|
*/
|
||||||
static int snd_pcm_lib_alloc_vmalloc_buffer
|
static int snd_pcm_lib_alloc_vmalloc_buffer
|
||||||
@ -975,6 +977,9 @@ static int snd_pcm_lib_alloc_vmalloc_buffer
|
|||||||
*
|
*
|
||||||
* This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
|
* This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
|
||||||
* vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
|
* vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
|
||||||
|
*
|
||||||
|
* Return: 1 if the buffer was changed, 0 if not changed, or a negative error
|
||||||
|
* code.
|
||||||
*/
|
*/
|
||||||
static int snd_pcm_lib_alloc_vmalloc_32_buffer
|
static int snd_pcm_lib_alloc_vmalloc_32_buffer
|
||||||
(struct snd_pcm_substream *substream, size_t size);
|
(struct snd_pcm_substream *substream, size_t size);
|
||||||
@ -1070,6 +1075,8 @@ const char *snd_pcm_format_name(snd_pcm_format_t format);
|
|||||||
/**
|
/**
|
||||||
* snd_pcm_stream_str - Get a string naming the direction of a stream
|
* snd_pcm_stream_str - Get a string naming the direction of a stream
|
||||||
* @substream: the pcm substream instance
|
* @substream: the pcm substream instance
|
||||||
|
*
|
||||||
|
* Return: A string naming the direction of the stream.
|
||||||
*/
|
*/
|
||||||
static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)
|
static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -1126,4 +1133,10 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
|
|||||||
unsigned long private_value,
|
unsigned long private_value,
|
||||||
struct snd_pcm_chmap **info_ret);
|
struct snd_pcm_chmap **info_ret);
|
||||||
|
|
||||||
|
/* Strong-typed conversion of pcm_format to bitwise */
|
||||||
|
static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
|
||||||
|
{
|
||||||
|
return 1ULL << (__force int) pcm_format;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __SOUND_PCM_H */
|
#endif /* __SOUND_PCM_H */
|
||||||
|
@ -95,14 +95,6 @@ struct snd_soc_dai_driver;
|
|||||||
struct snd_soc_dai;
|
struct snd_soc_dai;
|
||||||
struct snd_ac97_bus_ops;
|
struct snd_ac97_bus_ops;
|
||||||
|
|
||||||
/* Digital Audio Interface registration */
|
|
||||||
int snd_soc_register_dai(struct device *dev,
|
|
||||||
struct snd_soc_dai_driver *dai_drv);
|
|
||||||
void snd_soc_unregister_dai(struct device *dev);
|
|
||||||
int snd_soc_register_dais(struct device *dev,
|
|
||||||
struct snd_soc_dai_driver *dai_drv, size_t count);
|
|
||||||
void snd_soc_unregister_dais(struct device *dev, size_t count);
|
|
||||||
|
|
||||||
/* Digital Audio Interface clocking API.*/
|
/* Digital Audio Interface clocking API.*/
|
||||||
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
unsigned int freq, int dir);
|
unsigned int freq, int dir);
|
||||||
|
@ -566,7 +566,6 @@ struct snd_soc_dapm_update {
|
|||||||
|
|
||||||
/* DAPM context */
|
/* DAPM context */
|
||||||
struct snd_soc_dapm_context {
|
struct snd_soc_dapm_context {
|
||||||
int n_widgets; /* number of widgets in this context */
|
|
||||||
enum snd_soc_bias_level bias_level;
|
enum snd_soc_bias_level bias_level;
|
||||||
enum snd_soc_bias_level suspend_bias_level;
|
enum snd_soc_bias_level suspend_bias_level;
|
||||||
struct delayed_work delayed_work;
|
struct delayed_work delayed_work;
|
||||||
|
@ -324,6 +324,8 @@ struct snd_soc_dai_link;
|
|||||||
struct snd_soc_platform_driver;
|
struct snd_soc_platform_driver;
|
||||||
struct snd_soc_codec;
|
struct snd_soc_codec;
|
||||||
struct snd_soc_codec_driver;
|
struct snd_soc_codec_driver;
|
||||||
|
struct snd_soc_component;
|
||||||
|
struct snd_soc_component_driver;
|
||||||
struct soc_enum;
|
struct soc_enum;
|
||||||
struct snd_soc_jack;
|
struct snd_soc_jack;
|
||||||
struct snd_soc_jack_zone;
|
struct snd_soc_jack_zone;
|
||||||
@ -371,12 +373,20 @@ int snd_soc_suspend(struct device *dev);
|
|||||||
int snd_soc_resume(struct device *dev);
|
int snd_soc_resume(struct device *dev);
|
||||||
int snd_soc_poweroff(struct device *dev);
|
int snd_soc_poweroff(struct device *dev);
|
||||||
int snd_soc_register_platform(struct device *dev,
|
int snd_soc_register_platform(struct device *dev,
|
||||||
struct snd_soc_platform_driver *platform_drv);
|
const struct snd_soc_platform_driver *platform_drv);
|
||||||
void snd_soc_unregister_platform(struct device *dev);
|
void snd_soc_unregister_platform(struct device *dev);
|
||||||
|
int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
|
||||||
|
const struct snd_soc_platform_driver *platform_drv);
|
||||||
|
void snd_soc_remove_platform(struct snd_soc_platform *platform);
|
||||||
|
struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev);
|
||||||
int snd_soc_register_codec(struct device *dev,
|
int snd_soc_register_codec(struct device *dev,
|
||||||
const struct snd_soc_codec_driver *codec_drv,
|
const struct snd_soc_codec_driver *codec_drv,
|
||||||
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
||||||
void snd_soc_unregister_codec(struct device *dev);
|
void snd_soc_unregister_codec(struct device *dev);
|
||||||
|
int snd_soc_register_component(struct device *dev,
|
||||||
|
const struct snd_soc_component_driver *cmpnt_drv,
|
||||||
|
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
||||||
|
void snd_soc_unregister_component(struct device *dev);
|
||||||
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
|
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
|
||||||
unsigned int reg);
|
unsigned int reg);
|
||||||
int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
|
int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
|
||||||
@ -801,10 +811,10 @@ struct snd_soc_platform_driver {
|
|||||||
struct snd_soc_dai *);
|
struct snd_soc_dai *);
|
||||||
|
|
||||||
/* platform stream pcm ops */
|
/* platform stream pcm ops */
|
||||||
struct snd_pcm_ops *ops;
|
const struct snd_pcm_ops *ops;
|
||||||
|
|
||||||
/* platform stream compress ops */
|
/* platform stream compress ops */
|
||||||
struct snd_compr_ops *compr_ops;
|
const struct snd_compr_ops *compr_ops;
|
||||||
|
|
||||||
/* platform stream completion event */
|
/* platform stream completion event */
|
||||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||||
@ -823,7 +833,7 @@ struct snd_soc_platform {
|
|||||||
const char *name;
|
const char *name;
|
||||||
int id;
|
int id;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct snd_soc_platform_driver *driver;
|
const struct snd_soc_platform_driver *driver;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
|
||||||
unsigned int suspended:1; /* platform is suspended */
|
unsigned int suspended:1; /* platform is suspended */
|
||||||
@ -841,6 +851,20 @@ struct snd_soc_platform {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct snd_soc_component_driver {
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct snd_soc_component {
|
||||||
|
const char *name;
|
||||||
|
int id;
|
||||||
|
int num_dai;
|
||||||
|
struct device *dev;
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
const struct snd_soc_component_driver *driver;
|
||||||
|
};
|
||||||
|
|
||||||
struct snd_soc_dai_link {
|
struct snd_soc_dai_link {
|
||||||
/* config - must be set by machine driver */
|
/* config - must be set by machine driver */
|
||||||
const char *name; /* Codec name */
|
const char *name; /* Codec name */
|
||||||
@ -1086,7 +1110,6 @@ struct soc_enum {
|
|||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
const char * const *texts;
|
const char * const *texts;
|
||||||
const unsigned int *values;
|
const unsigned int *values;
|
||||||
void *dapm;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* codec IO */
|
/* codec IO */
|
||||||
|
7
include/sound/tas5086.h
Normal file
7
include/sound/tas5086.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef _SND_SOC_CODEC_TAS5086_H_
|
||||||
|
#define _SND_SOC_CODEC_TAS5086_H_
|
||||||
|
|
||||||
|
#define TAS5086_CLK_IDX_MCLK 0
|
||||||
|
#define TAS5086_CLK_IDX_SCLK 1
|
||||||
|
|
||||||
|
#endif /* _SND_SOC_CODEC_TAS5086_H_ */
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 NVIDIA, Inc.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
|
||||||
* may be copied, distributed, and modified under those terms.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SOUND_TEGRA_WM38903_H
|
|
||||||
#define __SOUND_TEGRA_WM38903_H
|
|
||||||
|
|
||||||
struct tegra_wm8903_platform_data {
|
|
||||||
int gpio_spkr_en;
|
|
||||||
int gpio_hp_det;
|
|
||||||
int gpio_hp_mute;
|
|
||||||
int gpio_int_mic_en;
|
|
||||||
int gpio_ext_mic_en;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -214,7 +214,9 @@ typedef int __bitwise snd_pcm_format_t;
|
|||||||
#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
|
#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
|
||||||
#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
|
#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
|
||||||
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
||||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
|
#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
|
||||||
|
#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
|
||||||
|
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE
|
||||||
|
|
||||||
#ifdef SNDRV_LITTLE_ENDIAN
|
#ifdef SNDRV_LITTLE_ENDIAN
|
||||||
#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
|
#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
|
||||||
|
@ -179,7 +179,7 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
|
|||||||
*/
|
*/
|
||||||
if (other->active) {
|
if (other->active) {
|
||||||
/* FIXME: is this guaranteed by the alsa api? */
|
/* FIXME: is this guaranteed by the alsa api? */
|
||||||
hw->formats &= (1ULL << i2sdev->format);
|
hw->formats &= pcm_format_to_bits(i2sdev->format);
|
||||||
/* see above, restrict rates to the one we already have */
|
/* see above, restrict rates to the one we already have */
|
||||||
hw->rate_min = i2sdev->rate;
|
hw->rate_min = i2sdev->rate;
|
||||||
hw->rate_max = i2sdev->rate;
|
hw->rate_max = i2sdev->rate;
|
||||||
|
@ -182,7 +182,7 @@ static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)
|
|||||||
runtime->hw.rate_max = chip->cur_rate;
|
runtime->hw.rate_max = chip->cur_rate;
|
||||||
}
|
}
|
||||||
if (chip->cur_format)
|
if (chip->cur_format)
|
||||||
runtime->hw.formats = (1ULL << chip->cur_format);
|
runtime->hw.formats = pcm_format_to_bits(chip->cur_format);
|
||||||
mutex_unlock(&opened_mutex);
|
mutex_unlock(&opened_mutex);
|
||||||
chip->playback_substream = substream;
|
chip->playback_substream = substream;
|
||||||
return 0;
|
return 0;
|
||||||
@ -201,7 +201,7 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
|
|||||||
runtime->hw.rate_max = chip->cur_rate;
|
runtime->hw.rate_max = chip->cur_rate;
|
||||||
}
|
}
|
||||||
if (chip->cur_format)
|
if (chip->cur_format)
|
||||||
runtime->hw.formats = (1ULL << chip->cur_format);
|
runtime->hw.formats = pcm_format_to_bits(chip->cur_format);
|
||||||
mutex_unlock(&opened_mutex);
|
mutex_unlock(&opened_mutex);
|
||||||
chip->capture_substream = substream;
|
chip->capture_substream = substream;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -28,11 +28,13 @@
|
|||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/types.h>
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -152,26 +154,23 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
|
|||||||
stream->ops->pointer(stream, tstamp);
|
stream->ops->pointer(stream, tstamp);
|
||||||
pr_debug("dsp consumed till %d total %d bytes\n",
|
pr_debug("dsp consumed till %d total %d bytes\n",
|
||||||
tstamp->byte_offset, tstamp->copied_total);
|
tstamp->byte_offset, tstamp->copied_total);
|
||||||
stream->runtime->hw_pointer = tstamp->byte_offset;
|
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||||
stream->runtime->total_bytes_transferred = tstamp->copied_total;
|
stream->runtime->total_bytes_transferred = tstamp->copied_total;
|
||||||
|
else
|
||||||
|
stream->runtime->total_bytes_available = tstamp->copied_total;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
|
static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
|
||||||
struct snd_compr_avail *avail)
|
struct snd_compr_avail *avail)
|
||||||
{
|
{
|
||||||
long avail_calc; /*this needs to be signed variable */
|
|
||||||
|
|
||||||
memset(avail, 0, sizeof(*avail));
|
memset(avail, 0, sizeof(*avail));
|
||||||
snd_compr_update_tstamp(stream, &avail->tstamp);
|
snd_compr_update_tstamp(stream, &avail->tstamp);
|
||||||
/* Still need to return avail even if tstamp can't be filled in */
|
/* Still need to return avail even if tstamp can't be filled in */
|
||||||
|
|
||||||
/* FIXME: This needs to be different for capture stream,
|
|
||||||
available is # of compressed data, for playback it's
|
|
||||||
remainder of buffer */
|
|
||||||
|
|
||||||
if (stream->runtime->total_bytes_available == 0 &&
|
if (stream->runtime->total_bytes_available == 0 &&
|
||||||
stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
|
stream->runtime->state == SNDRV_PCM_STATE_SETUP &&
|
||||||
|
stream->direction == SND_COMPRESS_PLAYBACK) {
|
||||||
pr_debug("detected init and someone forgot to do a write\n");
|
pr_debug("detected init and someone forgot to do a write\n");
|
||||||
return stream->runtime->buffer_size;
|
return stream->runtime->buffer_size;
|
||||||
}
|
}
|
||||||
@ -180,26 +179,22 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
|
|||||||
stream->runtime->total_bytes_transferred);
|
stream->runtime->total_bytes_transferred);
|
||||||
if (stream->runtime->total_bytes_available ==
|
if (stream->runtime->total_bytes_available ==
|
||||||
stream->runtime->total_bytes_transferred) {
|
stream->runtime->total_bytes_transferred) {
|
||||||
|
if (stream->direction == SND_COMPRESS_PLAYBACK) {
|
||||||
pr_debug("both pointers are same, returning full avail\n");
|
pr_debug("both pointers are same, returning full avail\n");
|
||||||
return stream->runtime->buffer_size;
|
return stream->runtime->buffer_size;
|
||||||
|
} else {
|
||||||
|
pr_debug("both pointers are same, returning no avail\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: this routine isn't consistent, in one test we use
|
avail->avail = stream->runtime->total_bytes_available -
|
||||||
* cumulative values and in the other byte offsets. Do we
|
stream->runtime->total_bytes_transferred;
|
||||||
* really need the byte offsets if the cumulative values have
|
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||||
* been updated? In the PCM interface app_ptr and hw_ptr are
|
avail->avail = stream->runtime->buffer_size - avail->avail;
|
||||||
* already cumulative */
|
|
||||||
|
|
||||||
avail_calc = stream->runtime->buffer_size -
|
pr_debug("ret avail as %lld\n", avail->avail);
|
||||||
(stream->runtime->app_pointer - stream->runtime->hw_pointer);
|
return avail->avail;
|
||||||
pr_debug("calc avail as %ld, app_ptr %lld, hw+ptr %lld\n", avail_calc,
|
|
||||||
stream->runtime->app_pointer,
|
|
||||||
stream->runtime->hw_pointer);
|
|
||||||
if (avail_calc >= stream->runtime->buffer_size)
|
|
||||||
avail_calc -= stream->runtime->buffer_size;
|
|
||||||
pr_debug("ret avail as %ld\n", avail_calc);
|
|
||||||
avail->avail = avail_calc;
|
|
||||||
return avail_calc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
|
static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
|
||||||
@ -230,21 +225,24 @@ static int snd_compr_write_data(struct snd_compr_stream *stream,
|
|||||||
void *dstn;
|
void *dstn;
|
||||||
size_t copy;
|
size_t copy;
|
||||||
struct snd_compr_runtime *runtime = stream->runtime;
|
struct snd_compr_runtime *runtime = stream->runtime;
|
||||||
|
/* 64-bit Modulus */
|
||||||
|
u64 app_pointer = div64_u64(runtime->total_bytes_available,
|
||||||
|
runtime->buffer_size);
|
||||||
|
app_pointer = runtime->total_bytes_available -
|
||||||
|
(app_pointer * runtime->buffer_size);
|
||||||
|
|
||||||
dstn = runtime->buffer + runtime->app_pointer;
|
dstn = runtime->buffer + app_pointer;
|
||||||
pr_debug("copying %ld at %lld\n",
|
pr_debug("copying %ld at %lld\n",
|
||||||
(unsigned long)count, runtime->app_pointer);
|
(unsigned long)count, app_pointer);
|
||||||
if (count < runtime->buffer_size - runtime->app_pointer) {
|
if (count < runtime->buffer_size - app_pointer) {
|
||||||
if (copy_from_user(dstn, buf, count))
|
if (copy_from_user(dstn, buf, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
runtime->app_pointer += count;
|
|
||||||
} else {
|
} else {
|
||||||
copy = runtime->buffer_size - runtime->app_pointer;
|
copy = runtime->buffer_size - app_pointer;
|
||||||
if (copy_from_user(dstn, buf, copy))
|
if (copy_from_user(dstn, buf, copy))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (copy_from_user(runtime->buffer, buf + copy, count - copy))
|
if (copy_from_user(runtime->buffer, buf + copy, count - copy))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
runtime->app_pointer = count - copy;
|
|
||||||
}
|
}
|
||||||
/* if DSP cares, let it know data has been written */
|
/* if DSP cares, let it know data has been written */
|
||||||
if (stream->ops->ack)
|
if (stream->ops->ack)
|
||||||
@ -278,10 +276,12 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
|
|||||||
if (avail > count)
|
if (avail > count)
|
||||||
avail = count;
|
avail = count;
|
||||||
|
|
||||||
if (stream->ops->copy)
|
if (stream->ops->copy) {
|
||||||
retval = stream->ops->copy(stream, buf, avail);
|
char __user* cbuf = (char __user*)buf;
|
||||||
else
|
retval = stream->ops->copy(stream, cbuf, avail);
|
||||||
|
} else {
|
||||||
retval = snd_compr_write_data(stream, buf, avail);
|
retval = snd_compr_write_data(stream, buf, avail);
|
||||||
|
}
|
||||||
if (retval > 0)
|
if (retval > 0)
|
||||||
stream->runtime->total_bytes_available += retval;
|
stream->runtime->total_bytes_available += retval;
|
||||||
|
|
||||||
@ -300,7 +300,49 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
|
|||||||
static ssize_t snd_compr_read(struct file *f, char __user *buf,
|
static ssize_t snd_compr_read(struct file *f, char __user *buf,
|
||||||
size_t count, loff_t *offset)
|
size_t count, loff_t *offset)
|
||||||
{
|
{
|
||||||
return -ENXIO;
|
struct snd_compr_file *data = f->private_data;
|
||||||
|
struct snd_compr_stream *stream;
|
||||||
|
size_t avail;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (snd_BUG_ON(!data))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
stream = &data->stream;
|
||||||
|
mutex_lock(&stream->device->lock);
|
||||||
|
|
||||||
|
/* read is allowed when stream is running, paused, draining and setup
|
||||||
|
* (yes setup is state which we transition to after stop, so if user
|
||||||
|
* wants to read data after stop we allow that)
|
||||||
|
*/
|
||||||
|
switch (stream->runtime->state) {
|
||||||
|
case SNDRV_PCM_STATE_OPEN:
|
||||||
|
case SNDRV_PCM_STATE_PREPARED:
|
||||||
|
case SNDRV_PCM_STATE_XRUN:
|
||||||
|
case SNDRV_PCM_STATE_SUSPENDED:
|
||||||
|
case SNDRV_PCM_STATE_DISCONNECTED:
|
||||||
|
retval = -EBADFD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
avail = snd_compr_get_avail(stream);
|
||||||
|
pr_debug("avail returned %ld\n", (unsigned long)avail);
|
||||||
|
/* calculate how much we can read from buffer */
|
||||||
|
if (avail > count)
|
||||||
|
avail = count;
|
||||||
|
|
||||||
|
if (stream->ops->copy) {
|
||||||
|
retval = stream->ops->copy(stream, buf, avail);
|
||||||
|
} else {
|
||||||
|
retval = -ENXIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (retval > 0)
|
||||||
|
stream->runtime->total_bytes_transferred += retval;
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&stream->device->lock);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
|
static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
|
||||||
@ -375,6 +417,7 @@ snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
|
|||||||
if (!stream->ops->get_caps)
|
if (!stream->ops->get_caps)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
memset(&caps, 0, sizeof(caps));
|
||||||
retval = stream->ops->get_caps(stream, &caps);
|
retval = stream->ops->get_caps(stream, &caps);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
@ -393,7 +436,7 @@ snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
|
|||||||
if (!stream->ops->get_codec_caps)
|
if (!stream->ops->get_codec_caps)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
caps = kmalloc(sizeof(*caps), GFP_KERNEL);
|
caps = kzalloc(sizeof(*caps), GFP_KERNEL);
|
||||||
if (!caps)
|
if (!caps)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -485,9 +528,14 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
|
|||||||
retval = stream->ops->set_params(stream, params);
|
retval = stream->ops->set_params(stream, params);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
|
||||||
stream->metadata_set = false;
|
stream->metadata_set = false;
|
||||||
stream->next_track = false;
|
stream->next_track = false;
|
||||||
|
|
||||||
|
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||||
|
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
||||||
|
else
|
||||||
|
stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
|
||||||
} else {
|
} else {
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
@ -505,7 +553,7 @@ snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
|
|||||||
if (!stream->ops->get_params)
|
if (!stream->ops->get_params)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
params = kmalloc(sizeof(*params), GFP_KERNEL);
|
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
||||||
if (!params)
|
if (!params)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
retval = stream->ops->get_params(stream, params);
|
retval = stream->ops->get_params(stream, params);
|
||||||
@ -622,8 +670,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
|
|||||||
if (!retval) {
|
if (!retval) {
|
||||||
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
||||||
wake_up(&stream->runtime->sleep);
|
wake_up(&stream->runtime->sleep);
|
||||||
stream->runtime->hw_pointer = 0;
|
|
||||||
stream->runtime->app_pointer = 0;
|
|
||||||
stream->runtime->total_bytes_available = 0;
|
stream->runtime->total_bytes_available = 0;
|
||||||
stream->runtime->total_bytes_transferred = 0;
|
stream->runtime->total_bytes_transferred = 0;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ EXPORT_SYMBOL(snd_ctl_notify);
|
|||||||
* Allocates a new struct snd_kcontrol instance and copies the given template
|
* Allocates a new struct snd_kcontrol instance and copies the given template
|
||||||
* to the new instance. It does not copy volatile data (access).
|
* to the new instance. It does not copy volatile data (access).
|
||||||
*
|
*
|
||||||
* Returns the pointer of the new instance, or NULL on failure.
|
* Return: The pointer of the new instance, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
|
static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
|
||||||
unsigned int access)
|
unsigned int access)
|
||||||
@ -224,7 +224,7 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
|
|||||||
* template. When the access field of ncontrol is 0, it's assumed as
|
* 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.
|
* READWRITE access. When the count field is 0, it's assumes as one.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the newly generated instance, or NULL on failure.
|
* Return: The pointer of the newly generated instance, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
|
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
|
||||||
void *private_data)
|
void *private_data)
|
||||||
@ -322,9 +322,10 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
|
|||||||
* snd_ctl_new1() to the given card. Assigns also an unique
|
* snd_ctl_new1() to the given card. Assigns also an unique
|
||||||
* numid used for fast search.
|
* numid used for fast search.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
|
||||||
*
|
|
||||||
* It frees automatically the control which cannot be added.
|
* 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 snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||||
{
|
{
|
||||||
@ -380,9 +381,9 @@ EXPORT_SYMBOL(snd_ctl_add);
|
|||||||
* and the add_on_replace flag is set, the control is added. If the
|
* and the add_on_replace flag is set, the control is added. If the
|
||||||
* control exists, it is destroyed first.
|
* control exists, it is destroyed first.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
|
||||||
*
|
|
||||||
* It frees automatically the control which cannot be added or replaced.
|
* It frees automatically the control which cannot be added or replaced.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
||||||
bool add_on_replace)
|
bool add_on_replace)
|
||||||
@ -443,7 +444,7 @@ EXPORT_SYMBOL(snd_ctl_replace);
|
|||||||
* You don't need to call snd_ctl_free_one(). You must be in
|
* You don't need to call snd_ctl_free_one(). You must be in
|
||||||
* the write lock - down_write(&card->controls_rwsem).
|
* the write lock - down_write(&card->controls_rwsem).
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, or a negative error code on failure.
|
* Return: 0 if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||||
{
|
{
|
||||||
@ -471,7 +472,7 @@ EXPORT_SYMBOL(snd_ctl_remove);
|
|||||||
* Finds the control instance with the given id, removes it from the
|
* Finds the control instance with the given id, removes it from the
|
||||||
* card list and releases it.
|
* card list and releases it.
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, or a negative error code on failure.
|
* Return: 0 if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
|
int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
|
||||||
{
|
{
|
||||||
@ -499,7 +500,7 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
|
|||||||
* Finds the control instance with the given id, removes it from the
|
* Finds the control instance with the given id, removes it from the
|
||||||
* card list and releases it.
|
* card list and releases it.
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, or a negative error code on failure.
|
* Return: 0 if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
||||||
struct snd_ctl_elem_id *id)
|
struct snd_ctl_elem_id *id)
|
||||||
@ -541,7 +542,7 @@ error:
|
|||||||
* Finds the control instance with the given id, and activate or
|
* Finds the control instance with the given id, and activate or
|
||||||
* inactivate the control together with notification, if changed.
|
* inactivate the control together with notification, if changed.
|
||||||
*
|
*
|
||||||
* Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
|
* Return: 0 if unchanged, 1 if changed, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
|
||||||
int active)
|
int active)
|
||||||
@ -587,7 +588,7 @@ EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
|
|||||||
* Finds the control with the old id from the card, and replaces the
|
* Finds the control with the old id from the card, and replaces the
|
||||||
* id with the new one.
|
* id with the new one.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
|
int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
|
||||||
struct snd_ctl_elem_id *dst_id)
|
struct snd_ctl_elem_id *dst_id)
|
||||||
@ -616,10 +617,11 @@ EXPORT_SYMBOL(snd_ctl_rename_id);
|
|||||||
*
|
*
|
||||||
* Finds the control instance with the given number-id from the card.
|
* Finds the control instance with the given number-id from the card.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the instance if found, or NULL if not.
|
|
||||||
*
|
|
||||||
* The caller must down card->controls_rwsem before calling this function
|
* The caller must down card->controls_rwsem before calling this function
|
||||||
* (if the race condition can happen).
|
* (if the race condition can happen).
|
||||||
|
*
|
||||||
|
* Return: The pointer of the instance if found, or %NULL if not.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
|
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
|
||||||
{
|
{
|
||||||
@ -643,10 +645,11 @@ EXPORT_SYMBOL(snd_ctl_find_numid);
|
|||||||
*
|
*
|
||||||
* Finds the control instance with the given id from the card.
|
* Finds the control instance with the given id from the card.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the instance if found, or NULL if not.
|
|
||||||
*
|
|
||||||
* The caller must down card->controls_rwsem before calling this function
|
* The caller must down card->controls_rwsem before calling this function
|
||||||
* (if the race condition can happen).
|
* (if the race condition can happen).
|
||||||
|
*
|
||||||
|
* Return: The pointer of the instance if found, or %NULL if not.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
|
||||||
struct snd_ctl_elem_id *id)
|
struct snd_ctl_elem_id *id)
|
||||||
@ -1710,6 +1713,8 @@ EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
|
|||||||
* Sets all required fields in @info to their appropriate values.
|
* Sets all required fields in @info to their appropriate values.
|
||||||
* If the control's accessibility is not the default (readable and writable),
|
* If the control's accessibility is not the default (readable and writable),
|
||||||
* the caller has to fill @info->access.
|
* the caller has to fill @info->access.
|
||||||
|
*
|
||||||
|
* Return: Zero.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
|
int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
|
||||||
unsigned int items, const char *const names[])
|
unsigned int items, const char *const names[])
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
* The data pointer plays a role as the identifier, too, so the
|
* The data pointer plays a role as the identifier, too, so the
|
||||||
* pointer address must be unique and unchanged.
|
* pointer address must be unique and unchanged.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_device_new(struct snd_card *card, snd_device_type_t type,
|
int snd_device_new(struct snd_card *card, snd_device_type_t type,
|
||||||
void *device_data, struct snd_device_ops *ops)
|
void *device_data, struct snd_device_ops *ops)
|
||||||
@ -73,7 +73,7 @@ EXPORT_SYMBOL(snd_device_new);
|
|||||||
* callbacks, dev_disconnect and dev_free, corresponding to the state.
|
* callbacks, dev_disconnect and dev_free, corresponding to the state.
|
||||||
* Then release the device.
|
* Then release the device.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure or if the
|
* Return: Zero if successful, or a negative error code on failure or if the
|
||||||
* device not found.
|
* device not found.
|
||||||
*/
|
*/
|
||||||
int snd_device_free(struct snd_card *card, void *device_data)
|
int snd_device_free(struct snd_card *card, void *device_data)
|
||||||
@ -116,7 +116,7 @@ EXPORT_SYMBOL(snd_device_free);
|
|||||||
*
|
*
|
||||||
* Usually called from snd_card_disconnect().
|
* Usually called from snd_card_disconnect().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure or if the
|
* Return: Zero if successful, or a negative error code on failure or if the
|
||||||
* device not found.
|
* device not found.
|
||||||
*/
|
*/
|
||||||
int snd_device_disconnect(struct snd_card *card, void *device_data)
|
int snd_device_disconnect(struct snd_card *card, void *device_data)
|
||||||
@ -151,7 +151,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
|
|||||||
* but it can be called later if any new devices are created after
|
* but it can be called later if any new devices are created after
|
||||||
* invocation of snd_card_register().
|
* invocation of snd_card_register().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure or if the
|
* Return: Zero if successful, or a negative error code on failure or if the
|
||||||
* device not found.
|
* device not found.
|
||||||
*/
|
*/
|
||||||
int snd_device_register(struct snd_card *card, void *device_data)
|
int snd_device_register(struct snd_card *card, void *device_data)
|
||||||
|
@ -356,7 +356,7 @@ static const struct file_operations snd_hwdep_f_ops =
|
|||||||
* The callbacks (hwdep->ops) must be set on the returned instance
|
* The callbacks (hwdep->ops) must be set on the returned instance
|
||||||
* after this call manually by the caller.
|
* after this call manually by the caller.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_hwdep_new(struct snd_card *card, char *id, int device,
|
int snd_hwdep_new(struct snd_card *card, char *id, int device,
|
||||||
struct snd_hwdep **rhwdep)
|
struct snd_hwdep **rhwdep)
|
||||||
|
@ -89,7 +89,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
|
|||||||
char *nbuf;
|
char *nbuf;
|
||||||
|
|
||||||
nsize = PAGE_ALIGN(nsize);
|
nsize = PAGE_ALIGN(nsize);
|
||||||
nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
|
nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL | __GFP_ZERO);
|
||||||
if (! nbuf)
|
if (! nbuf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
|
|||||||
*
|
*
|
||||||
* Outputs the string on the procfs buffer just like printf().
|
* Outputs the string on the procfs buffer just like printf().
|
||||||
*
|
*
|
||||||
* Returns the size of output string.
|
* Return: The size of output string, or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
|
int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -344,7 +344,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
|
|||||||
goto __nomem;
|
goto __nomem;
|
||||||
data->rbuffer = buffer;
|
data->rbuffer = buffer;
|
||||||
buffer->len = PAGE_SIZE;
|
buffer->len = PAGE_SIZE;
|
||||||
buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
|
buffer->buffer = kzalloc(buffer->len, GFP_KERNEL);
|
||||||
if (buffer->buffer == NULL)
|
if (buffer->buffer == NULL)
|
||||||
goto __nomem;
|
goto __nomem;
|
||||||
}
|
}
|
||||||
@ -683,32 +683,27 @@ int snd_info_card_free(struct snd_card *card)
|
|||||||
*
|
*
|
||||||
* Reads one line from the buffer and stores the string.
|
* Reads one line from the buffer and stores the string.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or 1 if error or EOF.
|
* Return: Zero if successful, or 1 if error or EOF.
|
||||||
*/
|
*/
|
||||||
int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
|
int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
|
||||||
{
|
{
|
||||||
int c = -1;
|
int c = -1;
|
||||||
|
|
||||||
|
if (snd_BUG_ON(!buffer || !buffer->buffer))
|
||||||
|
return 1;
|
||||||
if (len <= 0 || buffer->stop || buffer->error)
|
if (len <= 0 || buffer->stop || buffer->error)
|
||||||
return 1;
|
return 1;
|
||||||
while (--len > 0) {
|
while (!buffer->stop) {
|
||||||
c = buffer->buffer[buffer->curr++];
|
c = buffer->buffer[buffer->curr++];
|
||||||
if (c == '\n') {
|
|
||||||
if (buffer->curr >= buffer->size)
|
if (buffer->curr >= buffer->size)
|
||||||
buffer->stop = 1;
|
buffer->stop = 1;
|
||||||
|
if (c == '\n')
|
||||||
break;
|
break;
|
||||||
}
|
if (len) {
|
||||||
|
len--;
|
||||||
*line++ = c;
|
*line++ = c;
|
||||||
if (buffer->curr >= buffer->size) {
|
|
||||||
buffer->stop = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (c != '\n' && !buffer->stop) {
|
|
||||||
c = buffer->buffer[buffer->curr++];
|
|
||||||
if (buffer->curr >= buffer->size)
|
|
||||||
buffer->stop = 1;
|
|
||||||
}
|
|
||||||
*line = '\0';
|
*line = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -724,7 +719,7 @@ EXPORT_SYMBOL(snd_info_get_line);
|
|||||||
* Parses the original string and copy a token to the given
|
* Parses the original string and copy a token to the given
|
||||||
* string buffer.
|
* string buffer.
|
||||||
*
|
*
|
||||||
* Returns the updated pointer of the original string so that
|
* Return: The updated pointer of the original string so that
|
||||||
* it can be used for the next call.
|
* it can be used for the next call.
|
||||||
*/
|
*/
|
||||||
const char *snd_info_get_str(char *dest, const char *src, int len)
|
const char *snd_info_get_str(char *dest, const char *src, int len)
|
||||||
@ -763,7 +758,7 @@ EXPORT_SYMBOL(snd_info_get_str);
|
|||||||
* Usually called from other functions such as
|
* Usually called from other functions such as
|
||||||
* snd_info_create_card_entry().
|
* snd_info_create_card_entry().
|
||||||
*
|
*
|
||||||
* Returns the pointer of the new instance, or NULL on failure.
|
* Return: The pointer of the new instance, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
static struct snd_info_entry *snd_info_create_entry(const char *name)
|
static struct snd_info_entry *snd_info_create_entry(const char *name)
|
||||||
{
|
{
|
||||||
@ -792,7 +787,7 @@ static struct snd_info_entry *snd_info_create_entry(const char *name)
|
|||||||
*
|
*
|
||||||
* Creates a new info entry and assigns it to the given module.
|
* Creates a new info entry and assigns it to the given module.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the new instance, or NULL on failure.
|
* Return: The pointer of the new instance, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct snd_info_entry *snd_info_create_module_entry(struct module * module,
|
struct snd_info_entry *snd_info_create_module_entry(struct module * module,
|
||||||
const char *name,
|
const char *name,
|
||||||
@ -816,7 +811,7 @@ EXPORT_SYMBOL(snd_info_create_module_entry);
|
|||||||
*
|
*
|
||||||
* Creates a new info entry and assigns it to the given card.
|
* Creates a new info entry and assigns it to the given card.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the new instance, or NULL on failure.
|
* Return: The pointer of the new instance, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
|
struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
|
||||||
const char *name,
|
const char *name,
|
||||||
@ -882,7 +877,7 @@ static int snd_info_dev_register_entry(struct snd_device *device)
|
|||||||
* For releasing this entry, use snd_device_free() instead of
|
* For releasing this entry, use snd_device_free() instead of
|
||||||
* snd_info_free_entry().
|
* snd_info_free_entry().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_card_proc_new(struct snd_card *card, const char *name,
|
int snd_card_proc_new(struct snd_card *card, const char *name,
|
||||||
struct snd_info_entry **entryp)
|
struct snd_info_entry **entryp)
|
||||||
@ -938,7 +933,7 @@ EXPORT_SYMBOL(snd_info_free_entry);
|
|||||||
*
|
*
|
||||||
* Registers the proc info entry.
|
* Registers the proc info entry.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_info_register(struct snd_info_entry * entry)
|
int snd_info_register(struct snd_info_entry * entry)
|
||||||
{
|
{
|
||||||
|
@ -144,7 +144,7 @@ static inline int init_info_for_card(struct snd_card *card)
|
|||||||
* space for the driver to use freely. The allocated struct is stored
|
* space for the driver to use freely. The allocated struct is stored
|
||||||
* in the given card_ret pointer.
|
* in the given card_ret pointer.
|
||||||
*
|
*
|
||||||
* Returns zero if successful or a negative error code.
|
* Return: Zero if successful or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_card_create(int idx, const char *xid,
|
int snd_card_create(int idx, const char *xid,
|
||||||
struct module *module, int extra_size,
|
struct module *module, int extra_size,
|
||||||
@ -337,7 +337,7 @@ static const struct file_operations snd_shutdown_f_ops =
|
|||||||
*
|
*
|
||||||
* Disconnects all APIs from the file-operations (user space).
|
* Disconnects all APIs from the file-operations (user space).
|
||||||
*
|
*
|
||||||
* Returns zero, otherwise a negative error code.
|
* Return: Zero, otherwise a negative error code.
|
||||||
*
|
*
|
||||||
* Note: The current implementation replaces all active file->f_op with special
|
* Note: The current implementation replaces all active file->f_op with special
|
||||||
* dummy file operations (they do nothing except release).
|
* dummy file operations (they do nothing except release).
|
||||||
@ -415,7 +415,7 @@ EXPORT_SYMBOL(snd_card_disconnect);
|
|||||||
* devices automatically. That is, you don't have to release the devices
|
* devices automatically. That is, you don't have to release the devices
|
||||||
* by yourself.
|
* by yourself.
|
||||||
*
|
*
|
||||||
* Returns zero. Frees all associated devices and frees the control
|
* Return: Zero. Frees all associated devices and frees the control
|
||||||
* interface associated to given soundcard.
|
* interface associated to given soundcard.
|
||||||
*/
|
*/
|
||||||
static int snd_card_do_free(struct snd_card *card)
|
static int snd_card_do_free(struct snd_card *card)
|
||||||
@ -677,7 +677,7 @@ static struct device_attribute card_number_attrs =
|
|||||||
* external accesses. Thus, you should call this function at the end
|
* external accesses. Thus, you should call this function at the end
|
||||||
* of the initialization of the card.
|
* of the initialization of the card.
|
||||||
*
|
*
|
||||||
* Returns zero otherwise a negative error code if the registration failed.
|
* Return: Zero otherwise a negative error code if the registration failed.
|
||||||
*/
|
*/
|
||||||
int snd_card_register(struct snd_card *card)
|
int snd_card_register(struct snd_card *card)
|
||||||
{
|
{
|
||||||
@ -849,7 +849,7 @@ int __exit snd_card_info_done(void)
|
|||||||
* This function adds the component id string to the supported list.
|
* This function adds the component id string to the supported list.
|
||||||
* The component can be referred from the alsa-lib.
|
* The component can be referred from the alsa-lib.
|
||||||
*
|
*
|
||||||
* Returns zero otherwise a negative error code.
|
* Return: Zero otherwise a negative error code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int snd_component_add(struct snd_card *card, const char *component)
|
int snd_component_add(struct snd_card *card, const char *component)
|
||||||
@ -883,7 +883,7 @@ EXPORT_SYMBOL(snd_component_add);
|
|||||||
* This linked-list is used to keep tracking the connection state,
|
* This linked-list is used to keep tracking the connection state,
|
||||||
* and to avoid the release of busy resources by hotplug.
|
* and to avoid the release of busy resources by hotplug.
|
||||||
*
|
*
|
||||||
* Returns zero or a negative error code.
|
* Return: zero or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_card_file_add(struct snd_card *card, struct file *file)
|
int snd_card_file_add(struct snd_card *card, struct file *file)
|
||||||
{
|
{
|
||||||
@ -920,7 +920,7 @@ EXPORT_SYMBOL(snd_card_file_add);
|
|||||||
* called beforehand, it processes the pending release of
|
* called beforehand, it processes the pending release of
|
||||||
* resources.
|
* resources.
|
||||||
*
|
*
|
||||||
* Returns zero or a negative error code.
|
* Return: Zero or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_card_file_remove(struct snd_card *card, struct file *file)
|
int snd_card_file_remove(struct snd_card *card, struct file *file)
|
||||||
{
|
{
|
||||||
@ -959,6 +959,8 @@ EXPORT_SYMBOL(snd_card_file_remove);
|
|||||||
*
|
*
|
||||||
* Waits until the power-state is changed.
|
* 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.
|
* Note: the power lock must be active before call.
|
||||||
*/
|
*/
|
||||||
int snd_power_wait(struct snd_card *card, unsigned int power_state)
|
int snd_power_wait(struct snd_card *card, unsigned int power_state)
|
||||||
|
@ -81,7 +81,7 @@ EXPORT_SYMBOL(snd_dma_disable);
|
|||||||
* @dma: the dma number
|
* @dma: the dma number
|
||||||
* @size: the dma transfer size
|
* @size: the dma transfer size
|
||||||
*
|
*
|
||||||
* Returns the current pointer in DMA tranfer buffer in bytes
|
* Return: The current pointer in DMA transfer buffer in bytes.
|
||||||
*/
|
*/
|
||||||
unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
|
unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
|
||||||
{
|
{
|
||||||
|
@ -98,8 +98,8 @@ static int snd_jack_dev_register(struct snd_device *device)
|
|||||||
*
|
*
|
||||||
* Creates a new jack object.
|
* Creates a new jack object.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
* On success jjack will be initialised.
|
* On success @jjack will be initialised.
|
||||||
*/
|
*/
|
||||||
int snd_jack_new(struct snd_card *card, const char *id, int type,
|
int snd_jack_new(struct snd_card *card, const char *id, int type,
|
||||||
struct snd_jack **jjack)
|
struct snd_jack **jjack)
|
||||||
@ -189,6 +189,8 @@ EXPORT_SYMBOL(snd_jack_set_parent);
|
|||||||
* using this abstraction.
|
* using this abstraction.
|
||||||
*
|
*
|
||||||
* This function may only be called prior to registration of the jack.
|
* This function may only be called prior to registration of the jack.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
|
int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
|
||||||
int keytype)
|
int keytype)
|
||||||
|
@ -81,7 +81,7 @@ static inline void dec_snd_pages(int order)
|
|||||||
*
|
*
|
||||||
* Allocates the physically contiguous pages with the given size.
|
* Allocates the physically contiguous pages with the given size.
|
||||||
*
|
*
|
||||||
* Returns the pointer of the buffer, or NULL if no enoguh memory.
|
* Return: The pointer of the buffer, or %NULL if no enough memory.
|
||||||
*/
|
*/
|
||||||
void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
|
void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
|
||||||
{
|
{
|
||||||
@ -176,8 +176,8 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
|
|||||||
* Calls the memory-allocator function for the corresponding
|
* Calls the memory-allocator function for the corresponding
|
||||||
* buffer type.
|
* buffer type.
|
||||||
*
|
*
|
||||||
* Returns zero if the buffer with the given size is allocated successfully,
|
* Return: Zero if the buffer with the given size is allocated successfully,
|
||||||
* other a negative value at error.
|
* otherwise a negative value on error.
|
||||||
*/
|
*/
|
||||||
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
||||||
struct snd_dma_buffer *dmab)
|
struct snd_dma_buffer *dmab)
|
||||||
@ -230,8 +230,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
|||||||
* tries to allocate again. The size actually allocated is stored in
|
* tries to allocate again. The size actually allocated is stored in
|
||||||
* res_size argument.
|
* res_size argument.
|
||||||
*
|
*
|
||||||
* Returns zero if the buffer with the given size is allocated successfully,
|
* Return: Zero if the buffer with the given size is allocated successfully,
|
||||||
* other a negative value at error.
|
* otherwise a negative value on error.
|
||||||
*/
|
*/
|
||||||
int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
|
int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
|
||||||
struct snd_dma_buffer *dmab)
|
struct snd_dma_buffer *dmab)
|
||||||
@ -292,7 +292,7 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
|
|||||||
* Looks for the reserved-buffer list and re-uses if the same buffer
|
* Looks for the reserved-buffer list and re-uses if the same buffer
|
||||||
* is found in the list. When the buffer is found, it's removed from the free list.
|
* is found in the list. When the buffer is found, it's removed from the free list.
|
||||||
*
|
*
|
||||||
* Returns the size of buffer if the buffer is found, or zero if not found.
|
* Return: The size of buffer if the buffer is found, or zero if not found.
|
||||||
*/
|
*/
|
||||||
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
||||||
{
|
{
|
||||||
@ -327,7 +327,7 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
|||||||
*
|
*
|
||||||
* Reserves the given buffer as a reserved buffer.
|
* Reserves the given buffer as a reserved buffer.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative code at error.
|
* Return: Zero if successful, or a negative code on error.
|
||||||
*/
|
*/
|
||||||
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
*
|
*
|
||||||
* Copies the data from mmio-space to user-space.
|
* Copies the data from mmio-space to user-space.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or non-zero on failure.
|
* Return: Zero if successful, or non-zero on failure.
|
||||||
*/
|
*/
|
||||||
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
|
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ EXPORT_SYMBOL(copy_to_user_fromio);
|
|||||||
*
|
*
|
||||||
* Copies the data from user-space to mmio-space.
|
* Copies the data from user-space to mmio-space.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or non-zero on failure.
|
* Return: Zero if successful, or non-zero on failure.
|
||||||
*/
|
*/
|
||||||
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
|
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -209,6 +209,8 @@ static char *snd_pcm_format_names[] = {
|
|||||||
FORMAT(G723_24_1B),
|
FORMAT(G723_24_1B),
|
||||||
FORMAT(G723_40),
|
FORMAT(G723_40),
|
||||||
FORMAT(G723_40_1B),
|
FORMAT(G723_40_1B),
|
||||||
|
FORMAT(DSD_U8),
|
||||||
|
FORMAT(DSD_U16_LE),
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *snd_pcm_format_name(snd_pcm_format_t format)
|
const char *snd_pcm_format_name(snd_pcm_format_t format)
|
||||||
@ -637,7 +639,7 @@ static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substrea
|
|||||||
* calling this, i.e. zero must be given to the argument of
|
* calling this, i.e. zero must be given to the argument of
|
||||||
* snd_pcm_new().
|
* snd_pcm_new().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
|
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
|
||||||
{
|
{
|
||||||
@ -759,7 +761,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
|
|||||||
* The pcm operators have to be set afterwards to the new instance
|
* The pcm operators have to be set afterwards to the new instance
|
||||||
* via snd_pcm_set_ops().
|
* via snd_pcm_set_ops().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_new(struct snd_card *card, const char *id, int device,
|
int snd_pcm_new(struct snd_card *card, const char *id, int device,
|
||||||
int playback_count, int capture_count, struct snd_pcm **rpcm)
|
int playback_count, int capture_count, struct snd_pcm **rpcm)
|
||||||
@ -787,7 +789,7 @@ EXPORT_SYMBOL(snd_pcm_new);
|
|||||||
* The pcm operators have to be set afterwards to the new instance
|
* The pcm operators have to be set afterwards to the new instance
|
||||||
* via snd_pcm_set_ops().
|
* via snd_pcm_set_ops().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
|
int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
|
||||||
int playback_count, int capture_count,
|
int playback_count, int capture_count,
|
||||||
|
@ -666,7 +666,8 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
|
|||||||
* The interval is changed to the range satisfying both intervals.
|
* The interval is changed to the range satisfying both intervals.
|
||||||
* The interval status (min, max, integer, etc.) are evaluated.
|
* The interval status (min, max, integer, etc.) are evaluated.
|
||||||
*
|
*
|
||||||
* Returns non-zero if the value is changed, zero if not changed.
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
|
int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
|
||||||
{
|
{
|
||||||
@ -865,7 +866,8 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
|
|||||||
* @nump: pointer to store the resultant numerator
|
* @nump: pointer to store the resultant numerator
|
||||||
* @denp: pointer to store the resultant denominator
|
* @denp: pointer to store the resultant denominator
|
||||||
*
|
*
|
||||||
* Returns non-zero if the value is changed, zero if not changed.
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_interval_ratnum(struct snd_interval *i,
|
int snd_interval_ratnum(struct snd_interval *i,
|
||||||
unsigned int rats_count, struct snd_ratnum *rats,
|
unsigned int rats_count, struct snd_ratnum *rats,
|
||||||
@ -983,7 +985,8 @@ EXPORT_SYMBOL(snd_interval_ratnum);
|
|||||||
* @nump: pointer to store the resultant numerator
|
* @nump: pointer to store the resultant numerator
|
||||||
* @denp: pointer to store the resultant denominator
|
* @denp: pointer to store the resultant denominator
|
||||||
*
|
*
|
||||||
* Returns non-zero if the value is changed, zero if not changed.
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
static int snd_interval_ratden(struct snd_interval *i,
|
static int snd_interval_ratden(struct snd_interval *i,
|
||||||
unsigned int rats_count, struct snd_ratden *rats,
|
unsigned int rats_count, struct snd_ratden *rats,
|
||||||
@ -1082,7 +1085,8 @@ static int snd_interval_ratden(struct snd_interval *i,
|
|||||||
* When mask is non-zero, only the elements corresponding to bit 1 are
|
* When mask is non-zero, only the elements corresponding to bit 1 are
|
||||||
* evaluated.
|
* evaluated.
|
||||||
*
|
*
|
||||||
* Returns non-zero if the value is changed, zero if not changed.
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_interval_list(struct snd_interval *i, unsigned int count,
|
int snd_interval_list(struct snd_interval *i, unsigned int count,
|
||||||
const unsigned int *list, unsigned int mask)
|
const unsigned int *list, unsigned int mask)
|
||||||
@ -1142,7 +1146,7 @@ static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned
|
|||||||
* @private: the private data pointer passed to function
|
* @private: the private data pointer passed to function
|
||||||
* @dep: the dependent variables
|
* @dep: the dependent variables
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
|
int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
|
||||||
int var,
|
int var,
|
||||||
@ -1200,6 +1204,8 @@ EXPORT_SYMBOL(snd_pcm_hw_rule_add);
|
|||||||
* @mask: the bitmap mask
|
* @mask: the bitmap mask
|
||||||
*
|
*
|
||||||
* Apply the constraint of the given bitmap mask to a 32-bit mask parameter.
|
* Apply the constraint of the given bitmap mask to a 32-bit mask parameter.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
||||||
u_int32_t mask)
|
u_int32_t mask)
|
||||||
@ -1220,6 +1226,8 @@ int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param
|
|||||||
* @mask: the 64bit bitmap mask
|
* @mask: the 64bit bitmap mask
|
||||||
*
|
*
|
||||||
* Apply the constraint of the given bitmap mask to a 64-bit mask parameter.
|
* Apply the constraint of the given bitmap mask to a 64-bit mask parameter.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
||||||
u_int64_t mask)
|
u_int64_t mask)
|
||||||
@ -1240,6 +1248,9 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
|
|||||||
* @var: hw_params variable to apply the integer constraint
|
* @var: hw_params variable to apply the integer constraint
|
||||||
*
|
*
|
||||||
* Apply the constraint of integer to an interval parameter.
|
* Apply the constraint of integer to an interval parameter.
|
||||||
|
*
|
||||||
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var)
|
int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var)
|
||||||
{
|
{
|
||||||
@ -1257,6 +1268,9 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
|
|||||||
* @max: the maximal value
|
* @max: the maximal value
|
||||||
*
|
*
|
||||||
* Apply the min/max range constraint to an interval parameter.
|
* Apply the min/max range constraint to an interval parameter.
|
||||||
|
*
|
||||||
|
* Return: Positive if the value is changed, zero if it's not changed, or a
|
||||||
|
* negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
|
||||||
unsigned int min, unsigned int max)
|
unsigned int min, unsigned int max)
|
||||||
@ -1288,6 +1302,8 @@ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
|
|||||||
* @l: list
|
* @l: list
|
||||||
*
|
*
|
||||||
* Apply the list of constraints to an interval parameter.
|
* Apply the list of constraints to an interval parameter.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1322,6 +1338,8 @@ static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
|
|||||||
* @cond: condition bits
|
* @cond: condition bits
|
||||||
* @var: hw_params variable to apply the ratnums constraint
|
* @var: hw_params variable to apply the ratnums constraint
|
||||||
* @r: struct snd_ratnums constriants
|
* @r: struct snd_ratnums constriants
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1355,6 +1373,8 @@ static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
|
|||||||
* @cond: condition bits
|
* @cond: condition bits
|
||||||
* @var: hw_params variable to apply the ratdens constraint
|
* @var: hw_params variable to apply the ratdens constraint
|
||||||
* @r: struct snd_ratdens constriants
|
* @r: struct snd_ratdens constriants
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1386,6 +1406,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
|
|||||||
* @cond: condition bits
|
* @cond: condition bits
|
||||||
* @width: sample bits width
|
* @width: sample bits width
|
||||||
* @msbits: msbits width
|
* @msbits: msbits width
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1414,6 +1436,8 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
|
|||||||
* @cond: condition bits
|
* @cond: condition bits
|
||||||
* @var: hw_params variable to apply the step constraint
|
* @var: hw_params variable to apply the step constraint
|
||||||
* @step: step size
|
* @step: step size
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1444,6 +1468,8 @@ static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm
|
|||||||
* @runtime: PCM runtime instance
|
* @runtime: PCM runtime instance
|
||||||
* @cond: condition bits
|
* @cond: condition bits
|
||||||
* @var: hw_params variable to apply the power-of-2 constraint
|
* @var: hw_params variable to apply the power-of-2 constraint
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int cond,
|
unsigned int cond,
|
||||||
@ -1470,6 +1496,8 @@ static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
|
|||||||
* snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
|
* snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
|
||||||
* @runtime: PCM runtime instance
|
* @runtime: PCM runtime instance
|
||||||
* @base_rate: the rate at which the hardware does not resample
|
* @base_rate: the rate at which the hardware does not resample
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
|
int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
|
||||||
unsigned int base_rate)
|
unsigned int base_rate)
|
||||||
@ -1519,8 +1547,8 @@ EXPORT_SYMBOL(_snd_pcm_hw_params_any);
|
|||||||
* @var: parameter to retrieve
|
* @var: parameter to retrieve
|
||||||
* @dir: pointer to the direction (-1,0,1) or %NULL
|
* @dir: pointer to the direction (-1,0,1) or %NULL
|
||||||
*
|
*
|
||||||
* Return the value for field @var if it's fixed in configuration space
|
* Return: The value for field @var if it's fixed in configuration space
|
||||||
* defined by @params. Return -%EINVAL otherwise.
|
* defined by @params. -%EINVAL otherwise.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
|
int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
|
||||||
snd_pcm_hw_param_t var, int *dir)
|
snd_pcm_hw_param_t var, int *dir)
|
||||||
@ -1591,7 +1619,8 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
|
|||||||
*
|
*
|
||||||
* Inside configuration space defined by @params remove from @var all
|
* Inside configuration space defined by @params remove from @var all
|
||||||
* values > minimum. Reduce configuration space accordingly.
|
* values > minimum. Reduce configuration space accordingly.
|
||||||
* Return the minimum.
|
*
|
||||||
|
* Return: The minimum, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
|
int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
|
||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
@ -1637,7 +1666,8 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
|
|||||||
*
|
*
|
||||||
* Inside configuration space defined by @params remove from @var all
|
* Inside configuration space defined by @params remove from @var all
|
||||||
* values < maximum. Reduce configuration space accordingly.
|
* values < maximum. Reduce configuration space accordingly.
|
||||||
* Return the maximum.
|
*
|
||||||
|
* Return: The maximum, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
|
int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
|
||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
@ -1665,6 +1695,8 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
|
|||||||
* The configuration chosen is that obtained fixing in this order:
|
* The configuration chosen is that obtained fixing in this order:
|
||||||
* first access, first format, first subformat, min channels,
|
* first access, first format, first subformat, min channels,
|
||||||
* min rate, min period time, max buffer size, min tick time
|
* 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,
|
int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params)
|
||||||
@ -1771,7 +1803,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
|
|||||||
* Processes the generic ioctl commands for PCM.
|
* Processes the generic ioctl commands for PCM.
|
||||||
* Can be passed as the ioctl callback for PCM ops.
|
* Can be passed as the ioctl callback for PCM ops.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
|
int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
|
||||||
unsigned int cmd, void *arg)
|
unsigned int cmd, void *arg)
|
||||||
@ -2510,7 +2542,7 @@ static void pcm_chmap_ctl_private_free(struct snd_kcontrol *kcontrol)
|
|||||||
* @info_ret: store struct snd_pcm_chmap instance if non-NULL
|
* @info_ret: store struct snd_pcm_chmap instance if non-NULL
|
||||||
*
|
*
|
||||||
* Create channel-mapping control elements assigned to the given PCM stream(s).
|
* Create channel-mapping control elements assigned to the given PCM stream(s).
|
||||||
* Returns zero if succeed, or a negative error value.
|
* Return: Zero if successful, or a negative error value.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
|
int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
|
||||||
const struct snd_pcm_chmap_elem *chmap,
|
const struct snd_pcm_chmap_elem *chmap,
|
||||||
|
@ -95,7 +95,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
|
|||||||
*
|
*
|
||||||
* Releases the pre-allocated buffer of the given substream.
|
* Releases the pre-allocated buffer of the given substream.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
|
int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -115,7 +115,7 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
|
|||||||
*
|
*
|
||||||
* Releases all the pre-allocated buffers on the given pcm.
|
* Releases all the pre-allocated buffers on the given pcm.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
|
int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
|
||||||
{
|
{
|
||||||
@ -265,7 +265,7 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
|
|||||||
* destruction time. The dma_buf_id must be unique for all systems
|
* destruction time. The dma_buf_id must be unique for all systems
|
||||||
* (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
|
* (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
|
int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
|
||||||
int type, struct device *data,
|
int type, struct device *data,
|
||||||
@ -289,7 +289,7 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
|
|||||||
* Do pre-allocation to all substreams of the given pcm for the
|
* Do pre-allocation to all substreams of the given pcm for the
|
||||||
* specified DMA type.
|
* specified DMA type.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
|
int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
|
||||||
int type, void *data,
|
int type, void *data,
|
||||||
@ -313,8 +313,9 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
|
|||||||
* @substream: the pcm substream instance
|
* @substream: the pcm substream instance
|
||||||
* @offset: the buffer offset
|
* @offset: the buffer offset
|
||||||
*
|
*
|
||||||
* Returns the page struct at the given buffer offset.
|
|
||||||
* Used as the page callback of PCM ops.
|
* Used as the page callback of PCM ops.
|
||||||
|
*
|
||||||
|
* Return: The page struct at the given buffer offset. %NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
|
struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
|
||||||
{
|
{
|
||||||
@ -337,7 +338,7 @@ EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
|
|||||||
* Allocates the DMA buffer on the BUS type given earlier to
|
* Allocates the DMA buffer on the BUS type given earlier to
|
||||||
* snd_pcm_lib_preallocate_xxx_pages().
|
* snd_pcm_lib_preallocate_xxx_pages().
|
||||||
*
|
*
|
||||||
* Returns 1 if the buffer is changed, 0 if not changed, or a negative
|
* Return: 1 if the buffer is changed, 0 if not changed, or a negative
|
||||||
* code on failure.
|
* code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
|
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
|
||||||
@ -390,7 +391,7 @@ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
|
|||||||
*
|
*
|
||||||
* Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().
|
* Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -437,6 +438,8 @@ EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
|
|||||||
* snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
|
* snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
|
||||||
* @substream: the substream with a buffer allocated by
|
* @substream: the substream with a buffer allocated by
|
||||||
* snd_pcm_lib_alloc_vmalloc_buffer()
|
* snd_pcm_lib_alloc_vmalloc_buffer()
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
|
int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -458,6 +461,8 @@ EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
|
|||||||
* @offset: offset in the buffer
|
* @offset: offset in the buffer
|
||||||
*
|
*
|
||||||
* This function is to be used as the page callback in the PCM ops.
|
* This function is to be used as the page callback in the PCM ops.
|
||||||
|
*
|
||||||
|
* Return: The page struct, or %NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
|
@ -140,6 +140,14 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
|||||||
.width = 5, .phys = 5, .le = -1, .signd = -1,
|
.width = 5, .phys = 5, .le = -1, .signd = -1,
|
||||||
.silence = {},
|
.silence = {},
|
||||||
},
|
},
|
||||||
|
[SNDRV_PCM_FORMAT_DSD_U8] = {
|
||||||
|
.width = 8, .phys = 8, .le = 1, .signd = 0,
|
||||||
|
.silence = {},
|
||||||
|
},
|
||||||
|
[SNDRV_PCM_FORMAT_DSD_U16_LE] = {
|
||||||
|
.width = 16, .phys = 16, .le = 1, .signd = 0,
|
||||||
|
.silence = {},
|
||||||
|
},
|
||||||
/* FIXME: the following three formats are not defined properly yet */
|
/* FIXME: the following three formats are not defined properly yet */
|
||||||
[SNDRV_PCM_FORMAT_MPEG] = {
|
[SNDRV_PCM_FORMAT_MPEG] = {
|
||||||
.le = -1, .signd = -1,
|
.le = -1, .signd = -1,
|
||||||
@ -213,7 +221,7 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
|||||||
* snd_pcm_format_signed - Check the PCM format is signed linear
|
* snd_pcm_format_signed - Check the PCM format is signed linear
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is signed linear, 0 if unsigned
|
* Return: 1 if the given PCM format is signed linear, 0 if unsigned
|
||||||
* linear, and a negative error code for non-linear formats.
|
* linear, and a negative error code for non-linear formats.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_signed(snd_pcm_format_t format)
|
int snd_pcm_format_signed(snd_pcm_format_t format)
|
||||||
@ -232,7 +240,7 @@ EXPORT_SYMBOL(snd_pcm_format_signed);
|
|||||||
* snd_pcm_format_unsigned - Check the PCM format is unsigned linear
|
* snd_pcm_format_unsigned - Check the PCM format is unsigned linear
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is unsigned linear, 0 if signed
|
* Return: 1 if the given PCM format is unsigned linear, 0 if signed
|
||||||
* linear, and a negative error code for non-linear formats.
|
* linear, and a negative error code for non-linear formats.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_unsigned(snd_pcm_format_t format)
|
int snd_pcm_format_unsigned(snd_pcm_format_t format)
|
||||||
@ -251,7 +259,7 @@ EXPORT_SYMBOL(snd_pcm_format_unsigned);
|
|||||||
* snd_pcm_format_linear - Check the PCM format is linear
|
* snd_pcm_format_linear - Check the PCM format is linear
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is linear, 0 if not.
|
* Return: 1 if the given PCM format is linear, 0 if not.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_linear(snd_pcm_format_t format)
|
int snd_pcm_format_linear(snd_pcm_format_t format)
|
||||||
{
|
{
|
||||||
@ -264,7 +272,7 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
|
|||||||
* snd_pcm_format_little_endian - Check the PCM format is little-endian
|
* snd_pcm_format_little_endian - Check the PCM format is little-endian
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is little-endian, 0 if
|
* Return: 1 if the given PCM format is little-endian, 0 if
|
||||||
* big-endian, or a negative error code if endian not specified.
|
* big-endian, or a negative error code if endian not specified.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_little_endian(snd_pcm_format_t format)
|
int snd_pcm_format_little_endian(snd_pcm_format_t format)
|
||||||
@ -283,7 +291,7 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian);
|
|||||||
* snd_pcm_format_big_endian - Check the PCM format is big-endian
|
* snd_pcm_format_big_endian - Check the PCM format is big-endian
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns 1 if the given PCM format is big-endian, 0 if
|
* Return: 1 if the given PCM format is big-endian, 0 if
|
||||||
* little-endian, or a negative error code if endian not specified.
|
* little-endian, or a negative error code if endian not specified.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_big_endian(snd_pcm_format_t format)
|
int snd_pcm_format_big_endian(snd_pcm_format_t format)
|
||||||
@ -302,7 +310,7 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian);
|
|||||||
* snd_pcm_format_width - return the bit-width of the format
|
* snd_pcm_format_width - return the bit-width of the format
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns the bit-width of the format, or a negative error code
|
* Return: The bit-width of the format, or a negative error code
|
||||||
* if unknown format.
|
* if unknown format.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_width(snd_pcm_format_t format)
|
int snd_pcm_format_width(snd_pcm_format_t format)
|
||||||
@ -321,7 +329,7 @@ EXPORT_SYMBOL(snd_pcm_format_width);
|
|||||||
* snd_pcm_format_physical_width - return the physical bit-width of the format
|
* snd_pcm_format_physical_width - return the physical bit-width of the format
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns the physical bit-width of the format, or a negative error code
|
* Return: The physical bit-width of the format, or a negative error code
|
||||||
* if unknown format.
|
* if unknown format.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_physical_width(snd_pcm_format_t format)
|
int snd_pcm_format_physical_width(snd_pcm_format_t format)
|
||||||
@ -341,7 +349,7 @@ EXPORT_SYMBOL(snd_pcm_format_physical_width);
|
|||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
* @samples: sampling rate
|
* @samples: sampling rate
|
||||||
*
|
*
|
||||||
* Returns the byte size of the given samples for the format, or a
|
* Return: The byte size of the given samples for the format, or a
|
||||||
* negative error code if unknown format.
|
* negative error code if unknown format.
|
||||||
*/
|
*/
|
||||||
ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
|
ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
|
||||||
@ -358,7 +366,7 @@ EXPORT_SYMBOL(snd_pcm_format_size);
|
|||||||
* snd_pcm_format_silence_64 - return the silent data in 8 bytes array
|
* snd_pcm_format_silence_64 - return the silent data in 8 bytes array
|
||||||
* @format: the format to check
|
* @format: the format to check
|
||||||
*
|
*
|
||||||
* Returns the format pattern to fill or NULL if error.
|
* Return: The format pattern to fill or %NULL if error.
|
||||||
*/
|
*/
|
||||||
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
|
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
|
||||||
{
|
{
|
||||||
@ -379,7 +387,7 @@ EXPORT_SYMBOL(snd_pcm_format_silence_64);
|
|||||||
*
|
*
|
||||||
* Sets the silence data on the buffer for the given samples.
|
* Sets the silence data on the buffer for the given samples.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
|
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
|
||||||
{
|
{
|
||||||
@ -449,7 +457,7 @@ EXPORT_SYMBOL(snd_pcm_format_set_silence);
|
|||||||
* Determines the rate_min and rate_max fields from the rates bits of
|
* Determines the rate_min and rate_max fields from the rates bits of
|
||||||
* the given runtime->hw.
|
* the given runtime->hw.
|
||||||
*
|
*
|
||||||
* Returns zero if successful.
|
* Return: Zero if successful.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
|
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
|
||||||
{
|
{
|
||||||
@ -475,7 +483,7 @@ EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
|
|||||||
* snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
|
* snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
|
||||||
* @rate: the sample rate to convert
|
* @rate: the sample rate to convert
|
||||||
*
|
*
|
||||||
* Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
|
* Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
|
||||||
* SNDRV_PCM_RATE_KNOT for an unknown rate.
|
* SNDRV_PCM_RATE_KNOT for an unknown rate.
|
||||||
*/
|
*/
|
||||||
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
|
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
|
||||||
@ -493,8 +501,8 @@ EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
|
|||||||
* snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate
|
* snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate
|
||||||
* @rate_bit: the rate bit to convert
|
* @rate_bit: the rate bit to convert
|
||||||
*
|
*
|
||||||
* Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
|
* Return: The sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
|
||||||
* or 0 for an unknown rate bit
|
* or 0 for an unknown rate bit.
|
||||||
*/
|
*/
|
||||||
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
|
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
|
||||||
{
|
{
|
||||||
|
@ -898,6 +898,8 @@ static struct action_ops snd_pcm_action_start = {
|
|||||||
/**
|
/**
|
||||||
* snd_pcm_start - start all linked streams
|
* snd_pcm_start - start all linked streams
|
||||||
* @substream: the PCM substream instance
|
* @substream: the PCM substream instance
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_start(struct snd_pcm_substream *substream)
|
int snd_pcm_start(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -951,6 +953,8 @@ static struct action_ops snd_pcm_action_stop = {
|
|||||||
* @state: PCM state after stopping the stream
|
* @state: PCM state after stopping the stream
|
||||||
*
|
*
|
||||||
* The state of each stream is then changed to the given state unconditionally.
|
* The state of each stream is then changed to the given state unconditionally.
|
||||||
|
*
|
||||||
|
* Return: Zero if succesful, or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
|
int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
|
||||||
{
|
{
|
||||||
@ -965,6 +969,8 @@ EXPORT_SYMBOL(snd_pcm_stop);
|
|||||||
*
|
*
|
||||||
* After stopping, the state is changed to SETUP.
|
* After stopping, the state is changed to SETUP.
|
||||||
* Unlike snd_pcm_stop(), this affects only the given stream.
|
* Unlike snd_pcm_stop(), this affects only the given stream.
|
||||||
|
*
|
||||||
|
* Return: Zero if succesful, or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
|
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -1098,6 +1104,9 @@ static struct action_ops snd_pcm_action_suspend = {
|
|||||||
* @substream: the PCM substream
|
* @substream: the PCM substream
|
||||||
*
|
*
|
||||||
* After this call, all streams are changed to SUSPENDED state.
|
* After this call, all streams are changed to SUSPENDED state.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful (or @substream is %NULL), or a negative error
|
||||||
|
* code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_suspend(struct snd_pcm_substream *substream)
|
int snd_pcm_suspend(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
@ -1120,6 +1129,8 @@ EXPORT_SYMBOL(snd_pcm_suspend);
|
|||||||
* @pcm: the PCM instance
|
* @pcm: the PCM instance
|
||||||
*
|
*
|
||||||
* After this call, all streams are changed to SUSPENDED state.
|
* After this call, all streams are changed to SUSPENDED state.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful (or @pcm is %NULL), or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_suspend_all(struct snd_pcm *pcm)
|
int snd_pcm_suspend_all(struct snd_pcm *pcm)
|
||||||
{
|
{
|
||||||
@ -1343,6 +1354,8 @@ static struct action_ops snd_pcm_action_prepare = {
|
|||||||
* snd_pcm_prepare - prepare the PCM substream to be triggerable
|
* snd_pcm_prepare - prepare the PCM substream to be triggerable
|
||||||
* @substream: the PCM substream instance
|
* @substream: the PCM substream instance
|
||||||
* @file: file to refer f_flags
|
* @file: file to refer f_flags
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code.
|
||||||
*/
|
*/
|
||||||
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
|
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
|
@ -863,7 +863,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
|
|||||||
*
|
*
|
||||||
* Reads the data from the internal buffer.
|
* Reads the data from the internal buffer.
|
||||||
*
|
*
|
||||||
* Returns the size of read data, or a negative error code on failure.
|
* Return: The size of read data, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
|
int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
|
||||||
const unsigned char *buffer, int count)
|
const unsigned char *buffer, int count)
|
||||||
@ -1025,7 +1025,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
|
|||||||
* snd_rawmidi_transmit_empty - check whether the output buffer is empty
|
* snd_rawmidi_transmit_empty - check whether the output buffer is empty
|
||||||
* @substream: the rawmidi substream
|
* @substream: the rawmidi substream
|
||||||
*
|
*
|
||||||
* Returns 1 if the internal output buffer is empty, 0 if not.
|
* Return: 1 if the internal output buffer is empty, 0 if not.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
|
int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
|
||||||
{
|
{
|
||||||
@ -1055,7 +1055,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
|
|||||||
* and call snd_rawmidi_transmit_ack() after the transmission is
|
* and call snd_rawmidi_transmit_ack() after the transmission is
|
||||||
* finished.
|
* finished.
|
||||||
*
|
*
|
||||||
* Returns the size of copied data, or a negative error code on failure.
|
* Return: The size of copied data, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
||||||
unsigned char *buffer, int count)
|
unsigned char *buffer, int count)
|
||||||
@ -1107,7 +1107,7 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|||||||
* the given size and updates the condition.
|
* the given size and updates the condition.
|
||||||
* Call after the transmission is finished.
|
* Call after the transmission is finished.
|
||||||
*
|
*
|
||||||
* Returns the advanced size if successful, or a negative error code on failure.
|
* Return: The advanced size if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
||||||
{
|
{
|
||||||
@ -1140,7 +1140,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|||||||
*
|
*
|
||||||
* Copies data from the buffer to the device and advances the pointer.
|
* Copies data from the buffer to the device and advances the pointer.
|
||||||
*
|
*
|
||||||
* Returns the copied size if successful, or a negative error code on failure.
|
* Return: The copied size if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
|
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
|
||||||
unsigned char *buffer, int count)
|
unsigned char *buffer, int count)
|
||||||
@ -1438,7 +1438,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
|
|||||||
* Creates a new rawmidi instance.
|
* Creates a new rawmidi instance.
|
||||||
* Use snd_rawmidi_set_ops() to set the operators to the new instance.
|
* Use snd_rawmidi_set_ops() to set the operators to the new instance.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_rawmidi_new(struct snd_card *card, char *id, int device,
|
int snd_rawmidi_new(struct snd_card *card, char *id, int device,
|
||||||
int output_count, int input_count,
|
int output_count, int input_count,
|
||||||
|
@ -102,6 +102,9 @@ static void snd_request_other(int minor)
|
|||||||
* This function increments the reference counter of the card instance
|
* This function increments the reference counter of the card instance
|
||||||
* if an associated instance with the given minor number and type is found.
|
* if an associated instance with the given minor number and type is found.
|
||||||
* The caller must call snd_card_unref() appropriately later.
|
* The caller must call snd_card_unref() appropriately later.
|
||||||
|
*
|
||||||
|
* Return: The user data pointer if the specified device is found. %NULL
|
||||||
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
void *snd_lookup_minor_data(unsigned int minor, int type)
|
void *snd_lookup_minor_data(unsigned int minor, int type)
|
||||||
{
|
{
|
||||||
@ -261,7 +264,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
|
|||||||
* Registers an ALSA device file for the given card.
|
* Registers an ALSA device file for the given card.
|
||||||
* The operators have to be set in reg parameter.
|
* The operators have to be set in reg parameter.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
|
int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
|
||||||
const struct file_operations *f_ops,
|
const struct file_operations *f_ops,
|
||||||
@ -339,7 +342,7 @@ static int find_snd_minor(int type, struct snd_card *card, int dev)
|
|||||||
* Unregisters the device file already registered via
|
* Unregisters the device file already registered via
|
||||||
* snd_register_device().
|
* snd_register_device().
|
||||||
*
|
*
|
||||||
* Returns zero if sucecessful, or a negative error code on failure
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_unregister_device(int type, struct snd_card *card, int dev)
|
int snd_unregister_device(int type, struct snd_card *card, int dev)
|
||||||
{
|
{
|
||||||
|
@ -365,8 +365,7 @@ static void master_free(struct snd_kcontrol *kcontrol)
|
|||||||
* @name: name string of the control element to create
|
* @name: name string of the control element to create
|
||||||
* @tlv: optional TLV int array for dB information
|
* @tlv: optional TLV int array for dB information
|
||||||
*
|
*
|
||||||
* Creates a virtual matster control with the given name string.
|
* Creates a virtual master control with the given name string.
|
||||||
* Returns the created control element, or NULL for errors (ENOMEM).
|
|
||||||
*
|
*
|
||||||
* After creating a vmaster element, you can add the slave controls
|
* After creating a vmaster element, you can add the slave controls
|
||||||
* via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
|
* via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
|
||||||
@ -375,6 +374,8 @@ static void master_free(struct snd_kcontrol *kcontrol)
|
|||||||
* for dB scale of the master control. It should be a single element
|
* for dB scale of the master control. It should be a single element
|
||||||
* with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
|
* with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
|
||||||
* #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
|
* #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
|
||||||
|
*
|
||||||
|
* Return: The created control element, or %NULL for errors (ENOMEM).
|
||||||
*/
|
*/
|
||||||
struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
|
struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
|
||||||
const unsigned int *tlv)
|
const unsigned int *tlv)
|
||||||
@ -426,6 +427,8 @@ EXPORT_SYMBOL(snd_ctl_make_virtual_master);
|
|||||||
*
|
*
|
||||||
* Adds the given hook to the vmaster control element so that it's called
|
* Adds the given hook to the vmaster control element so that it's called
|
||||||
* at each time when the value is changed.
|
* at each time when the value is changed.
|
||||||
|
*
|
||||||
|
* Return: Zero.
|
||||||
*/
|
*/
|
||||||
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
|
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
|
||||||
void (*hook)(void *private_data, int),
|
void (*hook)(void *private_data, int),
|
||||||
|
@ -87,7 +87,7 @@ config SND_ALOOP
|
|||||||
configured number of substreams (see the pcm_substreams module
|
configured number of substreams (see the pcm_substreams module
|
||||||
parameter).
|
parameter).
|
||||||
|
|
||||||
The looback device allow time sychronization with an external
|
The loopback device allows time sychronization with an external
|
||||||
timing source using the time shift universal control (+-20%
|
timing source using the time shift universal control (+-20%
|
||||||
of system time).
|
of system time).
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ static void params_change(struct snd_pcm_substream *substream)
|
|||||||
struct loopback_pcm *dpcm = runtime->private_data;
|
struct loopback_pcm *dpcm = runtime->private_data;
|
||||||
struct loopback_cable *cable = dpcm->cable;
|
struct loopback_cable *cable = dpcm->cable;
|
||||||
|
|
||||||
cable->hw.formats = (1ULL << runtime->format);
|
cable->hw.formats = pcm_format_to_bits(runtime->format);
|
||||||
cable->hw.rate_min = runtime->rate;
|
cable->hw.rate_min = runtime->rate;
|
||||||
cable->hw.rate_max = runtime->rate;
|
cable->hw.rate_max = runtime->rate;
|
||||||
cable->hw.channels_min = runtime->channels;
|
cable->hw.channels_min = runtime->channels;
|
||||||
|
@ -129,6 +129,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
|
|||||||
* @dev_id: mpu401 instance
|
* @dev_id: mpu401 instance
|
||||||
*
|
*
|
||||||
* Processes the interrupt for MPU401-UART i/o.
|
* Processes the interrupt for MPU401-UART i/o.
|
||||||
|
*
|
||||||
|
* Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
|
||||||
*/
|
*/
|
||||||
irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id)
|
irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
@ -148,6 +150,8 @@ EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
|
|||||||
* @dev_id: mpu401 instance
|
* @dev_id: mpu401 instance
|
||||||
*
|
*
|
||||||
* Processes the interrupt for MPU401-UART output.
|
* Processes the interrupt for MPU401-UART output.
|
||||||
|
*
|
||||||
|
* Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
|
||||||
*/
|
*/
|
||||||
irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id)
|
irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
@ -519,7 +523,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
|
|||||||
* not the mpu401 instance itself. To access to the mpu401 instance,
|
* not the mpu401 instance itself. To access to the mpu401 instance,
|
||||||
* cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
|
* cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code.
|
* Return: Zero if successful, or a negative error code.
|
||||||
*/
|
*/
|
||||||
int snd_mpu401_uart_new(struct snd_card *card, int device,
|
int snd_mpu401_uart_new(struct snd_card *card, int device,
|
||||||
unsigned short hardware,
|
unsigned short hardware,
|
||||||
|
@ -114,7 +114,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dmap->raw_buf = start_addr;
|
dmap->raw_buf = start_addr;
|
||||||
dmap->raw_buf_phys = virt_to_bus(start_addr);
|
dmap->raw_buf_phys = dma_map_single(NULL, start_addr, dmap->buffsize, DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
|
for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
|
||||||
SetPageReserved(page);
|
SetPageReserved(page);
|
||||||
@ -139,6 +139,7 @@ static void sound_free_dmap(struct dma_buffparms *dmap)
|
|||||||
for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
|
for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
|
||||||
ClearPageReserved(page);
|
ClearPageReserved(page);
|
||||||
|
|
||||||
|
dma_unmap_single(NULL, dmap->raw_buf_phys, dmap->buffsize, DMA_BIDIRECTIONAL);
|
||||||
free_pages((unsigned long) dmap->raw_buf, sz);
|
free_pages((unsigned long) dmap->raw_buf, sz);
|
||||||
dmap->raw_buf = NULL;
|
dmap->raw_buf = NULL;
|
||||||
}
|
}
|
||||||
|
@ -626,13 +626,12 @@ int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL);
|
detected_devc = kmemdup(devc, sizeof(sb_devc), GFP_KERNEL);
|
||||||
if (detected_devc == NULL)
|
if (detected_devc == NULL)
|
||||||
{
|
{
|
||||||
printk(KERN_ERR "sb: Can't allocate memory for device information\n");
|
printk(KERN_ERR "sb: Can't allocate memory for device information\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(detected_devc, devc, sizeof(sb_devc));
|
|
||||||
MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
|
MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -352,23 +352,26 @@ int probe_uart401(struct address_info *hw_config, struct module *owner)
|
|||||||
goto cleanup_irq;
|
goto cleanup_irq;
|
||||||
}
|
}
|
||||||
conf_printf(name, hw_config);
|
conf_printf(name, hw_config);
|
||||||
midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
|
midi_devs[devc->my_dev] = kmemdup(&uart401_operations,
|
||||||
|
sizeof(struct midi_operations),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!midi_devs[devc->my_dev]) {
|
if (!midi_devs[devc->my_dev]) {
|
||||||
printk(KERN_ERR "uart401: Failed to allocate memory\n");
|
printk(KERN_ERR "uart401: Failed to allocate memory\n");
|
||||||
goto cleanup_unload_mididev;
|
goto cleanup_unload_mididev;
|
||||||
}
|
}
|
||||||
memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations));
|
|
||||||
|
|
||||||
if (owner)
|
if (owner)
|
||||||
midi_devs[devc->my_dev]->owner = owner;
|
midi_devs[devc->my_dev]->owner = owner;
|
||||||
|
|
||||||
midi_devs[devc->my_dev]->devc = devc;
|
midi_devs[devc->my_dev]->devc = devc;
|
||||||
midi_devs[devc->my_dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
|
midi_devs[devc->my_dev]->converter = kmemdup(&std_midi_synth,
|
||||||
|
sizeof(struct synth_operations),
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!midi_devs[devc->my_dev]->converter) {
|
if (!midi_devs[devc->my_dev]->converter) {
|
||||||
printk(KERN_WARNING "uart401: Failed to allocate memory\n");
|
printk(KERN_WARNING "uart401: Failed to allocate memory\n");
|
||||||
goto cleanup_midi_devs;
|
goto cleanup_midi_devs;
|
||||||
}
|
}
|
||||||
memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations));
|
|
||||||
strcpy(midi_devs[devc->my_dev]->info.name, name);
|
strcpy(midi_devs[devc->my_dev]->info.name, name);
|
||||||
midi_devs[devc->my_dev]->converter->id = "UART401";
|
midi_devs[devc->my_dev]->converter->id = "UART401";
|
||||||
midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
|
midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
|
||||||
|
@ -299,7 +299,7 @@ EXPORT_SYMBOL(snd_ac97_write);
|
|||||||
* Reads a value from the given register. This will invoke the read
|
* Reads a value from the given register. This will invoke the read
|
||||||
* callback directly after the register check.
|
* callback directly after the register check.
|
||||||
*
|
*
|
||||||
* Returns the read value.
|
* Return: The read value.
|
||||||
*/
|
*/
|
||||||
unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
|
unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
|
||||||
{
|
{
|
||||||
@ -352,7 +352,7 @@ EXPORT_SYMBOL(snd_ac97_write_cache);
|
|||||||
* Compares the value with the register cache and updates the value
|
* Compares the value with the register cache and updates the value
|
||||||
* only when the value is changed.
|
* only when the value is changed.
|
||||||
*
|
*
|
||||||
* Returns 1 if the value is changed, 0 if no change, or a negative
|
* Return: 1 if the value is changed, 0 if no change, or a negative
|
||||||
* code on failure.
|
* code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
|
int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
|
||||||
@ -384,7 +384,7 @@ EXPORT_SYMBOL(snd_ac97_update);
|
|||||||
* Updates the masked-bits on the given register only when the value
|
* Updates the masked-bits on the given register only when the value
|
||||||
* is changed.
|
* is changed.
|
||||||
*
|
*
|
||||||
* Returns 1 if the bits are changed, 0 if no change, or a negative
|
* Return: 1 if the bits are changed, 0 if no change, or a negative
|
||||||
* code on failure.
|
* code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
|
int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
|
||||||
@ -1836,7 +1836,7 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m
|
|||||||
* snd_ac97_get_short_name - retrieve codec name
|
* snd_ac97_get_short_name - retrieve codec name
|
||||||
* @ac97: the codec instance
|
* @ac97: the codec instance
|
||||||
*
|
*
|
||||||
* Returns the short identifying name of the codec.
|
* Return: The short identifying name of the codec.
|
||||||
*/
|
*/
|
||||||
const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
|
const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
|
||||||
{
|
{
|
||||||
@ -1910,7 +1910,7 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
|
|||||||
* The AC97 bus instance is registered as a low-level device, so you don't
|
* The AC97 bus instance is registered as a low-level device, so you don't
|
||||||
* have to release it manually.
|
* have to release it manually.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
|
int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
|
||||||
void *private_data, struct snd_ac97_bus **rbus)
|
void *private_data, struct snd_ac97_bus **rbus)
|
||||||
@ -2006,7 +2006,7 @@ static void do_update_power(struct work_struct *work)
|
|||||||
* The ac97 instance is registered as a low-level device, so you don't
|
* The ac97 instance is registered as a low-level device, so you don't
|
||||||
* have to release it manually.
|
* have to release it manually.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
|
int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
|
||||||
{
|
{
|
||||||
@ -2373,6 +2373,8 @@ static struct ac97_power_reg power_regs[PWIDX_SIZE] = {
|
|||||||
* @powerup: non-zero when power up the part
|
* @powerup: non-zero when power up the part
|
||||||
*
|
*
|
||||||
* Update the AC97 powerdown register bits of the given part.
|
* Update the AC97 powerdown register bits of the given part.
|
||||||
|
*
|
||||||
|
* Return: Zero.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
|
int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
|
||||||
{
|
{
|
||||||
@ -2885,7 +2887,7 @@ static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
|
|||||||
* headphone (true line-out) control as "Master".
|
* headphone (true line-out) control as "Master".
|
||||||
* The quirk-list must be terminated with a zero-filled entry.
|
* The quirk-list must be terminated with a zero-filled entry.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override)
|
int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override)
|
||||||
|
@ -253,7 +253,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate)
|
|||||||
* AC97_SPDIF is accepted as a pseudo register to modify the SPDIF
|
* AC97_SPDIF is accepted as a pseudo register to modify the SPDIF
|
||||||
* status bits.
|
* status bits.
|
||||||
*
|
*
|
||||||
* Returns zero if successful, or a negative error code on failure.
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
|
int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
|
||||||
{
|
{
|
||||||
@ -440,6 +440,8 @@ static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned
|
|||||||
* It assigns available AC97 slots for given PCMs. If none or only
|
* It assigns available AC97 slots for given PCMs. If none or only
|
||||||
* some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
|
* some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
|
||||||
* are reduced and might be zero.
|
* are reduced and might be zero.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
|
int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
|
||||||
unsigned short pcms_count,
|
unsigned short pcms_count,
|
||||||
@ -562,6 +564,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_assign);
|
|||||||
* @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
|
* @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
|
||||||
*
|
*
|
||||||
* It locks the specified slots and sets the given rate to AC97 registers.
|
* It locks the specified slots and sets the given rate to AC97 registers.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
|
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
|
||||||
enum ac97_pcm_cfg cfg, unsigned short slots)
|
enum ac97_pcm_cfg cfg, unsigned short slots)
|
||||||
@ -644,6 +648,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_open);
|
|||||||
* @pcm: the ac97 pcm instance
|
* @pcm: the ac97 pcm instance
|
||||||
*
|
*
|
||||||
* It frees the locked AC97 slots.
|
* It frees the locked AC97 slots.
|
||||||
|
*
|
||||||
|
* Return: Zero.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_pcm_close(struct ac97_pcm *pcm)
|
int snd_ac97_pcm_close(struct ac97_pcm *pcm)
|
||||||
{
|
{
|
||||||
@ -718,6 +724,8 @@ static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
|
|||||||
*
|
*
|
||||||
* Installs the hardware constraint rules to prevent using double rates and
|
* Installs the hardware constraint rules to prevent using double rates and
|
||||||
* more than two channels at the same time.
|
* more than two channels at the same time.
|
||||||
|
*
|
||||||
|
* Return: Zero if successful, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
|
int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
|
||||||
{
|
{
|
||||||
|
@ -451,10 +451,10 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
|
|||||||
if (pci_dev) {
|
if (pci_dev) {
|
||||||
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
||||||
pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
|
pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
|
||||||
udelay(5000);
|
mdelay(5);
|
||||||
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
||||||
pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
|
pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
|
||||||
udelay(5000);
|
mdelay(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_dev = codec->pci;
|
pci_dev = codec->pci;
|
||||||
@ -463,14 +463,14 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
|
|||||||
udelay(500);
|
udelay(500);
|
||||||
pci_read_config_dword(pci_dev, 0x44, &dwVal);
|
pci_read_config_dword(pci_dev, 0x44, &dwVal);
|
||||||
pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
|
pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
|
||||||
udelay(5000);
|
mdelay(5);
|
||||||
|
|
||||||
wCount = 200;
|
wCount = 200;
|
||||||
while(wCount--) {
|
while(wCount--) {
|
||||||
wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);
|
wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);
|
||||||
if ((wReg & 0x000f) == 0x000f)
|
if ((wReg & 0x000f) == 0x000f)
|
||||||
return 0;
|
return 0;
|
||||||
udelay(5000);
|
mdelay(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non-fatal if you have a non PM capable codec */
|
/* non-fatal if you have a non PM capable codec */
|
||||||
|
@ -966,7 +966,7 @@ static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi,
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = hpi_outstream_query_format(h_stream, &hpi_format);
|
err = hpi_outstream_query_format(h_stream, &hpi_format);
|
||||||
if (!err && (hpi_to_alsa_formats[format] != -1))
|
if (!err && (hpi_to_alsa_formats[format] != -1))
|
||||||
formats |= (1ULL << hpi_to_alsa_formats[format]);
|
formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]);
|
||||||
}
|
}
|
||||||
return formats;
|
return formats;
|
||||||
}
|
}
|
||||||
@ -1141,8 +1141,8 @@ static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi,
|
|||||||
format, sample_rate, 128000, 0);
|
format, sample_rate, 128000, 0);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = hpi_instream_query_format(h_stream, &hpi_format);
|
err = hpi_instream_query_format(h_stream, &hpi_format);
|
||||||
if (!err)
|
if (!err && (hpi_to_alsa_formats[format] != -1))
|
||||||
formats |= (1ULL << hpi_to_alsa_formats[format]);
|
formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]);
|
||||||
}
|
}
|
||||||
return formats;
|
return formats;
|
||||||
}
|
}
|
||||||
|
@ -657,14 +657,14 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu)
|
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu,
|
||||||
|
const struct firmware *fw_entry)
|
||||||
{
|
{
|
||||||
int n, i;
|
int n, i;
|
||||||
int reg;
|
int reg;
|
||||||
int value;
|
int value;
|
||||||
unsigned int write_post;
|
unsigned int write_post;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
const struct firmware *fw_entry = emu->firmware;
|
|
||||||
|
|
||||||
if (!fw_entry)
|
if (!fw_entry)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -725,9 +725,34 @@ static int emu1010_firmware_thread(void *data)
|
|||||||
/* Return to Audio Dock programming mode */
|
/* Return to Audio Dock programming mode */
|
||||||
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
|
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
|
||||||
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
|
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
|
||||||
err = snd_emu1010_load_firmware(emu);
|
|
||||||
if (err != 0)
|
if (!emu->dock_fw) {
|
||||||
|
const char *filename = NULL;
|
||||||
|
switch (emu->card_capabilities->emu_model) {
|
||||||
|
case EMU_MODEL_EMU1010:
|
||||||
|
filename = DOCK_FILENAME;
|
||||||
|
break;
|
||||||
|
case EMU_MODEL_EMU1010B:
|
||||||
|
filename = MICRO_DOCK_FILENAME;
|
||||||
|
break;
|
||||||
|
case EMU_MODEL_EMU1616:
|
||||||
|
filename = MICRO_DOCK_FILENAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (filename) {
|
||||||
|
err = request_firmware(&emu->dock_fw,
|
||||||
|
filename,
|
||||||
|
&emu->pci->dev);
|
||||||
|
if (err)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emu->dock_fw) {
|
||||||
|
err = snd_emu1010_load_firmware(emu, emu->dock_fw);
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
|
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
|
||||||
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®);
|
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®);
|
||||||
@ -862,7 +887,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
|
|||||||
filename, emu->firmware->size);
|
filename, emu->firmware->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_emu1010_load_firmware(emu);
|
err = snd_emu1010_load_firmware(emu, emu->firmware);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n");
|
snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n");
|
||||||
return err;
|
return err;
|
||||||
@ -1253,6 +1278,8 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
|
|||||||
kthread_stop(emu->emu1010.firmware_thread);
|
kthread_stop(emu->emu1010.firmware_thread);
|
||||||
if (emu->firmware)
|
if (emu->firmware)
|
||||||
release_firmware(emu->firmware);
|
release_firmware(emu->firmware);
|
||||||
|
if (emu->dock_fw)
|
||||||
|
release_firmware(emu->dock_fw);
|
||||||
if (emu->irq >= 0)
|
if (emu->irq >= 0)
|
||||||
free_irq(emu->irq, emu);
|
free_irq(emu->irq, emu);
|
||||||
/* remove reserved page */
|
/* remove reserved page */
|
||||||
|
@ -119,6 +119,32 @@ static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool can_be_headset_mic(struct hda_codec *codec,
|
||||||
|
struct auto_pin_cfg_item *item,
|
||||||
|
int seq_number)
|
||||||
|
{
|
||||||
|
int attr;
|
||||||
|
unsigned int def_conf;
|
||||||
|
if (item->type != AUTO_PIN_MIC)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (item->is_headset_mic || item->is_headphone_mic)
|
||||||
|
return false; /* Already assigned */
|
||||||
|
|
||||||
|
def_conf = snd_hda_codec_get_pincfg(codec, item->pin);
|
||||||
|
attr = snd_hda_get_input_pin_attr(def_conf);
|
||||||
|
if (attr <= INPUT_PIN_ATTR_DOCK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (seq_number >= 0) {
|
||||||
|
int seq = get_defcfg_sequence(def_conf);
|
||||||
|
if (seq != seq_number)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse all pin widgets and store the useful pin nids to cfg
|
* Parse all pin widgets and store the useful pin nids to cfg
|
||||||
*
|
*
|
||||||
@ -260,6 +286,38 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find a pin that could be a headset or headphone mic */
|
||||||
|
if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) {
|
||||||
|
bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC);
|
||||||
|
bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC);
|
||||||
|
for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++)
|
||||||
|
if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) {
|
||||||
|
cfg->inputs[i].is_headset_mic = 1;
|
||||||
|
hsmic = false;
|
||||||
|
} else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) {
|
||||||
|
cfg->inputs[i].is_headphone_mic = 1;
|
||||||
|
hpmic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we didn't find our sequence number mark, fall back to any sequence number */
|
||||||
|
for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) {
|
||||||
|
if (!can_be_headset_mic(codec, &cfg->inputs[i], -1))
|
||||||
|
continue;
|
||||||
|
if (hsmic) {
|
||||||
|
cfg->inputs[i].is_headset_mic = 1;
|
||||||
|
hsmic = false;
|
||||||
|
} else if (hpmic) {
|
||||||
|
cfg->inputs[i].is_headphone_mic = 1;
|
||||||
|
hpmic = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hsmic)
|
||||||
|
snd_printdd("Told to look for a headset mic, but didn't find any.\n");
|
||||||
|
if (hpmic)
|
||||||
|
snd_printdd("Told to look for a headphone mic, but didn't find any.\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* FIX-UP:
|
/* FIX-UP:
|
||||||
* If no line-out is defined but multiple HPs are found,
|
* If no line-out is defined but multiple HPs are found,
|
||||||
* some of them might be the real line-outs.
|
* some of them might be the real line-outs.
|
||||||
@ -388,6 +446,7 @@ EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static const char *hda_get_input_pin_label(struct hda_codec *codec,
|
static const char *hda_get_input_pin_label(struct hda_codec *codec,
|
||||||
|
const struct auto_pin_cfg_item *item,
|
||||||
hda_nid_t pin, bool check_location)
|
hda_nid_t pin, bool check_location)
|
||||||
{
|
{
|
||||||
unsigned int def_conf;
|
unsigned int def_conf;
|
||||||
@ -400,6 +459,10 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec,
|
|||||||
|
|
||||||
switch (get_defcfg_device(def_conf)) {
|
switch (get_defcfg_device(def_conf)) {
|
||||||
case AC_JACK_MIC_IN:
|
case AC_JACK_MIC_IN:
|
||||||
|
if (item && item->is_headset_mic)
|
||||||
|
return "Headset Mic";
|
||||||
|
if (item && item->is_headphone_mic)
|
||||||
|
return "Headphone Mic";
|
||||||
if (!check_location)
|
if (!check_location)
|
||||||
return "Mic";
|
return "Mic";
|
||||||
attr = snd_hda_get_input_pin_attr(def_conf);
|
attr = snd_hda_get_input_pin_attr(def_conf);
|
||||||
@ -480,7 +543,8 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
|
|||||||
has_multiple_pins = 1;
|
has_multiple_pins = 1;
|
||||||
if (has_multiple_pins && type == AUTO_PIN_MIC)
|
if (has_multiple_pins && type == AUTO_PIN_MIC)
|
||||||
has_multiple_pins &= check_mic_location_need(codec, cfg, input);
|
has_multiple_pins &= check_mic_location_need(codec, cfg, input);
|
||||||
return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
|
return hda_get_input_pin_label(codec, &cfg->inputs[input],
|
||||||
|
cfg->inputs[input].pin,
|
||||||
has_multiple_pins);
|
has_multiple_pins);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
|
EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
|
||||||
@ -649,7 +713,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!name)
|
if (!name)
|
||||||
name = hda_get_input_pin_label(codec, nid, true);
|
name = hda_get_input_pin_label(codec, NULL, nid, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!name)
|
if (!name)
|
||||||
|
@ -36,6 +36,8 @@ enum {
|
|||||||
struct auto_pin_cfg_item {
|
struct auto_pin_cfg_item {
|
||||||
hda_nid_t pin;
|
hda_nid_t pin;
|
||||||
int type;
|
int type;
|
||||||
|
unsigned int is_headset_mic:1;
|
||||||
|
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct auto_pin_cfg;
|
struct auto_pin_cfg;
|
||||||
@ -80,6 +82,8 @@ struct auto_pin_cfg {
|
|||||||
/* bit-flags for snd_hda_parse_pin_def_config() behavior */
|
/* bit-flags for snd_hda_parse_pin_def_config() behavior */
|
||||||
#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
|
#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
|
||||||
#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
|
#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
|
||||||
|
#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */
|
||||||
|
#define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */
|
||||||
|
|
||||||
int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
||||||
struct auto_pin_cfg *cfg,
|
struct auto_pin_cfg *cfg,
|
||||||
@ -90,4 +94,25 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
|||||||
#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
|
#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
|
||||||
snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
|
snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
|
||||||
|
|
||||||
|
static inline int auto_cfg_hp_outs(const struct auto_pin_cfg *cfg)
|
||||||
|
{
|
||||||
|
return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
|
||||||
|
cfg->line_outs : cfg->hp_outs;
|
||||||
|
}
|
||||||
|
static inline const hda_nid_t *auto_cfg_hp_pins(const struct auto_pin_cfg *cfg)
|
||||||
|
{
|
||||||
|
return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
|
||||||
|
cfg->line_out_pins : cfg->hp_pins;
|
||||||
|
}
|
||||||
|
static inline int auto_cfg_speaker_outs(const struct auto_pin_cfg *cfg)
|
||||||
|
{
|
||||||
|
return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
|
||||||
|
cfg->line_outs : cfg->speaker_outs;
|
||||||
|
}
|
||||||
|
static inline const hda_nid_t *auto_cfg_speaker_pins(const struct auto_pin_cfg *cfg)
|
||||||
|
{
|
||||||
|
return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
|
||||||
|
cfg->line_out_pins : cfg->speaker_pins;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __SOUND_HDA_AUTO_PARSER_H */
|
#endif /* __SOUND_HDA_AUTO_PARSER_H */
|
||||||
|
@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work)
|
|||||||
struct hda_beep *beep =
|
struct hda_beep *beep =
|
||||||
container_of(work, struct hda_beep, beep_work);
|
container_of(work, struct hda_beep, beep_work);
|
||||||
struct hda_codec *codec = beep->codec;
|
struct hda_codec *codec = beep->codec;
|
||||||
|
int tone;
|
||||||
|
|
||||||
if (!beep->enabled)
|
if (!beep->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
tone = beep->tone;
|
||||||
|
if (tone && !beep->playing) {
|
||||||
|
snd_hda_power_up(codec);
|
||||||
|
beep->playing = 1;
|
||||||
|
}
|
||||||
/* generate tone */
|
/* generate tone */
|
||||||
snd_hda_codec_write(codec, beep->nid, 0,
|
snd_hda_codec_write(codec, beep->nid, 0,
|
||||||
AC_VERB_SET_BEEP_CONTROL, beep->tone);
|
AC_VERB_SET_BEEP_CONTROL, tone);
|
||||||
|
if (!tone && beep->playing) {
|
||||||
|
beep->playing = 0;
|
||||||
|
snd_hda_power_down(codec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
|
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
|
||||||
@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void turn_off_beep(struct hda_beep *beep)
|
||||||
|
{
|
||||||
|
cancel_work_sync(&beep->beep_work);
|
||||||
|
if (beep->playing) {
|
||||||
|
/* turn off beep */
|
||||||
|
snd_hda_codec_write(beep->codec, beep->nid, 0,
|
||||||
|
AC_VERB_SET_BEEP_CONTROL, 0);
|
||||||
|
beep->playing = 0;
|
||||||
|
snd_hda_power_down(beep->codec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void snd_hda_do_detach(struct hda_beep *beep)
|
static void snd_hda_do_detach(struct hda_beep *beep)
|
||||||
{
|
{
|
||||||
input_unregister_device(beep->dev);
|
input_unregister_device(beep->dev);
|
||||||
beep->dev = NULL;
|
beep->dev = NULL;
|
||||||
cancel_work_sync(&beep->beep_work);
|
turn_off_beep(beep);
|
||||||
/* turn off beep for sure */
|
|
||||||
snd_hda_codec_write(beep->codec, beep->nid, 0,
|
|
||||||
AC_VERB_SET_BEEP_CONTROL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_hda_do_attach(struct hda_beep *beep)
|
static int snd_hda_do_attach(struct hda_beep *beep)
|
||||||
@ -170,12 +189,8 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
|
|||||||
enable = !!enable;
|
enable = !!enable;
|
||||||
if (beep->enabled != enable) {
|
if (beep->enabled != enable) {
|
||||||
beep->enabled = enable;
|
beep->enabled = enable;
|
||||||
if (!enable) {
|
if (!enable)
|
||||||
cancel_work_sync(&beep->beep_work);
|
turn_off_beep(beep);
|
||||||
/* turn off beep */
|
|
||||||
snd_hda_codec_write(beep->codec, beep->nid, 0,
|
|
||||||
AC_VERB_SET_BEEP_CONTROL, 0);
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -198,7 +213,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
|
|||||||
snprintf(beep->phys, sizeof(beep->phys),
|
snprintf(beep->phys, sizeof(beep->phys),
|
||||||
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
|
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
|
||||||
/* enable linear scale */
|
/* enable linear scale */
|
||||||
snd_hda_codec_write(codec, nid, 0,
|
snd_hda_codec_write_cache(codec, nid, 0,
|
||||||
AC_VERB_SET_DIGI_CONVERT_2, 0x01);
|
AC_VERB_SET_DIGI_CONVERT_2, 0x01);
|
||||||
|
|
||||||
beep->nid = nid;
|
beep->nid = nid;
|
||||||
|
@ -36,6 +36,7 @@ struct hda_beep {
|
|||||||
hda_nid_t nid;
|
hda_nid_t nid;
|
||||||
unsigned int enabled:1;
|
unsigned int enabled:1;
|
||||||
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
|
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
|
||||||
|
unsigned int playing:1;
|
||||||
struct work_struct beep_work; /* scheduled task for beep event */
|
struct work_struct beep_work; /* scheduled task for beep event */
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
};
|
};
|
||||||
|
@ -1065,8 +1065,14 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
|
|||||||
{
|
{
|
||||||
struct hda_pincfg *pin;
|
struct hda_pincfg *pin;
|
||||||
|
|
||||||
|
/* the check below may be invalid when pins are added by a fixup
|
||||||
|
* dynamically (e.g. via snd_hda_codec_update_widgets()), so disabled
|
||||||
|
* for now
|
||||||
|
*/
|
||||||
|
/*
|
||||||
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
|
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
*/
|
||||||
|
|
||||||
pin = look_up_pincfg(codec, list, nid);
|
pin = look_up_pincfg(codec, list, nid);
|
||||||
if (!pin) {
|
if (!pin) {
|
||||||
@ -1300,8 +1306,6 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
|
|||||||
|
|
||||||
static unsigned int hda_set_power_state(struct hda_codec *codec,
|
static unsigned int hda_set_power_state(struct hda_codec *codec,
|
||||||
unsigned int power_state);
|
unsigned int power_state);
|
||||||
static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
|
|
||||||
unsigned int power_state);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_codec_new - create a HDA codec
|
* snd_hda_codec_new - create a HDA codec
|
||||||
@ -1422,7 +1426,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
|
|||||||
#endif
|
#endif
|
||||||
codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
|
codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
|
||||||
AC_PWRST_EPSS);
|
AC_PWRST_EPSS);
|
||||||
codec->power_filter = default_power_filter;
|
|
||||||
|
|
||||||
/* power-up all before initialization */
|
/* power-up all before initialization */
|
||||||
hda_set_power_state(codec, AC_PWRST_D0);
|
hda_set_power_state(codec, AC_PWRST_D0);
|
||||||
@ -2787,6 +2790,11 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
|
|||||||
{
|
{
|
||||||
if (!hook->hook || !hook->codec)
|
if (!hook->hook || !hook->codec)
|
||||||
return;
|
return;
|
||||||
|
/* don't call vmaster hook in the destructor since it might have
|
||||||
|
* been already destroyed
|
||||||
|
*/
|
||||||
|
if (hook->codec->bus->shutdown)
|
||||||
|
return;
|
||||||
switch (hook->mute_mode) {
|
switch (hook->mute_mode) {
|
||||||
case HDA_VMUTE_FOLLOW_MASTER:
|
case HDA_VMUTE_FOLLOW_MASTER:
|
||||||
snd_ctl_sync_vmaster_hook(hook->sw_kctl);
|
snd_ctl_sync_vmaster_hook(hook->sw_kctl);
|
||||||
@ -3770,7 +3778,8 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */
|
/* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */
|
||||||
static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
|
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
||||||
|
hda_nid_t nid,
|
||||||
unsigned int power_state)
|
unsigned int power_state)
|
||||||
{
|
{
|
||||||
if (power_state == AC_PWRST_D3 &&
|
if (power_state == AC_PWRST_D3 &&
|
||||||
@ -3783,6 +3792,7 @@ static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
|
|||||||
}
|
}
|
||||||
return power_state;
|
return power_state;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set power state of the codec, and return the power state
|
* set power state of the codec, and return the power state
|
||||||
@ -3827,8 +3837,8 @@ static void sync_power_up_states(struct hda_codec *codec)
|
|||||||
hda_nid_t nid = codec->start_nid;
|
hda_nid_t nid = codec->start_nid;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* don't care if no or standard filter is used */
|
/* don't care if no filter is used */
|
||||||
if (!codec->power_filter || codec->power_filter == default_power_filter)
|
if (!codec->power_filter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||||
@ -5546,14 +5556,12 @@ void *snd_array_new(struct snd_array *array)
|
|||||||
if (array->used >= array->alloced) {
|
if (array->used >= array->alloced) {
|
||||||
int num = array->alloced + array->alloc_align;
|
int num = array->alloced + array->alloc_align;
|
||||||
int size = (num + 1) * array->elem_size;
|
int size = (num + 1) * array->elem_size;
|
||||||
int oldsize = array->alloced * array->elem_size;
|
|
||||||
void *nlist;
|
void *nlist;
|
||||||
if (snd_BUG_ON(num >= 4096))
|
if (snd_BUG_ON(num >= 4096))
|
||||||
return NULL;
|
return NULL;
|
||||||
nlist = krealloc(array->list, size, GFP_KERNEL);
|
nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
|
||||||
if (!nlist)
|
if (!nlist)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(nlist + oldsize, 0, size - oldsize);
|
|
||||||
array->list = nlist;
|
array->list = nlist;
|
||||||
array->alloced = num;
|
array->alloced = num;
|
||||||
}
|
}
|
||||||
|
@ -757,6 +757,9 @@ struct hda_pcm_ops {
|
|||||||
struct snd_pcm_substream *substream);
|
struct snd_pcm_substream *substream);
|
||||||
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||||
struct snd_pcm_substream *substream);
|
struct snd_pcm_substream *substream);
|
||||||
|
unsigned int (*get_delay)(struct hda_pcm_stream *info,
|
||||||
|
struct hda_codec *codec,
|
||||||
|
struct snd_pcm_substream *substream);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PCM information for each substream */
|
/* PCM information for each substream */
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
#include "hda_auto_parser.h"
|
#include "hda_auto_parser.h"
|
||||||
#include "hda_jack.h"
|
#include "hda_jack.h"
|
||||||
|
#include "hda_beep.h"
|
||||||
#include "hda_generic.h"
|
#include "hda_generic.h"
|
||||||
|
|
||||||
|
|
||||||
@ -150,15 +151,25 @@ static void parse_user_hints(struct hda_codec *codec)
|
|||||||
val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
|
val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->add_stereo_mix_input = !!val;
|
spec->add_stereo_mix_input = !!val;
|
||||||
|
/* the following two are just for compatibility */
|
||||||
val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
|
val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->add_out_jack_modes = !!val;
|
spec->add_jack_modes = !!val;
|
||||||
val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
|
val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->add_in_jack_modes = !!val;
|
spec->add_jack_modes = !!val;
|
||||||
|
val = snd_hda_get_bool_hint(codec, "add_jack_modes");
|
||||||
|
if (val >= 0)
|
||||||
|
spec->add_jack_modes = !!val;
|
||||||
val = snd_hda_get_bool_hint(codec, "power_down_unused");
|
val = snd_hda_get_bool_hint(codec, "power_down_unused");
|
||||||
if (val >= 0)
|
if (val >= 0)
|
||||||
spec->power_down_unused = !!val;
|
spec->power_down_unused = !!val;
|
||||||
|
val = snd_hda_get_bool_hint(codec, "add_hp_mic");
|
||||||
|
if (val >= 0)
|
||||||
|
spec->hp_mic = !!val;
|
||||||
|
val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
|
||||||
|
if (val >= 0)
|
||||||
|
spec->suppress_hp_mic_detect = !val;
|
||||||
|
|
||||||
if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
|
if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
|
||||||
spec->mixer_nid = val;
|
spec->mixer_nid = val;
|
||||||
@ -996,7 +1007,7 @@ enum {
|
|||||||
/* Primary DAC shared with main surrounds */
|
/* Primary DAC shared with main surrounds */
|
||||||
BAD_SHARED_SURROUND = 0x100,
|
BAD_SHARED_SURROUND = 0x100,
|
||||||
/* No independent HP possible */
|
/* No independent HP possible */
|
||||||
BAD_NO_INDEP_HP = 0x40,
|
BAD_NO_INDEP_HP = 0x10,
|
||||||
/* Primary DAC shared with main CLFE */
|
/* Primary DAC shared with main CLFE */
|
||||||
BAD_SHARED_CLFE = 0x10,
|
BAD_SHARED_CLFE = 0x10,
|
||||||
/* Primary DAC shared with extra surrounds */
|
/* Primary DAC shared with extra surrounds */
|
||||||
@ -1051,16 +1062,7 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
|||||||
return badness;
|
return badness;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct badness_table {
|
const struct badness_table hda_main_out_badness = {
|
||||||
int no_primary_dac; /* no primary DAC */
|
|
||||||
int no_dac; /* no secondary DACs */
|
|
||||||
int shared_primary; /* primary DAC is shared with main output */
|
|
||||||
int shared_surr; /* secondary DAC shared with main or primary */
|
|
||||||
int shared_clfe; /* third DAC shared with main or primary */
|
|
||||||
int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct badness_table main_out_badness = {
|
|
||||||
.no_primary_dac = BAD_NO_PRIMARY_DAC,
|
.no_primary_dac = BAD_NO_PRIMARY_DAC,
|
||||||
.no_dac = BAD_NO_DAC,
|
.no_dac = BAD_NO_DAC,
|
||||||
.shared_primary = BAD_NO_PRIMARY_DAC,
|
.shared_primary = BAD_NO_PRIMARY_DAC,
|
||||||
@ -1068,8 +1070,9 @@ static struct badness_table main_out_badness = {
|
|||||||
.shared_clfe = BAD_SHARED_CLFE,
|
.shared_clfe = BAD_SHARED_CLFE,
|
||||||
.shared_surr_main = BAD_SHARED_SURROUND,
|
.shared_surr_main = BAD_SHARED_SURROUND,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_HDA(hda_main_out_badness);
|
||||||
|
|
||||||
static struct badness_table extra_out_badness = {
|
const struct badness_table hda_extra_out_badness = {
|
||||||
.no_primary_dac = BAD_NO_DAC,
|
.no_primary_dac = BAD_NO_DAC,
|
||||||
.no_dac = BAD_NO_DAC,
|
.no_dac = BAD_NO_DAC,
|
||||||
.shared_primary = BAD_NO_EXTRA_DAC,
|
.shared_primary = BAD_NO_EXTRA_DAC,
|
||||||
@ -1077,6 +1080,7 @@ static struct badness_table extra_out_badness = {
|
|||||||
.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
|
.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
|
||||||
.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
|
.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_HDA(hda_extra_out_badness);
|
||||||
|
|
||||||
/* get the DAC of the primary output corresponding to the given array index */
|
/* get the DAC of the primary output corresponding to the given array index */
|
||||||
static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
|
static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
|
||||||
@ -1367,22 +1371,25 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
|
|||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
struct nid_path *path;
|
struct nid_path *path;
|
||||||
hda_nid_t dac, pin;
|
hda_nid_t path_dac, dac, pin;
|
||||||
|
|
||||||
path = snd_hda_get_path_from_idx(codec, path_idx);
|
path = snd_hda_get_path_from_idx(codec, path_idx);
|
||||||
if (!path || !path->depth ||
|
if (!path || !path->depth ||
|
||||||
is_nid_contained(path, spec->mixer_nid))
|
is_nid_contained(path, spec->mixer_nid))
|
||||||
return 0;
|
return 0;
|
||||||
dac = path->path[0];
|
path_dac = path->path[0];
|
||||||
|
dac = spec->private_dac_nids[0];
|
||||||
pin = path->path[path->depth - 1];
|
pin = path->path[path->depth - 1];
|
||||||
path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
|
path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
if (dac != spec->multiout.dac_nids[0])
|
if (dac != path_dac)
|
||||||
dac = spec->multiout.dac_nids[0];
|
dac = path_dac;
|
||||||
else if (spec->multiout.hp_out_nid[0])
|
else if (spec->multiout.hp_out_nid[0])
|
||||||
dac = spec->multiout.hp_out_nid[0];
|
dac = spec->multiout.hp_out_nid[0];
|
||||||
else if (spec->multiout.extra_out_nid[0])
|
else if (spec->multiout.extra_out_nid[0])
|
||||||
dac = spec->multiout.extra_out_nid[0];
|
dac = spec->multiout.extra_out_nid[0];
|
||||||
|
else
|
||||||
|
dac = 0;
|
||||||
if (dac)
|
if (dac)
|
||||||
path = snd_hda_add_new_path(codec, dac, pin,
|
path = snd_hda_add_new_path(codec, dac, pin,
|
||||||
spec->mixer_nid);
|
spec->mixer_nid);
|
||||||
@ -1507,7 +1514,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|||||||
|
|
||||||
badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
|
badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
|
||||||
spec->private_dac_nids, spec->out_paths,
|
spec->private_dac_nids, spec->out_paths,
|
||||||
&main_out_badness);
|
spec->main_out_badness);
|
||||||
|
|
||||||
if (fill_mio_first &&
|
if (fill_mio_first &&
|
||||||
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||||
@ -1522,7 +1529,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|||||||
err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
|
err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
|
||||||
spec->multiout.hp_out_nid,
|
spec->multiout.hp_out_nid,
|
||||||
spec->hp_paths,
|
spec->hp_paths,
|
||||||
&extra_out_badness);
|
spec->extra_out_badness);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
badness += err;
|
badness += err;
|
||||||
@ -1532,7 +1539,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|||||||
cfg->speaker_pins,
|
cfg->speaker_pins,
|
||||||
spec->multiout.extra_out_nid,
|
spec->multiout.extra_out_nid,
|
||||||
spec->speaker_paths,
|
spec->speaker_paths,
|
||||||
&extra_out_badness);
|
spec->extra_out_badness);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
badness += err;
|
badness += err;
|
||||||
@ -1926,6 +1933,17 @@ static int create_speaker_out_ctls(struct hda_codec *codec)
|
|||||||
* independent HP controls
|
* independent HP controls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* update HP auto-mute state too */
|
||||||
|
static void update_hp_automute_hook(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
|
||||||
|
if (spec->hp_automute_hook)
|
||||||
|
spec->hp_automute_hook(codec, NULL);
|
||||||
|
else
|
||||||
|
snd_hda_gen_hp_automute(codec, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int indep_hp_info(struct snd_kcontrol *kcontrol,
|
static int indep_hp_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
@ -1986,12 +2004,7 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol,
|
|||||||
else
|
else
|
||||||
*dacp = spec->alt_dac_nid;
|
*dacp = spec->alt_dac_nid;
|
||||||
|
|
||||||
/* update HP auto-mute state too */
|
update_hp_automute_hook(codec);
|
||||||
if (spec->hp_automute_hook)
|
|
||||||
spec->hp_automute_hook(codec, NULL);
|
|
||||||
else
|
|
||||||
snd_hda_gen_hp_automute(codec, NULL);
|
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
unlock:
|
unlock:
|
||||||
@ -2072,6 +2085,14 @@ get_multiio_path(struct hda_codec *codec, int idx)
|
|||||||
|
|
||||||
static void update_automute_all(struct hda_codec *codec);
|
static void update_automute_all(struct hda_codec *codec);
|
||||||
|
|
||||||
|
/* Default value to be passed as aamix argument for snd_hda_activate_path();
|
||||||
|
* used for output paths
|
||||||
|
*/
|
||||||
|
static bool aamix_default(struct hda_gen_spec *spec)
|
||||||
|
{
|
||||||
|
return !spec->have_aamix_ctl || spec->aamix_mode;
|
||||||
|
}
|
||||||
|
|
||||||
static int set_multi_io(struct hda_codec *codec, int idx, bool output)
|
static int set_multi_io(struct hda_codec *codec, int idx, bool output)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
@ -2087,11 +2108,11 @@ static int set_multi_io(struct hda_codec *codec, int idx, bool output)
|
|||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
set_pin_target(codec, nid, PIN_OUT, true);
|
set_pin_target(codec, nid, PIN_OUT, true);
|
||||||
snd_hda_activate_path(codec, path, true, true);
|
snd_hda_activate_path(codec, path, true, aamix_default(spec));
|
||||||
set_pin_eapd(codec, nid, true);
|
set_pin_eapd(codec, nid, true);
|
||||||
} else {
|
} else {
|
||||||
set_pin_eapd(codec, nid, false);
|
set_pin_eapd(codec, nid, false);
|
||||||
snd_hda_activate_path(codec, path, false, true);
|
snd_hda_activate_path(codec, path, false, aamix_default(spec));
|
||||||
set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
|
set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
|
||||||
path_power_down_sync(codec, path);
|
path_power_down_sync(codec, path);
|
||||||
}
|
}
|
||||||
@ -2182,8 +2203,8 @@ static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
|
|||||||
snd_hda_activate_path(codec, mix_path, true, true);
|
snd_hda_activate_path(codec, mix_path, true, true);
|
||||||
path_power_down_sync(codec, nomix_path);
|
path_power_down_sync(codec, nomix_path);
|
||||||
} else {
|
} else {
|
||||||
snd_hda_activate_path(codec, mix_path, false, true);
|
snd_hda_activate_path(codec, mix_path, false, false);
|
||||||
snd_hda_activate_path(codec, nomix_path, true, true);
|
snd_hda_activate_path(codec, nomix_path, true, false);
|
||||||
path_power_down_sync(codec, mix_path);
|
path_power_down_sync(codec, mix_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2240,63 +2261,95 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
|
|||||||
static void call_update_outputs(struct hda_codec *codec);
|
static void call_update_outputs(struct hda_codec *codec);
|
||||||
|
|
||||||
/* for shared I/O, change the pin-control accordingly */
|
/* for shared I/O, change the pin-control accordingly */
|
||||||
static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
|
static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
bool as_mic;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
hda_nid_t pin = spec->autocfg.inputs[1].pin;
|
hda_nid_t pin;
|
||||||
/* NOTE: this assumes that there are only two inputs, the
|
|
||||||
* first is the real internal mic and the second is HP/mic jack.
|
pin = spec->hp_mic_pin;
|
||||||
*/
|
as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
|
||||||
|
|
||||||
|
if (!force) {
|
||||||
|
val = snd_hda_codec_get_pin_target(codec, pin);
|
||||||
|
if (as_mic) {
|
||||||
|
if (val & PIN_IN)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (val & PIN_OUT)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val = snd_hda_get_default_vref(codec, pin);
|
val = snd_hda_get_default_vref(codec, pin);
|
||||||
|
/* if the HP pin doesn't support VREF and the codec driver gives an
|
||||||
/* This pin does not have vref caps - let's enable vref on pin 0x18
|
* alternative pin, set up the VREF on that pin instead
|
||||||
instead, as suggested by Realtek */
|
*/
|
||||||
if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
|
if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
|
||||||
const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
|
const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
|
||||||
unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
|
unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
|
||||||
if (vref_val != AC_PINCTL_VREF_HIZ)
|
if (vref_val != AC_PINCTL_VREF_HIZ)
|
||||||
snd_hda_set_pin_ctl_cache(codec, vref_pin,
|
snd_hda_set_pin_ctl_cache(codec, vref_pin,
|
||||||
PIN_IN | (set_as_mic ? vref_val : 0));
|
PIN_IN | (as_mic ? vref_val : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
val = set_as_mic ? val | PIN_IN : PIN_HP;
|
if (!spec->hp_mic_jack_modes) {
|
||||||
|
if (as_mic)
|
||||||
|
val |= PIN_IN;
|
||||||
|
else
|
||||||
|
val = PIN_HP;
|
||||||
set_pin_target(codec, pin, val, true);
|
set_pin_target(codec, pin, val, true);
|
||||||
|
update_hp_automute_hook(codec);
|
||||||
spec->automute_speaker = !set_as_mic;
|
}
|
||||||
call_update_outputs(codec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a shared input with the headphone out */
|
/* create a shared input with the headphone out */
|
||||||
static int create_shared_input(struct hda_codec *codec)
|
static int create_hp_mic(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
struct auto_pin_cfg *cfg = &spec->autocfg;
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
||||||
unsigned int defcfg;
|
unsigned int defcfg;
|
||||||
hda_nid_t nid;
|
hda_nid_t nid;
|
||||||
|
|
||||||
/* only one internal input pin? */
|
if (!spec->hp_mic) {
|
||||||
if (cfg->num_inputs != 1)
|
if (spec->suppress_hp_mic_detect)
|
||||||
return 0;
|
return 0;
|
||||||
|
/* automatic detection: only if no input or a single internal
|
||||||
|
* input pin is found, try to detect the shared hp/mic
|
||||||
|
*/
|
||||||
|
if (cfg->num_inputs > 1)
|
||||||
|
return 0;
|
||||||
|
else if (cfg->num_inputs == 1) {
|
||||||
defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
|
defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
|
||||||
if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
|
if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
|
spec->hp_mic = 0; /* clear once */
|
||||||
nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
|
if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
|
||||||
else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
|
return 0;
|
||||||
nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
|
|
||||||
else
|
nid = 0;
|
||||||
return 0; /* both not available */
|
if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
|
||||||
|
nid = cfg->line_out_pins[0];
|
||||||
|
else if (cfg->hp_outs > 0)
|
||||||
|
nid = cfg->hp_pins[0];
|
||||||
|
if (!nid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
|
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
|
||||||
return 0; /* no input */
|
return 0; /* no input */
|
||||||
|
|
||||||
cfg->inputs[1].pin = nid;
|
cfg->inputs[cfg->num_inputs].pin = nid;
|
||||||
cfg->inputs[1].type = AUTO_PIN_MIC;
|
cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
|
||||||
cfg->num_inputs = 2;
|
cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
|
||||||
spec->shared_mic_hp = 1;
|
cfg->num_inputs++;
|
||||||
|
spec->hp_mic = 1;
|
||||||
|
spec->hp_mic_pin = nid;
|
||||||
|
/* we can't handle auto-mic together with HP-mic */
|
||||||
|
spec->suppress_auto_mic = 1;
|
||||||
snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
|
snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2304,13 +2357,17 @@ static int create_shared_input(struct hda_codec *codec)
|
|||||||
/*
|
/*
|
||||||
* output jack mode
|
* output jack mode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
|
||||||
|
|
||||||
|
static const char * const out_jack_texts[] = {
|
||||||
|
"Line Out", "Headphone Out",
|
||||||
|
};
|
||||||
|
|
||||||
static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
|
static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static const char * const texts[] = {
|
return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
|
||||||
"Line Out", "Headphone Out",
|
|
||||||
};
|
|
||||||
return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
|
static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
|
||||||
@ -2372,6 +2429,17 @@ static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
if (spec->add_jack_modes) {
|
||||||
|
unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
|
||||||
|
if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
|
static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
|
||||||
hda_nid_t *pins)
|
hda_nid_t *pins)
|
||||||
{
|
{
|
||||||
@ -2380,8 +2448,13 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
|
|||||||
|
|
||||||
for (i = 0; i < num_pins; i++) {
|
for (i = 0; i < num_pins; i++) {
|
||||||
hda_nid_t pin = pins[i];
|
hda_nid_t pin = pins[i];
|
||||||
unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
|
if (pin == spec->hp_mic_pin) {
|
||||||
if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
|
int ret = create_hp_mic_jack_mode(codec, pin);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (get_out_jack_num_items(codec, pin) > 1) {
|
||||||
struct snd_kcontrol_new *knew;
|
struct snd_kcontrol_new *knew;
|
||||||
char name[44];
|
char name[44];
|
||||||
get_jack_mode_name(codec, pin, name, sizeof(name));
|
get_jack_mode_name(codec, pin, name, sizeof(name));
|
||||||
@ -2502,12 +2575,24 @@ static const struct snd_kcontrol_new in_jack_mode_enum = {
|
|||||||
.put = in_jack_mode_put,
|
.put = in_jack_mode_put,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
int nitems = 0;
|
||||||
|
if (spec->add_jack_modes)
|
||||||
|
nitems = hweight32(get_vref_caps(codec, pin));
|
||||||
|
return nitems ? nitems : 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
|
static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
unsigned int defcfg;
|
|
||||||
struct snd_kcontrol_new *knew;
|
struct snd_kcontrol_new *knew;
|
||||||
char name[44];
|
char name[44];
|
||||||
|
unsigned int defcfg;
|
||||||
|
|
||||||
|
if (pin == spec->hp_mic_pin)
|
||||||
|
return 0; /* already done in create_out_jack_mode() */
|
||||||
|
|
||||||
/* no jack mode for fixed pins */
|
/* no jack mode for fixed pins */
|
||||||
defcfg = snd_hda_codec_get_pincfg(codec, pin);
|
defcfg = snd_hda_codec_get_pincfg(codec, pin);
|
||||||
@ -2515,7 +2600,7 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* no multiple vref caps? */
|
/* no multiple vref caps? */
|
||||||
if (hweight32(get_vref_caps(codec, pin)) <= 1)
|
if (get_in_jack_num_items(codec, pin) <= 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
get_jack_mode_name(codec, pin, name, sizeof(name));
|
get_jack_mode_name(codec, pin, name, sizeof(name));
|
||||||
@ -2526,6 +2611,132 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HP/mic shared jack mode
|
||||||
|
*/
|
||||||
|
static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
hda_nid_t nid = kcontrol->private_value;
|
||||||
|
int out_jacks = get_out_jack_num_items(codec, nid);
|
||||||
|
int in_jacks = get_in_jack_num_items(codec, nid);
|
||||||
|
const char *text = NULL;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||||
|
uinfo->count = 1;
|
||||||
|
uinfo->value.enumerated.items = out_jacks + in_jacks;
|
||||||
|
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
||||||
|
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
|
||||||
|
idx = uinfo->value.enumerated.item;
|
||||||
|
if (idx < out_jacks) {
|
||||||
|
if (out_jacks > 1)
|
||||||
|
text = out_jack_texts[idx];
|
||||||
|
else
|
||||||
|
text = "Headphone Out";
|
||||||
|
} else {
|
||||||
|
idx -= out_jacks;
|
||||||
|
if (in_jacks > 1) {
|
||||||
|
unsigned int vref_caps = get_vref_caps(codec, nid);
|
||||||
|
text = vref_texts[get_vref_idx(vref_caps, idx)];
|
||||||
|
} else
|
||||||
|
text = "Mic In";
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(uinfo->value.enumerated.name, text);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
int out_jacks = get_out_jack_num_items(codec, nid);
|
||||||
|
int in_jacks = get_in_jack_num_items(codec, nid);
|
||||||
|
unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (val & PIN_OUT) {
|
||||||
|
if (out_jacks > 1 && val == PIN_HP)
|
||||||
|
idx = 1;
|
||||||
|
} else if (val & PIN_IN) {
|
||||||
|
idx = out_jacks;
|
||||||
|
if (in_jacks > 1) {
|
||||||
|
unsigned int vref_caps = get_vref_caps(codec, nid);
|
||||||
|
val &= AC_PINCTL_VREFEN;
|
||||||
|
idx += cvt_from_vref_idx(vref_caps, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
hda_nid_t nid = kcontrol->private_value;
|
||||||
|
ucontrol->value.enumerated.item[0] =
|
||||||
|
get_cur_hp_mic_jack_mode(codec, nid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
hda_nid_t nid = kcontrol->private_value;
|
||||||
|
int out_jacks = get_out_jack_num_items(codec, nid);
|
||||||
|
int in_jacks = get_in_jack_num_items(codec, nid);
|
||||||
|
unsigned int val, oldval, idx;
|
||||||
|
|
||||||
|
oldval = get_cur_hp_mic_jack_mode(codec, nid);
|
||||||
|
idx = ucontrol->value.enumerated.item[0];
|
||||||
|
if (oldval == idx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (idx < out_jacks) {
|
||||||
|
if (out_jacks > 1)
|
||||||
|
val = idx ? PIN_HP : PIN_OUT;
|
||||||
|
else
|
||||||
|
val = PIN_HP;
|
||||||
|
} else {
|
||||||
|
idx -= out_jacks;
|
||||||
|
if (in_jacks > 1) {
|
||||||
|
unsigned int vref_caps = get_vref_caps(codec, nid);
|
||||||
|
val = snd_hda_codec_get_pin_target(codec, nid);
|
||||||
|
val &= ~(AC_PINCTL_VREFEN | PIN_HP);
|
||||||
|
val |= get_vref_idx(vref_caps, idx) | PIN_IN;
|
||||||
|
} else
|
||||||
|
val = snd_hda_get_default_vref(codec, nid);
|
||||||
|
}
|
||||||
|
snd_hda_set_pin_ctl_cache(codec, nid, val);
|
||||||
|
update_hp_automute_hook(codec);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
|
.info = hp_mic_jack_mode_info,
|
||||||
|
.get = hp_mic_jack_mode_get,
|
||||||
|
.put = hp_mic_jack_mode_put,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
|
||||||
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
struct snd_kcontrol_new *knew;
|
||||||
|
|
||||||
|
if (get_out_jack_num_items(codec, pin) <= 1 &&
|
||||||
|
get_in_jack_num_items(codec, pin) <= 1)
|
||||||
|
return 0; /* no need */
|
||||||
|
knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
|
||||||
|
&hp_mic_jack_mode_enum);
|
||||||
|
if (!knew)
|
||||||
|
return -ENOMEM;
|
||||||
|
knew->private_value = pin;
|
||||||
|
spec->hp_mic_jack_modes = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse input paths
|
* Parse input paths
|
||||||
@ -2648,7 +2859,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
|
|||||||
unsigned int ok_bits;
|
unsigned int ok_bits;
|
||||||
int i, n, nums;
|
int i, n, nums;
|
||||||
|
|
||||||
again:
|
|
||||||
nums = 0;
|
nums = 0;
|
||||||
ok_bits = 0;
|
ok_bits = 0;
|
||||||
for (n = 0; n < spec->num_adc_nids; n++) {
|
for (n = 0; n < spec->num_adc_nids; n++) {
|
||||||
@ -2663,12 +2873,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ok_bits) {
|
if (!ok_bits) {
|
||||||
if (spec->shared_mic_hp) {
|
|
||||||
spec->shared_mic_hp = 0;
|
|
||||||
imux->num_items = 1;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check whether ADC-switch is possible */
|
/* check whether ADC-switch is possible */
|
||||||
for (i = 0; i < imux->num_items; i++) {
|
for (i = 0; i < imux->num_items; i++) {
|
||||||
for (n = 0; n < spec->num_adc_nids; n++) {
|
for (n = 0; n < spec->num_adc_nids; n++) {
|
||||||
@ -2701,7 +2905,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
|
|||||||
spec->num_adc_nids = nums;
|
spec->num_adc_nids = nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imux->num_items == 1 || spec->shared_mic_hp) {
|
if (imux->num_items == 1 ||
|
||||||
|
(imux->num_items == 2 && spec->hp_mic)) {
|
||||||
snd_printdd("hda-codec: reducing to a single ADC\n");
|
snd_printdd("hda-codec: reducing to a single ADC\n");
|
||||||
spec->num_adc_nids = 1; /* reduce to a single ADC */
|
spec->num_adc_nids = 1; /* reduce to a single ADC */
|
||||||
}
|
}
|
||||||
@ -2738,6 +2943,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
|
|||||||
snd_hda_get_path_idx(codec, path);
|
snd_hda_get_path_idx(codec, path);
|
||||||
|
|
||||||
if (!imux_added) {
|
if (!imux_added) {
|
||||||
|
if (spec->hp_mic_pin == pin)
|
||||||
|
spec->hp_mic_mux_idx = imux->num_items;
|
||||||
spec->imux_pins[imux->num_items] = pin;
|
spec->imux_pins[imux->num_items] = pin;
|
||||||
snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
|
snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
|
||||||
imux_added = true;
|
imux_added = true;
|
||||||
@ -2812,6 +3019,7 @@ static int create_input_ctls(struct hda_codec *codec)
|
|||||||
val = PIN_IN;
|
val = PIN_IN;
|
||||||
if (cfg->inputs[i].type == AUTO_PIN_MIC)
|
if (cfg->inputs[i].type == AUTO_PIN_MIC)
|
||||||
val |= snd_hda_get_default_vref(codec, pin);
|
val |= snd_hda_get_default_vref(codec, pin);
|
||||||
|
if (pin != spec->hp_mic_pin)
|
||||||
set_pin_target(codec, pin, val, false);
|
set_pin_target(codec, pin, val, false);
|
||||||
|
|
||||||
if (mixer) {
|
if (mixer) {
|
||||||
@ -2830,7 +3038,7 @@ static int create_input_ctls(struct hda_codec *codec)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (spec->add_in_jack_modes) {
|
if (spec->add_jack_modes) {
|
||||||
err = create_in_jack_mode(codec, pin);
|
err = create_in_jack_mode(codec, pin);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -3462,8 +3670,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
|||||||
|
|
||||||
spec->cur_mux[adc_idx] = idx;
|
spec->cur_mux[adc_idx] = idx;
|
||||||
|
|
||||||
if (spec->shared_mic_hp)
|
if (spec->hp_mic)
|
||||||
update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
|
update_hp_mic(codec, adc_idx, false);
|
||||||
|
|
||||||
if (spec->dyn_adc_switch)
|
if (spec->dyn_adc_switch)
|
||||||
dyn_adc_pcm_resetup(codec, idx);
|
dyn_adc_pcm_resetup(codec, idx);
|
||||||
@ -3511,18 +3719,21 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
|
|||||||
|
|
||||||
for (i = 0; i < num_pins; i++) {
|
for (i = 0; i < num_pins; i++) {
|
||||||
hda_nid_t nid = pins[i];
|
hda_nid_t nid = pins[i];
|
||||||
unsigned int val;
|
unsigned int val, oldval;
|
||||||
if (!nid)
|
if (!nid)
|
||||||
break;
|
break;
|
||||||
|
oldval = snd_hda_codec_get_pin_target(codec, nid);
|
||||||
|
if (oldval & PIN_IN)
|
||||||
|
continue; /* no mute for inputs */
|
||||||
/* don't reset VREF value in case it's controlling
|
/* don't reset VREF value in case it's controlling
|
||||||
* the amp (see alc861_fixup_asus_amp_vref_0f())
|
* the amp (see alc861_fixup_asus_amp_vref_0f())
|
||||||
*/
|
*/
|
||||||
if (spec->keep_vref_in_automute)
|
if (spec->keep_vref_in_automute)
|
||||||
val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
|
val = oldval & ~PIN_HP;
|
||||||
else
|
else
|
||||||
val = 0;
|
val = 0;
|
||||||
if (!mute)
|
if (!mute)
|
||||||
val |= snd_hda_codec_get_pin_target(codec, nid);
|
val |= oldval;
|
||||||
/* here we call update_pin_ctl() so that the pinctl is changed
|
/* here we call update_pin_ctl() so that the pinctl is changed
|
||||||
* without changing the pinctl target value;
|
* without changing the pinctl target value;
|
||||||
* the original target value will be still referred at the
|
* the original target value will be still referred at the
|
||||||
@ -3543,7 +3754,6 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
|||||||
* in general, HP pins/amps control should be enabled in all cases,
|
* in general, HP pins/amps control should be enabled in all cases,
|
||||||
* but currently set only for master_mute, just to be safe
|
* but currently set only for master_mute, just to be safe
|
||||||
*/
|
*/
|
||||||
if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
|
|
||||||
do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
|
do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
|
||||||
spec->autocfg.hp_pins, spec->master_mute);
|
spec->autocfg.hp_pins, spec->master_mute);
|
||||||
|
|
||||||
@ -3649,10 +3859,7 @@ static void update_automute_all(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
|
|
||||||
if (spec->hp_automute_hook)
|
update_hp_automute_hook(codec);
|
||||||
spec->hp_automute_hook(codec, NULL);
|
|
||||||
else
|
|
||||||
snd_hda_gen_hp_automute(codec, NULL);
|
|
||||||
if (spec->line_automute_hook)
|
if (spec->line_automute_hook)
|
||||||
spec->line_automute_hook(codec, NULL);
|
spec->line_automute_hook(codec, NULL);
|
||||||
else
|
else
|
||||||
@ -3978,6 +4185,11 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||||||
cfg = &spec->autocfg;
|
cfg = &spec->autocfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!spec->main_out_badness)
|
||||||
|
spec->main_out_badness = &hda_main_out_badness;
|
||||||
|
if (!spec->extra_out_badness)
|
||||||
|
spec->extra_out_badness = &hda_extra_out_badness;
|
||||||
|
|
||||||
fill_all_dac_nids(codec);
|
fill_all_dac_nids(codec);
|
||||||
|
|
||||||
if (!cfg->line_outs) {
|
if (!cfg->line_outs) {
|
||||||
@ -4024,7 +4236,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||||||
err = create_loopback_mixing_ctl(codec);
|
err = create_loopback_mixing_ctl(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = create_shared_input(codec);
|
err = create_hp_mic(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = create_input_ctls(codec);
|
err = create_input_ctls(codec);
|
||||||
@ -4050,11 +4262,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!spec->shared_mic_hp) {
|
|
||||||
err = check_auto_mic_availability(codec);
|
err = check_auto_mic_availability(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
err = create_capture_mixers(codec);
|
err = create_capture_mixers(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -4064,7 +4274,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (spec->add_out_jack_modes) {
|
if (spec->add_jack_modes) {
|
||||||
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||||
err = create_out_jack_modes(codec, cfg->line_outs,
|
err = create_out_jack_modes(codec, cfg->line_outs,
|
||||||
cfg->line_out_pins);
|
cfg->line_out_pins);
|
||||||
@ -4085,6 +4295,12 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||||||
if (spec->power_down_unused)
|
if (spec->power_down_unused)
|
||||||
codec->power_filter = snd_hda_gen_path_power_filter;
|
codec->power_filter = snd_hda_gen_path_power_filter;
|
||||||
|
|
||||||
|
if (!spec->no_analog && spec->beep_nid) {
|
||||||
|
err = snd_hda_attach_beep_device(codec, spec->beep_nid);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
|
EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
|
||||||
@ -4161,17 +4377,6 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
|
|||||||
|
|
||||||
free_kctls(spec); /* no longer needed */
|
free_kctls(spec); /* no longer needed */
|
||||||
|
|
||||||
if (spec->shared_mic_hp) {
|
|
||||||
int err;
|
|
||||||
int nid = spec->autocfg.inputs[1].pin;
|
|
||||||
err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = snd_hda_jack_detect_enable(codec, nid, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
|
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -4729,7 +4934,8 @@ static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
|
|||||||
return;
|
return;
|
||||||
pin = path->path[path->depth - 1];
|
pin = path->path[path->depth - 1];
|
||||||
restore_pin_ctl(codec, pin);
|
restore_pin_ctl(codec, pin);
|
||||||
snd_hda_activate_path(codec, path, path->active, true);
|
snd_hda_activate_path(codec, path, path->active,
|
||||||
|
aamix_default(codec->spec));
|
||||||
set_pin_eapd(codec, pin, path->active);
|
set_pin_eapd(codec, pin, path->active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4779,7 +4985,8 @@ static void init_multi_io(struct hda_codec *codec)
|
|||||||
if (!spec->multi_io[i].ctl_in)
|
if (!spec->multi_io[i].ctl_in)
|
||||||
spec->multi_io[i].ctl_in =
|
spec->multi_io[i].ctl_in =
|
||||||
snd_hda_codec_get_pin_target(codec, pin);
|
snd_hda_codec_get_pin_target(codec, pin);
|
||||||
snd_hda_activate_path(codec, path, path->active, true);
|
snd_hda_activate_path(codec, path, path->active,
|
||||||
|
aamix_default(spec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4826,11 +5033,10 @@ static void init_input_src(struct hda_codec *codec)
|
|||||||
snd_hda_activate_path(codec, path, active, false);
|
snd_hda_activate_path(codec, path, active, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (spec->hp_mic)
|
||||||
|
update_hp_mic(codec, c, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spec->shared_mic_hp)
|
|
||||||
update_shared_mic_hp(codec, spec->cur_mux[0]);
|
|
||||||
|
|
||||||
if (spec->cap_sync_hook)
|
if (spec->cap_sync_hook)
|
||||||
spec->cap_sync_hook(codec, NULL);
|
spec->cap_sync_hook(codec, NULL);
|
||||||
}
|
}
|
||||||
@ -4911,6 +5117,7 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_init);
|
|||||||
*/
|
*/
|
||||||
void snd_hda_gen_free(struct hda_codec *codec)
|
void snd_hda_gen_free(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
|
snd_hda_detach_beep_device(codec);
|
||||||
snd_hda_gen_spec_free(codec->spec);
|
snd_hda_gen_spec_free(codec->spec);
|
||||||
kfree(codec->spec);
|
kfree(codec->spec);
|
||||||
codec->spec = NULL;
|
codec->spec = NULL;
|
||||||
|
@ -76,6 +76,19 @@ enum {
|
|||||||
HDA_GEN_PCM_ACT_CLOSE,
|
HDA_GEN_PCM_ACT_CLOSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DAC assignment badness table */
|
||||||
|
struct badness_table {
|
||||||
|
int no_primary_dac; /* no primary DAC */
|
||||||
|
int no_dac; /* no secondary DACs */
|
||||||
|
int shared_primary; /* primary DAC is shared with main output */
|
||||||
|
int shared_surr; /* secondary DAC shared with main or primary */
|
||||||
|
int shared_clfe; /* third DAC shared with main or primary */
|
||||||
|
int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct badness_table hda_main_out_badness;
|
||||||
|
extern const struct badness_table hda_extra_out_badness;
|
||||||
|
|
||||||
struct hda_gen_spec {
|
struct hda_gen_spec {
|
||||||
char stream_name_analog[32]; /* analog PCM stream */
|
char stream_name_analog[32]; /* analog PCM stream */
|
||||||
const struct hda_pcm_stream *stream_analog_playback;
|
const struct hda_pcm_stream *stream_analog_playback;
|
||||||
@ -145,7 +158,10 @@ struct hda_gen_spec {
|
|||||||
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
|
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
|
||||||
hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
|
hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
|
||||||
unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
|
unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
|
||||||
|
/* shared hp/mic */
|
||||||
hda_nid_t shared_mic_vref_pin;
|
hda_nid_t shared_mic_vref_pin;
|
||||||
|
hda_nid_t hp_mic_pin;
|
||||||
|
int hp_mic_mux_idx;
|
||||||
|
|
||||||
/* DAC/ADC lists */
|
/* DAC/ADC lists */
|
||||||
int num_all_dacs;
|
int num_all_dacs;
|
||||||
@ -200,7 +216,8 @@ struct hda_gen_spec {
|
|||||||
|
|
||||||
/* other parse behavior flags */
|
/* other parse behavior flags */
|
||||||
unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
|
unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
|
||||||
unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
|
unsigned int hp_mic:1; /* Allow HP as a mic-in */
|
||||||
|
unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
|
||||||
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
|
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
|
||||||
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
|
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
|
||||||
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
|
unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
|
||||||
@ -209,8 +226,7 @@ struct hda_gen_spec {
|
|||||||
unsigned int indep_hp:1; /* independent HP supported */
|
unsigned int indep_hp:1; /* independent HP supported */
|
||||||
unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
|
unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
|
||||||
unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
|
unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
|
||||||
unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */
|
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
|
||||||
unsigned int add_in_jack_modes:1; /* add input jack mode enum ctls */
|
|
||||||
unsigned int power_down_unused:1; /* power down unused widgets */
|
unsigned int power_down_unused:1; /* power down unused widgets */
|
||||||
|
|
||||||
/* other internal flags */
|
/* other internal flags */
|
||||||
@ -218,10 +234,18 @@ struct hda_gen_spec {
|
|||||||
unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
|
unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
|
||||||
unsigned int indep_hp_enabled:1; /* independent HP enabled */
|
unsigned int indep_hp_enabled:1; /* independent HP enabled */
|
||||||
unsigned int have_aamix_ctl:1;
|
unsigned int have_aamix_ctl:1;
|
||||||
|
unsigned int hp_mic_jack_modes:1;
|
||||||
|
|
||||||
|
/* badness tables for output path evaluations */
|
||||||
|
const struct badness_table *main_out_badness;
|
||||||
|
const struct badness_table *extra_out_badness;
|
||||||
|
|
||||||
/* loopback mixing mode */
|
/* loopback mixing mode */
|
||||||
bool aamix_mode;
|
bool aamix_mode;
|
||||||
|
|
||||||
|
/* digital beep */
|
||||||
|
hda_nid_t beep_nid;
|
||||||
|
|
||||||
/* for virtual master */
|
/* for virtual master */
|
||||||
hda_nid_t vmaster_nid;
|
hda_nid_t vmaster_nid;
|
||||||
unsigned int vmaster_tlv[4];
|
unsigned int vmaster_tlv[4];
|
||||||
|
@ -1889,6 +1889,26 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream,
|
|||||||
tc->cycle_last = last;
|
tc->cycle_last = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
|
||||||
|
u64 nsec)
|
||||||
|
{
|
||||||
|
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||||
|
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
|
||||||
|
u64 codec_frames, codec_nsecs;
|
||||||
|
|
||||||
|
if (!hinfo->ops.get_delay)
|
||||||
|
return nsec;
|
||||||
|
|
||||||
|
codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream);
|
||||||
|
codec_nsecs = div_u64(codec_frames * 1000000000LL,
|
||||||
|
substream->runtime->rate);
|
||||||
|
|
||||||
|
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||||
|
return nsec + codec_nsecs;
|
||||||
|
|
||||||
|
return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
|
static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
|
||||||
struct timespec *ts)
|
struct timespec *ts)
|
||||||
{
|
{
|
||||||
@ -1897,6 +1917,7 @@ static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
nsec = timecounter_read(&azx_dev->azx_tc);
|
nsec = timecounter_read(&azx_dev->azx_tc);
|
||||||
nsec = div_u64(nsec, 3); /* can be optimized */
|
nsec = div_u64(nsec, 3); /* can be optimized */
|
||||||
|
nsec = azx_adjust_codec_delay(substream, nsec);
|
||||||
|
|
||||||
*ts = ns_to_timespec(nsec);
|
*ts = ns_to_timespec(nsec);
|
||||||
|
|
||||||
@ -2349,8 +2370,11 @@ static unsigned int azx_get_position(struct azx *chip,
|
|||||||
struct azx_dev *azx_dev,
|
struct azx_dev *azx_dev,
|
||||||
bool with_check)
|
bool with_check)
|
||||||
{
|
{
|
||||||
|
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||||
|
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
int stream = azx_dev->substream->stream;
|
int stream = substream->stream;
|
||||||
|
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
|
||||||
int delay = 0;
|
int delay = 0;
|
||||||
|
|
||||||
switch (chip->position_fix[stream]) {
|
switch (chip->position_fix[stream]) {
|
||||||
@ -2381,7 +2405,7 @@ static unsigned int azx_get_position(struct azx *chip,
|
|||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
/* calculate runtime delay from LPIB */
|
/* calculate runtime delay from LPIB */
|
||||||
if (azx_dev->substream->runtime &&
|
if (substream->runtime &&
|
||||||
chip->position_fix[stream] == POS_FIX_POSBUF &&
|
chip->position_fix[stream] == POS_FIX_POSBUF &&
|
||||||
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
|
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
|
||||||
unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
|
unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
|
||||||
@ -2399,9 +2423,16 @@ static unsigned int azx_get_position(struct azx *chip,
|
|||||||
delay = 0;
|
delay = 0;
|
||||||
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
|
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
|
||||||
}
|
}
|
||||||
azx_dev->substream->runtime->delay =
|
delay = bytes_to_frames(substream->runtime, delay);
|
||||||
bytes_to_frames(azx_dev->substream->runtime, delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (substream->runtime) {
|
||||||
|
if (hinfo->ops.get_delay)
|
||||||
|
delay += hinfo->ops.get_delay(hinfo, apcm->codec,
|
||||||
|
substream);
|
||||||
|
substream->runtime->delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
trace_azx_get_position(chip, azx_dev, pos, delay);
|
trace_azx_get_position(chip, azx_dev, pos, delay);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,8 @@ static int get_unique_index(struct hda_codec *codec, const char *name, int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
||||||
const struct auto_pin_cfg *cfg)
|
const struct auto_pin_cfg *cfg,
|
||||||
|
const char *base_name)
|
||||||
{
|
{
|
||||||
unsigned int def_conf, conn;
|
unsigned int def_conf, conn;
|
||||||
char name[44];
|
char name[44];
|
||||||
@ -410,6 +411,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
|||||||
phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
|
phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
|
||||||
!is_jack_detectable(codec, nid);
|
!is_jack_detectable(codec, nid);
|
||||||
|
|
||||||
|
if (base_name) {
|
||||||
|
strlcpy(name, base_name, sizeof(name));
|
||||||
|
idx = 0;
|
||||||
|
} else
|
||||||
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
|
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
|
||||||
if (phantom_jack)
|
if (phantom_jack)
|
||||||
/* Example final name: "Internal Mic Phantom Jack" */
|
/* Example final name: "Internal Mic Phantom Jack" */
|
||||||
@ -433,39 +438,51 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
|
|||||||
const hda_nid_t *p;
|
const hda_nid_t *p;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
|
for (i = 0; i < cfg->num_inputs; i++) {
|
||||||
|
/* If we have headphone mics; make sure they get the right name
|
||||||
|
before grabbed by output pins */
|
||||||
|
if (cfg->inputs[i].is_headphone_mic) {
|
||||||
|
if (auto_cfg_hp_outs(cfg) == 1)
|
||||||
|
err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0],
|
||||||
|
cfg, "Headphone Mic");
|
||||||
|
else
|
||||||
|
err = add_jack_kctl(codec, cfg->inputs[i].pin,
|
||||||
|
cfg, "Headphone Mic");
|
||||||
|
} else
|
||||||
|
err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
|
||||||
|
NULL);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
|
for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
|
||||||
err = add_jack_kctl(codec, *p, cfg);
|
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
|
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
|
||||||
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
||||||
break;
|
break;
|
||||||
err = add_jack_kctl(codec, *p, cfg);
|
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
|
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
|
||||||
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
||||||
break;
|
break;
|
||||||
err = add_jack_kctl(codec, *p, cfg);
|
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
|
||||||
err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
|
for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
|
||||||
err = add_jack_kctl(codec, *p, cfg);
|
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
|
err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
|
err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -670,6 +670,10 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
|
|||||||
return (state != target_state);
|
return (state != target_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
||||||
|
hda_nid_t nid,
|
||||||
|
unsigned int power_state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AMP control callbacks
|
* AMP control callbacks
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,6 @@ struct ad198x_spec {
|
|||||||
hda_nid_t eapd_nid;
|
hda_nid_t eapd_nid;
|
||||||
|
|
||||||
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
|
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
|
||||||
hda_nid_t beep_dev_nid;
|
|
||||||
|
|
||||||
#ifdef ENABLE_AD_STATIC_QUIRKS
|
#ifdef ENABLE_AD_STATIC_QUIRKS
|
||||||
const struct snd_kcontrol_new *mixers[6];
|
const struct snd_kcontrol_new *mixers[6];
|
||||||
@ -609,7 +608,7 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
|
|||||||
.build_controls = ad198x_auto_build_controls,
|
.build_controls = ad198x_auto_build_controls,
|
||||||
.build_pcms = snd_hda_gen_build_pcms,
|
.build_pcms = snd_hda_gen_build_pcms,
|
||||||
.init = snd_hda_gen_init,
|
.init = snd_hda_gen_init,
|
||||||
.free = ad198x_free,
|
.free = snd_hda_gen_free,
|
||||||
.unsol_event = snd_hda_jack_unsol_event,
|
.unsol_event = snd_hda_jack_unsol_event,
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
.check_power_status = snd_hda_gen_check_power_status,
|
.check_power_status = snd_hda_gen_check_power_status,
|
||||||
@ -638,12 +637,6 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (spec->beep_dev_nid) {
|
|
||||||
err = snd_hda_attach_beep_device(codec, spec->beep_dev_nid);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
codec->patch_ops = ad198x_auto_patch_ops;
|
codec->patch_ops = ad198x_auto_patch_ops;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1240,7 +1233,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
|
|||||||
codec->inv_eapd = 1;
|
codec->inv_eapd = 1;
|
||||||
|
|
||||||
spec->gen.mixer_nid = 0x07;
|
spec->gen.mixer_nid = 0x07;
|
||||||
spec->beep_dev_nid = 0x19;
|
spec->gen.beep_nid = 0x19;
|
||||||
set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
|
||||||
|
|
||||||
/* AD1986A has a hardware problem that it can't share a stream
|
/* AD1986A has a hardware problem that it can't share a stream
|
||||||
@ -1256,7 +1249,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
|
|||||||
|
|
||||||
err = ad198x_parse_auto_config(codec);
|
err = ad198x_parse_auto_config(codec);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1673,7 +1666,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
|
|||||||
return err;
|
return err;
|
||||||
spec = codec->spec;
|
spec = codec->spec;
|
||||||
|
|
||||||
spec->beep_dev_nid = 0x10;
|
spec->gen.beep_nid = 0x10;
|
||||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||||
err = ad198x_parse_auto_config(codec);
|
err = ad198x_parse_auto_config(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -1684,7 +1677,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2187,7 +2180,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
|
|||||||
spec = codec->spec;
|
spec = codec->spec;
|
||||||
|
|
||||||
spec->gen.mixer_nid = 0x0e;
|
spec->gen.mixer_nid = 0x0e;
|
||||||
spec->beep_dev_nid = 0x10;
|
spec->gen.beep_nid = 0x10;
|
||||||
set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
|
||||||
|
|
||||||
snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
|
snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
|
||||||
@ -2205,7 +2198,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3236,7 +3229,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
|
|||||||
|
|
||||||
spec->gen.mixer_nid = 0x20;
|
spec->gen.mixer_nid = 0x20;
|
||||||
spec->gen.mixer_merge_nid = 0x21;
|
spec->gen.mixer_merge_nid = 0x21;
|
||||||
spec->beep_dev_nid = 0x10;
|
spec->gen.beep_nid = 0x10;
|
||||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||||
err = ad198x_parse_auto_config(codec);
|
err = ad198x_parse_auto_config(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -3247,7 +3240,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3653,7 +3646,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
|
|||||||
spec = codec->spec;
|
spec = codec->spec;
|
||||||
|
|
||||||
spec->gen.mixer_nid = 0x20;
|
spec->gen.mixer_nid = 0x20;
|
||||||
spec->beep_dev_nid = 0x10;
|
spec->gen.beep_nid = 0x10;
|
||||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||||
|
|
||||||
snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
|
snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
|
||||||
@ -3671,7 +3664,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5155,7 +5148,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
|
|||||||
|
|
||||||
spec->gen.mixer_nid = 0x20;
|
spec->gen.mixer_nid = 0x20;
|
||||||
spec->gen.mixer_merge_nid = 0x21;
|
spec->gen.mixer_merge_nid = 0x21;
|
||||||
spec->beep_dev_nid = 0x10;
|
spec->gen.beep_nid = 0x10;
|
||||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||||
err = ad198x_parse_auto_config(codec);
|
err = ad198x_parse_auto_config(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -5166,7 +5159,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ad198x_free(codec);
|
snd_hda_gen_free(codec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +131,13 @@ enum {
|
|||||||
/* Effects values size*/
|
/* Effects values size*/
|
||||||
#define EFFECT_VALS_MAX_COUNT 12
|
#define EFFECT_VALS_MAX_COUNT 12
|
||||||
|
|
||||||
|
/* Latency introduced by DSP blocks in milliseconds. */
|
||||||
|
#define DSP_CAPTURE_INIT_LATENCY 0
|
||||||
|
#define DSP_CRYSTAL_VOICE_LATENCY 124
|
||||||
|
#define DSP_PLAYBACK_INIT_LATENCY 13
|
||||||
|
#define DSP_PLAY_ENHANCEMENT_LATENCY 30
|
||||||
|
#define DSP_SPEAKER_OUT_LATENCY 7
|
||||||
|
|
||||||
struct ct_effect {
|
struct ct_effect {
|
||||||
char name[44];
|
char name[44];
|
||||||
hda_nid_t nid;
|
hda_nid_t nid;
|
||||||
@ -741,6 +748,9 @@ struct ca0132_spec {
|
|||||||
long voicefx_val;
|
long voicefx_val;
|
||||||
long cur_mic_boost;
|
long cur_mic_boost;
|
||||||
|
|
||||||
|
struct hda_codec *codec;
|
||||||
|
struct delayed_work unsol_hp_work;
|
||||||
|
|
||||||
#ifdef ENABLE_TUNING_CONTROLS
|
#ifdef ENABLE_TUNING_CONTROLS
|
||||||
long cur_ctl_vals[TUNING_CTLS_COUNT];
|
long cur_ctl_vals[TUNING_CTLS_COUNT];
|
||||||
#endif
|
#endif
|
||||||
@ -2740,6 +2750,31 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int ca0132_playback_pcm_delay(struct hda_pcm_stream *info,
|
||||||
|
struct hda_codec *codec,
|
||||||
|
struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct ca0132_spec *spec = codec->spec;
|
||||||
|
unsigned int latency = DSP_PLAYBACK_INIT_LATENCY;
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
if (spec->dsp_state != DSP_DOWNLOADED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Add latency if playback enhancement and either effect is enabled. */
|
||||||
|
if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) {
|
||||||
|
if ((spec->effects_switch[SURROUND - EFFECT_START_NID]) ||
|
||||||
|
(spec->effects_switch[DIALOG_PLUS - EFFECT_START_NID]))
|
||||||
|
latency += DSP_PLAY_ENHANCEMENT_LATENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applying Speaker EQ adds latency as well. */
|
||||||
|
if (spec->cur_out_type == SPEAKER_OUT)
|
||||||
|
latency += DSP_SPEAKER_OUT_LATENCY;
|
||||||
|
|
||||||
|
return (latency * runtime->rate) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Digital out
|
* Digital out
|
||||||
*/
|
*/
|
||||||
@ -2808,6 +2843,23 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info,
|
||||||
|
struct hda_codec *codec,
|
||||||
|
struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct ca0132_spec *spec = codec->spec;
|
||||||
|
unsigned int latency = DSP_CAPTURE_INIT_LATENCY;
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
|
||||||
|
if (spec->dsp_state != DSP_DOWNLOADED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID])
|
||||||
|
latency += DSP_CRYSTAL_VOICE_LATENCY;
|
||||||
|
|
||||||
|
return (latency * runtime->rate) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controls stuffs.
|
* Controls stuffs.
|
||||||
*/
|
*/
|
||||||
@ -3227,6 +3279,14 @@ exit:
|
|||||||
return err < 0 ? err : 0;
|
return err < 0 ? err : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ca0132_unsol_hp_delayed(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct ca0132_spec *spec = container_of(
|
||||||
|
to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
|
||||||
|
ca0132_select_out(spec->codec);
|
||||||
|
snd_hda_jack_report_sync(spec->codec);
|
||||||
|
}
|
||||||
|
|
||||||
static void ca0132_set_dmic(struct hda_codec *codec, int enable);
|
static void ca0132_set_dmic(struct hda_codec *codec, int enable);
|
||||||
static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
|
static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
|
||||||
static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
|
static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
|
||||||
@ -3991,7 +4051,8 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = {
|
|||||||
.channels_max = 6,
|
.channels_max = 6,
|
||||||
.ops = {
|
.ops = {
|
||||||
.prepare = ca0132_playback_pcm_prepare,
|
.prepare = ca0132_playback_pcm_prepare,
|
||||||
.cleanup = ca0132_playback_pcm_cleanup
|
.cleanup = ca0132_playback_pcm_cleanup,
|
||||||
|
.get_delay = ca0132_playback_pcm_delay,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4001,7 +4062,8 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {
|
|||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.ops = {
|
.ops = {
|
||||||
.prepare = ca0132_capture_pcm_prepare,
|
.prepare = ca0132_capture_pcm_prepare,
|
||||||
.cleanup = ca0132_capture_pcm_cleanup
|
.cleanup = ca0132_capture_pcm_cleanup,
|
||||||
|
.get_delay = ca0132_capture_pcm_delay,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4399,8 +4461,7 @@ static void ca0132_process_dsp_response(struct hda_codec *codec)
|
|||||||
|
|
||||||
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||||
{
|
{
|
||||||
snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res);
|
struct ca0132_spec *spec = codec->spec;
|
||||||
|
|
||||||
|
|
||||||
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
|
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
|
||||||
ca0132_process_dsp_response(codec);
|
ca0132_process_dsp_response(codec);
|
||||||
@ -4412,8 +4473,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
|||||||
|
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case UNSOL_TAG_HP:
|
case UNSOL_TAG_HP:
|
||||||
ca0132_select_out(codec);
|
/* Delay enabling the HP amp, to let the mic-detection
|
||||||
snd_hda_jack_report_sync(codec);
|
* state machine run.
|
||||||
|
*/
|
||||||
|
cancel_delayed_work_sync(&spec->unsol_hp_work);
|
||||||
|
queue_delayed_work(codec->bus->workq,
|
||||||
|
&spec->unsol_hp_work,
|
||||||
|
msecs_to_jiffies(500));
|
||||||
break;
|
break;
|
||||||
case UNSOL_TAG_AMIC1:
|
case UNSOL_TAG_AMIC1:
|
||||||
ca0132_select_mic(codec);
|
ca0132_select_mic(codec);
|
||||||
@ -4588,6 +4654,7 @@ static void ca0132_free(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct ca0132_spec *spec = codec->spec;
|
struct ca0132_spec *spec = codec->spec;
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&spec->unsol_hp_work);
|
||||||
snd_hda_power_up(codec);
|
snd_hda_power_up(codec);
|
||||||
snd_hda_sequence_write(codec, spec->base_exit_verbs);
|
snd_hda_sequence_write(codec, spec->base_exit_verbs);
|
||||||
ca0132_exit_chip(codec);
|
ca0132_exit_chip(codec);
|
||||||
@ -4653,6 +4720,7 @@ static int patch_ca0132(struct hda_codec *codec)
|
|||||||
if (!spec)
|
if (!spec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
codec->spec = spec;
|
codec->spec = spec;
|
||||||
|
spec->codec = codec;
|
||||||
|
|
||||||
spec->num_mixers = 1;
|
spec->num_mixers = 1;
|
||||||
spec->mixers[0] = ca0132_mixer;
|
spec->mixers[0] = ca0132_mixer;
|
||||||
@ -4663,6 +4731,8 @@ static int patch_ca0132(struct hda_codec *codec)
|
|||||||
spec->init_verbs[1] = ca0132_init_verbs1;
|
spec->init_verbs[1] = ca0132_init_verbs1;
|
||||||
spec->num_init_verbs = 2;
|
spec->num_init_verbs = 2;
|
||||||
|
|
||||||
|
INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
|
||||||
|
|
||||||
ca0132_init_chip(codec);
|
ca0132_init_chip(codec);
|
||||||
|
|
||||||
ca0132_config(codec);
|
ca0132_config(codec);
|
||||||
|
@ -68,6 +68,7 @@ enum {
|
|||||||
enum {
|
enum {
|
||||||
CS421X_CDB4210,
|
CS421X_CDB4210,
|
||||||
CS421X_SENSE_B,
|
CS421X_SENSE_B,
|
||||||
|
CS421X_STUMPY,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Vendor-specific processing widget */
|
/* Vendor-specific processing widget */
|
||||||
@ -538,6 +539,7 @@ static int patch_cs420x(struct hda_codec *codec)
|
|||||||
/* CS4210 board names */
|
/* CS4210 board names */
|
||||||
static const struct hda_model_fixup cs421x_models[] = {
|
static const struct hda_model_fixup cs421x_models[] = {
|
||||||
{ .id = CS421X_CDB4210, .name = "cdb4210" },
|
{ .id = CS421X_CDB4210, .name = "cdb4210" },
|
||||||
|
{ .id = CS421X_STUMPY, .name = "stumpy" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -559,6 +561,17 @@ static const struct hda_pintbl cdb4210_pincfgs[] = {
|
|||||||
{} /* terminator */
|
{} /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Stumpy ChromeBox */
|
||||||
|
static const struct hda_pintbl stumpy_pincfgs[] = {
|
||||||
|
{ 0x05, 0x022120f0 },
|
||||||
|
{ 0x06, 0x901700f0 },
|
||||||
|
{ 0x07, 0x02a120f0 },
|
||||||
|
{ 0x08, 0x77a70037 },
|
||||||
|
{ 0x09, 0x77a6003e },
|
||||||
|
{ 0x0a, 0x434510f0 },
|
||||||
|
{} /* terminator */
|
||||||
|
};
|
||||||
|
|
||||||
/* Setup GPIO/SENSE for each board (if used) */
|
/* Setup GPIO/SENSE for each board (if used) */
|
||||||
static void cs421x_fixup_sense_b(struct hda_codec *codec,
|
static void cs421x_fixup_sense_b(struct hda_codec *codec,
|
||||||
const struct hda_fixup *fix, int action)
|
const struct hda_fixup *fix, int action)
|
||||||
@ -578,7 +591,11 @@ static const struct hda_fixup cs421x_fixups[] = {
|
|||||||
[CS421X_SENSE_B] = {
|
[CS421X_SENSE_B] = {
|
||||||
.type = HDA_FIXUP_FUNC,
|
.type = HDA_FIXUP_FUNC,
|
||||||
.v.func = cs421x_fixup_sense_b,
|
.v.func = cs421x_fixup_sense_b,
|
||||||
}
|
},
|
||||||
|
[CS421X_STUMPY] = {
|
||||||
|
.type = HDA_FIXUP_PINS,
|
||||||
|
.v.pins = stumpy_pincfgs,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hda_verb cs421x_coef_init_verbs[] = {
|
static const struct hda_verb cs421x_coef_init_verbs[] = {
|
||||||
|
@ -139,8 +139,12 @@ struct conexant_spec {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||||
#define set_beep_amp(spec, nid, idx, dir) \
|
static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
|
||||||
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
|
int idx, int dir)
|
||||||
|
{
|
||||||
|
spec->gen.beep_nid = nid;
|
||||||
|
spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
|
||||||
|
}
|
||||||
/* additional beep mixers; the actual parameters are overwritten at build */
|
/* additional beep mixers; the actual parameters are overwritten at build */
|
||||||
static const struct snd_kcontrol_new cxt_beep_mixer[] = {
|
static const struct snd_kcontrol_new cxt_beep_mixer[] = {
|
||||||
HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
|
HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
|
||||||
@ -2942,7 +2946,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
|
|||||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
|
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
|
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
|
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
|
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
|
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
|
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
|
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
|
||||||
@ -3191,17 +3194,11 @@ static int cx_auto_build_controls(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cx_auto_free(struct hda_codec *codec)
|
|
||||||
{
|
|
||||||
snd_hda_detach_beep_device(codec);
|
|
||||||
snd_hda_gen_free(codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct hda_codec_ops cx_auto_patch_ops = {
|
static const struct hda_codec_ops cx_auto_patch_ops = {
|
||||||
.build_controls = cx_auto_build_controls,
|
.build_controls = cx_auto_build_controls,
|
||||||
.build_pcms = snd_hda_gen_build_pcms,
|
.build_pcms = snd_hda_gen_build_pcms,
|
||||||
.init = snd_hda_gen_init,
|
.init = snd_hda_gen_init,
|
||||||
.free = cx_auto_free,
|
.free = snd_hda_gen_free,
|
||||||
.unsol_event = snd_hda_jack_unsol_event,
|
.unsol_event = snd_hda_jack_unsol_event,
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
.check_power_status = snd_hda_gen_check_power_status,
|
.check_power_status = snd_hda_gen_check_power_status,
|
||||||
@ -3310,6 +3307,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
|
|||||||
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
|
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
|
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
|
SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
|
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
|
||||||
@ -3356,7 +3354,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||||||
switch (codec->vendor_id) {
|
switch (codec->vendor_id) {
|
||||||
case 0x14f15045:
|
case 0x14f15045:
|
||||||
codec->single_adc_amp = 1;
|
codec->single_adc_amp = 1;
|
||||||
codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */
|
|
||||||
break;
|
break;
|
||||||
case 0x14f15047:
|
case 0x14f15047:
|
||||||
codec->pin_amp_workaround = 1;
|
codec->pin_amp_workaround = 1;
|
||||||
@ -3396,8 +3393,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
codec->patch_ops = cx_auto_patch_ops;
|
codec->patch_ops = cx_auto_patch_ops;
|
||||||
if (spec->beep_amp)
|
|
||||||
snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
|
|
||||||
|
|
||||||
/* Some laptops with Conexant chips show stalls in S3 resume,
|
/* Some laptops with Conexant chips show stalls in S3 resume,
|
||||||
* which falls into the single-cmd mode.
|
* which falls into the single-cmd mode.
|
||||||
|
@ -44,16 +44,6 @@ static bool static_hdmi_pcm;
|
|||||||
module_param(static_hdmi_pcm, bool, 0644);
|
module_param(static_hdmi_pcm, bool, 0644);
|
||||||
MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
|
MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
|
||||||
|
|
||||||
/*
|
|
||||||
* The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
|
|
||||||
* could support N independent pipes, each of them can be connected to one or
|
|
||||||
* more ports (DVI, HDMI or DisplayPort).
|
|
||||||
*
|
|
||||||
* The HDA correspondence of pipes/ports are converter/pin nodes.
|
|
||||||
*/
|
|
||||||
#define MAX_HDMI_CVTS 8
|
|
||||||
#define MAX_HDMI_PINS 8
|
|
||||||
|
|
||||||
struct hdmi_spec_per_cvt {
|
struct hdmi_spec_per_cvt {
|
||||||
hda_nid_t cvt_nid;
|
hda_nid_t cvt_nid;
|
||||||
int assigned;
|
int assigned;
|
||||||
@ -80,16 +70,17 @@ struct hdmi_spec_per_pin {
|
|||||||
bool non_pcm;
|
bool non_pcm;
|
||||||
bool chmap_set; /* channel-map override by ALSA API? */
|
bool chmap_set; /* channel-map override by ALSA API? */
|
||||||
unsigned char chmap[8]; /* ALSA API channel-map */
|
unsigned char chmap[8]; /* ALSA API channel-map */
|
||||||
|
char pcm_name[8]; /* filled in build_pcm callbacks */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hdmi_spec {
|
struct hdmi_spec {
|
||||||
int num_cvts;
|
int num_cvts;
|
||||||
struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS];
|
struct snd_array cvts; /* struct hdmi_spec_per_cvt */
|
||||||
hda_nid_t cvt_nids[MAX_HDMI_CVTS];
|
hda_nid_t cvt_nids[4]; /* only for haswell fix */
|
||||||
|
|
||||||
int num_pins;
|
int num_pins;
|
||||||
struct hdmi_spec_per_pin pins[MAX_HDMI_PINS];
|
struct snd_array pins; /* struct hdmi_spec_per_pin */
|
||||||
struct hda_pcm pcm_rec[MAX_HDMI_PINS];
|
struct snd_array pcm_rec; /* struct hda_pcm */
|
||||||
unsigned int channels_max; /* max over all cvts */
|
unsigned int channels_max; /* max over all cvts */
|
||||||
|
|
||||||
struct hdmi_eld temp_eld;
|
struct hdmi_eld temp_eld;
|
||||||
@ -304,12 +295,19 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
|
|||||||
* HDMI routines
|
* HDMI routines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define get_pin(spec, idx) \
|
||||||
|
((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
|
||||||
|
#define get_cvt(spec, idx) \
|
||||||
|
((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx))
|
||||||
|
#define get_pcm_rec(spec, idx) \
|
||||||
|
((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx))
|
||||||
|
|
||||||
static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid)
|
static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid)
|
||||||
{
|
{
|
||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
||||||
if (spec->pins[pin_idx].pin_nid == pin_nid)
|
if (get_pin(spec, pin_idx)->pin_nid == pin_nid)
|
||||||
return pin_idx;
|
return pin_idx;
|
||||||
|
|
||||||
snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid);
|
snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid);
|
||||||
@ -322,7 +320,7 @@ static int hinfo_to_pin_index(struct hdmi_spec *spec,
|
|||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
||||||
if (&spec->pcm_rec[pin_idx].stream[0] == hinfo)
|
if (get_pcm_rec(spec, pin_idx)->stream == hinfo)
|
||||||
return pin_idx;
|
return pin_idx;
|
||||||
|
|
||||||
snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo);
|
snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo);
|
||||||
@ -334,7 +332,7 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
|
|||||||
int cvt_idx;
|
int cvt_idx;
|
||||||
|
|
||||||
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++)
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++)
|
||||||
if (spec->cvts[cvt_idx].cvt_nid == cvt_nid)
|
if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid)
|
||||||
return cvt_idx;
|
return cvt_idx;
|
||||||
|
|
||||||
snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid);
|
snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid);
|
||||||
@ -352,7 +350,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
|
|||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
||||||
|
|
||||||
pin_idx = kcontrol->private_value;
|
pin_idx = kcontrol->private_value;
|
||||||
eld = &spec->pins[pin_idx].sink_eld;
|
eld = &get_pin(spec, pin_idx)->sink_eld;
|
||||||
|
|
||||||
mutex_lock(&eld->lock);
|
mutex_lock(&eld->lock);
|
||||||
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
|
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
|
||||||
@ -370,7 +368,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
|
|||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
pin_idx = kcontrol->private_value;
|
pin_idx = kcontrol->private_value;
|
||||||
eld = &spec->pins[pin_idx].sink_eld;
|
eld = &get_pin(spec, pin_idx)->sink_eld;
|
||||||
|
|
||||||
mutex_lock(&eld->lock);
|
mutex_lock(&eld->lock);
|
||||||
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
|
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
|
||||||
@ -410,11 +408,11 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
|
|||||||
kctl->private_value = pin_idx;
|
kctl->private_value = pin_idx;
|
||||||
kctl->id.device = device;
|
kctl->id.device = device;
|
||||||
|
|
||||||
err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl);
|
err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
spec->pins[pin_idx].eld_ctl = kctl;
|
get_pin(spec, pin_idx)->eld_ctl = kctl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,14 +873,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
|
|||||||
struct snd_pcm_substream *substream)
|
struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||||
int channels = substream->runtime->channels;
|
int channels = substream->runtime->channels;
|
||||||
struct hdmi_eld *eld;
|
struct hdmi_eld *eld;
|
||||||
int ca;
|
int ca;
|
||||||
union audio_infoframe ai;
|
union audio_infoframe ai;
|
||||||
|
|
||||||
eld = &spec->pins[pin_idx].sink_eld;
|
eld = &per_pin->sink_eld;
|
||||||
if (!eld->monitor_present)
|
if (!eld->monitor_present)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -977,7 +975,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
|||||||
if (pin_idx < 0)
|
if (pin_idx < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hdmi_present_sense(&spec->pins[pin_idx], 1);
|
hdmi_present_sense(get_pin(spec, pin_idx), 1);
|
||||||
snd_hda_jack_report_sync(codec);
|
snd_hda_jack_report_sync(codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,6 +1018,41 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
|
|||||||
hdmi_non_intrinsic_event(codec, res);
|
hdmi_non_intrinsic_event(codec, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
int pwr, lamp, ramp;
|
||||||
|
|
||||||
|
pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
|
||||||
|
pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
|
||||||
|
if (pwr != AC_PWRST_D0) {
|
||||||
|
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
|
||||||
|
AC_PWRST_D0);
|
||||||
|
msleep(40);
|
||||||
|
pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
|
||||||
|
pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
|
||||||
|
snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr);
|
||||||
|
}
|
||||||
|
|
||||||
|
lamp = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_AMP_GAIN_MUTE,
|
||||||
|
AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
|
||||||
|
ramp = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_AMP_GAIN_MUTE,
|
||||||
|
AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
|
||||||
|
if (lamp != ramp) {
|
||||||
|
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||||
|
AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT | lamp);
|
||||||
|
|
||||||
|
lamp = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_AMP_GAIN_MUTE,
|
||||||
|
AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
|
||||||
|
ramp = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_AMP_GAIN_MUTE,
|
||||||
|
AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
|
||||||
|
snd_printd("Haswell HDMI audio: Mute after set on pin 0x%x: [0x%x 0x%x]\n", nid, lamp, ramp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callbacks
|
* Callbacks
|
||||||
*/
|
*/
|
||||||
@ -1034,6 +1067,9 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
|||||||
int pinctl;
|
int pinctl;
|
||||||
int new_pinctl = 0;
|
int new_pinctl = 0;
|
||||||
|
|
||||||
|
if (codec->vendor_id == 0x80862807)
|
||||||
|
haswell_verify_pin_D0(codec, pin_nid);
|
||||||
|
|
||||||
if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
|
if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
|
||||||
pinctl = snd_hda_codec_read(codec, pin_nid, 0,
|
pinctl = snd_hda_codec_read(codec, pin_nid, 0,
|
||||||
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
||||||
@ -1083,12 +1119,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
|||||||
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
||||||
if (snd_BUG_ON(pin_idx < 0))
|
if (snd_BUG_ON(pin_idx < 0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
per_pin = &spec->pins[pin_idx];
|
per_pin = get_pin(spec, pin_idx);
|
||||||
eld = &per_pin->sink_eld;
|
eld = &per_pin->sink_eld;
|
||||||
|
|
||||||
/* Dynamically assign converter to stream */
|
/* Dynamically assign converter to stream */
|
||||||
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
|
||||||
per_cvt = &spec->cvts[cvt_idx];
|
per_cvt = get_cvt(spec, cvt_idx);
|
||||||
|
|
||||||
/* Must not already be assigned */
|
/* Must not already be assigned */
|
||||||
if (per_cvt->assigned)
|
if (per_cvt->assigned)
|
||||||
@ -1151,7 +1187,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
|||||||
static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
|
static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||||
|
|
||||||
if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
|
if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
|
||||||
@ -1275,14 +1311,13 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
|||||||
if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
|
if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS))
|
|
||||||
return -E2BIG;
|
|
||||||
|
|
||||||
if (codec->vendor_id == 0x80862807)
|
if (codec->vendor_id == 0x80862807)
|
||||||
intel_haswell_fixup_connect_list(codec, pin_nid);
|
intel_haswell_fixup_connect_list(codec, pin_nid);
|
||||||
|
|
||||||
pin_idx = spec->num_pins;
|
pin_idx = spec->num_pins;
|
||||||
per_pin = &spec->pins[pin_idx];
|
per_pin = snd_array_new(&spec->pins);
|
||||||
|
if (!per_pin)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
per_pin->pin_nid = pin_nid;
|
per_pin->pin_nid = pin_nid;
|
||||||
per_pin->non_pcm = false;
|
per_pin->non_pcm = false;
|
||||||
@ -1299,19 +1334,16 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
|||||||
static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int cvt_idx;
|
|
||||||
struct hdmi_spec_per_cvt *per_cvt;
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
unsigned int chans;
|
unsigned int chans;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS))
|
|
||||||
return -E2BIG;
|
|
||||||
|
|
||||||
chans = get_wcaps(codec, cvt_nid);
|
chans = get_wcaps(codec, cvt_nid);
|
||||||
chans = get_wcaps_channels(chans);
|
chans = get_wcaps_channels(chans);
|
||||||
|
|
||||||
cvt_idx = spec->num_cvts;
|
per_cvt = snd_array_new(&spec->cvts);
|
||||||
per_cvt = &spec->cvts[cvt_idx];
|
if (!per_cvt)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
per_cvt->cvt_nid = cvt_nid;
|
per_cvt->cvt_nid = cvt_nid;
|
||||||
per_cvt->channels_min = 2;
|
per_cvt->channels_min = 2;
|
||||||
@ -1328,7 +1360,9 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
spec->cvt_nids[spec->num_cvts++] = cvt_nid;
|
if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids))
|
||||||
|
spec->cvt_nids[spec->num_cvts] = cvt_nid;
|
||||||
|
spec->num_cvts++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1384,13 +1418,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
static char *get_hdmi_pcm_name(int idx)
|
|
||||||
{
|
|
||||||
static char names[MAX_HDMI_PINS][8];
|
|
||||||
sprintf(&names[idx][0], "HDMI %d", idx);
|
|
||||||
return &names[idx][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
||||||
{
|
{
|
||||||
struct hda_spdif_out *spdif;
|
struct hda_spdif_out *spdif;
|
||||||
@ -1417,7 +1444,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|||||||
hda_nid_t cvt_nid = hinfo->nid;
|
hda_nid_t cvt_nid = hinfo->nid;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int pin_idx = hinfo_to_pin_index(spec, hinfo);
|
int pin_idx = hinfo_to_pin_index(spec, hinfo);
|
||||||
hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid;
|
hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid;
|
||||||
bool non_pcm;
|
bool non_pcm;
|
||||||
|
|
||||||
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
||||||
@ -1450,7 +1477,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
|
|||||||
cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
|
cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
|
||||||
if (snd_BUG_ON(cvt_idx < 0))
|
if (snd_BUG_ON(cvt_idx < 0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
per_cvt = &spec->cvts[cvt_idx];
|
per_cvt = get_cvt(spec, cvt_idx);
|
||||||
|
|
||||||
snd_BUG_ON(!per_cvt->assigned);
|
snd_BUG_ON(!per_cvt->assigned);
|
||||||
per_cvt->assigned = 0;
|
per_cvt->assigned = 0;
|
||||||
@ -1459,7 +1486,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
|
|||||||
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
||||||
if (snd_BUG_ON(pin_idx < 0))
|
if (snd_BUG_ON(pin_idx < 0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
per_pin = &spec->pins[pin_idx];
|
per_pin = get_pin(spec, pin_idx);
|
||||||
|
|
||||||
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
||||||
per_pin->chmap_set = false;
|
per_pin->chmap_set = false;
|
||||||
@ -1553,7 +1580,7 @@ static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
|||||||
struct hda_codec *codec = info->private_data;
|
struct hda_codec *codec = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int pin_idx = kcontrol->private_value;
|
int pin_idx = kcontrol->private_value;
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
|
for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
|
||||||
@ -1568,7 +1595,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
|||||||
struct hda_codec *codec = info->private_data;
|
struct hda_codec *codec = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int pin_idx = kcontrol->private_value;
|
int pin_idx = kcontrol->private_value;
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
unsigned int ctl_idx;
|
unsigned int ctl_idx;
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
unsigned char chmap[8];
|
unsigned char chmap[8];
|
||||||
@ -1613,9 +1640,14 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
|
|||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hda_pcm *info;
|
struct hda_pcm *info;
|
||||||
struct hda_pcm_stream *pstr;
|
struct hda_pcm_stream *pstr;
|
||||||
|
struct hdmi_spec_per_pin *per_pin;
|
||||||
|
|
||||||
info = &spec->pcm_rec[pin_idx];
|
per_pin = get_pin(spec, pin_idx);
|
||||||
info->name = get_hdmi_pcm_name(pin_idx);
|
sprintf(per_pin->pcm_name, "HDMI %d", pin_idx);
|
||||||
|
info = snd_array_new(&spec->pcm_rec);
|
||||||
|
if (!info)
|
||||||
|
return -ENOMEM;
|
||||||
|
info->name = per_pin->pcm_name;
|
||||||
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
||||||
info->own_chmap = true;
|
info->own_chmap = true;
|
||||||
|
|
||||||
@ -1626,7 +1658,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
codec->num_pcms = spec->num_pins;
|
codec->num_pcms = spec->num_pins;
|
||||||
codec->pcm_info = spec->pcm_rec;
|
codec->pcm_info = spec->pcm_rec.list;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1635,8 +1667,8 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
|
|||||||
{
|
{
|
||||||
char hdmi_str[32] = "HDMI/DP";
|
char hdmi_str[32] = "HDMI/DP";
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
int pcmdev = spec->pcm_rec[pin_idx].device;
|
int pcmdev = get_pcm_rec(spec, pin_idx)->device;
|
||||||
|
|
||||||
if (pcmdev > 0)
|
if (pcmdev > 0)
|
||||||
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
|
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
|
||||||
@ -1654,7 +1686,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
|
|||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
|
|
||||||
err = generic_hdmi_build_jack(codec, pin_idx);
|
err = generic_hdmi_build_jack(codec, pin_idx);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -1669,9 +1701,8 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
|
|||||||
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
||||||
|
|
||||||
/* add control for ELD Bytes */
|
/* add control for ELD Bytes */
|
||||||
err = hdmi_create_eld_ctl(codec,
|
err = hdmi_create_eld_ctl(codec, pin_idx,
|
||||||
pin_idx,
|
get_pcm_rec(spec, pin_idx)->device);
|
||||||
spec->pcm_rec[pin_idx].device);
|
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -1709,7 +1740,7 @@ static int generic_hdmi_init_per_pins(struct hda_codec *codec)
|
|||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
struct hdmi_eld *eld = &per_pin->sink_eld;
|
struct hdmi_eld *eld = &per_pin->sink_eld;
|
||||||
|
|
||||||
per_pin->codec = codec;
|
per_pin->codec = codec;
|
||||||
@ -1726,7 +1757,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
|||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
hda_nid_t pin_nid = per_pin->pin_nid;
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
||||||
|
|
||||||
hdmi_init_pin(codec, pin_nid);
|
hdmi_init_pin(codec, pin_nid);
|
||||||
@ -1735,13 +1766,27 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdmi_array_init(struct hdmi_spec *spec, int nums)
|
||||||
|
{
|
||||||
|
snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums);
|
||||||
|
snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums);
|
||||||
|
snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hdmi_array_free(struct hdmi_spec *spec)
|
||||||
|
{
|
||||||
|
snd_array_free(&spec->pins);
|
||||||
|
snd_array_free(&spec->cvts);
|
||||||
|
snd_array_free(&spec->pcm_rec);
|
||||||
|
}
|
||||||
|
|
||||||
static void generic_hdmi_free(struct hda_codec *codec)
|
static void generic_hdmi_free(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int pin_idx;
|
int pin_idx;
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
struct hdmi_eld *eld = &per_pin->sink_eld;
|
struct hdmi_eld *eld = &per_pin->sink_eld;
|
||||||
|
|
||||||
cancel_delayed_work(&per_pin->work);
|
cancel_delayed_work(&per_pin->work);
|
||||||
@ -1749,6 +1794,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
flush_workqueue(codec->bus->workq);
|
flush_workqueue(codec->bus->workq);
|
||||||
|
hdmi_array_free(spec);
|
||||||
kfree(spec);
|
kfree(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1775,6 +1821,7 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
|||||||
|
|
||||||
/* override pins connection list */
|
/* override pins connection list */
|
||||||
snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
|
snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
|
||||||
|
nconns = max(spec->num_cvts, 4);
|
||||||
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
|
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1855,6 +1902,7 @@ static int patch_generic_hdmi(struct hda_codec *codec)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
codec->spec = spec;
|
codec->spec = spec;
|
||||||
|
hdmi_array_init(spec, 4);
|
||||||
|
|
||||||
snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups);
|
snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups);
|
||||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
||||||
@ -1882,24 +1930,30 @@ static int patch_generic_hdmi(struct hda_codec *codec)
|
|||||||
static int simple_playback_build_pcms(struct hda_codec *codec)
|
static int simple_playback_build_pcms(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hda_pcm *info = spec->pcm_rec;
|
struct hda_pcm *info;
|
||||||
unsigned int chans;
|
unsigned int chans;
|
||||||
struct hda_pcm_stream *pstr;
|
struct hda_pcm_stream *pstr;
|
||||||
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
|
|
||||||
codec->num_pcms = 1;
|
per_cvt = get_cvt(spec, 0);
|
||||||
codec->pcm_info = info;
|
chans = get_wcaps(codec, per_cvt->cvt_nid);
|
||||||
|
|
||||||
chans = get_wcaps(codec, spec->cvts[0].cvt_nid);
|
|
||||||
chans = get_wcaps_channels(chans);
|
chans = get_wcaps_channels(chans);
|
||||||
|
|
||||||
info->name = get_hdmi_pcm_name(0);
|
info = snd_array_new(&spec->pcm_rec);
|
||||||
|
if (!info)
|
||||||
|
return -ENOMEM;
|
||||||
|
info->name = get_pin(spec, 0)->pcm_name;
|
||||||
|
sprintf(info->name, "HDMI 0");
|
||||||
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
||||||
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
|
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
|
||||||
*pstr = spec->pcm_playback;
|
*pstr = spec->pcm_playback;
|
||||||
pstr->nid = spec->cvts[0].cvt_nid;
|
pstr->nid = per_cvt->cvt_nid;
|
||||||
if (pstr->channels_max <= 2 && chans && chans <= 16)
|
if (pstr->channels_max <= 2 && chans && chans <= 16)
|
||||||
pstr->channels_max = chans;
|
pstr->channels_max = chans;
|
||||||
|
|
||||||
|
codec->num_pcms = 1;
|
||||||
|
codec->pcm_info = info;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1919,11 +1973,12 @@ static void simple_hdmi_unsol_event(struct hda_codec *codec,
|
|||||||
static int simple_playback_build_controls(struct hda_codec *codec)
|
static int simple_playback_build_controls(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = snd_hda_create_spdif_out_ctls(codec,
|
per_cvt = get_cvt(spec, 0);
|
||||||
spec->cvts[0].cvt_nid,
|
err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
|
||||||
spec->cvts[0].cvt_nid);
|
per_cvt->cvt_nid);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return simple_hdmi_build_jack(codec, 0);
|
return simple_hdmi_build_jack(codec, 0);
|
||||||
@ -1932,7 +1987,8 @@ static int simple_playback_build_controls(struct hda_codec *codec)
|
|||||||
static int simple_playback_init(struct hda_codec *codec)
|
static int simple_playback_init(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
hda_nid_t pin = spec->pins[0].pin_nid;
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0);
|
||||||
|
hda_nid_t pin = per_pin->pin_nid;
|
||||||
|
|
||||||
snd_hda_codec_write(codec, pin, 0,
|
snd_hda_codec_write(codec, pin, 0,
|
||||||
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
||||||
@ -1948,6 +2004,7 @@ static void simple_playback_free(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
|
|
||||||
|
hdmi_array_free(spec);
|
||||||
kfree(spec);
|
kfree(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2111,20 +2168,29 @@ static int patch_simple_hdmi(struct hda_codec *codec,
|
|||||||
hda_nid_t cvt_nid, hda_nid_t pin_nid)
|
hda_nid_t cvt_nid, hda_nid_t pin_nid)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec;
|
struct hdmi_spec *spec;
|
||||||
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
|
struct hdmi_spec_per_pin *per_pin;
|
||||||
|
|
||||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||||
if (!spec)
|
if (!spec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
codec->spec = spec;
|
codec->spec = spec;
|
||||||
|
hdmi_array_init(spec, 1);
|
||||||
|
|
||||||
spec->multiout.num_dacs = 0; /* no analog */
|
spec->multiout.num_dacs = 0; /* no analog */
|
||||||
spec->multiout.max_channels = 2;
|
spec->multiout.max_channels = 2;
|
||||||
spec->multiout.dig_out_nid = cvt_nid;
|
spec->multiout.dig_out_nid = cvt_nid;
|
||||||
spec->num_cvts = 1;
|
spec->num_cvts = 1;
|
||||||
spec->num_pins = 1;
|
spec->num_pins = 1;
|
||||||
spec->cvts[0].cvt_nid = cvt_nid;
|
per_pin = snd_array_new(&spec->pins);
|
||||||
spec->pins[0].pin_nid = pin_nid;
|
per_cvt = snd_array_new(&spec->cvts);
|
||||||
|
if (!per_pin || !per_cvt) {
|
||||||
|
simple_playback_free(codec);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
per_cvt->cvt_nid = cvt_nid;
|
||||||
|
per_pin->pin_nid = pin_nid;
|
||||||
spec->pcm_playback = simple_pcm_playback;
|
spec->pcm_playback = simple_pcm_playback;
|
||||||
|
|
||||||
codec->patch_ops = simple_hdmi_patch_ops;
|
codec->patch_ops = simple_hdmi_patch_ops;
|
||||||
@ -2201,9 +2267,11 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|||||||
int i;
|
int i;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hda_spdif_out *spdif;
|
struct hda_spdif_out *spdif;
|
||||||
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
|
per_cvt = get_cvt(spec, 0);
|
||||||
|
spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
|
||||||
|
|
||||||
chs = substream->runtime->channels;
|
chs = substream->runtime->channels;
|
||||||
|
|
||||||
@ -2325,13 +2393,17 @@ static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
int err = simple_playback_build_pcms(codec);
|
int err = simple_playback_build_pcms(codec);
|
||||||
spec->pcm_rec[0].own_chmap = true;
|
if (!err) {
|
||||||
|
struct hda_pcm *info = get_pcm_rec(spec, 0);
|
||||||
|
info->own_chmap = true;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
|
struct hda_pcm *info;
|
||||||
struct snd_pcm_chmap *chmap;
|
struct snd_pcm_chmap *chmap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -2340,7 +2412,8 @@ static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* add channel maps */
|
/* add channel maps */
|
||||||
err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm,
|
info = get_pcm_rec(spec, 0);
|
||||||
|
err = snd_pcm_add_chmap_ctls(info->pcm,
|
||||||
SNDRV_PCM_STREAM_PLAYBACK,
|
SNDRV_PCM_STREAM_PLAYBACK,
|
||||||
snd_pcm_alt_chmaps, 8, 0, &chmap);
|
snd_pcm_alt_chmaps, 8, 0, &chmap);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -2395,6 +2468,7 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|||||||
struct snd_pcm_substream *substream)
|
struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
|
struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0);
|
||||||
int chans = substream->runtime->channels;
|
int chans = substream->runtime->channels;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
@ -2402,11 +2476,11 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|||||||
substream);
|
substream);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0,
|
snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
|
||||||
AC_VERB_SET_CVT_CHAN_COUNT, chans - 1);
|
AC_VERB_SET_CVT_CHAN_COUNT, chans - 1);
|
||||||
/* FIXME: XXX */
|
/* FIXME: XXX */
|
||||||
for (i = 0; i < chans; i++) {
|
for (i = 0; i < chans; i++) {
|
||||||
snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0,
|
snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
|
||||||
AC_VERB_SET_HDMI_CHAN_SLOT,
|
AC_VERB_SET_HDMI_CHAN_SLOT,
|
||||||
(i << 4) | i);
|
(i << 4) | i);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -211,7 +211,6 @@ struct sigmatel_spec {
|
|||||||
|
|
||||||
/* beep widgets */
|
/* beep widgets */
|
||||||
hda_nid_t anabeep_nid;
|
hda_nid_t anabeep_nid;
|
||||||
hda_nid_t digbeep_nid;
|
|
||||||
|
|
||||||
/* SPDIF-out mux */
|
/* SPDIF-out mux */
|
||||||
const char * const *spdif_labels;
|
const char * const *spdif_labels;
|
||||||
@ -3529,8 +3528,12 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct sigmatel_spec *spec = codec->spec;
|
struct sigmatel_spec *spec = codec->spec;
|
||||||
int err;
|
int err;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
|
if (spec->headset_jack)
|
||||||
|
flags |= HDA_PINCFG_HEADSET_MIC;
|
||||||
|
|
||||||
|
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -3560,14 +3563,11 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
|||||||
|
|
||||||
/* setup digital beep controls and input device */
|
/* setup digital beep controls and input device */
|
||||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||||
if (spec->digbeep_nid > 0) {
|
if (spec->gen.beep_nid) {
|
||||||
hda_nid_t nid = spec->digbeep_nid;
|
hda_nid_t nid = spec->gen.beep_nid;
|
||||||
unsigned int caps;
|
unsigned int caps;
|
||||||
|
|
||||||
err = stac_auto_create_beep_ctls(codec, nid);
|
err = stac_auto_create_beep_ctls(codec, nid);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = snd_hda_attach_beep_device(codec, nid);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (codec->beep) {
|
if (codec->beep) {
|
||||||
@ -3657,17 +3657,7 @@ static void stac_shutup(struct hda_codec *codec)
|
|||||||
~spec->eapd_mask);
|
~spec->eapd_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stac_free(struct hda_codec *codec)
|
#define stac_free snd_hda_gen_free
|
||||||
{
|
|
||||||
struct sigmatel_spec *spec = codec->spec;
|
|
||||||
|
|
||||||
if (!spec)
|
|
||||||
return;
|
|
||||||
|
|
||||||
snd_hda_gen_spec_free(&spec->gen);
|
|
||||||
kfree(spec);
|
|
||||||
snd_hda_detach_beep_device(codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
|
static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
|
||||||
@ -3797,6 +3787,7 @@ static int patch_stac9200(struct hda_codec *codec)
|
|||||||
spec->gen.own_eapd_ctl = 1;
|
spec->gen.own_eapd_ctl = 1;
|
||||||
|
|
||||||
codec->patch_ops = stac_patch_ops;
|
codec->patch_ops = stac_patch_ops;
|
||||||
|
codec->power_filter = snd_hda_codec_eapd_power_filter;
|
||||||
|
|
||||||
snd_hda_add_verbs(codec, stac9200_eapd_init);
|
snd_hda_add_verbs(codec, stac9200_eapd_init);
|
||||||
|
|
||||||
@ -3884,7 +3875,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
|
|||||||
spec->aloopback_mask = 0x01;
|
spec->aloopback_mask = 0x01;
|
||||||
spec->aloopback_shift = 8;
|
spec->aloopback_shift = 8;
|
||||||
|
|
||||||
spec->digbeep_nid = 0x1c;
|
spec->gen.beep_nid = 0x1c; /* digital beep */
|
||||||
|
|
||||||
/* GPIO0 High = Enable EAPD */
|
/* GPIO0 High = Enable EAPD */
|
||||||
spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
|
spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
|
||||||
@ -3968,7 +3959,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
|
|||||||
spec->gen.power_down_unused = 1;
|
spec->gen.power_down_unused = 1;
|
||||||
spec->gen.mixer_nid = 0x1b;
|
spec->gen.mixer_nid = 0x1b;
|
||||||
|
|
||||||
spec->digbeep_nid = 0x21;
|
spec->gen.beep_nid = 0x21; /* digital beep */
|
||||||
spec->pwr_nids = stac92hd83xxx_pwr_nids;
|
spec->pwr_nids = stac92hd83xxx_pwr_nids;
|
||||||
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
|
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
|
||||||
spec->default_polarity = -1; /* no default cfg */
|
spec->default_polarity = -1; /* no default cfg */
|
||||||
@ -4016,7 +4007,7 @@ static int patch_stac92hd95(struct hda_codec *codec)
|
|||||||
spec->gen.own_eapd_ctl = 1;
|
spec->gen.own_eapd_ctl = 1;
|
||||||
spec->gen.power_down_unused = 1;
|
spec->gen.power_down_unused = 1;
|
||||||
|
|
||||||
spec->digbeep_nid = 0x19;
|
spec->gen.beep_nid = 0x19; /* digital beep */
|
||||||
spec->pwr_nids = stac92hd95_pwr_nids;
|
spec->pwr_nids = stac92hd95_pwr_nids;
|
||||||
spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids);
|
spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids);
|
||||||
spec->default_polarity = -1; /* no default cfg */
|
spec->default_polarity = -1; /* no default cfg */
|
||||||
@ -4091,7 +4082,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
|
|||||||
spec->aloopback_shift = 0;
|
spec->aloopback_shift = 0;
|
||||||
|
|
||||||
spec->powerdown_adcs = 1;
|
spec->powerdown_adcs = 1;
|
||||||
spec->digbeep_nid = 0x26;
|
spec->gen.beep_nid = 0x26; /* digital beep */
|
||||||
spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
|
spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
|
||||||
spec->pwr_nids = stac92hd71bxx_pwr_nids;
|
spec->pwr_nids = stac92hd71bxx_pwr_nids;
|
||||||
|
|
||||||
@ -4173,7 +4164,7 @@ static int patch_stac927x(struct hda_codec *codec)
|
|||||||
spec->have_spdif_mux = 1;
|
spec->have_spdif_mux = 1;
|
||||||
spec->spdif_labels = stac927x_spdif_labels;
|
spec->spdif_labels = stac927x_spdif_labels;
|
||||||
|
|
||||||
spec->digbeep_nid = 0x23;
|
spec->gen.beep_nid = 0x23; /* digital beep */
|
||||||
|
|
||||||
/* GPIO0 High = Enable EAPD */
|
/* GPIO0 High = Enable EAPD */
|
||||||
spec->eapd_mask = spec->gpio_mask = 0x01;
|
spec->eapd_mask = spec->gpio_mask = 0x01;
|
||||||
@ -4232,7 +4223,7 @@ static int patch_stac9205(struct hda_codec *codec)
|
|||||||
spec->gen.own_eapd_ctl = 1;
|
spec->gen.own_eapd_ctl = 1;
|
||||||
spec->have_spdif_mux = 1;
|
spec->have_spdif_mux = 1;
|
||||||
|
|
||||||
spec->digbeep_nid = 0x23;
|
spec->gen.beep_nid = 0x23; /* digital beep */
|
||||||
|
|
||||||
snd_hda_add_verbs(codec, stac9205_core_init);
|
snd_hda_add_verbs(codec, stac9205_core_init);
|
||||||
spec->aloopback_ctl = &stac9205_loopback;
|
spec->aloopback_ctl = &stac9205_loopback;
|
||||||
|
@ -626,11 +626,31 @@ static void via_set_jack_unsol_events(struct hda_codec *codec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct badness_table via_main_out_badness = {
|
||||||
|
.no_primary_dac = 0x10000,
|
||||||
|
.no_dac = 0x4000,
|
||||||
|
.shared_primary = 0x10000,
|
||||||
|
.shared_surr = 0x20,
|
||||||
|
.shared_clfe = 0x20,
|
||||||
|
.shared_surr_main = 0x20,
|
||||||
|
};
|
||||||
|
static const struct badness_table via_extra_out_badness = {
|
||||||
|
.no_primary_dac = 0x4000,
|
||||||
|
.no_dac = 0x4000,
|
||||||
|
.shared_primary = 0x12,
|
||||||
|
.shared_surr = 0x20,
|
||||||
|
.shared_clfe = 0x20,
|
||||||
|
.shared_surr_main = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
static int via_parse_auto_config(struct hda_codec *codec)
|
static int via_parse_auto_config(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
spec->gen.main_out_badness = &via_main_out_badness;
|
||||||
|
spec->gen.extra_out_badness = &via_extra_out_badness;
|
||||||
|
|
||||||
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
|
err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -969,6 +969,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card,
|
|||||||
struct hdspm *hdspm);
|
struct hdspm *hdspm);
|
||||||
|
|
||||||
static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
|
static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
|
||||||
|
static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
|
||||||
static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
|
static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
|
||||||
static int hdspm_autosync_ref(struct hdspm *hdspm);
|
static int hdspm_autosync_ref(struct hdspm *hdspm);
|
||||||
static int snd_hdspm_set_defaults(struct hdspm *hdspm);
|
static int snd_hdspm_set_defaults(struct hdspm *hdspm);
|
||||||
@ -1075,6 +1076,20 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* round arbitary sample rates to commonly known rates */
|
||||||
|
static int hdspm_round_frequency(int rate)
|
||||||
|
{
|
||||||
|
if (rate < 38050)
|
||||||
|
return 32000;
|
||||||
|
if (rate < 46008)
|
||||||
|
return 44100;
|
||||||
|
else
|
||||||
|
return 48000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdspm_tco_sync_check(struct hdspm *hdspm);
|
||||||
|
static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
|
||||||
|
|
||||||
/* check for external sample rate */
|
/* check for external sample rate */
|
||||||
static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
||||||
{
|
{
|
||||||
@ -1216,6 +1231,30 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} /* endif HDSPM_madiLock */
|
||||||
|
|
||||||
|
/* check sample rate from TCO or SYNC_IN */
|
||||||
|
{
|
||||||
|
bool is_valid_input = 0;
|
||||||
|
bool has_sync = 0;
|
||||||
|
|
||||||
|
syncref = hdspm_autosync_ref(hdspm);
|
||||||
|
if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
|
||||||
|
is_valid_input = 1;
|
||||||
|
has_sync = (HDSPM_SYNC_CHECK_SYNC ==
|
||||||
|
hdspm_tco_sync_check(hdspm));
|
||||||
|
} else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
|
||||||
|
is_valid_input = 1;
|
||||||
|
has_sync = (HDSPM_SYNC_CHECK_SYNC ==
|
||||||
|
hdspm_sync_in_sync_check(hdspm));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_valid_input && has_sync) {
|
||||||
|
rate = hdspm_round_frequency(
|
||||||
|
hdspm_get_pll_freq(hdspm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* QS and DS rates normally can not be detected
|
/* QS and DS rates normally can not be detected
|
||||||
* automatically by the card. Only exception is MADI
|
* automatically by the card. Only exception is MADI
|
||||||
* in 96k frame mode.
|
* in 96k frame mode.
|
||||||
@ -1231,7 +1270,6 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
|||||||
HDSPM_DoubleSpeed)
|
HDSPM_DoubleSpeed)
|
||||||
rate *= 2;
|
rate *= 2;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1979,16 +2017,25 @@ static void hdspm_midi_tasklet(unsigned long arg)
|
|||||||
/* get the system sample rate which is set */
|
/* get the system sample rate which is set */
|
||||||
|
|
||||||
|
|
||||||
|
static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
|
||||||
|
{
|
||||||
|
unsigned int period, rate;
|
||||||
|
|
||||||
|
period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
|
||||||
|
rate = hdspm_calc_dds_value(hdspm, period);
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the real sample rate from the
|
* Calculate the real sample rate from the
|
||||||
* current DDS value.
|
* current DDS value.
|
||||||
**/
|
**/
|
||||||
static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
|
static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
|
||||||
{
|
{
|
||||||
unsigned int period, rate;
|
unsigned int rate;
|
||||||
|
|
||||||
period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
|
rate = hdspm_get_pll_freq(hdspm);
|
||||||
rate = hdspm_calc_dds_value(hdspm, period);
|
|
||||||
|
|
||||||
if (rate > 207000) {
|
if (rate > 207000) {
|
||||||
/* Unreasonable high sample rate as seen on PCI MADI cards. */
|
/* Unreasonable high sample rate as seen on PCI MADI cards. */
|
||||||
@ -2128,6 +2175,16 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
|
|||||||
return (status >> (idx*4)) & 0xF;
|
return (status >> (idx*4)) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ENUMERATED_CTL_INFO(info, texts) \
|
||||||
|
{ \
|
||||||
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \
|
||||||
|
uinfo->count = 1; \
|
||||||
|
uinfo->value.enumerated.items = ARRAY_SIZE(texts); \
|
||||||
|
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \
|
||||||
|
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; \
|
||||||
|
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
|
#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
|
||||||
@ -2143,14 +2200,7 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
|
|||||||
static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
|
static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts_freq);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 10;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts_freq[uinfo->value.enumerated.item]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2316,15 +2366,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "Master", "AutoSync" };
|
static char *texts[] = { "Master", "AutoSync" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 2;
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2888,6 +2930,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
|
||||||
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||||
|
.name = xname, \
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_READ |\
|
||||||
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
|
||||||
|
.info = snd_hdspm_info_tco_video_input_format, \
|
||||||
|
.get = snd_hdspm_get_tco_video_input_format, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
static char *texts[] = {"No video", "NTSC", "PAL"};
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
u32 status;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
|
||||||
|
status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
|
||||||
|
switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
|
||||||
|
HDSPM_TCO1_Video_Input_Format_PAL)) {
|
||||||
|
case HDSPM_TCO1_Video_Input_Format_NTSC:
|
||||||
|
/* ntsc */
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
case HDSPM_TCO1_Video_Input_Format_PAL:
|
||||||
|
/* pal */
|
||||||
|
ret = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* no video */
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ucontrol->value.enumerated.item[0] = ret;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
|
||||||
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||||
|
.name = xname, \
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_READ |\
|
||||||
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
|
||||||
|
.info = snd_hdspm_info_tco_ltc_frames, \
|
||||||
|
.get = snd_hdspm_get_tco_ltc_frames, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
|
||||||
|
"30 fps"};
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
|
||||||
|
{
|
||||||
|
u32 status;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
|
||||||
|
if (status & HDSPM_TCO1_LTC_Input_valid) {
|
||||||
|
switch (status & (HDSPM_TCO1_LTC_Format_LSB |
|
||||||
|
HDSPM_TCO1_LTC_Format_MSB)) {
|
||||||
|
case 0:
|
||||||
|
/* 24 fps */
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
case HDSPM_TCO1_LTC_Format_LSB:
|
||||||
|
/* 25 fps */
|
||||||
|
ret = 2;
|
||||||
|
break;
|
||||||
|
case HDSPM_TCO1_LTC_Format_MSB:
|
||||||
|
/* 25 fps */
|
||||||
|
ret = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* 30 fps */
|
||||||
|
ret = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
|
||||||
|
|
||||||
|
ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define HDSPM_TOGGLE_SETTING(xname, xindex) \
|
#define HDSPM_TOGGLE_SETTING(xname, xindex) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||||
.name = xname, \
|
.name = xname, \
|
||||||
@ -2974,17 +3122,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "optical", "coaxial" };
|
static char *texts[] = { "optical", "coaxial" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 2;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3046,17 +3184,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "Single", "Double" };
|
static char *texts[] = { "Single", "Double" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 2;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3129,17 +3257,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "Single", "Double", "Quad" };
|
static char *texts[] = { "Single", "Double", "Quad" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 3;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3215,17 +3333,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "Single", "Double", "Quad" };
|
static char *texts[] = { "Single", "Double", "Quad" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 3;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3445,19 +3553,30 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
|
|||||||
.get = snd_hdspm_get_sync_check \
|
.get = snd_hdspm_get_sync_check \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
|
||||||
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||||
|
.name = xname, \
|
||||||
|
.private_value = xindex, \
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
|
||||||
|
.info = snd_hdspm_tco_info_lock_check, \
|
||||||
|
.get = snd_hdspm_get_sync_check \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
|
static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
|
static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
return 0;
|
||||||
uinfo->value.enumerated.items = 4;
|
}
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
|
||||||
uinfo->value.enumerated.items - 1;
|
struct snd_ctl_elem_info *uinfo)
|
||||||
strcpy(uinfo->value.enumerated.name,
|
{
|
||||||
texts[uinfo->value.enumerated.item]);
|
static char *texts[] = { "No Lock", "Lock" };
|
||||||
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3590,6 +3709,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
|
||||||
|
{
|
||||||
|
u32 status;
|
||||||
|
status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
|
||||||
|
|
||||||
|
return (status & mask) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hdspm_tco_sync_check(struct hdspm *hdspm)
|
static int hdspm_tco_sync_check(struct hdspm *hdspm)
|
||||||
{
|
{
|
||||||
@ -3697,6 +3824,22 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hdspm->tco) {
|
||||||
|
switch (kcontrol->private_value) {
|
||||||
|
case 11:
|
||||||
|
/* Check TCO for lock state of its current input */
|
||||||
|
val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
/* Check TCO for valid time code on LTC input. */
|
||||||
|
val = hdspm_tco_input_check(hdspm,
|
||||||
|
HDSPM_TCO1_LTC_Input_valid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (-1 == val)
|
if (-1 == val)
|
||||||
val = 3;
|
val = 3;
|
||||||
|
|
||||||
@ -3813,17 +3956,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "44.1 kHz", "48 kHz" };
|
static char *texts[] = { "44.1 kHz", "48 kHz" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 2;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3869,17 +4002,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
|
static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 5;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3924,17 +4047,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
|
static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 3;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3981,17 +4094,7 @@ static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
|
|||||||
{
|
{
|
||||||
static char *texts[] = { "24 fps", "25 fps", "29.97fps",
|
static char *texts[] = { "24 fps", "25 fps", "29.97fps",
|
||||||
"29.97 dfps", "30 fps", "30 dfps" };
|
"29.97 dfps", "30 fps", "30 dfps" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 6;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4037,17 +4140,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
static char *texts[] = { "LTC", "Video", "WCK" };
|
static char *texts[] = { "LTC", "Video", "WCK" };
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||||
uinfo->count = 1;
|
|
||||||
uinfo->value.enumerated.items = 3;
|
|
||||||
|
|
||||||
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
||||||
uinfo->value.enumerated.item =
|
|
||||||
uinfo->value.enumerated.items - 1;
|
|
||||||
|
|
||||||
strcpy(uinfo->value.enumerated.name,
|
|
||||||
texts[uinfo->value.enumerated.item]);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4145,6 +4238,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
|
|||||||
HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
|
HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
|
||||||
HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
|
HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
|
||||||
HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
|
HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
|
||||||
|
HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
|
||||||
HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
|
HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
|
||||||
HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
|
HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
|
||||||
HDSPM_INPUT_SELECT("Input Select", 0),
|
HDSPM_INPUT_SELECT("Input Select", 0),
|
||||||
@ -4272,7 +4366,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
|
|||||||
HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
|
HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
|
||||||
HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
|
HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
|
||||||
HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
|
HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
|
||||||
HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
|
HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
|
||||||
|
HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
|
||||||
|
HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
|
||||||
|
HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
|
||||||
|
HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ config SND_SOC_AC97_BUS
|
|||||||
config SND_SOC_DMAENGINE_PCM
|
config SND_SOC_DMAENGINE_PCM
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config SND_SOC_GENERIC_DMAENGINE_PCM
|
||||||
|
bool
|
||||||
|
select SND_SOC_DMAENGINE_PCM
|
||||||
|
|
||||||
# All the supported SoCs
|
# All the supported SoCs
|
||||||
source "sound/soc/atmel/Kconfig"
|
source "sound/soc/atmel/Kconfig"
|
||||||
source "sound/soc/au1x/Kconfig"
|
source "sound/soc/au1x/Kconfig"
|
||||||
|
@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
|
|||||||
snd-soc-core-objs += soc-dmaengine-pcm.o
|
snd-soc-core-objs += soc-dmaengine-pcm.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
|
||||||
|
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
|
||||||
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
|
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
|
||||||
obj-$(CONFIG_SND_SOC) += codecs/
|
obj-$(CONFIG_SND_SOC) += codecs/
|
||||||
obj-$(CONFIG_SND_SOC) += generic/
|
obj-$(CONFIG_SND_SOC) += generic/
|
||||||
|
@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
|
|||||||
static void atmel_pcm_dma_irq(u32 ssc_sr,
|
static void atmel_pcm_dma_irq(u32 ssc_sr,
|
||||||
struct snd_pcm_substream *substream)
|
struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct atmel_pcm_dma_params *prtd;
|
struct atmel_pcm_dma_params *prtd;
|
||||||
|
|
||||||
prtd = snd_dmaengine_pcm_get_data(substream);
|
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||||
|
|
||||||
if (ssc_sr & prtd->mask->ssc_error) {
|
if (ssc_sr & prtd->mask->ssc_error) {
|
||||||
if (snd_pcm_running(substream))
|
if (snd_pcm_running(substream))
|
||||||
@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
|
static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
|
||||||
{
|
{
|
||||||
struct atmel_pcm_dma_params *prtd;
|
|
||||||
struct ssc_device *ssc;
|
struct ssc_device *ssc;
|
||||||
struct dma_chan *dma_chan;
|
struct dma_chan *dma_chan;
|
||||||
struct dma_slave_config slave_config;
|
struct dma_slave_config slave_config;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
prtd = snd_dmaengine_pcm_get_data(substream);
|
|
||||||
ssc = prtd->ssc;
|
ssc = prtd->ssc;
|
||||||
|
|
||||||
ret = snd_hwparams_to_dma_slave_config(substream, params,
|
ret = snd_hwparams_to_dma_slave_config(substream, params,
|
||||||
@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
|
|||||||
slave_config.src_maxburst = 1;
|
slave_config.src_maxburst = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
slave_config.device_fc = false;
|
|
||||||
|
|
||||||
dma_chan = snd_dmaengine_pcm_get_chan(substream);
|
dma_chan = snd_dmaengine_pcm_get_chan(substream);
|
||||||
if (dmaengine_slave_config(dma_chan, &slave_config)) {
|
if (dmaengine_slave_config(dma_chan, &slave_config)) {
|
||||||
pr_err("atmel-pcm: failed to configure dma channel\n");
|
pr_err("atmel-pcm: failed to configure dma channel\n");
|
||||||
@ -158,15 +155,13 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
if (ssc->pdev)
|
if (ssc->pdev)
|
||||||
sdata = ssc->pdev->dev.platform_data;
|
sdata = ssc->pdev->dev.platform_data;
|
||||||
|
|
||||||
ret = snd_dmaengine_pcm_open(substream, filter, sdata);
|
ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("atmel-pcm: dmaengine pcm open failed\n");
|
pr_err("atmel-pcm: dmaengine pcm open failed\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_dmaengine_pcm_set_data(substream, prtd);
|
ret = atmel_pcm_configure_dma(substream, params, prtd);
|
||||||
|
|
||||||
ret = atmel_pcm_configure_dma(substream, params);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("atmel-pcm: failed to configure dmai\n");
|
pr_err("atmel-pcm: failed to configure dmai\n");
|
||||||
goto err;
|
goto err;
|
||||||
@ -176,15 +171,16 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
snd_dmaengine_pcm_close(substream);
|
snd_dmaengine_pcm_close_release_chan(substream);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
|
static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct atmel_pcm_dma_params *prtd;
|
struct atmel_pcm_dma_params *prtd;
|
||||||
|
|
||||||
prtd = snd_dmaengine_pcm_get_data(substream);
|
prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||||
|
|
||||||
ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
|
ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
|
||||||
ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
|
ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
|
||||||
@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atmel_pcm_close(struct snd_pcm_substream *substream)
|
|
||||||
{
|
|
||||||
snd_dmaengine_pcm_close(substream);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct snd_pcm_ops atmel_pcm_ops = {
|
static struct snd_pcm_ops atmel_pcm_ops = {
|
||||||
.open = atmel_pcm_open,
|
.open = atmel_pcm_open,
|
||||||
.close = atmel_pcm_close,
|
.close = snd_dmaengine_pcm_close_release_chan,
|
||||||
.ioctl = snd_pcm_lib_ioctl,
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
.hw_params = atmel_pcm_hw_params,
|
.hw_params = atmel_pcm_hw_params,
|
||||||
.prepare = atmel_pcm_dma_prepare,
|
.prepare = atmel_pcm_dma_prepare,
|
||||||
|
@ -533,6 +533,49 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
|
||||||
|
/*
|
||||||
|
* DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks.
|
||||||
|
*
|
||||||
|
* The SSC transmit clock is obtained from the BCLK signal on
|
||||||
|
* on the TK line, and the SSC receive clock is
|
||||||
|
* generated from the transmit clock.
|
||||||
|
*
|
||||||
|
* Data is transferred on first BCLK after LRC pulse rising
|
||||||
|
* edge.If stereo, the right channel data is contiguous with
|
||||||
|
* the left channel data.
|
||||||
|
*/
|
||||||
|
rcmr = SSC_BF(RCMR_PERIOD, 0)
|
||||||
|
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
||||||
|
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
|
||||||
|
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
||||||
|
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||||
|
| SSC_BF(RCMR_CKS, SSC_CKS_PIN);
|
||||||
|
|
||||||
|
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||||
|
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
|
||||||
|
| SSC_BF(RFMR_FSLEN, 0)
|
||||||
|
| SSC_BF(RFMR_DATNB, (channels - 1))
|
||||||
|
| SSC_BIT(RFMR_MSBF)
|
||||||
|
| SSC_BF(RFMR_LOOP, 0)
|
||||||
|
| SSC_BF(RFMR_DATLEN, (bits - 1));
|
||||||
|
|
||||||
|
tcmr = SSC_BF(TCMR_PERIOD, 0)
|
||||||
|
| SSC_BF(TCMR_STTDLY, START_DELAY)
|
||||||
|
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
|
||||||
|
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
|
||||||
|
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
|
||||||
|
| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
|
||||||
|
|
||||||
|
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||||
|
| SSC_BF(TFMR_FSDEN, 0)
|
||||||
|
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
|
||||||
|
| SSC_BF(TFMR_FSLEN, 0)
|
||||||
|
| SSC_BF(TFMR_DATNB, (channels - 1))
|
||||||
|
| SSC_BIT(TFMR_MSBF)
|
||||||
|
| SSC_BF(TFMR_DATDEF, 0)
|
||||||
|
| SSC_BF(TFMR_DATLEN, (bits - 1));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
|
printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
|
||||||
ssc_p->daifmt);
|
ssc_p->daifmt);
|
||||||
@ -707,13 +750,18 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
|
|||||||
.ops = &atmel_ssc_dai_ops,
|
.ops = &atmel_ssc_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver atmel_ssc_component = {
|
||||||
|
.name = "atmel-ssc",
|
||||||
|
};
|
||||||
|
|
||||||
static int asoc_ssc_init(struct device *dev)
|
static int asoc_ssc_init(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct ssc_device *ssc = platform_get_drvdata(pdev);
|
struct ssc_device *ssc = platform_get_drvdata(pdev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
|
ret = snd_soc_register_component(dev, &atmel_ssc_component,
|
||||||
|
&atmel_ssc_dai, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Could not register DAI: %d\n", ret);
|
dev_err(dev, "Could not register DAI: %d\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
@ -732,7 +780,7 @@ static int asoc_ssc_init(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister_dai:
|
err_unregister_dai:
|
||||||
snd_soc_unregister_dai(dev);
|
snd_soc_unregister_component(dev);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -747,7 +795,7 @@ static void asoc_ssc_exit(struct device *dev)
|
|||||||
else
|
else
|
||||||
atmel_pcm_pdc_platform_unregister(dev);
|
atmel_pcm_pdc_platform_unregister(dev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(dev);
|
snd_soc_unregister_component(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -223,6 +223,10 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
|
|||||||
.ops = &alchemy_ac97c_ops,
|
.ops = &alchemy_ac97c_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver au1xac97c_component = {
|
||||||
|
.name = "au1xac97c",
|
||||||
|
};
|
||||||
|
|
||||||
static int au1xac97c_drvprobe(struct platform_device *pdev)
|
static int au1xac97c_drvprobe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -268,7 +272,8 @@ static int au1xac97c_drvprobe(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_set_drvdata(pdev, ctx);
|
platform_set_drvdata(pdev, ctx);
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
|
ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component,
|
||||||
|
&au1xac97c_dai_driver, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -280,7 +285,7 @@ static int au1xac97c_drvremove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
|
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
|
|
||||||
WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */
|
WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */
|
||||||
|
|
||||||
|
@ -225,6 +225,10 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
|
|||||||
.ops = &au1xi2s_dai_ops,
|
.ops = &au1xi2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver au1xi2s_component = {
|
||||||
|
.name = "au1xi2s",
|
||||||
|
};
|
||||||
|
|
||||||
static int au1xi2s_drvprobe(struct platform_device *pdev)
|
static int au1xi2s_drvprobe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *iores, *dmares;
|
struct resource *iores, *dmares;
|
||||||
@ -260,14 +264,15 @@ static int au1xi2s_drvprobe(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_set_drvdata(pdev, ctx);
|
platform_set_drvdata(pdev, ctx);
|
||||||
|
|
||||||
return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
|
return snd_soc_register_component(&pdev->dev, &au1xi2s_component,
|
||||||
|
&au1xi2s_dai_driver, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int au1xi2s_drvremove(struct platform_device *pdev)
|
static int au1xi2s_drvremove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
|
struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
|
|
||||||
WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */
|
WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */
|
||||||
|
|
||||||
|
@ -361,6 +361,10 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
|
|||||||
.ops = &au1xpsc_ac97_dai_ops,
|
.ops = &au1xpsc_ac97_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver au1xpsc_ac97_component = {
|
||||||
|
.name = "au1xpsc-ac97",
|
||||||
|
};
|
||||||
|
|
||||||
static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -419,7 +423,8 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_set_drvdata(pdev, wd);
|
platform_set_drvdata(pdev, wd);
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
|
ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,
|
||||||
|
&wd->dai_drv, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -431,7 +436,7 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
|
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
|
|
||||||
/* disable PSC completely */
|
/* disable PSC completely */
|
||||||
au_writel(0, AC97_CFG(wd));
|
au_writel(0, AC97_CFG(wd));
|
||||||
|
@ -288,6 +288,10 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
|
|||||||
.ops = &au1xpsc_i2s_dai_ops,
|
.ops = &au1xpsc_i2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver au1xpsc_i2s_component = {
|
||||||
|
.name = "au1xpsc-i2s",
|
||||||
|
};
|
||||||
|
|
||||||
static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *iores, *dmares;
|
struct resource *iores, *dmares;
|
||||||
@ -350,14 +354,15 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_set_drvdata(pdev, wd);
|
platform_set_drvdata(pdev, wd);
|
||||||
|
|
||||||
return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
|
return snd_soc_register_component(&pdev->dev, &au1xpsc_i2s_component,
|
||||||
|
&wd->dai_drv, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
|
static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
|
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
|
|
||||||
au_writel(0, I2S_CFG(wd));
|
au_writel(0, I2S_CFG(wd));
|
||||||
au_sync();
|
au_sync();
|
||||||
|
@ -282,6 +282,10 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
|
|||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
|
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver bfin_ac97_component = {
|
||||||
|
.name = "bfin-ac97",
|
||||||
|
};
|
||||||
|
|
||||||
static int asoc_bfin_ac97_probe(struct platform_device *pdev)
|
static int asoc_bfin_ac97_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct sport_device *sport_handle;
|
struct sport_device *sport_handle;
|
||||||
@ -331,7 +335,8 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
|
|||||||
goto sport_config_err;
|
goto sport_config_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
|
ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component,
|
||||||
|
&bfin_ac97_dai, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Failed to register DAI: %d\n", ret);
|
pr_err("Failed to register DAI: %d\n", ret);
|
||||||
goto sport_config_err;
|
goto sport_config_err;
|
||||||
@ -356,7 +361,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct sport_device *sport_handle = platform_get_drvdata(pdev);
|
struct sport_device *sport_handle = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
sport_done(sport_handle);
|
sport_done(sport_handle);
|
||||||
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
|
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
|
||||||
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
|
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
|
||||||
|
@ -245,6 +245,10 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
|
|||||||
.ops = &bf5xx_i2s_dai_ops,
|
.ops = &bf5xx_i2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver bf5xx_i2s_component = {
|
||||||
|
.name = "bf5xx-i2s",
|
||||||
|
};
|
||||||
|
|
||||||
static int bf5xx_i2s_probe(struct platform_device *pdev)
|
static int bf5xx_i2s_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct sport_device *sport_handle;
|
struct sport_device *sport_handle;
|
||||||
@ -257,7 +261,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* register with the ASoC layers */
|
/* register with the ASoC layers */
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
|
ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component,
|
||||||
|
&bf5xx_i2s_dai, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Failed to register DAI: %d\n", ret);
|
pr_err("Failed to register DAI: %d\n", ret);
|
||||||
sport_done(sport_handle);
|
sport_done(sport_handle);
|
||||||
@ -273,7 +278,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
pr_debug("%s enter\n", __func__);
|
pr_debug("%s enter\n", __func__);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
sport_done(sport_handle);
|
sport_done(sport_handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -249,6 +249,10 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
|
|||||||
.ops = &bf5xx_tdm_dai_ops,
|
.ops = &bf5xx_tdm_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver bf5xx_tdm_component = {
|
||||||
|
.name = "bf5xx-tdm",
|
||||||
|
};
|
||||||
|
|
||||||
static int bfin_tdm_probe(struct platform_device *pdev)
|
static int bfin_tdm_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct sport_device *sport_handle;
|
struct sport_device *sport_handle;
|
||||||
@ -282,7 +286,8 @@ static int bfin_tdm_probe(struct platform_device *pdev)
|
|||||||
goto sport_config_err;
|
goto sport_config_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
|
ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component,
|
||||||
|
&bf5xx_tdm_dai, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Failed to register DAI: %d\n", ret);
|
pr_err("Failed to register DAI: %d\n", ret);
|
||||||
goto sport_config_err;
|
goto sport_config_err;
|
||||||
@ -299,7 +304,7 @@ static int bfin_tdm_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct sport_device *sport_handle = platform_get_drvdata(pdev);
|
struct sport_device *sport_handle = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
sport_done(sport_handle);
|
sport_done(sport_handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -186,6 +186,10 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
|
|||||||
.ops = &bfin_i2s_dai_ops,
|
.ops = &bfin_i2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver bfin_i2s_component = {
|
||||||
|
.name = "bfin-i2s",
|
||||||
|
};
|
||||||
|
|
||||||
static int bfin_i2s_probe(struct platform_device *pdev)
|
static int bfin_i2s_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct sport_device *sport;
|
struct sport_device *sport;
|
||||||
@ -197,7 +201,8 @@ static int bfin_i2s_probe(struct platform_device *pdev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* register with the ASoC layers */
|
/* register with the ASoC layers */
|
||||||
ret = snd_soc_register_dai(dev, &bfin_i2s_dai);
|
ret = snd_soc_register_component(dev, &bfin_i2s_component,
|
||||||
|
&bfin_i2s_dai, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to register DAI: %d\n", ret);
|
dev_err(dev, "Failed to register DAI: %d\n", ret);
|
||||||
sport_delete(sport);
|
sport_delete(sport);
|
||||||
@ -212,7 +217,7 @@ static int bfin_i2s_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct sport_device *sport = platform_get_drvdata(pdev);
|
struct sport_device *sport = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
sport_delete(sport);
|
sport_delete(sport);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
static int edb93xx_hw_params(struct snd_pcm_substream *substream,
|
static int edb93xx_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params)
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
|
|
||||||
#include <linux/platform_data/dma-ep93xx.h>
|
#include <linux/platform_data/dma-ep93xx.h>
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per channel (1-4) registers.
|
* Per channel (1-4) registers.
|
||||||
@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
|
|||||||
/* currently ALSA only supports a single AC97 device */
|
/* currently ALSA only supports a single AC97 device */
|
||||||
static struct ep93xx_ac97_info *ep93xx_ac97_info;
|
static struct ep93xx_ac97_info *ep93xx_ac97_info;
|
||||||
|
|
||||||
static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
|
static struct ep93xx_dma_data ep93xx_ac97_pcm_out = {
|
||||||
.name = "ac97-pcm-out",
|
.name = "ac97-pcm-out",
|
||||||
.dma_port = EP93XX_DMA_AAC1,
|
.dma_port = EP93XX_DMA_AAC1,
|
||||||
|
.direction = DMA_MEM_TO_DEV,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
|
static struct ep93xx_dma_data ep93xx_ac97_pcm_in = {
|
||||||
.name = "ac97-pcm-in",
|
.name = "ac97-pcm-in",
|
||||||
.dma_port = EP93XX_DMA_AAC1,
|
.dma_port = EP93XX_DMA_AAC1,
|
||||||
|
.direction = DMA_DEV_TO_MEM,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
|
static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
|
||||||
@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
|
|||||||
static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
|
static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct ep93xx_pcm_dma_params *dma_data;
|
struct ep93xx_dma_data *dma_data;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
dma_data = &ep93xx_ac97_pcm_out;
|
dma_data = &ep93xx_ac97_pcm_out;
|
||||||
@ -353,6 +354,10 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
|
|||||||
.ops = &ep93xx_ac97_dai_ops,
|
.ops = &ep93xx_ac97_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver ep93xx_ac97_component = {
|
||||||
|
.name = "ep93xx-ac97",
|
||||||
|
};
|
||||||
|
|
||||||
static int ep93xx_ac97_probe(struct platform_device *pdev)
|
static int ep93xx_ac97_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ep93xx_ac97_info *info;
|
struct ep93xx_ac97_info *info;
|
||||||
@ -390,7 +395,8 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
|
|||||||
ep93xx_ac97_info = info;
|
ep93xx_ac97_info = info;
|
||||||
platform_set_drvdata(pdev, info);
|
platform_set_drvdata(pdev, info);
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
|
ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component,
|
||||||
|
&ep93xx_ac97_dai, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -407,7 +413,7 @@ static int ep93xx_ac97_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
|
struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
|
|
||||||
/* disable the AC97 controller */
|
/* disable the AC97 controller */
|
||||||
ep93xx_ac97_write_reg(info, AC97GCR, 0);
|
ep93xx_ac97_write_reg(info, AC97GCR, 0);
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
#include <mach/ep93xx-regs.h>
|
#include <mach/ep93xx-regs.h>
|
||||||
#include <linux/platform_data/dma-ep93xx.h>
|
#include <linux/platform_data/dma-ep93xx.h>
|
||||||
|
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
#define EP93XX_I2S_TXCLKCFG 0x00
|
#define EP93XX_I2S_TXCLKCFG 0x00
|
||||||
#define EP93XX_I2S_RXCLKCFG 0x04
|
#define EP93XX_I2S_RXCLKCFG 0x04
|
||||||
#define EP93XX_I2S_GLCTRL 0x0C
|
#define EP93XX_I2S_GLCTRL 0x0C
|
||||||
@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
|
|||||||
struct clk *mclk;
|
struct clk *mclk;
|
||||||
struct clk *sclk;
|
struct clk *sclk;
|
||||||
struct clk *lrclk;
|
struct clk *lrclk;
|
||||||
struct ep93xx_pcm_dma_params *dma_params;
|
struct ep93xx_dma_data *dma_data;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
|
struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
|
||||||
[SNDRV_PCM_STREAM_PLAYBACK] = {
|
[SNDRV_PCM_STREAM_PLAYBACK] = {
|
||||||
.name = "i2s-pcm-out",
|
.name = "i2s-pcm-out",
|
||||||
.dma_port = EP93XX_DMA_I2S1,
|
.port = EP93XX_DMA_I2S1,
|
||||||
|
.direction = DMA_MEM_TO_DEV,
|
||||||
},
|
},
|
||||||
[SNDRV_PCM_STREAM_CAPTURE] = {
|
[SNDRV_PCM_STREAM_CAPTURE] = {
|
||||||
.name = "i2s-pcm-in",
|
.name = "i2s-pcm-in",
|
||||||
.dma_port = EP93XX_DMA_I2S1,
|
.port = EP93XX_DMA_I2S1,
|
||||||
|
.direction = DMA_DEV_TO_MEM,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
|
|||||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
|
|
||||||
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
||||||
&info->dma_params[substream->stream]);
|
&info->dma_data[substream->stream]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,6 +366,10 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
|
|||||||
.ops = &ep93xx_i2s_dai_ops,
|
.ops = &ep93xx_i2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver ep93xx_i2s_component = {
|
||||||
|
.name = "ep93xx-i2s",
|
||||||
|
};
|
||||||
|
|
||||||
static int ep93xx_i2s_probe(struct platform_device *pdev)
|
static int ep93xx_i2s_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ep93xx_i2s_info *info;
|
struct ep93xx_i2s_info *info;
|
||||||
@ -403,9 +407,10 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, info);
|
dev_set_drvdata(&pdev->dev, info);
|
||||||
info->dma_params = ep93xx_i2s_dma_params;
|
info->dma_data = ep93xx_i2s_dma_data;
|
||||||
|
|
||||||
err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
|
err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
|
||||||
|
&ep93xx_i2s_dai, 1);
|
||||||
if (err)
|
if (err)
|
||||||
goto fail_put_lrclk;
|
goto fail_put_lrclk;
|
||||||
|
|
||||||
@ -426,7 +431,7 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
|
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
clk_put(info->lrclk);
|
clk_put(info->lrclk);
|
||||||
clk_put(info->sclk);
|
clk_put(info->sclk);
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/ep93xx-regs.h>
|
#include <mach/ep93xx-regs.h>
|
||||||
|
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
|
static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
|
||||||
.info = (SNDRV_PCM_INFO_MMAP |
|
.info = (SNDRV_PCM_INFO_MMAP |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID |
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
@ -68,40 +66,12 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
|
|||||||
static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
|
static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
|
||||||
struct ep93xx_pcm_dma_params *dma_params;
|
|
||||||
struct ep93xx_dma_data *dma_data;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
|
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
|
||||||
|
|
||||||
dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
|
return snd_dmaengine_pcm_open_request_chan(substream,
|
||||||
if (!dma_data)
|
ep93xx_pcm_dma_filter,
|
||||||
return -ENOMEM;
|
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
|
||||||
|
|
||||||
dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
|
|
||||||
dma_data->port = dma_params->dma_port;
|
|
||||||
dma_data->name = dma_params->name;
|
|
||||||
dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
|
|
||||||
|
|
||||||
ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
|
|
||||||
if (ret) {
|
|
||||||
kfree(dma_data);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_dmaengine_pcm_set_data(substream, dma_data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
|
|
||||||
{
|
|
||||||
struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
|
|
||||||
|
|
||||||
snd_dmaengine_pcm_close(substream);
|
|
||||||
kfree(dma_data);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
@ -131,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
static struct snd_pcm_ops ep93xx_pcm_ops = {
|
static struct snd_pcm_ops ep93xx_pcm_ops = {
|
||||||
.open = ep93xx_pcm_open,
|
.open = ep93xx_pcm_open,
|
||||||
.close = ep93xx_pcm_close,
|
.close = snd_dmaengine_pcm_close_release_chan,
|
||||||
.ioctl = snd_pcm_lib_ioctl,
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
.hw_params = ep93xx_pcm_hw_params,
|
.hw_params = ep93xx_pcm_hw_params,
|
||||||
.hw_free = ep93xx_pcm_hw_free,
|
.hw_free = ep93xx_pcm_hw_free,
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
|
||||||
* Copyright (C) 2006 Applied Data Systems
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _EP93XX_SND_SOC_PCM_H
|
|
||||||
#define _EP93XX_SND_SOC_PCM_H
|
|
||||||
|
|
||||||
struct ep93xx_pcm_dma_params {
|
|
||||||
char *name;
|
|
||||||
int dma_port;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _EP93XX_SND_SOC_PCM_H */
|
|
@ -21,8 +21,6 @@
|
|||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
|
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
static struct snd_soc_dai_link simone_dai = {
|
static struct snd_soc_dai_link simone_dai = {
|
||||||
.name = "AC97",
|
.name = "AC97",
|
||||||
.stream_name = "AC97 HiFi",
|
.stream_name = "AC97 HiFi",
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
|
|
||||||
#include "../codecs/tlv320aic23.h"
|
#include "../codecs/tlv320aic23.h"
|
||||||
#include "ep93xx-pcm.h"
|
|
||||||
|
|
||||||
#define CODEC_CLOCK 5644800
|
#define CODEC_CLOCK 5644800
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS
|
|||||||
select SND_SOC_AK4641 if I2C
|
select SND_SOC_AK4641 if I2C
|
||||||
select SND_SOC_AK4642 if I2C
|
select SND_SOC_AK4642 if I2C
|
||||||
select SND_SOC_AK4671 if I2C
|
select SND_SOC_AK4671 if I2C
|
||||||
|
select SND_SOC_AK5386
|
||||||
select SND_SOC_ALC5623 if I2C
|
select SND_SOC_ALC5623 if I2C
|
||||||
select SND_SOC_ALC5632 if I2C
|
select SND_SOC_ALC5632 if I2C
|
||||||
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
|
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
|
||||||
@ -63,6 +64,7 @@ config SND_SOC_ALL_CODECS
|
|||||||
select SND_SOC_STA32X if I2C
|
select SND_SOC_STA32X if I2C
|
||||||
select SND_SOC_STA529 if I2C
|
select SND_SOC_STA529 if I2C
|
||||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||||
|
select SND_SOC_TAS5086 if I2C
|
||||||
select SND_SOC_TLV320AIC23 if I2C
|
select SND_SOC_TLV320AIC23 if I2C
|
||||||
select SND_SOC_TLV320AIC26 if SPI_MASTER
|
select SND_SOC_TLV320AIC26 if SPI_MASTER
|
||||||
select SND_SOC_TLV320AIC32X4 if I2C
|
select SND_SOC_TLV320AIC32X4 if I2C
|
||||||
@ -203,6 +205,9 @@ config SND_SOC_AK4642
|
|||||||
config SND_SOC_AK4671
|
config SND_SOC_AK4671
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_AK5386
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_SOC_ALC5623
|
config SND_SOC_ALC5623
|
||||||
tristate
|
tristate
|
||||||
config SND_SOC_ALC5632
|
config SND_SOC_ALC5632
|
||||||
@ -320,11 +325,14 @@ config SND_SOC_STA529
|
|||||||
config SND_SOC_STAC9766
|
config SND_SOC_STAC9766
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
config SND_SOC_TAS5086
|
||||||
|
tristate
|
||||||
|
|
||||||
config SND_SOC_TLV320AIC23
|
config SND_SOC_TLV320AIC23
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
config SND_SOC_TLV320AIC26
|
config SND_SOC_TLV320AIC26
|
||||||
tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
|
tristate
|
||||||
depends on SPI
|
depends on SPI
|
||||||
|
|
||||||
config SND_SOC_TLV320AIC32X4
|
config SND_SOC_TLV320AIC32X4
|
||||||
|
@ -14,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
|
|||||||
snd-soc-ak4641-objs := ak4641.o
|
snd-soc-ak4641-objs := ak4641.o
|
||||||
snd-soc-ak4642-objs := ak4642.o
|
snd-soc-ak4642-objs := ak4642.o
|
||||||
snd-soc-ak4671-objs := ak4671.o
|
snd-soc-ak4671-objs := ak4671.o
|
||||||
|
snd-soc-ak5386-objs := ak5386.o
|
||||||
snd-soc-arizona-objs := arizona.o
|
snd-soc-arizona-objs := arizona.o
|
||||||
snd-soc-cq93vc-objs := cq93vc.o
|
snd-soc-cq93vc-objs := cq93vc.o
|
||||||
snd-soc-cs42l51-objs := cs42l51.o
|
snd-soc-cs42l51-objs := cs42l51.o
|
||||||
@ -55,6 +56,7 @@ snd-soc-ssm2602-objs := ssm2602.o
|
|||||||
snd-soc-sta32x-objs := sta32x.o
|
snd-soc-sta32x-objs := sta32x.o
|
||||||
snd-soc-sta529-objs := sta529.o
|
snd-soc-sta529-objs := sta529.o
|
||||||
snd-soc-stac9766-objs := stac9766.o
|
snd-soc-stac9766-objs := stac9766.o
|
||||||
|
snd-soc-tas5086-objs := tas5086.o
|
||||||
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
||||||
snd-soc-tlv320aic26-objs := tlv320aic26.o
|
snd-soc-tlv320aic26-objs := tlv320aic26.o
|
||||||
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
|
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
|
||||||
@ -137,6 +139,7 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
|
|||||||
obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
|
obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
|
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
|
||||||
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
|
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
|
||||||
|
obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o
|
||||||
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
|
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
|
||||||
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
|
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
|
||||||
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
|
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
|
||||||
@ -177,6 +180,7 @@ obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
|
|||||||
obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
|
obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
|
||||||
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
||||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||||
|
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
|
||||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||||
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
|
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
|
||||||
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||||
|
@ -133,6 +133,8 @@ struct adau1373 {
|
|||||||
#define ADAU1373_DAI_FORMAT_DSP 0x3
|
#define ADAU1373_DAI_FORMAT_DSP 0x3
|
||||||
|
|
||||||
#define ADAU1373_BCLKDIV_SOURCE BIT(5)
|
#define ADAU1373_BCLKDIV_SOURCE BIT(5)
|
||||||
|
#define ADAU1373_BCLKDIV_SR_MASK (0x07 << 2)
|
||||||
|
#define ADAU1373_BCLKDIV_BCLK_MASK 0x03
|
||||||
#define ADAU1373_BCLKDIV_32 0x03
|
#define ADAU1373_BCLKDIV_32 0x03
|
||||||
#define ADAU1373_BCLKDIV_64 0x02
|
#define ADAU1373_BCLKDIV_64 0x02
|
||||||
#define ADAU1373_BCLKDIV_128 0x01
|
#define ADAU1373_BCLKDIV_128 0x01
|
||||||
@ -937,7 +939,8 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
|
|||||||
adau1373_dai->enable_src = (div != 0);
|
adau1373_dai->enable_src = (div != 0);
|
||||||
|
|
||||||
snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
|
snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
|
||||||
~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64);
|
ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
|
||||||
|
(div << 2) | ADAU1373_BCLKDIV_64);
|
||||||
|
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
|
@ -55,6 +55,7 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||||||
unsigned int format)
|
unsigned int format)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = codec_dai->codec;
|
struct snd_soc_codec *codec = codec_dai->codec;
|
||||||
|
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||||
int val = 0;
|
int val = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|||||||
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
|
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||||
AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
|
AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
|
||||||
val);
|
val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -91,11 +92,12 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = dai->codec;
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
int val = 0;
|
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||||
|
int ret, val = 0;
|
||||||
|
|
||||||
/* set the IEC958 bits: consumer mode, no copyright bit */
|
/* set the IEC958 bits: consumer mode, no copyright bit */
|
||||||
val |= IEC958_AES0_CON_NOT_COPYRIGHT;
|
val |= IEC958_AES0_CON_NOT_COPYRIGHT;
|
||||||
snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
|
regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val);
|
||||||
|
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|
||||||
@ -132,11 +134,33 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
|
ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* enable transmitter */
|
||||||
|
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||||
|
AK4104_TX_TXE, AK4104_TX_TXE);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ak4104_hw_free(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
/* disable transmitter */
|
||||||
|
return regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||||
|
AK4104_TX_TXE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_soc_dai_ops ak4101_dai_ops = {
|
static const struct snd_soc_dai_ops ak4101_dai_ops = {
|
||||||
.hw_params = ak4104_hw_params,
|
.hw_params = ak4104_hw_params,
|
||||||
|
.hw_free = ak4104_hw_free,
|
||||||
.set_fmt = ak4104_set_dai_fmt,
|
.set_fmt = ak4104_set_dai_fmt,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,19 +184,16 @@ static int ak4104_probe(struct snd_soc_codec *codec)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
codec->control_data = ak4104->regmap;
|
codec->control_data = ak4104->regmap;
|
||||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* set power-up and non-reset bits */
|
/* set power-up and non-reset bits */
|
||||||
ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
|
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
|
||||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
|
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* enable transmitter */
|
/* enable transmitter */
|
||||||
ret = snd_soc_update_bits(codec, AK4104_REG_TX,
|
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||||
AK4104_TX_TXE, AK4104_TX_TXE);
|
AK4104_TX_TXE, AK4104_TX_TXE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -182,7 +203,9 @@ static int ak4104_probe(struct snd_soc_codec *codec)
|
|||||||
|
|
||||||
static int ak4104_remove(struct snd_soc_codec *codec)
|
static int ak4104_remove(struct snd_soc_codec *codec)
|
||||||
{
|
{
|
||||||
snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
|
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user