mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00: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>
|
||||
The macro takes an conditional expression to evaluate.
|
||||
When <constant>CONFIG_SND_DEBUG</constant>, is set, the
|
||||
expression is actually evaluated. If it's non-zero, it shows
|
||||
the warning message such as
|
||||
When <constant>CONFIG_SND_DEBUG</constant>, is set, if the
|
||||
expression is non-zero, it shows the warning message such as
|
||||
<computeroutput>BUG? (xxx)</computeroutput>
|
||||
normally followed by stack trace. It returns the evaluated
|
||||
value.
|
||||
When no <constant>CONFIG_SND_DEBUG</constant> is set, this
|
||||
macro always returns zero.
|
||||
normally followed by stack trace.
|
||||
|
||||
In both cases it returns the evaluated value.
|
||||
</para>
|
||||
|
||||
</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)
|
||||
|
||||
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
|
||||
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
|
||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
||||
request selector for the first APBIF channel.
|
||||
- nvidia,dma-request-selector : A list of the DMA channel specifiers. Each
|
||||
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.
|
||||
Can be empty since the mapping is 1:1.
|
||||
- #address-cells : For the configlink bus. Should be <1>;
|
||||
@ -25,7 +35,13 @@ ahub@70080000 {
|
||||
reg = <0x70080000 0x200 0x70080200 0x100>;
|
||||
interrupts = < 0 103 0x04 >;
|
||||
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;
|
||||
#address-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
|
||||
- add_stereo_mix_input (bool): add the stereo mix (analog-loopback
|
||||
mix) to the input mux if available
|
||||
- add_out_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
||||
output jack for allowing to change the headphone amp capability
|
||||
- add_in_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
||||
input jack for allowing to change the mic bias vref
|
||||
- add_jack_modes (bool): add "xxx Jack Mode" enum controls to each
|
||||
I/O jack for allowing to change the headphone amp and mic bias VREF
|
||||
capabilities
|
||||
- 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
|
||||
|
||||
|
@ -25,10 +25,8 @@
|
||||
|
||||
#include <plat/regs-serial.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <plat/regs-ac97.h>
|
||||
#include <plat/regs-dma.h>
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <plat/regs-iis.h>
|
||||
#include <plat/regs-spi.h>
|
||||
|
||||
static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
|
||||
|
@ -25,10 +25,8 @@
|
||||
|
||||
#include <plat/regs-serial.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <plat/regs-ac97.h>
|
||||
#include <plat/regs-dma.h>
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <plat/regs-iis.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 }
|
||||
|
@ -25,10 +25,8 @@
|
||||
|
||||
#include <plat/regs-serial.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <plat/regs-ac97.h>
|
||||
#include <plat/regs-dma.h>
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <plat/regs-iis.h>
|
||||
#include <plat/regs-spi.h>
|
||||
|
||||
static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
|
||||
|
@ -25,10 +25,8 @@
|
||||
|
||||
#include <plat/regs-serial.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <plat/regs-ac97.h>
|
||||
#include <plat/regs-dma.h>
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <plat/regs-iis.h>
|
||||
#include <plat/regs-spi.h>
|
||||
|
||||
#define MAP(x) { \
|
||||
|
@ -146,14 +146,20 @@ struct platform_device s3c_device_camif = {
|
||||
|
||||
/* ASOC DMA */
|
||||
|
||||
#ifdef CONFIG_PLAT_S5P
|
||||
static struct resource samsung_asoc_idma_resource = DEFINE_RES_IRQ(IRQ_I2S0);
|
||||
|
||||
struct platform_device samsung_asoc_idma = {
|
||||
.name = "samsung-idma",
|
||||
.id = -1,
|
||||
.num_resources = 1,
|
||||
.resource = &samsung_asoc_idma_resource,
|
||||
.dev = {
|
||||
.dma_mask = &samsung_device_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/* FB */
|
||||
|
||||
|
@ -290,12 +290,14 @@ static const struct reg_default wm5102_reg_default[] = {
|
||||
{ 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
|
||||
{ 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */
|
||||
{ 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
|
||||
{ 0x00000179, 0x0000 }, /* R377 - FLL1 Control 7 */
|
||||
{ 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
|
||||
{ 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
|
||||
{ 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
|
||||
{ 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
|
||||
{ 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
|
||||
{ 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
|
||||
{ 0x00000187, 0x0001 }, /* R391 - FLL1 Synchroniser 7 */
|
||||
{ 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
|
||||
{ 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */
|
||||
{ 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */
|
||||
@ -306,12 +308,14 @@ static const struct reg_default wm5102_reg_default[] = {
|
||||
{ 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
|
||||
{ 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
|
||||
{ 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
|
||||
{ 0x00000199, 0x0000 }, /* R409 - FLL2 Control 7 */
|
||||
{ 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
|
||||
{ 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
|
||||
{ 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
|
||||
{ 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
|
||||
{ 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
|
||||
{ 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
|
||||
{ 0x000001A7, 0x0001 }, /* R423 - FLL2 Synchroniser 7 */
|
||||
{ 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
|
||||
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
|
||||
{ 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_LOOP_FILTER_TEST_1:
|
||||
case ARIZONA_FLL1_NCO_TEST_0:
|
||||
case ARIZONA_FLL1_CONTROL_7:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_1:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_2:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_3:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_4:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_5:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_6:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_7:
|
||||
case ARIZONA_FLL1_SPREAD_SPECTRUM:
|
||||
case ARIZONA_FLL1_GPIO_CLOCK:
|
||||
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_LOOP_FILTER_TEST_1:
|
||||
case ARIZONA_FLL2_NCO_TEST_0:
|
||||
case ARIZONA_FLL2_CONTROL_7:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_1:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_2:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_3:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_4:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_5:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_6:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_7:
|
||||
case ARIZONA_FLL2_SPREAD_SPECTRUM:
|
||||
case ARIZONA_FLL2_GPIO_CLOCK:
|
||||
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_PDM_SPK1_CTRL_1:
|
||||
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_2:
|
||||
case ARIZONA_DAC_COMP_3:
|
||||
|
@ -85,12 +85,14 @@
|
||||
#define ARIZONA_FLL1_CONTROL_6 0x176
|
||||
#define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177
|
||||
#define ARIZONA_FLL1_NCO_TEST_0 0x178
|
||||
#define ARIZONA_FLL1_CONTROL_7 0x179
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_1 0x181
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_2 0x182
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_3 0x183
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_4 0x184
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_5 0x185
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_6 0x186
|
||||
#define ARIZONA_FLL1_SYNCHRONISER_7 0x187
|
||||
#define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189
|
||||
#define ARIZONA_FLL1_GPIO_CLOCK 0x18A
|
||||
#define ARIZONA_FLL2_CONTROL_1 0x191
|
||||
@ -101,12 +103,14 @@
|
||||
#define ARIZONA_FLL2_CONTROL_6 0x196
|
||||
#define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197
|
||||
#define ARIZONA_FLL2_NCO_TEST_0 0x198
|
||||
#define ARIZONA_FLL2_CONTROL_7 0x199
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6
|
||||
#define ARIZONA_FLL2_SYNCHRONISER_7 0x1A7
|
||||
#define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9
|
||||
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
|
||||
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200
|
||||
@ -217,6 +221,8 @@
|
||||
#define ARIZONA_PDM_SPK1_CTRL_2 0x491
|
||||
#define ARIZONA_PDM_SPK2_CTRL_1 0x492
|
||||
#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_2 0x4DD
|
||||
#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_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
|
||||
*/
|
||||
@ -1727,6 +1740,17 @@
|
||||
#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] */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
@ -1819,6 +1843,13 @@
|
||||
#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] */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
@ -1865,6 +1896,17 @@
|
||||
#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] */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#define WM8994_NUM_LDO 2
|
||||
#define WM8994_NUM_GPIO 11
|
||||
#define WM8994_NUM_AIF 3
|
||||
|
||||
struct wm8994_ldo_pdata {
|
||||
/** GPIOs to enable regulator, 0 or less if not available */
|
||||
@ -215,6 +216,13 @@ struct wm8994_pdata {
|
||||
* system.
|
||||
*/
|
||||
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
|
||||
|
@ -170,6 +170,8 @@ struct uac2_as_header_descriptor {
|
||||
__u8 iChannelNames;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define UAC2_FORMAT_TYPE_I_RAW_DATA (1 << 31)
|
||||
|
||||
/* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
|
||||
|
||||
struct uac2_iso_endpoint_descriptor {
|
||||
|
@ -56,8 +56,6 @@ struct snd_compr_runtime {
|
||||
u64 buffer_size;
|
||||
u32 fragment_size;
|
||||
u32 fragments;
|
||||
u64 hw_pointer;
|
||||
u64 app_pointer;
|
||||
u64 total_bytes_available;
|
||||
u64 total_bytes_transferred;
|
||||
wait_queue_head_t sleep;
|
||||
@ -121,7 +119,7 @@ struct snd_compr_ops {
|
||||
int (*trigger)(struct snd_compr_stream *stream, int cmd);
|
||||
int (*pointer)(struct snd_compr_stream *stream,
|
||||
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);
|
||||
int (*mmap)(struct snd_compr_stream *stream,
|
||||
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
|
||||
* 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
|
||||
* 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,
|
||||
* logarithmic volume control (dB level) thus no linear volume,
|
||||
* master can only attenuate the volume without gain
|
||||
*
|
||||
* Return: Zero if successful or a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* Return: Zero if successful or a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
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
|
||||
* 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,
|
||||
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
|
||||
* @cond: condition to evaluate
|
||||
*
|
||||
* When CONFIG_SND_DEBUG is set, this macro evaluates the given condition,
|
||||
* and call WARN() and returns the value if it's non-zero.
|
||||
*
|
||||
* 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().
|
||||
* Has the same behavior as WARN_ON when CONFIG_SND_DEBUG is set,
|
||||
* otherwise just evaluates the conditional and returns the value.
|
||||
*/
|
||||
#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond))
|
||||
#define snd_BUG_ON(cond) WARN_ON((cond))
|
||||
|
||||
#else /* !CONFIG_SND_DEBUG */
|
||||
|
||||
@ -400,11 +392,11 @@ __printf(2, 3)
|
||||
static inline void _snd_printd(int level, const char *format, ...) {}
|
||||
|
||||
#define snd_BUG() do { } while (0)
|
||||
static inline int __snd_bug_on(int cond)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#define snd_BUG_ON(cond) __snd_bug_on(0 && (cond)) /* always false */
|
||||
|
||||
#define snd_BUG_ON(condition) ({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#endif /* CONFIG_SND_DEBUG */
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define __SOUND_DMAENGINE_PCM_H__
|
||||
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.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;
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
@ -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);
|
||||
|
||||
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_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 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
|
||||
|
@ -1787,6 +1787,7 @@ struct snd_emu10k1 {
|
||||
unsigned int next_free_voice;
|
||||
|
||||
const struct firmware *firmware;
|
||||
const struct firmware *dock_fw;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
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_40 _SNDRV_PCM_FMTBIT(G723_40)
|
||||
#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
|
||||
#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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* @substream: the pcm substream instance
|
||||
*
|
||||
* Checks whether any data exists on the playback buffer. If stop_threshold
|
||||
* is bigger or equal to boundary, then this function returns always non-zero.
|
||||
* Checks whether any data exists on the playback buffer.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -705,7 +707,7 @@ static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -719,7 +721,7 @@ static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
(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
|
||||
* @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)
|
||||
{
|
||||
@ -1126,4 +1133,10 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
|
||||
unsigned long private_value,
|
||||
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 */
|
||||
|
@ -95,14 +95,6 @@ struct snd_soc_dai_driver;
|
||||
struct snd_soc_dai;
|
||||
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.*/
|
||||
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir);
|
||||
|
@ -566,7 +566,6 @@ struct snd_soc_dapm_update {
|
||||
|
||||
/* 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 suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
|
@ -324,6 +324,8 @@ struct snd_soc_dai_link;
|
||||
struct snd_soc_platform_driver;
|
||||
struct snd_soc_codec;
|
||||
struct snd_soc_codec_driver;
|
||||
struct snd_soc_component;
|
||||
struct snd_soc_component_driver;
|
||||
struct soc_enum;
|
||||
struct snd_soc_jack;
|
||||
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_poweroff(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);
|
||||
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,
|
||||
const struct snd_soc_codec_driver *codec_drv,
|
||||
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
||||
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,
|
||||
unsigned int reg);
|
||||
int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
|
||||
@ -801,10 +811,10 @@ struct snd_soc_platform_driver {
|
||||
struct snd_soc_dai *);
|
||||
|
||||
/* platform stream pcm ops */
|
||||
struct snd_pcm_ops *ops;
|
||||
const struct snd_pcm_ops *ops;
|
||||
|
||||
/* platform stream compress ops */
|
||||
struct snd_compr_ops *compr_ops;
|
||||
const struct snd_compr_ops *compr_ops;
|
||||
|
||||
/* platform stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
@ -823,7 +833,7 @@ struct snd_soc_platform {
|
||||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
struct snd_soc_platform_driver *driver;
|
||||
const struct snd_soc_platform_driver *driver;
|
||||
struct mutex mutex;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
@ -841,6 +851,20 @@ struct snd_soc_platform {
|
||||
#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 {
|
||||
/* config - must be set by machine driver */
|
||||
const char *name; /* Codec name */
|
||||
@ -1086,7 +1110,6 @@ struct soc_enum {
|
||||
unsigned int mask;
|
||||
const char * const *texts;
|
||||
const unsigned int *values;
|
||||
void *dapm;
|
||||
};
|
||||
|
||||
/* 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_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
|
||||
#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
|
||||
#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) {
|
||||
/* 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 */
|
||||
hw->rate_min = 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;
|
||||
}
|
||||
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);
|
||||
chip->playback_substream = substream;
|
||||
return 0;
|
||||
@ -201,7 +201,7 @@ static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
|
||||
runtime->hw.rate_max = chip->cur_rate;
|
||||
}
|
||||
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);
|
||||
chip->capture_substream = substream;
|
||||
return 0;
|
||||
|
@ -28,11 +28,13 @@
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/uaccess.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);
|
||||
pr_debug("dsp consumed till %d total %d bytes\n",
|
||||
tstamp->byte_offset, tstamp->copied_total);
|
||||
stream->runtime->hw_pointer = tstamp->byte_offset;
|
||||
stream->runtime->total_bytes_transferred = tstamp->copied_total;
|
||||
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||
stream->runtime->total_bytes_transferred = tstamp->copied_total;
|
||||
else
|
||||
stream->runtime->total_bytes_available = tstamp->copied_total;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
|
||||
struct snd_compr_avail *avail)
|
||||
{
|
||||
long avail_calc; /*this needs to be signed variable */
|
||||
|
||||
memset(avail, 0, sizeof(*avail));
|
||||
snd_compr_update_tstamp(stream, &avail->tstamp);
|
||||
/* 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 &&
|
||||
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");
|
||||
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);
|
||||
if (stream->runtime->total_bytes_available ==
|
||||
stream->runtime->total_bytes_transferred) {
|
||||
pr_debug("both pointers are same, returning full avail\n");
|
||||
return stream->runtime->buffer_size;
|
||||
if (stream->direction == SND_COMPRESS_PLAYBACK) {
|
||||
pr_debug("both pointers are same, returning full avail\n");
|
||||
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
|
||||
* cumulative values and in the other byte offsets. Do we
|
||||
* really need the byte offsets if the cumulative values have
|
||||
* been updated? In the PCM interface app_ptr and hw_ptr are
|
||||
* already cumulative */
|
||||
avail->avail = stream->runtime->total_bytes_available -
|
||||
stream->runtime->total_bytes_transferred;
|
||||
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||
avail->avail = stream->runtime->buffer_size - avail->avail;
|
||||
|
||||
avail_calc = stream->runtime->buffer_size -
|
||||
(stream->runtime->app_pointer - stream->runtime->hw_pointer);
|
||||
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;
|
||||
pr_debug("ret avail as %lld\n", avail->avail);
|
||||
return avail->avail;
|
||||
}
|
||||
|
||||
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;
|
||||
size_t copy;
|
||||
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",
|
||||
(unsigned long)count, runtime->app_pointer);
|
||||
if (count < runtime->buffer_size - runtime->app_pointer) {
|
||||
(unsigned long)count, app_pointer);
|
||||
if (count < runtime->buffer_size - app_pointer) {
|
||||
if (copy_from_user(dstn, buf, count))
|
||||
return -EFAULT;
|
||||
runtime->app_pointer += count;
|
||||
} else {
|
||||
copy = runtime->buffer_size - runtime->app_pointer;
|
||||
copy = runtime->buffer_size - app_pointer;
|
||||
if (copy_from_user(dstn, buf, copy))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(runtime->buffer, buf + copy, count - copy))
|
||||
return -EFAULT;
|
||||
runtime->app_pointer = count - copy;
|
||||
}
|
||||
/* if DSP cares, let it know data has been written */
|
||||
if (stream->ops->ack)
|
||||
@ -278,10 +276,12 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
|
||||
if (avail > count)
|
||||
avail = count;
|
||||
|
||||
if (stream->ops->copy)
|
||||
retval = stream->ops->copy(stream, buf, avail);
|
||||
else
|
||||
if (stream->ops->copy) {
|
||||
char __user* cbuf = (char __user*)buf;
|
||||
retval = stream->ops->copy(stream, cbuf, avail);
|
||||
} else {
|
||||
retval = snd_compr_write_data(stream, buf, avail);
|
||||
}
|
||||
if (retval > 0)
|
||||
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,
|
||||
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)
|
||||
@ -375,6 +417,7 @@ snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
|
||||
if (!stream->ops->get_caps)
|
||||
return -ENXIO;
|
||||
|
||||
memset(&caps, 0, sizeof(caps));
|
||||
retval = stream->ops->get_caps(stream, &caps);
|
||||
if (retval)
|
||||
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)
|
||||
return -ENXIO;
|
||||
|
||||
caps = kmalloc(sizeof(*caps), GFP_KERNEL);
|
||||
caps = kzalloc(sizeof(*caps), GFP_KERNEL);
|
||||
if (!caps)
|
||||
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);
|
||||
if (retval)
|
||||
goto out;
|
||||
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
||||
|
||||
stream->metadata_set = 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 {
|
||||
return -EPERM;
|
||||
}
|
||||
@ -505,7 +553,7 @@ snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
|
||||
if (!stream->ops->get_params)
|
||||
return -EBADFD;
|
||||
|
||||
params = kmalloc(sizeof(*params), GFP_KERNEL);
|
||||
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
||||
if (!params)
|
||||
return -ENOMEM;
|
||||
retval = stream->ops->get_params(stream, params);
|
||||
@ -622,8 +670,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
|
||||
if (!retval) {
|
||||
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
|
||||
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_transferred = 0;
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ EXPORT_SYMBOL(snd_ctl_notify);
|
||||
* Allocates a new struct snd_kcontrol instance and copies the given template
|
||||
* 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,
|
||||
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
|
||||
* 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,
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* Return: Zero if successful, or a negative error code on failure.
|
||||
*
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* Return: Zero if successful, or a negative error code on failure.
|
||||
*/
|
||||
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
||||
bool add_on_replace)
|
||||
@ -442,8 +443,8 @@ EXPORT_SYMBOL(snd_ctl_replace);
|
||||
* Removes the control from the card and then releases the instance.
|
||||
* You don't need to call snd_ctl_free_one(). You must be in
|
||||
* 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)
|
||||
{
|
||||
@ -470,8 +471,8 @@ EXPORT_SYMBOL(snd_ctl_remove);
|
||||
*
|
||||
* Finds the control instance with the given id, removes it from the
|
||||
* 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)
|
||||
{
|
||||
@ -498,8 +499,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
|
||||
*
|
||||
* Finds the control instance with the given id, removes it from the
|
||||
* 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,
|
||||
struct snd_ctl_elem_id *id)
|
||||
@ -541,7 +542,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
|
||||
* Finds the control instance with the given id, and activate or
|
||||
* 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 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
|
||||
* 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,
|
||||
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.
|
||||
*
|
||||
* Returns the pointer of the instance if found, or NULL if not.
|
||||
*
|
||||
* The caller must down card->controls_rwsem before calling this function
|
||||
* (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)
|
||||
{
|
||||
@ -643,10 +645,11 @@ EXPORT_SYMBOL(snd_ctl_find_numid);
|
||||
*
|
||||
* 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
|
||||
* (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_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.
|
||||
* If the control's accessibility is not the default (readable and writable),
|
||||
* the caller has to fill @info->access.
|
||||
*
|
||||
* Return: Zero.
|
||||
*/
|
||||
int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
|
||||
unsigned int items, const char *const names[])
|
||||
|
@ -39,7 +39,7 @@
|
||||
* The data pointer plays a role as the identifier, too, so the
|
||||
* 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,
|
||||
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.
|
||||
* 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.
|
||||
*/
|
||||
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().
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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,
|
||||
struct snd_hwdep **rhwdep)
|
||||
|
@ -89,7 +89,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
|
||||
char *nbuf;
|
||||
|
||||
nsize = PAGE_ALIGN(nsize);
|
||||
nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
|
||||
nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL | __GFP_ZERO);
|
||||
if (! nbuf)
|
||||
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().
|
||||
*
|
||||
* 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, ...)
|
||||
{
|
||||
@ -344,7 +344,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
|
||||
goto __nomem;
|
||||
data->rbuffer = buffer;
|
||||
buffer->len = PAGE_SIZE;
|
||||
buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
|
||||
buffer->buffer = kzalloc(buffer->len, GFP_KERNEL);
|
||||
if (buffer->buffer == NULL)
|
||||
goto __nomem;
|
||||
}
|
||||
@ -683,31 +683,26 @@ int snd_info_card_free(struct snd_card *card)
|
||||
*
|
||||
* 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 c = -1;
|
||||
|
||||
if (snd_BUG_ON(!buffer || !buffer->buffer))
|
||||
return 1;
|
||||
if (len <= 0 || buffer->stop || buffer->error)
|
||||
return 1;
|
||||
while (--len > 0) {
|
||||
c = buffer->buffer[buffer->curr++];
|
||||
if (c == '\n') {
|
||||
if (buffer->curr >= buffer->size)
|
||||
buffer->stop = 1;
|
||||
break;
|
||||
}
|
||||
*line++ = c;
|
||||
if (buffer->curr >= buffer->size) {
|
||||
buffer->stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (c != '\n' && !buffer->stop) {
|
||||
while (!buffer->stop) {
|
||||
c = buffer->buffer[buffer->curr++];
|
||||
if (buffer->curr >= buffer->size)
|
||||
buffer->stop = 1;
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (len) {
|
||||
len--;
|
||||
*line++ = c;
|
||||
}
|
||||
}
|
||||
*line = '\0';
|
||||
return 0;
|
||||
@ -724,7 +719,7 @@ EXPORT_SYMBOL(snd_info_get_line);
|
||||
* Parses the original string and copy a token to the given
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -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.
|
||||
*
|
||||
* 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,
|
||||
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.
|
||||
*
|
||||
* 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,
|
||||
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
|
||||
* 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,
|
||||
struct snd_info_entry **entryp)
|
||||
@ -938,7 +933,7 @@ EXPORT_SYMBOL(snd_info_free_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)
|
||||
{
|
||||
|
@ -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
|
||||
* 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,
|
||||
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).
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -849,7 +849,7 @@ int __exit snd_card_info_done(void)
|
||||
* This function adds the component id string to the supported list.
|
||||
* 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)
|
||||
@ -883,7 +883,7 @@ EXPORT_SYMBOL(snd_component_add);
|
||||
* This linked-list is used to keep tracking the connection state,
|
||||
* 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)
|
||||
{
|
||||
@ -920,7 +920,7 @@ EXPORT_SYMBOL(snd_card_file_add);
|
||||
* called beforehand, it processes the pending release of
|
||||
* 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)
|
||||
{
|
||||
@ -959,6 +959,8 @@ EXPORT_SYMBOL(snd_card_file_remove);
|
||||
*
|
||||
* Waits until the power-state is changed.
|
||||
*
|
||||
* Return: Zero if successful, or a negative error code.
|
||||
*
|
||||
* Note: the power lock must be active before call.
|
||||
*/
|
||||
int snd_power_wait(struct snd_card *card, unsigned int power_state)
|
||||
|
@ -81,7 +81,7 @@ EXPORT_SYMBOL(snd_dma_disable);
|
||||
* @dma: the dma number
|
||||
* @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)
|
||||
{
|
||||
|
@ -98,8 +98,8 @@ static int snd_jack_dev_register(struct snd_device *device)
|
||||
*
|
||||
* Creates a new jack object.
|
||||
*
|
||||
* Returns zero if successful, or a negative error code on failure.
|
||||
* On success jjack will be initialised.
|
||||
* Return: Zero if successful, or a negative error code on failure.
|
||||
* On success @jjack will be initialised.
|
||||
*/
|
||||
int snd_jack_new(struct snd_card *card, const char *id, int type,
|
||||
struct snd_jack **jjack)
|
||||
@ -189,6 +189,8 @@ EXPORT_SYMBOL(snd_jack_set_parent);
|
||||
* using this abstraction.
|
||||
*
|
||||
* 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 keytype)
|
||||
|
@ -81,7 +81,7 @@ static inline void dec_snd_pages(int order)
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -175,9 +175,9 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
|
||||
*
|
||||
* Calls the memory-allocator function for the corresponding
|
||||
* buffer type.
|
||||
*
|
||||
* Returns zero if the buffer with the given size is allocated successfully,
|
||||
* other a negative value at error.
|
||||
*
|
||||
* Return: Zero if the buffer with the given size is allocated successfully,
|
||||
* otherwise a negative value on error.
|
||||
*/
|
||||
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
||||
struct snd_dma_buffer *dmab)
|
||||
@ -229,9 +229,9 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
|
||||
* buffer type. When no space is left, this function reduces the size and
|
||||
* tries to allocate again. The size actually allocated is stored in
|
||||
* res_size argument.
|
||||
*
|
||||
* Returns zero if the buffer with the given size is allocated successfully,
|
||||
* other a negative value at error.
|
||||
*
|
||||
* Return: Zero if the buffer with the given size is allocated successfully,
|
||||
* otherwise a negative value on error.
|
||||
*/
|
||||
int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -326,8 +326,8 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
|
||||
* @id: the buffer id
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -66,7 +66,7 @@ EXPORT_SYMBOL(copy_to_user_fromio);
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
|
@ -209,6 +209,8 @@ static char *snd_pcm_format_names[] = {
|
||||
FORMAT(G723_24_1B),
|
||||
FORMAT(G723_40),
|
||||
FORMAT(G723_40_1B),
|
||||
FORMAT(DSD_U8),
|
||||
FORMAT(DSD_U16_LE),
|
||||
};
|
||||
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* 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 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
|
||||
* 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 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 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)
|
||||
{
|
||||
@ -865,7 +866,8 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
|
||||
* @nump: pointer to store the resultant numerator
|
||||
* @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,
|
||||
unsigned int rats_count, struct snd_ratnum *rats,
|
||||
@ -983,7 +985,8 @@ EXPORT_SYMBOL(snd_interval_ratnum);
|
||||
* @nump: pointer to store the resultant numerator
|
||||
* @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,
|
||||
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
|
||||
* 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,
|
||||
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
|
||||
* @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 var,
|
||||
@ -1200,6 +1204,8 @@ EXPORT_SYMBOL(snd_pcm_hw_rule_add);
|
||||
* @mask: the bitmap mask
|
||||
*
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -1257,6 +1268,9 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
|
||||
* @max: the maximal value
|
||||
*
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
* 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,
|
||||
unsigned int cond,
|
||||
@ -1322,6 +1338,8 @@ static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
|
||||
* @cond: condition bits
|
||||
* @var: hw_params variable to apply the ratnums constraint
|
||||
* @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,
|
||||
unsigned int cond,
|
||||
@ -1355,6 +1373,8 @@ static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
|
||||
* @cond: condition bits
|
||||
* @var: hw_params variable to apply the ratdens constraint
|
||||
* @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,
|
||||
unsigned int cond,
|
||||
@ -1386,6 +1406,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
|
||||
* @cond: condition bits
|
||||
* @width: sample bits 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,
|
||||
unsigned int cond,
|
||||
@ -1414,6 +1436,8 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
|
||||
* @cond: condition bits
|
||||
* @var: hw_params variable to apply the step constraint
|
||||
* @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,
|
||||
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
|
||||
* @cond: condition bits
|
||||
* @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,
|
||||
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
|
||||
* @runtime: PCM runtime instance
|
||||
* @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,
|
||||
unsigned int base_rate)
|
||||
@ -1519,8 +1547,8 @@ EXPORT_SYMBOL(_snd_pcm_hw_params_any);
|
||||
* @var: parameter to retrieve
|
||||
* @dir: pointer to the direction (-1,0,1) or %NULL
|
||||
*
|
||||
* Return the value for field @var if it's fixed in configuration space
|
||||
* defined by @params. Return -%EINVAL otherwise.
|
||||
* Return: The value for field @var if it's fixed in configuration space
|
||||
* defined by @params. -%EINVAL otherwise.
|
||||
*/
|
||||
int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
|
||||
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
|
||||
* 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,
|
||||
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
|
||||
* 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,
|
||||
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:
|
||||
* first access, first format, first subformat, min channels,
|
||||
* min rate, min period time, max buffer size, min tick time
|
||||
*
|
||||
* Return: Zero if successful, or a negative error code on failure.
|
||||
*/
|
||||
int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
|
||||
struct snd_pcm_hw_params *params)
|
||||
@ -1771,7 +1803,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
|
||||
* Processes the generic ioctl commands for PCM.
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
* 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,
|
||||
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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* (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 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
|
||||
* 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 type, void *data,
|
||||
@ -313,8 +313,9 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
|
||||
* @substream: the pcm substream instance
|
||||
* @offset: the buffer offset
|
||||
*
|
||||
* Returns the page struct at the given buffer offset.
|
||||
* 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)
|
||||
{
|
||||
@ -337,7 +338,7 @@ EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
|
||||
* Allocates the DMA buffer on the BUS type given earlier to
|
||||
* 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.
|
||||
*/
|
||||
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().
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -437,6 +438,8 @@ EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
|
||||
* snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
|
||||
* @substream: the substream with a buffer allocated by
|
||||
* 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)
|
||||
{
|
||||
@ -458,6 +461,8 @@ EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
|
||||
* @offset: offset in the buffer
|
||||
*
|
||||
* 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,
|
||||
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,
|
||||
.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 */
|
||||
[SNDRV_PCM_FORMAT_MPEG] = {
|
||||
.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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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)
|
||||
{
|
||||
@ -264,7 +272,7 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
|
||||
* snd_pcm_format_little_endian - Check the PCM format is little-endian
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @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)
|
||||
{
|
||||
@ -379,7 +387,7 @@ EXPORT_SYMBOL(snd_pcm_format_silence_64);
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -449,7 +457,7 @@ EXPORT_SYMBOL(snd_pcm_format_set_silence);
|
||||
* Determines the rate_min and rate_max fields from the rates bits of
|
||||
* the given runtime->hw.
|
||||
*
|
||||
* Returns zero if successful.
|
||||
* Return: Zero if successful.
|
||||
*/
|
||||
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
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* @rate_bit: the rate bit to convert
|
||||
*
|
||||
* Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
|
||||
* or 0 for an unknown rate bit
|
||||
* Return: The sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
|
||||
* or 0 for an unknown 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
|
||||
* @substream: the PCM substream instance
|
||||
*
|
||||
* Return: Zero if successful, or a negative error code.
|
||||
*/
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -965,6 +969,8 @@ EXPORT_SYMBOL(snd_pcm_stop);
|
||||
*
|
||||
* After stopping, the state is changed to SETUP.
|
||||
* 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)
|
||||
{
|
||||
@ -1098,6 +1104,9 @@ static struct action_ops snd_pcm_action_suspend = {
|
||||
* @substream: the PCM substream
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -1120,6 +1129,8 @@ EXPORT_SYMBOL(snd_pcm_suspend);
|
||||
* @pcm: the PCM instance
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -1343,6 +1354,8 @@ static struct action_ops snd_pcm_action_prepare = {
|
||||
* snd_pcm_prepare - prepare the PCM substream to be triggerable
|
||||
* @substream: the PCM substream instance
|
||||
* @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,
|
||||
struct file *file)
|
||||
|
@ -863,7 +863,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
|
||||
*
|
||||
* 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,
|
||||
const unsigned char *buffer, int count)
|
||||
@ -1024,8 +1024,8 @@ 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
|
||||
* @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)
|
||||
{
|
||||
@ -1055,7 +1055,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
|
||||
* and call snd_rawmidi_transmit_ack() after the transmission is
|
||||
* 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,
|
||||
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.
|
||||
* 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)
|
||||
{
|
||||
@ -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.
|
||||
*
|
||||
* 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,
|
||||
unsigned char *buffer, int count)
|
||||
@ -1438,7 +1438,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
|
||||
* Creates a new rawmidi 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 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
|
||||
* if an associated instance with the given minor number and type is found.
|
||||
* 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)
|
||||
{
|
||||
@ -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.
|
||||
* 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,
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
|
@ -365,8 +365,7 @@ static void master_free(struct snd_kcontrol *kcontrol)
|
||||
* @name: name string of the control element to create
|
||||
* @tlv: optional TLV int array for dB information
|
||||
*
|
||||
* Creates a virtual matster control with the given name string.
|
||||
* Returns the created control element, or NULL for errors (ENOMEM).
|
||||
* Creates a virtual master control with the given name string.
|
||||
*
|
||||
* After creating a vmaster element, you can add the slave controls
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* Return: The created control element, or %NULL for errors (ENOMEM).
|
||||
*/
|
||||
struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
|
||||
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
|
||||
* at each time when the value is changed.
|
||||
*
|
||||
* Return: Zero.
|
||||
*/
|
||||
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
|
||||
void (*hook)(void *private_data, int),
|
||||
|
@ -87,7 +87,7 @@ config SND_ALOOP
|
||||
configured number of substreams (see the pcm_substreams module
|
||||
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%
|
||||
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_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_max = runtime->rate;
|
||||
cable->hw.channels_min = runtime->channels;
|
||||
|
@ -129,6 +129,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
|
||||
* @dev_id: mpu401 instance
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -148,6 +150,8 @@ EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
|
||||
* @dev_id: mpu401 instance
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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,
|
||||
* 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,
|
||||
unsigned short hardware,
|
||||
|
@ -114,7 +114,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap)
|
||||
}
|
||||
}
|
||||
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++)
|
||||
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++)
|
||||
ClearPageReserved(page);
|
||||
|
||||
dma_unmap_single(NULL, dmap->raw_buf_phys, dmap->buffsize, DMA_BIDIRECTIONAL);
|
||||
free_pages((unsigned long) dmap->raw_buf, sz);
|
||||
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)
|
||||
{
|
||||
printk(KERN_ERR "sb: Can't allocate memory for device information\n");
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
|
@ -352,23 +352,26 @@ int probe_uart401(struct address_info *hw_config, struct module *owner)
|
||||
goto cleanup_irq;
|
||||
}
|
||||
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]) {
|
||||
printk(KERN_ERR "uart401: Failed to allocate memory\n");
|
||||
goto cleanup_unload_mididev;
|
||||
}
|
||||
memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations));
|
||||
|
||||
if (owner)
|
||||
midi_devs[devc->my_dev]->owner = owner;
|
||||
|
||||
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) {
|
||||
printk(KERN_WARNING "uart401: Failed to allocate memory\n");
|
||||
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);
|
||||
midi_devs[devc->my_dev]->converter->id = "UART401";
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -352,7 +352,7 @@ EXPORT_SYMBOL(snd_ac97_write_cache);
|
||||
* Compares the value with the register cache and updates the value
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* @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)
|
||||
{
|
||||
@ -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
|
||||
* 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,
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
@ -2373,6 +2373,8 @@ static struct ac97_power_reg power_regs[PWIDX_SIZE] = {
|
||||
* @powerup: non-zero when power up the 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)
|
||||
{
|
||||
@ -2885,7 +2887,7 @@ static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
|
||||
* headphone (true line-out) control as "Master".
|
||||
* 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)
|
||||
|
@ -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
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
* 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,
|
||||
enum ac97_pcm_cfg cfg, unsigned short slots)
|
||||
@ -644,6 +648,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_open);
|
||||
* @pcm: the ac97 pcm instance
|
||||
*
|
||||
* It frees the locked AC97 slots.
|
||||
*
|
||||
* Return: Zero.
|
||||
*/
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
|
@ -451,10 +451,10 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
|
||||
if (pci_dev) {
|
||||
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
||||
pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
pci_read_config_dword(pci_dev, 0x7c, &dwVal);
|
||||
pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
pci_dev = codec->pci;
|
||||
@ -463,14 +463,14 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
|
||||
udelay(500);
|
||||
pci_read_config_dword(pci_dev, 0x44, &dwVal);
|
||||
pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
|
||||
wCount = 200;
|
||||
while(wCount--) {
|
||||
wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);
|
||||
if ((wReg & 0x000f) == 0x000f)
|
||||
return 0;
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
err = hpi_outstream_query_format(h_stream, &hpi_format);
|
||||
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;
|
||||
}
|
||||
@ -1141,8 +1141,8 @@ static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi,
|
||||
format, sample_rate, 128000, 0);
|
||||
if (!err)
|
||||
err = hpi_instream_query_format(h_stream, &hpi_format);
|
||||
if (!err)
|
||||
formats |= (1ULL << hpi_to_alsa_formats[format]);
|
||||
if (!err && (hpi_to_alsa_formats[format] != -1))
|
||||
formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]);
|
||||
}
|
||||
return formats;
|
||||
}
|
||||
|
@ -657,14 +657,14 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu)
|
||||
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu,
|
||||
const struct firmware *fw_entry)
|
||||
{
|
||||
int n, i;
|
||||
int reg;
|
||||
int value;
|
||||
unsigned int write_post;
|
||||
unsigned long flags;
|
||||
const struct firmware *fw_entry = emu->firmware;
|
||||
|
||||
if (!fw_entry)
|
||||
return -EIO;
|
||||
@ -725,9 +725,34 @@ static int emu1010_firmware_thread(void *data)
|
||||
/* Return to Audio Dock programming mode */
|
||||
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
|
||||
err = snd_emu1010_load_firmware(emu);
|
||||
if (err != 0)
|
||||
continue;
|
||||
|
||||
if (!emu->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;
|
||||
}
|
||||
}
|
||||
|
||||
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_read(emu, EMU_HANA_IRQ_STATUS, ®);
|
||||
@ -862,7 +887,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
|
||||
filename, emu->firmware->size);
|
||||
}
|
||||
|
||||
err = snd_emu1010_load_firmware(emu);
|
||||
err = snd_emu1010_load_firmware(emu, emu->firmware);
|
||||
if (err != 0) {
|
||||
snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n");
|
||||
return err;
|
||||
@ -1253,6 +1278,8 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
|
||||
kthread_stop(emu->emu1010.firmware_thread);
|
||||
if (emu->firmware)
|
||||
release_firmware(emu->firmware);
|
||||
if (emu->dock_fw)
|
||||
release_firmware(emu->dock_fw);
|
||||
if (emu->irq >= 0)
|
||||
free_irq(emu->irq, emu);
|
||||
/* 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
|
||||
*
|
||||
@ -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:
|
||||
* If no line-out is defined but multiple HPs are found,
|
||||
* 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,
|
||||
const struct auto_pin_cfg_item *item,
|
||||
hda_nid_t pin, bool check_location)
|
||||
{
|
||||
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)) {
|
||||
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)
|
||||
return "Mic";
|
||||
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;
|
||||
if (has_multiple_pins && type == AUTO_PIN_MIC)
|
||||
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);
|
||||
}
|
||||
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)
|
||||
name = hda_get_input_pin_label(codec, nid, true);
|
||||
name = hda_get_input_pin_label(codec, NULL, nid, true);
|
||||
break;
|
||||
}
|
||||
if (!name)
|
||||
|
@ -36,6 +36,8 @@ enum {
|
||||
struct auto_pin_cfg_item {
|
||||
hda_nid_t pin;
|
||||
int type;
|
||||
unsigned int is_headset_mic:1;
|
||||
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
|
||||
};
|
||||
|
||||
struct auto_pin_cfg;
|
||||
@ -78,8 +80,10 @@ struct auto_pin_cfg {
|
||||
};
|
||||
|
||||
/* 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_LO_FIXUP (1 << 1) /* don't take other outs as LO */
|
||||
#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_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,
|
||||
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) \
|
||||
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 */
|
||||
|
@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work)
|
||||
struct hda_beep *beep =
|
||||
container_of(work, struct hda_beep, beep_work);
|
||||
struct hda_codec *codec = beep->codec;
|
||||
int tone;
|
||||
|
||||
if (!beep->enabled)
|
||||
return;
|
||||
|
||||
tone = beep->tone;
|
||||
if (tone && !beep->playing) {
|
||||
snd_hda_power_up(codec);
|
||||
beep->playing = 1;
|
||||
}
|
||||
/* generate tone */
|
||||
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
|
||||
@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
|
||||
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)
|
||||
{
|
||||
input_unregister_device(beep->dev);
|
||||
beep->dev = NULL;
|
||||
cancel_work_sync(&beep->beep_work);
|
||||
/* turn off beep for sure */
|
||||
snd_hda_codec_write(beep->codec, beep->nid, 0,
|
||||
AC_VERB_SET_BEEP_CONTROL, 0);
|
||||
turn_off_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;
|
||||
if (beep->enabled != enable) {
|
||||
beep->enabled = enable;
|
||||
if (!enable) {
|
||||
cancel_work_sync(&beep->beep_work);
|
||||
/* turn off beep */
|
||||
snd_hda_codec_write(beep->codec, beep->nid, 0,
|
||||
AC_VERB_SET_BEEP_CONTROL, 0);
|
||||
}
|
||||
if (!enable)
|
||||
turn_off_beep(beep);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -198,7 +213,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
|
||||
snprintf(beep->phys, sizeof(beep->phys),
|
||||
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
|
||||
/* 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);
|
||||
|
||||
beep->nid = nid;
|
||||
|
@ -36,6 +36,7 @@ struct hda_beep {
|
||||
hda_nid_t nid;
|
||||
unsigned int enabled:1;
|
||||
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 mutex mutex;
|
||||
};
|
||||
|
@ -1065,8 +1065,14 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
|
||||
{
|
||||
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)
|
||||
return -EINVAL;
|
||||
*/
|
||||
|
||||
pin = look_up_pincfg(codec, list, nid);
|
||||
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,
|
||||
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
|
||||
@ -1422,7 +1426,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
|
||||
#endif
|
||||
codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
|
||||
AC_PWRST_EPSS);
|
||||
codec->power_filter = default_power_filter;
|
||||
|
||||
/* power-up all before initialization */
|
||||
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)
|
||||
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) {
|
||||
case HDA_VMUTE_FOLLOW_MASTER:
|
||||
snd_ctl_sync_vmaster_hook(hook->sw_kctl);
|
||||
@ -3770,8 +3778,9 @@ 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 */
|
||||
static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned int power_state)
|
||||
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
||||
hda_nid_t nid,
|
||||
unsigned int power_state)
|
||||
{
|
||||
if (power_state == AC_PWRST_D3 &&
|
||||
get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
|
||||
@ -3783,6 +3792,7 @@ static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
|
||||
}
|
||||
return power_state;
|
||||
}
|
||||
EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
int i;
|
||||
|
||||
/* don't care if no or standard filter is used */
|
||||
if (!codec->power_filter || codec->power_filter == default_power_filter)
|
||||
/* don't care if no filter is used */
|
||||
if (!codec->power_filter)
|
||||
return;
|
||||
|
||||
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) {
|
||||
int num = array->alloced + array->alloc_align;
|
||||
int size = (num + 1) * array->elem_size;
|
||||
int oldsize = array->alloced * array->elem_size;
|
||||
void *nlist;
|
||||
if (snd_BUG_ON(num >= 4096))
|
||||
return NULL;
|
||||
nlist = krealloc(array->list, size, GFP_KERNEL);
|
||||
nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
|
||||
if (!nlist)
|
||||
return NULL;
|
||||
memset(nlist + oldsize, 0, size - oldsize);
|
||||
array->list = nlist;
|
||||
array->alloced = num;
|
||||
}
|
||||
|
@ -757,6 +757,9 @@ struct hda_pcm_ops {
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
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 */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
#include "hda_jack.h"
|
||||
#include "hda_beep.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");
|
||||
if (val >= 0)
|
||||
spec->add_stereo_mix_input = !!val;
|
||||
/* the following two are just for compatibility */
|
||||
val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
|
||||
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");
|
||||
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");
|
||||
if (val >= 0)
|
||||
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))
|
||||
spec->mixer_nid = val;
|
||||
@ -996,7 +1007,7 @@ enum {
|
||||
/* Primary DAC shared with main surrounds */
|
||||
BAD_SHARED_SURROUND = 0x100,
|
||||
/* No independent HP possible */
|
||||
BAD_NO_INDEP_HP = 0x40,
|
||||
BAD_NO_INDEP_HP = 0x10,
|
||||
/* Primary DAC shared with main CLFE */
|
||||
BAD_SHARED_CLFE = 0x10,
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
static struct badness_table main_out_badness = {
|
||||
const struct badness_table hda_main_out_badness = {
|
||||
.no_primary_dac = BAD_NO_PRIMARY_DAC,
|
||||
.no_dac = BAD_NO_DAC,
|
||||
.shared_primary = BAD_NO_PRIMARY_DAC,
|
||||
@ -1068,8 +1070,9 @@ static struct badness_table main_out_badness = {
|
||||
.shared_clfe = BAD_SHARED_CLFE,
|
||||
.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_dac = BAD_NO_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_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 */
|
||||
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 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);
|
||||
if (!path || !path->depth ||
|
||||
is_nid_contained(path, spec->mixer_nid))
|
||||
return 0;
|
||||
dac = path->path[0];
|
||||
path_dac = path->path[0];
|
||||
dac = spec->private_dac_nids[0];
|
||||
pin = path->path[path->depth - 1];
|
||||
path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
|
||||
if (!path) {
|
||||
if (dac != spec->multiout.dac_nids[0])
|
||||
dac = spec->multiout.dac_nids[0];
|
||||
if (dac != path_dac)
|
||||
dac = path_dac;
|
||||
else if (spec->multiout.hp_out_nid[0])
|
||||
dac = spec->multiout.hp_out_nid[0];
|
||||
else if (spec->multiout.extra_out_nid[0])
|
||||
dac = spec->multiout.extra_out_nid[0];
|
||||
else
|
||||
dac = 0;
|
||||
if (dac)
|
||||
path = snd_hda_add_new_path(codec, dac, pin,
|
||||
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,
|
||||
spec->private_dac_nids, spec->out_paths,
|
||||
&main_out_badness);
|
||||
spec->main_out_badness);
|
||||
|
||||
if (fill_mio_first &&
|
||||
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,
|
||||
spec->multiout.hp_out_nid,
|
||||
spec->hp_paths,
|
||||
&extra_out_badness);
|
||||
spec->extra_out_badness);
|
||||
if (err < 0)
|
||||
return err;
|
||||
badness += err;
|
||||
@ -1532,7 +1539,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
||||
cfg->speaker_pins,
|
||||
spec->multiout.extra_out_nid,
|
||||
spec->speaker_paths,
|
||||
&extra_out_badness);
|
||||
spec->extra_out_badness);
|
||||
if (err < 0)
|
||||
return err;
|
||||
badness += err;
|
||||
@ -1926,6 +1933,17 @@ static int create_speaker_out_ctls(struct hda_codec *codec)
|
||||
* 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,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
@ -1986,12 +2004,7 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol,
|
||||
else
|
||||
*dacp = spec->alt_dac_nid;
|
||||
|
||||
/* update HP auto-mute state too */
|
||||
if (spec->hp_automute_hook)
|
||||
spec->hp_automute_hook(codec, NULL);
|
||||
else
|
||||
snd_hda_gen_hp_automute(codec, NULL);
|
||||
|
||||
update_hp_automute_hook(codec);
|
||||
ret = 1;
|
||||
}
|
||||
unlock:
|
||||
@ -2072,6 +2085,14 @@ get_multiio_path(struct hda_codec *codec, int idx)
|
||||
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
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);
|
||||
path_power_down_sync(codec, nomix_path);
|
||||
} else {
|
||||
snd_hda_activate_path(codec, mix_path, false, true);
|
||||
snd_hda_activate_path(codec, nomix_path, true, true);
|
||||
snd_hda_activate_path(codec, mix_path, false, false);
|
||||
snd_hda_activate_path(codec, nomix_path, true, false);
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
bool as_mic;
|
||||
unsigned int val;
|
||||
hda_nid_t pin = spec->autocfg.inputs[1].pin;
|
||||
/* NOTE: this assumes that there are only two inputs, the
|
||||
* first is the real internal mic and the second is HP/mic jack.
|
||||
*/
|
||||
hda_nid_t pin;
|
||||
|
||||
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);
|
||||
|
||||
/* This pin does not have vref caps - let's enable vref on pin 0x18
|
||||
instead, as suggested by Realtek */
|
||||
/* if the HP pin doesn't support VREF and the codec driver gives an
|
||||
* alternative pin, set up the VREF on that pin instead
|
||||
*/
|
||||
if (val == AC_PINCTL_VREF_HIZ && 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);
|
||||
if (vref_val != AC_PINCTL_VREF_HIZ)
|
||||
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;
|
||||
set_pin_target(codec, pin, val, true);
|
||||
|
||||
spec->automute_speaker = !set_as_mic;
|
||||
call_update_outputs(codec);
|
||||
if (!spec->hp_mic_jack_modes) {
|
||||
if (as_mic)
|
||||
val |= PIN_IN;
|
||||
else
|
||||
val = PIN_HP;
|
||||
set_pin_target(codec, pin, val, true);
|
||||
update_hp_automute_hook(codec);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 auto_pin_cfg *cfg = &spec->autocfg;
|
||||
unsigned int defcfg;
|
||||
hda_nid_t nid;
|
||||
|
||||
/* only one internal input pin? */
|
||||
if (cfg->num_inputs != 1)
|
||||
return 0;
|
||||
defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
|
||||
if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
|
||||
if (!spec->hp_mic) {
|
||||
if (spec->suppress_hp_mic_detect)
|
||||
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);
|
||||
if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
spec->hp_mic = 0; /* clear once */
|
||||
if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
|
||||
return 0;
|
||||
|
||||
if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
|
||||
nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
|
||||
else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
|
||||
nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
|
||||
else
|
||||
return 0; /* both not available */
|
||||
nid = 0;
|
||||
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))
|
||||
return 0; /* no input */
|
||||
|
||||
cfg->inputs[1].pin = nid;
|
||||
cfg->inputs[1].type = AUTO_PIN_MIC;
|
||||
cfg->num_inputs = 2;
|
||||
spec->shared_mic_hp = 1;
|
||||
cfg->inputs[cfg->num_inputs].pin = nid;
|
||||
cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
|
||||
cfg->inputs[cfg->num_inputs].is_headphone_mic = 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);
|
||||
return 0;
|
||||
}
|
||||
@ -2304,13 +2357,17 @@ static int create_shared_input(struct hda_codec *codec)
|
||||
/*
|
||||
* 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,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static const char * const texts[] = {
|
||||
"Line Out", "Headphone Out",
|
||||
};
|
||||
return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
|
||||
return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
|
||||
}
|
||||
|
||||
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,
|
||||
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++) {
|
||||
hda_nid_t pin = pins[i];
|
||||
unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
|
||||
if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
|
||||
if (pin == spec->hp_mic_pin) {
|
||||
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;
|
||||
char name[44];
|
||||
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
unsigned int defcfg;
|
||||
struct snd_kcontrol_new *knew;
|
||||
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 */
|
||||
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;
|
||||
|
||||
/* no multiple vref caps? */
|
||||
if (hweight32(get_vref_caps(codec, pin)) <= 1)
|
||||
if (get_in_jack_num_items(codec, pin) <= 1)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -2648,7 +2859,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
|
||||
unsigned int ok_bits;
|
||||
int i, n, nums;
|
||||
|
||||
again:
|
||||
nums = 0;
|
||||
ok_bits = 0;
|
||||
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 (spec->shared_mic_hp) {
|
||||
spec->shared_mic_hp = 0;
|
||||
imux->num_items = 1;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* check whether ADC-switch is possible */
|
||||
for (i = 0; i < imux->num_items; i++) {
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
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);
|
||||
|
||||
if (!imux_added) {
|
||||
if (spec->hp_mic_pin == pin)
|
||||
spec->hp_mic_mux_idx = imux->num_items;
|
||||
spec->imux_pins[imux->num_items] = pin;
|
||||
snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
|
||||
imux_added = true;
|
||||
@ -2812,7 +3019,8 @@ static int create_input_ctls(struct hda_codec *codec)
|
||||
val = PIN_IN;
|
||||
if (cfg->inputs[i].type == AUTO_PIN_MIC)
|
||||
val |= snd_hda_get_default_vref(codec, pin);
|
||||
set_pin_target(codec, pin, val, false);
|
||||
if (pin != spec->hp_mic_pin)
|
||||
set_pin_target(codec, pin, val, false);
|
||||
|
||||
if (mixer) {
|
||||
if (is_reachable_path(codec, pin, mixer)) {
|
||||
@ -2830,7 +3038,7 @@ static int create_input_ctls(struct hda_codec *codec)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (spec->add_in_jack_modes) {
|
||||
if (spec->add_jack_modes) {
|
||||
err = create_in_jack_mode(codec, pin);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -3462,8 +3670,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
||||
|
||||
spec->cur_mux[adc_idx] = idx;
|
||||
|
||||
if (spec->shared_mic_hp)
|
||||
update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
|
||||
if (spec->hp_mic)
|
||||
update_hp_mic(codec, adc_idx, false);
|
||||
|
||||
if (spec->dyn_adc_switch)
|
||||
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++) {
|
||||
hda_nid_t nid = pins[i];
|
||||
unsigned int val;
|
||||
unsigned int val, oldval;
|
||||
if (!nid)
|
||||
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
|
||||
* the amp (see alc861_fixup_asus_amp_vref_0f())
|
||||
*/
|
||||
if (spec->keep_vref_in_automute)
|
||||
val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
|
||||
val = oldval & ~PIN_HP;
|
||||
else
|
||||
val = 0;
|
||||
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
|
||||
* without changing the pinctl target value;
|
||||
* the original target value will be still referred at the
|
||||
@ -3543,8 +3754,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
|
||||
* in general, HP pins/amps control should be enabled in all cases,
|
||||
* 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);
|
||||
|
||||
if (!spec->automute_speaker)
|
||||
@ -3649,10 +3859,7 @@ static void update_automute_all(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);
|
||||
update_hp_automute_hook(codec);
|
||||
if (spec->line_automute_hook)
|
||||
spec->line_automute_hook(codec, NULL);
|
||||
else
|
||||
@ -3978,6 +4185,11 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
||||
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);
|
||||
|
||||
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);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = create_shared_input(codec);
|
||||
err = create_hp_mic(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = create_input_ctls(codec);
|
||||
@ -4050,11 +4262,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!spec->shared_mic_hp) {
|
||||
err = check_auto_mic_availability(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
err = check_auto_mic_availability(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = create_capture_mixers(codec);
|
||||
if (err < 0)
|
||||
@ -4064,7 +4274,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (spec->add_out_jack_modes) {
|
||||
if (spec->add_jack_modes) {
|
||||
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
||||
err = create_out_jack_modes(codec, cfg->line_outs,
|
||||
cfg->line_out_pins);
|
||||
@ -4085,6 +4295,12 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
||||
if (spec->power_down_unused)
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
|
||||
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);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -4729,7 +4934,8 @@ static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
|
||||
return;
|
||||
pin = path->path[path->depth - 1];
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4779,7 +4985,8 @@ static void init_multi_io(struct hda_codec *codec)
|
||||
if (!spec->multi_io[i].ctl_in)
|
||||
spec->multi_io[i].ctl_in =
|
||||
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);
|
||||
}
|
||||
}
|
||||
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)
|
||||
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)
|
||||
{
|
||||
snd_hda_detach_beep_device(codec);
|
||||
snd_hda_gen_spec_free(codec->spec);
|
||||
kfree(codec->spec);
|
||||
codec->spec = NULL;
|
||||
|
@ -76,6 +76,19 @@ enum {
|
||||
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 {
|
||||
char stream_name_analog[32]; /* analog PCM stream */
|
||||
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 imux_pins[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 hp_mic_pin;
|
||||
int hp_mic_mux_idx;
|
||||
|
||||
/* DAC/ADC lists */
|
||||
int num_all_dacs;
|
||||
@ -200,7 +216,8 @@ struct hda_gen_spec {
|
||||
|
||||
/* other parse behavior flags */
|
||||
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 multi_cap_vol:1; /* allow multiple capture xxx volumes */
|
||||
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 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_out_jack_modes:1; /* add output jack mode enum ctls */
|
||||
unsigned int add_in_jack_modes:1; /* add input jack mode enum ctls */
|
||||
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
|
||||
unsigned int power_down_unused:1; /* power down unused widgets */
|
||||
|
||||
/* other internal flags */
|
||||
@ -218,10 +234,18 @@ struct hda_gen_spec {
|
||||
unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
|
||||
unsigned int indep_hp_enabled:1; /* independent HP enabled */
|
||||
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 */
|
||||
bool aamix_mode;
|
||||
|
||||
/* digital beep */
|
||||
hda_nid_t beep_nid;
|
||||
|
||||
/* for virtual master */
|
||||
hda_nid_t vmaster_nid;
|
||||
unsigned int vmaster_tlv[4];
|
||||
|
@ -1889,6 +1889,26 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream,
|
||||
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,
|
||||
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 = div_u64(nsec, 3); /* can be optimized */
|
||||
nsec = azx_adjust_codec_delay(substream, nsec);
|
||||
|
||||
*ts = ns_to_timespec(nsec);
|
||||
|
||||
@ -2349,8 +2370,11 @@ static unsigned int azx_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev,
|
||||
bool with_check)
|
||||
{
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||
unsigned int pos;
|
||||
int stream = azx_dev->substream->stream;
|
||||
int stream = substream->stream;
|
||||
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
|
||||
int delay = 0;
|
||||
|
||||
switch (chip->position_fix[stream]) {
|
||||
@ -2381,7 +2405,7 @@ static unsigned int azx_get_position(struct azx *chip,
|
||||
pos = 0;
|
||||
|
||||
/* calculate runtime delay from LPIB */
|
||||
if (azx_dev->substream->runtime &&
|
||||
if (substream->runtime &&
|
||||
chip->position_fix[stream] == POS_FIX_POSBUF &&
|
||||
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
|
||||
unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
|
||||
@ -2399,9 +2423,16 @@ static unsigned int azx_get_position(struct azx *chip,
|
||||
delay = 0;
|
||||
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
|
||||
}
|
||||
azx_dev->substream->runtime->delay =
|
||||
bytes_to_frames(azx_dev->substream->runtime, delay);
|
||||
delay = bytes_to_frames(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);
|
||||
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,
|
||||
const struct auto_pin_cfg *cfg)
|
||||
const struct auto_pin_cfg *cfg,
|
||||
const char *base_name)
|
||||
{
|
||||
unsigned int def_conf, conn;
|
||||
char name[44];
|
||||
@ -410,7 +411,11 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
||||
phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
|
||||
!is_jack_detectable(codec, nid);
|
||||
|
||||
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
|
||||
if (base_name) {
|
||||
strlcpy(name, base_name, sizeof(name));
|
||||
idx = 0;
|
||||
} else
|
||||
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
|
||||
if (phantom_jack)
|
||||
/* Example final name: "Internal Mic Phantom Jack" */
|
||||
strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
|
||||
@ -433,39 +438,51 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
|
||||
const hda_nid_t *p;
|
||||
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++) {
|
||||
err = add_jack_kctl(codec, *p, cfg);
|
||||
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
|
||||
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
||||
break;
|
||||
err = add_jack_kctl(codec, *p, cfg);
|
||||
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
|
||||
if (*p == *cfg->line_out_pins) /* might be duplicated */
|
||||
break;
|
||||
err = add_jack_kctl(codec, *p, cfg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < cfg->num_inputs; i++) {
|
||||
err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
|
||||
err = add_jack_kctl(codec, *p, cfg, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return err;
|
||||
return 0;
|
||||
|
@ -670,6 +670,10 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
|
||||
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
|
||||
*/
|
||||
|
@ -43,7 +43,6 @@ struct ad198x_spec {
|
||||
hda_nid_t eapd_nid;
|
||||
|
||||
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
|
||||
hda_nid_t beep_dev_nid;
|
||||
|
||||
#ifdef ENABLE_AD_STATIC_QUIRKS
|
||||
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_pcms = snd_hda_gen_build_pcms,
|
||||
.init = snd_hda_gen_init,
|
||||
.free = ad198x_free,
|
||||
.free = snd_hda_gen_free,
|
||||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
#ifdef CONFIG_PM
|
||||
.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)
|
||||
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;
|
||||
|
||||
return 0;
|
||||
@ -1240,7 +1233,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
|
||||
codec->inv_eapd = 1;
|
||||
|
||||
spec->gen.mixer_nid = 0x07;
|
||||
spec->beep_dev_nid = 0x19;
|
||||
spec->gen.beep_nid = 0x19;
|
||||
set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
|
||||
|
||||
/* 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);
|
||||
if (err < 0) {
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1673,7 +1666,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
|
||||
return err;
|
||||
spec = codec->spec;
|
||||
|
||||
spec->beep_dev_nid = 0x10;
|
||||
spec->gen.beep_nid = 0x10;
|
||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||
err = ad198x_parse_auto_config(codec);
|
||||
if (err < 0)
|
||||
@ -1684,7 +1677,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2187,7 +2180,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
|
||||
spec = codec->spec;
|
||||
|
||||
spec->gen.mixer_nid = 0x0e;
|
||||
spec->beep_dev_nid = 0x10;
|
||||
spec->gen.beep_nid = 0x10;
|
||||
set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
|
||||
|
||||
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;
|
||||
|
||||
error:
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -3236,7 +3229,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
|
||||
|
||||
spec->gen.mixer_nid = 0x20;
|
||||
spec->gen.mixer_merge_nid = 0x21;
|
||||
spec->beep_dev_nid = 0x10;
|
||||
spec->gen.beep_nid = 0x10;
|
||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||
err = ad198x_parse_auto_config(codec);
|
||||
if (err < 0)
|
||||
@ -3247,7 +3240,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -3653,7 +3646,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
|
||||
spec = codec->spec;
|
||||
|
||||
spec->gen.mixer_nid = 0x20;
|
||||
spec->beep_dev_nid = 0x10;
|
||||
spec->gen.beep_nid = 0x10;
|
||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||
|
||||
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;
|
||||
|
||||
error:
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -5155,7 +5148,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
|
||||
|
||||
spec->gen.mixer_nid = 0x20;
|
||||
spec->gen.mixer_merge_nid = 0x21;
|
||||
spec->beep_dev_nid = 0x10;
|
||||
spec->gen.beep_nid = 0x10;
|
||||
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
|
||||
err = ad198x_parse_auto_config(codec);
|
||||
if (err < 0)
|
||||
@ -5166,7 +5159,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ad198x_free(codec);
|
||||
snd_hda_gen_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -131,6 +131,13 @@ enum {
|
||||
/* Effects values size*/
|
||||
#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 {
|
||||
char name[44];
|
||||
hda_nid_t nid;
|
||||
@ -741,6 +748,9 @@ struct ca0132_spec {
|
||||
long voicefx_val;
|
||||
long cur_mic_boost;
|
||||
|
||||
struct hda_codec *codec;
|
||||
struct delayed_work unsol_hp_work;
|
||||
|
||||
#ifdef ENABLE_TUNING_CONTROLS
|
||||
long cur_ctl_vals[TUNING_CTLS_COUNT];
|
||||
#endif
|
||||
@ -2740,6 +2750,31 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
||||
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
|
||||
*/
|
||||
@ -2808,6 +2843,23 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
||||
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.
|
||||
*/
|
||||
@ -3227,6 +3279,14 @@ static int ca0132_select_out(struct hda_codec *codec)
|
||||
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 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);
|
||||
@ -3991,7 +4051,8 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = {
|
||||
.channels_max = 6,
|
||||
.ops = {
|
||||
.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,
|
||||
.ops = {
|
||||
.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)
|
||||
{
|
||||
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) {
|
||||
ca0132_process_dsp_response(codec);
|
||||
@ -4412,8 +4473,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
|
||||
|
||||
switch (res) {
|
||||
case UNSOL_TAG_HP:
|
||||
ca0132_select_out(codec);
|
||||
snd_hda_jack_report_sync(codec);
|
||||
/* Delay enabling the HP amp, to let the mic-detection
|
||||
* 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;
|
||||
case UNSOL_TAG_AMIC1:
|
||||
ca0132_select_mic(codec);
|
||||
@ -4588,6 +4654,7 @@ static void ca0132_free(struct hda_codec *codec)
|
||||
{
|
||||
struct ca0132_spec *spec = codec->spec;
|
||||
|
||||
cancel_delayed_work_sync(&spec->unsol_hp_work);
|
||||
snd_hda_power_up(codec);
|
||||
snd_hda_sequence_write(codec, spec->base_exit_verbs);
|
||||
ca0132_exit_chip(codec);
|
||||
@ -4653,6 +4720,7 @@ static int patch_ca0132(struct hda_codec *codec)
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
codec->spec = spec;
|
||||
spec->codec = codec;
|
||||
|
||||
spec->num_mixers = 1;
|
||||
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->num_init_verbs = 2;
|
||||
|
||||
INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
|
||||
|
||||
ca0132_init_chip(codec);
|
||||
|
||||
ca0132_config(codec);
|
||||
|
@ -68,6 +68,7 @@ enum {
|
||||
enum {
|
||||
CS421X_CDB4210,
|
||||
CS421X_SENSE_B,
|
||||
CS421X_STUMPY,
|
||||
};
|
||||
|
||||
/* Vendor-specific processing widget */
|
||||
@ -538,6 +539,7 @@ static int patch_cs420x(struct hda_codec *codec)
|
||||
/* CS4210 board names */
|
||||
static const struct hda_model_fixup cs421x_models[] = {
|
||||
{ .id = CS421X_CDB4210, .name = "cdb4210" },
|
||||
{ .id = CS421X_STUMPY, .name = "stumpy" },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -559,6 +561,17 @@ static const struct hda_pintbl cdb4210_pincfgs[] = {
|
||||
{} /* 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) */
|
||||
static void cs421x_fixup_sense_b(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
@ -578,7 +591,11 @@ static const struct hda_fixup cs421x_fixups[] = {
|
||||
[CS421X_SENSE_B] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.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[] = {
|
||||
|
@ -139,8 +139,12 @@ struct conexant_spec {
|
||||
|
||||
|
||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||
#define set_beep_amp(spec, nid, idx, dir) \
|
||||
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
|
||||
static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
|
||||
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 */
|
||||
static const struct snd_kcontrol_new cxt_beep_mixer[] = {
|
||||
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, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
|
||||
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, 0x3a0d, "Lenovo U350", 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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.build_controls = cx_auto_build_controls,
|
||||
.build_pcms = snd_hda_gen_build_pcms,
|
||||
.init = snd_hda_gen_init,
|
||||
.free = cx_auto_free,
|
||||
.free = snd_hda_gen_free,
|
||||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
#ifdef CONFIG_PM
|
||||
.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, 0x21ce, "Lenovo T420", 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, 0x3977, "Lenovo IdeaPad U310", 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) {
|
||||
case 0x14f15045:
|
||||
codec->single_adc_amp = 1;
|
||||
codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */
|
||||
break;
|
||||
case 0x14f15047:
|
||||
codec->pin_amp_workaround = 1;
|
||||
@ -3396,8 +3393,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||
goto error;
|
||||
|
||||
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,
|
||||
* which falls into the single-cmd mode.
|
||||
|
@ -44,16 +44,6 @@ static bool static_hdmi_pcm;
|
||||
module_param(static_hdmi_pcm, bool, 0644);
|
||||
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 {
|
||||
hda_nid_t cvt_nid;
|
||||
int assigned;
|
||||
@ -80,16 +70,17 @@ struct hdmi_spec_per_pin {
|
||||
bool non_pcm;
|
||||
bool chmap_set; /* channel-map override by ALSA API? */
|
||||
unsigned char chmap[8]; /* ALSA API channel-map */
|
||||
char pcm_name[8]; /* filled in build_pcm callbacks */
|
||||
};
|
||||
|
||||
struct hdmi_spec {
|
||||
int num_cvts;
|
||||
struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS];
|
||||
hda_nid_t cvt_nids[MAX_HDMI_CVTS];
|
||||
struct snd_array cvts; /* struct hdmi_spec_per_cvt */
|
||||
hda_nid_t cvt_nids[4]; /* only for haswell fix */
|
||||
|
||||
int num_pins;
|
||||
struct hdmi_spec_per_pin pins[MAX_HDMI_PINS];
|
||||
struct hda_pcm pcm_rec[MAX_HDMI_PINS];
|
||||
struct snd_array pins; /* struct hdmi_spec_per_pin */
|
||||
struct snd_array pcm_rec; /* struct hda_pcm */
|
||||
unsigned int channels_max; /* max over all cvts */
|
||||
|
||||
struct hdmi_eld temp_eld;
|
||||
@ -304,12 +295,19 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
|
||||
* 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)
|
||||
{
|
||||
int 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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
pin_idx = kcontrol->private_value;
|
||||
eld = &spec->pins[pin_idx].sink_eld;
|
||||
eld = &get_pin(spec, pin_idx)->sink_eld;
|
||||
|
||||
mutex_lock(&eld->lock);
|
||||
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;
|
||||
|
||||
pin_idx = kcontrol->private_value;
|
||||
eld = &spec->pins[pin_idx].sink_eld;
|
||||
eld = &get_pin(spec, pin_idx)->sink_eld;
|
||||
|
||||
mutex_lock(&eld->lock);
|
||||
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->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)
|
||||
return err;
|
||||
|
||||
spec->pins[pin_idx].eld_ctl = kctl;
|
||||
get_pin(spec, pin_idx)->eld_ctl = kctl;
|
||||
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 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;
|
||||
int channels = substream->runtime->channels;
|
||||
struct hdmi_eld *eld;
|
||||
int ca;
|
||||
union audio_infoframe ai;
|
||||
|
||||
eld = &spec->pins[pin_idx].sink_eld;
|
||||
eld = &per_pin->sink_eld;
|
||||
if (!eld->monitor_present)
|
||||
return;
|
||||
|
||||
@ -977,7 +975,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
||||
if (pin_idx < 0)
|
||||
return;
|
||||
|
||||
hdmi_present_sense(&spec->pins[pin_idx], 1);
|
||||
hdmi_present_sense(get_pin(spec, pin_idx), 1);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
@ -1034,6 +1067,9 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
||||
int pinctl;
|
||||
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) {
|
||||
pinctl = snd_hda_codec_read(codec, pin_nid, 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);
|
||||
if (snd_BUG_ON(pin_idx < 0))
|
||||
return -EINVAL;
|
||||
per_pin = &spec->pins[pin_idx];
|
||||
per_pin = get_pin(spec, pin_idx);
|
||||
eld = &per_pin->sink_eld;
|
||||
|
||||
/* Dynamically assign converter to stream */
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS))
|
||||
return -E2BIG;
|
||||
|
||||
if (codec->vendor_id == 0x80862807)
|
||||
intel_haswell_fixup_connect_list(codec, pin_nid);
|
||||
|
||||
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->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)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int cvt_idx;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
unsigned int chans;
|
||||
int err;
|
||||
|
||||
if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS))
|
||||
return -E2BIG;
|
||||
|
||||
chans = get_wcaps(codec, cvt_nid);
|
||||
chans = get_wcaps_channels(chans);
|
||||
|
||||
cvt_idx = spec->num_cvts;
|
||||
per_cvt = &spec->cvts[cvt_idx];
|
||||
per_cvt = snd_array_new(&spec->cvts);
|
||||
if (!per_cvt)
|
||||
return -ENOMEM;
|
||||
|
||||
per_cvt->cvt_nid = cvt_nid;
|
||||
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)
|
||||
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;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
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;
|
||||
|
||||
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);
|
||||
if (snd_BUG_ON(cvt_idx < 0))
|
||||
return -EINVAL;
|
||||
per_cvt = &spec->cvts[cvt_idx];
|
||||
per_cvt = get_cvt(spec, cvt_idx);
|
||||
|
||||
snd_BUG_ON(!per_cvt->assigned);
|
||||
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);
|
||||
if (snd_BUG_ON(pin_idx < 0))
|
||||
return -EINVAL;
|
||||
per_pin = &spec->pins[pin_idx];
|
||||
per_pin = get_pin(spec, pin_idx);
|
||||
|
||||
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
||||
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 hdmi_spec *spec = codec->spec;
|
||||
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;
|
||||
|
||||
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 hdmi_spec *spec = codec->spec;
|
||||
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;
|
||||
struct snd_pcm_substream *substream;
|
||||
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++) {
|
||||
struct hda_pcm *info;
|
||||
struct hda_pcm_stream *pstr;
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
|
||||
info = &spec->pcm_rec[pin_idx];
|
||||
info->name = get_hdmi_pcm_name(pin_idx);
|
||||
per_pin = get_pin(spec, 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->own_chmap = true;
|
||||
|
||||
@ -1626,7 +1658,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
codec->num_pcms = spec->num_pins;
|
||||
codec->pcm_info = spec->pcm_rec;
|
||||
codec->pcm_info = spec->pcm_rec.list;
|
||||
|
||||
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";
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
|
||||
int pcmdev = spec->pcm_rec[pin_idx].device;
|
||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||
int pcmdev = get_pcm_rec(spec, pin_idx)->device;
|
||||
|
||||
if (pcmdev > 0)
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/* add control for ELD Bytes */
|
||||
err = hdmi_create_eld_ctl(codec,
|
||||
pin_idx,
|
||||
spec->pcm_rec[pin_idx].device);
|
||||
err = hdmi_create_eld_ctl(codec, pin_idx,
|
||||
get_pcm_rec(spec, pin_idx)->device);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -1709,7 +1740,7 @@ static int generic_hdmi_init_per_pins(struct hda_codec *codec)
|
||||
int 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;
|
||||
|
||||
per_pin->codec = codec;
|
||||
@ -1726,7 +1757,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
||||
int 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;
|
||||
|
||||
hdmi_init_pin(codec, pin_nid);
|
||||
@ -1735,13 +1766,27 @@ static int generic_hdmi_init(struct hda_codec *codec)
|
||||
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)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int 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;
|
||||
|
||||
cancel_delayed_work(&per_pin->work);
|
||||
@ -1749,6 +1794,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
flush_workqueue(codec->bus->workq);
|
||||
hdmi_array_free(spec);
|
||||
kfree(spec);
|
||||
}
|
||||
|
||||
@ -1775,6 +1821,7 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
||||
|
||||
/* override pins connection list */
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1855,6 +1902,7 @@ static int patch_generic_hdmi(struct hda_codec *codec)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->spec = spec;
|
||||
hdmi_array_init(spec, 4);
|
||||
|
||||
snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups);
|
||||
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)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hda_pcm *info = spec->pcm_rec;
|
||||
struct hda_pcm *info;
|
||||
unsigned int chans;
|
||||
struct hda_pcm_stream *pstr;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
|
||||
codec->num_pcms = 1;
|
||||
codec->pcm_info = info;
|
||||
|
||||
chans = get_wcaps(codec, spec->cvts[0].cvt_nid);
|
||||
per_cvt = get_cvt(spec, 0);
|
||||
chans = get_wcaps(codec, per_cvt->cvt_nid);
|
||||
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;
|
||||
pstr = &info->stream[SNDRV_PCM_STREAM_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)
|
||||
pstr->channels_max = chans;
|
||||
|
||||
codec->num_pcms = 1;
|
||||
codec->pcm_info = info;
|
||||
|
||||
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)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
int err;
|
||||
|
||||
err = snd_hda_create_spdif_out_ctls(codec,
|
||||
spec->cvts[0].cvt_nid,
|
||||
spec->cvts[0].cvt_nid);
|
||||
per_cvt = get_cvt(spec, 0);
|
||||
err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
|
||||
per_cvt->cvt_nid);
|
||||
if (err < 0)
|
||||
return err;
|
||||
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)
|
||||
{
|
||||
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,
|
||||
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;
|
||||
|
||||
hdmi_array_free(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)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->spec = spec;
|
||||
hdmi_array_init(spec, 1);
|
||||
|
||||
spec->multiout.num_dacs = 0; /* no analog */
|
||||
spec->multiout.max_channels = 2;
|
||||
spec->multiout.dig_out_nid = cvt_nid;
|
||||
spec->num_cvts = 1;
|
||||
spec->num_pins = 1;
|
||||
spec->cvts[0].cvt_nid = cvt_nid;
|
||||
spec->pins[0].pin_nid = pin_nid;
|
||||
per_pin = snd_array_new(&spec->pins);
|
||||
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;
|
||||
|
||||
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;
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hda_spdif_out *spdif;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
|
||||
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;
|
||||
|
||||
@ -2325,13 +2393,17 @@ static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
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;
|
||||
}
|
||||
|
||||
static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hda_pcm *info;
|
||||
struct snd_pcm_chmap *chmap;
|
||||
int err;
|
||||
|
||||
@ -2340,7 +2412,8 @@ static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
||||
return err;
|
||||
|
||||
/* 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,
|
||||
snd_pcm_alt_chmaps, 8, 0, &chmap);
|
||||
if (err < 0)
|
||||
@ -2395,6 +2468,7 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0);
|
||||
int chans = substream->runtime->channels;
|
||||
int i, err;
|
||||
|
||||
@ -2402,11 +2476,11 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
substream);
|
||||
if (err < 0)
|
||||
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);
|
||||
/* FIXME: XXX */
|
||||
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,
|
||||
(i << 4) | i);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -211,7 +211,6 @@ struct sigmatel_spec {
|
||||
|
||||
/* beep widgets */
|
||||
hda_nid_t anabeep_nid;
|
||||
hda_nid_t digbeep_nid;
|
||||
|
||||
/* SPDIF-out mux */
|
||||
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;
|
||||
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)
|
||||
return err;
|
||||
|
||||
@ -3560,14 +3563,11 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||
|
||||
/* setup digital beep controls and input device */
|
||||
#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
||||
if (spec->digbeep_nid > 0) {
|
||||
hda_nid_t nid = spec->digbeep_nid;
|
||||
if (spec->gen.beep_nid) {
|
||||
hda_nid_t nid = spec->gen.beep_nid;
|
||||
unsigned int caps;
|
||||
|
||||
err = stac_auto_create_beep_ctls(codec, nid);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_hda_attach_beep_device(codec, nid);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (codec->beep) {
|
||||
@ -3657,17 +3657,7 @@ static void stac_shutup(struct hda_codec *codec)
|
||||
~spec->eapd_mask);
|
||||
}
|
||||
|
||||
static void stac_free(struct hda_codec *codec)
|
||||
{
|
||||
struct sigmatel_spec *spec = codec->spec;
|
||||
|
||||
if (!spec)
|
||||
return;
|
||||
|
||||
snd_hda_gen_spec_free(&spec->gen);
|
||||
kfree(spec);
|
||||
snd_hda_detach_beep_device(codec);
|
||||
}
|
||||
#define stac_free snd_hda_gen_free
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
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;
|
||||
|
||||
codec->patch_ops = stac_patch_ops;
|
||||
codec->power_filter = snd_hda_codec_eapd_power_filter;
|
||||
|
||||
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_shift = 8;
|
||||
|
||||
spec->digbeep_nid = 0x1c;
|
||||
spec->gen.beep_nid = 0x1c; /* digital beep */
|
||||
|
||||
/* GPIO0 High = Enable EAPD */
|
||||
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.mixer_nid = 0x1b;
|
||||
|
||||
spec->digbeep_nid = 0x21;
|
||||
spec->gen.beep_nid = 0x21; /* digital beep */
|
||||
spec->pwr_nids = stac92hd83xxx_pwr_nids;
|
||||
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
|
||||
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.power_down_unused = 1;
|
||||
|
||||
spec->digbeep_nid = 0x19;
|
||||
spec->gen.beep_nid = 0x19; /* digital beep */
|
||||
spec->pwr_nids = stac92hd95_pwr_nids;
|
||||
spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids);
|
||||
spec->default_polarity = -1; /* no default cfg */
|
||||
@ -4091,7 +4082,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
|
||||
spec->aloopback_shift = 0;
|
||||
|
||||
spec->powerdown_adcs = 1;
|
||||
spec->digbeep_nid = 0x26;
|
||||
spec->gen.beep_nid = 0x26; /* digital beep */
|
||||
spec->num_pwrs = ARRAY_SIZE(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->spdif_labels = stac927x_spdif_labels;
|
||||
|
||||
spec->digbeep_nid = 0x23;
|
||||
spec->gen.beep_nid = 0x23; /* digital beep */
|
||||
|
||||
/* GPIO0 High = Enable EAPD */
|
||||
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->have_spdif_mux = 1;
|
||||
|
||||
spec->digbeep_nid = 0x23;
|
||||
spec->gen.beep_nid = 0x23; /* digital beep */
|
||||
|
||||
snd_hda_add_verbs(codec, stac9205_core_init);
|
||||
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)
|
||||
{
|
||||
struct via_spec *spec = codec->spec;
|
||||
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);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -969,6 +969,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card,
|
||||
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_autosync_ref(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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
||||
{
|
||||
@ -1216,21 +1231,44 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
|
||||
break;
|
||||
}
|
||||
|
||||
/* QS and DS rates normally can not be detected
|
||||
* automatically by the card. Only exception is MADI
|
||||
* in 96k frame mode.
|
||||
*
|
||||
* So if we read SS values (32 .. 48k), check for
|
||||
* user-provided DS/QS bits in the control register
|
||||
* and multiply the base frequency accordingly.
|
||||
*/
|
||||
if (rate <= 48000) {
|
||||
if (hdspm->control_register & HDSPM_QuadSpeed)
|
||||
rate *= 4;
|
||||
else if (hdspm->control_register &
|
||||
HDSPM_DoubleSpeed)
|
||||
rate *= 2;
|
||||
} /* 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
|
||||
* automatically by the card. Only exception is MADI
|
||||
* in 96k frame mode.
|
||||
*
|
||||
* So if we read SS values (32 .. 48k), check for
|
||||
* user-provided DS/QS bits in the control register
|
||||
* and multiply the base frequency accordingly.
|
||||
*/
|
||||
if (rate <= 48000) {
|
||||
if (hdspm->control_register & HDSPM_QuadSpeed)
|
||||
rate *= 4;
|
||||
else if (hdspm->control_register &
|
||||
HDSPM_DoubleSpeed)
|
||||
rate *= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1979,16 +2017,25 @@ static void hdspm_midi_tasklet(unsigned long arg)
|
||||
/* 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
|
||||
* current DDS value.
|
||||
**/
|
||||
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_calc_dds_value(hdspm, period);
|
||||
rate = hdspm_get_pll_freq(hdspm);
|
||||
|
||||
if (rate > 207000) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#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) \
|
||||
@ -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,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
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]);
|
||||
ENUMERATED_CTL_INFO(uinfo, texts_freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2316,15 +2366,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "Master", "AutoSync" };
|
||||
|
||||
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]);
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2888,6 +2930,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
|
||||
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) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||
.name = xname, \
|
||||
@ -2974,17 +3122,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "optical", "coaxial" };
|
||||
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3046,17 +3184,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "Single", "Double" };
|
||||
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3129,17 +3257,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "Single", "Double", "Quad" };
|
||||
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3215,17 +3333,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "Single", "Double", "Quad" };
|
||||
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3445,19 +3553,30 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
|
||||
.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,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.enumerated.items = 4;
|
||||
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]);
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "No Lock", "Lock" };
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3590,6 +3709,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
val = 3;
|
||||
|
||||
@ -3813,17 +3956,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "44.1 kHz", "48 kHz" };
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3869,17 +4002,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3924,17 +4047,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
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",
|
||||
"29.97 dfps", "30 fps", "30 dfps" };
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4037,17 +4140,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
static char *texts[] = { "LTC", "Video", "WCK" };
|
||||
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]);
|
||||
|
||||
ENUMERATED_CTL_INFO(uinfo, texts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4145,6 +4238,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
|
||||
HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
|
||||
HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
|
||||
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("Safe Mode", HDSPM_AutoInp),
|
||||
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_FRAME_RATE("TCO Frame Rate", 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
|
||||
bool
|
||||
|
||||
config SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
bool
|
||||
select SND_SOC_DMAENGINE_PCM
|
||||
|
||||
# All the supported SoCs
|
||||
source "sound/soc/atmel/Kconfig"
|
||||
source "sound/soc/au1x/Kconfig"
|
||||
|
@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
|
||||
snd-soc-core-objs += soc-dmaengine-pcm.o
|
||||
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) += codecs/
|
||||
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,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
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 (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,
|
||||
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 dma_chan *dma_chan;
|
||||
struct dma_slave_config slave_config;
|
||||
int ret;
|
||||
|
||||
prtd = snd_dmaengine_pcm_get_data(substream);
|
||||
ssc = prtd->ssc;
|
||||
|
||||
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.device_fc = false;
|
||||
|
||||
dma_chan = snd_dmaengine_pcm_get_chan(substream);
|
||||
if (dmaengine_slave_config(dma_chan, &slave_config)) {
|
||||
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)
|
||||
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) {
|
||||
pr_err("atmel-pcm: dmaengine pcm open failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_dmaengine_pcm_set_data(substream, prtd);
|
||||
|
||||
ret = atmel_pcm_configure_dma(substream, params);
|
||||
ret = atmel_pcm_configure_dma(substream, params, prtd);
|
||||
if (ret) {
|
||||
pr_err("atmel-pcm: failed to configure dmai\n");
|
||||
goto err;
|
||||
@ -176,15 +171,16 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
return 0;
|
||||
err:
|
||||
snd_dmaengine_pcm_close(substream);
|
||||
snd_dmaengine_pcm_close_release_chan(substream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_CR, prtd->mask->ssc_enable);
|
||||
@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
|
||||
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 = {
|
||||
.open = atmel_pcm_open,
|
||||
.close = atmel_pcm_close,
|
||||
.close = snd_dmaengine_pcm_close_release_chan,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = atmel_pcm_hw_params,
|
||||
.prepare = atmel_pcm_dma_prepare,
|
||||
|
@ -533,6 +533,49 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
|
||||
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:
|
||||
printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
|
||||
ssc_p->daifmt);
|
||||
@ -707,13 +750,18 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
|
||||
.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)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct ssc_device *ssc = platform_get_drvdata(pdev);
|
||||
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) {
|
||||
dev_err(dev, "Could not register DAI: %d\n", ret);
|
||||
goto err;
|
||||
@ -732,7 +780,7 @@ static int asoc_ssc_init(struct device *dev)
|
||||
return 0;
|
||||
|
||||
err_unregister_dai:
|
||||
snd_soc_unregister_dai(dev);
|
||||
snd_soc_unregister_component(dev);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -747,7 +795,7 @@ static void asoc_ssc_exit(struct device *dev)
|
||||
else
|
||||
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,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver au1xac97c_component = {
|
||||
.name = "au1xac97c",
|
||||
};
|
||||
|
||||
static int au1xac97c_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
@ -268,7 +272,8 @@ static int au1xac97c_drvprobe(struct platform_device *pdev)
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
@ -280,7 +285,7 @@ static int au1xac97c_drvremove(struct platform_device *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 */
|
||||
|
||||
|
@ -225,6 +225,10 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
|
||||
.ops = &au1xi2s_dai_ops,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver au1xi2s_component = {
|
||||
.name = "au1xi2s",
|
||||
};
|
||||
|
||||
static int au1xi2s_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *iores, *dmares;
|
||||
@ -260,14 +264,15 @@ static int au1xi2s_drvprobe(struct platform_device *pdev)
|
||||
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
|
||||
|
@ -361,6 +361,10 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
|
||||
.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)
|
||||
{
|
||||
int ret;
|
||||
@ -419,7 +423,8 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
@ -431,7 +436,7 @@ static int au1xpsc_ac97_drvremove(struct platform_device *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 */
|
||||
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,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver au1xpsc_i2s_component = {
|
||||
.name = "au1xpsc-i2s",
|
||||
};
|
||||
|
||||
static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *iores, *dmares;
|
||||
@ -350,14 +354,15 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
|
||||
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)
|
||||
{
|
||||
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_sync();
|
||||
|
@ -282,6 +282,10 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
|
||||
.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)
|
||||
{
|
||||
struct sport_device *sport_handle;
|
||||
@ -331,7 +335,8 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
|
||||
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) {
|
||||
pr_err("Failed to register DAI: %d\n", ret);
|
||||
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);
|
||||
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
sport_done(sport_handle);
|
||||
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
|
||||
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,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver bf5xx_i2s_component = {
|
||||
.name = "bf5xx-i2s",
|
||||
};
|
||||
|
||||
static int bf5xx_i2s_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sport_device *sport_handle;
|
||||
@ -257,7 +261,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
|
||||
/* 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) {
|
||||
pr_err("Failed to register DAI: %d\n", ret);
|
||||
sport_done(sport_handle);
|
||||
@ -273,7 +278,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
sport_done(sport_handle);
|
||||
|
||||
return 0;
|
||||
|
@ -249,6 +249,10 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
|
||||
.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)
|
||||
{
|
||||
struct sport_device *sport_handle;
|
||||
@ -282,7 +286,8 @@ static int bfin_tdm_probe(struct platform_device *pdev)
|
||||
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) {
|
||||
pr_err("Failed to register DAI: %d\n", ret);
|
||||
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);
|
||||
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
sport_done(sport_handle);
|
||||
|
||||
return 0;
|
||||
|
@ -186,6 +186,10 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
|
||||
.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)
|
||||
{
|
||||
struct sport_device *sport;
|
||||
@ -197,7 +201,8 @@ static int bfin_i2s_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
|
||||
/* 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) {
|
||||
dev_err(dev, "Failed to register DAI: %d\n", ret);
|
||||
sport_delete(sport);
|
||||
@ -212,7 +217,7 @@ static int bfin_i2s_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sport_device *sport = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
sport_delete(sport);
|
||||
|
||||
return 0;
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <sound/soc.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
static int edb93xx_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
/*
|
||||
* Per channel (1-4) registers.
|
||||
@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
|
||||
/* currently ALSA only supports a single AC97 device */
|
||||
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",
|
||||
.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",
|
||||
.dma_port = EP93XX_DMA_AAC1,
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
};
|
||||
|
||||
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,
|
||||
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)
|
||||
dma_data = &ep93xx_ac97_pcm_out;
|
||||
@ -353,6 +354,10 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
|
||||
.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)
|
||||
{
|
||||
struct ep93xx_ac97_info *info;
|
||||
@ -390,7 +395,8 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
|
||||
ep93xx_ac97_info = 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)
|
||||
goto fail;
|
||||
|
||||
@ -407,7 +413,7 @@ static int ep93xx_ac97_remove(struct platform_device *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 */
|
||||
ep93xx_ac97_write_reg(info, AC97GCR, 0);
|
||||
|
@ -30,8 +30,6 @@
|
||||
#include <mach/ep93xx-regs.h>
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
#define EP93XX_I2S_TXCLKCFG 0x00
|
||||
#define EP93XX_I2S_RXCLKCFG 0x04
|
||||
#define EP93XX_I2S_GLCTRL 0x0C
|
||||
@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
|
||||
struct clk *mclk;
|
||||
struct clk *sclk;
|
||||
struct clk *lrclk;
|
||||
struct ep93xx_pcm_dma_params *dma_params;
|
||||
struct ep93xx_dma_data *dma_data;
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
|
||||
struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
|
||||
[SNDRV_PCM_STREAM_PLAYBACK] = {
|
||||
.name = "i2s-pcm-out",
|
||||
.dma_port = EP93XX_DMA_I2S1,
|
||||
.port = EP93XX_DMA_I2S1,
|
||||
.direction = DMA_MEM_TO_DEV,
|
||||
},
|
||||
[SNDRV_PCM_STREAM_CAPTURE] = {
|
||||
.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;
|
||||
|
||||
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
||||
&info->dma_params[substream->stream]);
|
||||
&info->dma_data[substream->stream]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -366,6 +366,10 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
|
||||
.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)
|
||||
{
|
||||
struct ep93xx_i2s_info *info;
|
||||
@ -403,9 +407,10 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
clk_put(info->lrclk);
|
||||
clk_put(info->sclk);
|
||||
|
@ -29,8 +29,6 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/ep93xx-regs.h>
|
||||
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
|
||||
.info = (SNDRV_PCM_INFO_MMAP |
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
|
||||
if (!dma_data)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
return snd_dmaengine_pcm_open_request_chan(substream,
|
||||
ep93xx_pcm_dma_filter,
|
||||
snd_soc_dai_get_dma_data(rtd->cpu_dai, 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 = {
|
||||
.open = ep93xx_pcm_open,
|
||||
.close = ep93xx_pcm_close,
|
||||
.close = snd_dmaengine_pcm_close_release_chan,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = ep93xx_pcm_hw_params,
|
||||
.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 <mach/hardware.h>
|
||||
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
static struct snd_soc_dai_link simone_dai = {
|
||||
.name = "AC97",
|
||||
.stream_name = "AC97 HiFi",
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "../codecs/tlv320aic23.h"
|
||||
#include "ep93xx-pcm.h"
|
||||
|
||||
#define CODEC_CLOCK 5644800
|
||||
|
||||
|
@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_AK4641 if I2C
|
||||
select SND_SOC_AK4642 if I2C
|
||||
select SND_SOC_AK4671 if I2C
|
||||
select SND_SOC_AK5386
|
||||
select SND_SOC_ALC5623 if I2C
|
||||
select SND_SOC_ALC5632 if I2C
|
||||
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_STA529 if I2C
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TAS5086 if I2C
|
||||
select SND_SOC_TLV320AIC23 if I2C
|
||||
select SND_SOC_TLV320AIC26 if SPI_MASTER
|
||||
select SND_SOC_TLV320AIC32X4 if I2C
|
||||
@ -203,6 +205,9 @@ config SND_SOC_AK4642
|
||||
config SND_SOC_AK4671
|
||||
tristate
|
||||
|
||||
config SND_SOC_AK5386
|
||||
tristate
|
||||
|
||||
config SND_SOC_ALC5623
|
||||
tristate
|
||||
config SND_SOC_ALC5632
|
||||
@ -320,11 +325,14 @@ config SND_SOC_STA529
|
||||
config SND_SOC_STAC9766
|
||||
tristate
|
||||
|
||||
config SND_SOC_TAS5086
|
||||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC23
|
||||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC26
|
||||
tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
|
||||
tristate
|
||||
depends on SPI
|
||||
|
||||
config SND_SOC_TLV320AIC32X4
|
||||
|
@ -14,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
|
||||
snd-soc-ak4641-objs := ak4641.o
|
||||
snd-soc-ak4642-objs := ak4642.o
|
||||
snd-soc-ak4671-objs := ak4671.o
|
||||
snd-soc-ak5386-objs := ak5386.o
|
||||
snd-soc-arizona-objs := arizona.o
|
||||
snd-soc-cq93vc-objs := cq93vc.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-sta529-objs := sta529.o
|
||||
snd-soc-stac9766-objs := stac9766.o
|
||||
snd-soc-tas5086-objs := tas5086.o
|
||||
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
||||
snd-soc-tlv320aic26-objs := tlv320aic26.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_AK4642) += snd-soc-ak4642.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_ALC5632) += snd-soc-alc5632.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_STA529) += snd-soc-sta529.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_TLV320AIC26) += snd-soc-tlv320aic26.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||
|
@ -133,6 +133,8 @@ struct adau1373 {
|
||||
#define ADAU1373_DAI_FORMAT_DSP 0x3
|
||||
|
||||
#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_64 0x02
|
||||
#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);
|
||||
|
||||
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)) {
|
||||
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)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
|
||||
int val = 0;
|
||||
int ret;
|
||||
|
||||
@ -77,9 +78,9 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
|
||||
val);
|
||||
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
|
||||
val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -91,11 +92,12 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
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 */
|
||||
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;
|
||||
|
||||
@ -132,11 +134,33 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
||||
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 = {
|
||||
.hw_params = ak4104_hw_params,
|
||||
.hw_free = ak4104_hw_free,
|
||||
.set_fmt = ak4104_set_dai_fmt,
|
||||
};
|
||||
|
||||
@ -160,20 +184,17 @@ static int ak4104_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
|
||||
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 */
|
||||
ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
|
||||
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* enable transmitter */
|
||||
ret = snd_soc_update_bits(codec, AK4104_REG_TX,
|
||||
AK4104_TX_TXE, AK4104_TX_TXE);
|
||||
ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
|
||||
AK4104_TX_TXE, AK4104_TX_TXE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -182,8 +203,10 @@ static int ak4104_probe(struct snd_soc_codec *codec)
|
||||
|
||||
static int ak4104_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
|
||||
AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
|
||||
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);
|
||||
|
||||
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