提交 2e341ca6 编写于 作者: L Linus Torvalds

Merge tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
 "This is the first big chunk for 3.5 merges of sound stuff.

  There are a few big changes in different areas.  First off, the
  streaming logic of USB-audio endpoints has been largely rewritten for
  the better support of "implicit feedback".  If anything about USB got
  broken, this change has to be checked.

  For HD-audio, the resume procedure was changed; instead of delaying
  the resume of the hardware until the first use, now waking up
  immediately at resume.  This is for buggy BIOS.

  For ASoC, dynamic PCM support and the improved support for digital
  links between off-SoC devices are major framework changes.

  Some highlights are below:

  * HD-audio
   - Avoid accesses of invalid pin-control bits that may stall the codec
   - V-ref setup cleanups
   - Fix the races in power-saving code
   - Fix the races in codec cache hashes and connection lists
   - Split some common codes for BIOS auto-parser to hda_auto_parser.c
   - Changed the PM resume code to wake up immediately for buggy BIOS
   - Creative SoundCore3D support
   - Add Conexant CX20751/2/3/4 codec support

  * ASoC
   - Dynamic PCM support, allowing support for SoCs with internal
     routing through components with tight sequencing and formatting
     constraints within their internal paths or where there are multiple
     components connected with CPU managed DMA controllers inside the
     SoC.
   - Greatly improved support for direct digital links between off-SoC
     devices, providing a much simpler way of connecting things like
     digital basebands to CODECs.
   - Much more fine grained and robust locking, cleaning up some of the
     confusion that crept in with multi-component.
   - CPU support for nVidia Tegra 30 I2S and audio hub controllers and
     ST-Ericsson MSP I2S controolers
   - New CODEC drivers for Cirrus CS42L52, LAPIS Semiconductor ML26124,
     Texas Instruments LM49453.
   - Some regmap changes needed by the Tegra I2S driver.
   - mc13783 audio support.

  * Misc
   - Rewrite with module_pci_driver()
   - Xonar DGX support for snd-oxygen
   - Improvement of packet handling in snd-firewire driver
   - New USB-endpoint streaming logic
   - Enhanced M-audio FTU quirks and relevant cleanups
   - Increment the support of OSS devices to 256
   - snd-aloop accuracy improvement

  There are a few more pending changes for 3.5, but they will be sent
  slightly later as partly depending on the changes of DRM."

Fix up conflicts in regmap (due to duplicate patches, with some further
updates then having already come in from the regmap tree).  Also some
fairly trivial context conflicts in the imx and mcx soc drivers.

* tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (280 commits)
  ALSA: snd-usb: fix stream info output in /proc
  ALSA: pcm - Add proper state checks to snd_pcm_drain()
  ALSA: sh: Fix up namespace collision in sh_dac_audio.
  ALSA: hda/realtek - Fix unused variable compile warning
  ASoC: sh: fsi: enable chip specific data transfer mode
  ASoC: sh: fsi: call fsi_hw_startup/shutdown from fsi_dai_trigger()
  ASoC: sh: fsi: use same format for IN/OUT
  ASoC: sh: fsi: add fsi_version() and removed meaningless version check
  ASoC: sh: fsi: use register field macro name on IN/OUT_DMAC
  ASoC: tegra: Add machine driver for WM8753 codec
  ALSA: hda - Fix possible races of accesses to connection list array
  ASoC: OMAP: HDMI: Introduce codec
  ARM: mx31_3ds: Add sound support
  ASoC: imx-mc13783 cleanup
  mx31moboard: Add sound support
  ASoC: mc13783 codec cleanups
  ASoC: add imx-mc13783 sound support
  ASoC: Add mc13783 codec
  mfd: mc13xxx: add codec platform data
  ASoC: don't flip master of DT-instantiated DAI links
  ...
无相关合并请求
Freescale i.MX audio complex with SGTL5000 codec
Required properties:
- compatible : "fsl,imx-audio-sgtl5000"
- model : The user-visible name of this sound complex
- ssi-controller : The phandle of the i.MX SSI controller
- audio-codec : The phandle of the SGTL5000 audio codec
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names could be power
supplies, SGTL5000 pins, and the jacks on the board:
Power supplies:
* Mic Bias
SGTL5000 pins:
* MIC_IN
* LINE_IN
* HP_OUT
* LINE_OUT
Board connectors:
* Mic Jack
* Line In Jack
* Headphone Jack
* Line Out Jack
* Ext Spk
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
- mux-ext-port : The external port of the i.MX audio muxer
Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.
Example:
sound {
compatible = "fsl,imx51-babbage-sgtl5000",
"fsl,imx-audio-sgtl5000";
model = "imx51-babbage-sgtl5000";
ssi-controller = <&ssi1>;
audio-codec = <&sgtl5000>;
audio-routing =
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
mux-int-port = <1>;
mux-ext-port = <3>;
};
* Freescale MXS audio complex with SGTL5000 codec
Required properties:
- compatible: "fsl,mxs-audio-sgtl5000"
- model: The user-visible name of this sound complex
- saif-controllers: The phandle list of the MXS SAIF controller
- audio-codec: The phandle of the SGTL5000 audio codec
Example:
sound {
compatible = "fsl,imx28-evk-sgtl5000",
"fsl,mxs-audio-sgtl5000";
model = "imx28-evk-sgtl5000";
saif-controllers = <&saif0 &saif1>;
audio-codec = <&sgtl5000>;
};
* Freescale MXS Serial Audio Interface (SAIF)
Required properties:
- compatible: Should be "fsl,<chip>-saif"
- reg: Should contain registers location and length
- interrupts: Should contain ERROR and DMA interrupts
- fsl,saif-dma-channel: APBX DMA channel for the SAIF
Optional properties:
- fsl,saif-master: phandle to the master SAIF. It's only required for
the slave SAIF.
Note: Each SAIF controller should have an alias correctly numbered
in "aliases" node.
Example:
aliases {
saif0 = &saif0;
saif1 = &saif1;
};
saif0: saif@80042000 {
compatible = "fsl,imx28-saif";
reg = <0x80042000 2000>;
interrupts = <59 80>;
fsl,saif-dma-channel = <4>;
};
saif1: saif@80046000 {
compatible = "fsl,imx28-saif";
reg = <0x80046000 2000>;
interrupts = <58 81>;
fsl,saif-dma-channel = <5>;
fsl,saif-master = <&saif0>;
};
NVIDIA Tegra30 AHUB (Audio Hub)
Required properties:
- compatible : "nvidia,tegra30-ahub"
- reg : Should contain the register physical address and length for each of
the AHUB's APBIF registers and the AHUB's own registers.
- interrupts : Should contain AHUB interrupt
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
request selector for the first APBIF channel.
- 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>;
- #size-cells : For the configlink bus. Should be <1>.
AHUB client modules need to specify the IDs of their CIFs (Client InterFaces).
For RX CIFs, the numbers indicate the register number within AHUB routing
register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1, SPDIF RX 0..1).
For TX CIFs, the numbers indicate the bit position within the AHUB routing
registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF TX 0..1).
Example:
ahub@70080000 {
compatible = "nvidia,tegra30-ahub";
reg = <0x70080000 0x200 0x70080200 0x100>;
interrupts = < 0 103 0x04 >;
nvidia,dma-request-selector = <&apbdma 1>;
ranges;
#address-cells = <1>;
#size-cells = <1>;
};
NVIDIA Tegra30 I2S controller
Required properties:
- compatible : "nvidia,tegra30-i2s"
- reg : Should contain I2S registers location and length
- nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback)
first, tx (capture) second. See nvidia,tegra30-ahub.txt for values.
Example:
i2s@70002800 {
compatible = "nvidia,tegra30-i2s";
reg = <0x70080300 0x100>;
nvidia,ahub-cif-ids = <4 4>;
};
NVIDIA Tegra audio complex for TrimSlice
Required properties:
- compatible : "nvidia,tegra-audio-trimslice"
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
- nvidia,audio-codec : The phandle of the WM8903 audio codec
Example:
sound {
compatible = "nvidia,tegra-audio-trimslice";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&codec>;
};
NVIDIA Tegra audio complex
Required properties:
- compatible : "nvidia,tegra-audio-wm8753"
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the WM8753's pins, and the jacks on the board:
WM8753 pins:
* LOUT1
* LOUT2
* ROUT1
* ROUT2
* MONO1
* MONO2
* OUT3
* OUT4
* LINE1
* LINE2
* RXP
* RXN
* ACIN
* ACOP
* MIC1N
* MIC1
* MIC2N
* MIC2
* Mic Bias
Board connectors:
* Headphone Jack
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
- nvidia,audio-codec : The phandle of the WM8753 audio codec
Example:
sound {
compatible = "nvidia,tegra-audio-wm8753-whistler",
"nvidia,tegra-audio-wm8753"
nvidia,model = "tegra-wm8753-harmony";
nvidia,audio-routing =
"Headphone Jack", "LOUT1",
"Headphone Jack", "ROUT1";
nvidia,i2s-controller = <&i2s1>;
nvidia,audio-codec = <&wm8753>;
};
......@@ -1545,7 +1545,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
* Asound A-8788
* Asus Xonar DG
* Asus Xonar DG/DGX
* AuzenTech X-Meridian
* AuzenTech X-Meridian 2G
* Bgears b-Enspirer
......
......@@ -6691,6 +6691,12 @@ F: drivers/misc/tifm*
F: drivers/mmc/host/tifm_sd.c
F: include/linux/tifm.h
TI LM49xxx FAMILY ASoC CODEC DRIVERS
M: M R Swami Reddy <mr.swami.reddy@ti.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: sound/soc/codecs/lm49453*
TI TWL4030 SERIES SOC CODEC DRIVER
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
......@@ -151,6 +151,7 @@ config MACH_MX25_3DS
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMXDI_RTC
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_FB
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_UART
......@@ -495,6 +496,7 @@ config MACH_MX31MOBOARD
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_IPU_CORE
select IMX_HAVE_PLATFORM_MXC_EHCI
......
......@@ -156,6 +156,11 @@ static int mx31_3ds_pins[] = {
MX31_PIN_CSI_VSYNC__CSI_VSYNC,
MX31_PIN_CSI_D5__GPIO3_5, /* CMOS PWDN */
IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
/* SSI */
MX31_PIN_STXD4__STXD4,
MX31_PIN_SRXD4__SRXD4,
MX31_PIN_SCK4__SCK4,
MX31_PIN_SFS4__SFS4,
};
/*
......@@ -488,12 +493,23 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
};
/* MC13783 */
static struct mc13xxx_codec_platform_data mx31_3ds_codec = {
.dac_ssi_port = MC13783_SSI1_PORT,
.adc_ssi_port = MC13783_SSI1_PORT,
};
static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
},
.flags = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
.codec = &mx31_3ds_codec,
.flags = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC | MC13XXX_USE_CODEC,
};
static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = {
.flags = IMX_SSI_DMA | IMX_SSI_NET,
};
/* SPI */
......@@ -741,6 +757,10 @@ static void __init mx31_3ds_init(void)
}
mx31_3ds_init_camera();
imx31_add_imx_ssi(0, &mx31_3ds_ssi_pdata);
imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
}
static void __init mx31_3ds_timer_init(void)
......
......@@ -47,6 +47,7 @@
#include <mach/hardware.h>
#include <mach/iomux-mx3.h>
#include <mach/ulpi.h>
#include <mach/ssi.h>
#include "devices-imx31.h"
......@@ -102,6 +103,9 @@ static unsigned int moboard_pins[] = {
MX31_PIN_CSPI3_MOSI__MOSI, MX31_PIN_CSPI3_MISO__MISO,
MX31_PIN_CSPI3_SCLK__SCLK, MX31_PIN_CSPI3_SPI_RDY__SPI_RDY,
MX31_PIN_CSPI2_SS1__CSPI3_SS1,
/* SSI */
MX31_PIN_STXD4__STXD4, MX31_PIN_SRXD4__SRXD4,
MX31_PIN_SCK4__SCK4, MX31_PIN_SFS4__SFS4,
};
static struct physmap_flash_data mx31moboard_flash_data = {
......@@ -276,6 +280,11 @@ static struct mc13xxx_buttons_platform_data moboard_buttons = {
.b1on_key = KEY_POWER,
};
static struct mc13xxx_codec_platform_data moboard_codec = {
.dac_ssi_port = MC13783_SSI1_PORT,
.adc_ssi_port = MC13783_SSI1_PORT,
};
static struct mc13xxx_platform_data moboard_pmic = {
.regulators = {
.regulators = moboard_regulators,
......@@ -283,7 +292,12 @@ static struct mc13xxx_platform_data moboard_pmic = {
},
.leds = &moboard_leds,
.buttons = &moboard_buttons,
.flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC,
.codec = &moboard_codec,
.flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC | MC13XXX_USE_CODEC,
};
static struct imx_ssi_platform_data moboard_ssi_pdata = {
.flags = IMX_SSI_DMA | IMX_SSI_NET,
};
static struct spi_board_info moboard_spi_board_info[] __initdata = {
......@@ -554,6 +568,10 @@ static void __init mx31moboard_init(void)
moboard_usbh2_init();
imx31_add_imx_ssi(0, &moboard_ssi_pdata);
imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
pm_power_off = mx31moboard_poweroff;
switch (mx31moboard_baseboard) {
......
......@@ -64,6 +64,7 @@ config MACH_AP4EVB
depends on ARCH_SH7372
select ARCH_REQUIRE_GPIOLIB
select SH_LCD_MIPI_DSI
select SND_SOC_AK4642 if SND_SIMPLE_CARD
choice
prompt "AP4EVB LCD panel selection"
......@@ -88,6 +89,7 @@ config MACH_MACKEREL
bool "mackerel board"
depends on ARCH_SH7372
select ARCH_REQUIRE_GPIOLIB
select SND_SOC_AK4642 if SND_SIMPLE_CARD
config MACH_KOTA2
bool "KOTA2 board"
......
......@@ -50,6 +50,7 @@
#include <media/soc_camera.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
#include <video/sh_mobile_hdmi.h>
#include <video/sh_mobile_lcdc.h>
......@@ -785,17 +786,25 @@ static struct platform_device fsi_device = {
},
};
static struct fsi_ak4642_info fsi2_ak4643_info = {
static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
.fmt = SND_SOC_DAIFMT_LEFT_J,
.codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
.cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
.sysclk = 11289600,
};
static struct asoc_simple_card_info fsi2_ak4643_info = {
.name = "AK4643",
.card = "FSI2A-AK4643",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0013",
.platform = "sh_fsi2",
.id = FSI_PORT_A,
.codec_dai = "ak4642-hifi",
.init = &fsi2_ak4643_init_info,
};
static struct platform_device fsi_ak4643_device = {
.name = "fsi-ak4642-audio",
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4643_info,
},
......@@ -900,8 +909,26 @@ static struct platform_device lcdc1_device = {
},
};
static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
.cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
};
static struct asoc_simple_card_info fsi2_hdmi_info = {
.name = "HDMI",
.card = "FSI2B-HDMI",
.cpu_dai = "fsib-dai",
.codec = "sh-mobile-hdmi",
.platform = "sh_fsi2",
.codec_dai = "sh_mobile_hdmi-hifi",
.init = &fsi2_hdmi_init_info,
};
static struct platform_device fsi_hdmi_device = {
.name = "sh_fsi2_b_hdmi",
.name = "asoc-simple-card",
.id = 1,
.dev = {
.platform_data = &fsi2_hdmi_info,
},
};
static struct gpio_led ap4evb_leds[] = {
......
......@@ -53,6 +53,7 @@
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
#include <mach/common.h>
#include <mach/irqs.h>
......@@ -502,8 +503,26 @@ static struct platform_device hdmi_lcdc_device = {
},
};
static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
.cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
};
static struct asoc_simple_card_info fsi2_hdmi_info = {
.name = "HDMI",
.card = "FSI2B-HDMI",
.cpu_dai = "fsib-dai",
.codec = "sh-mobile-hdmi",
.platform = "sh_fsi2",
.codec_dai = "sh_mobile_hdmi-hifi",
.init = &fsi2_hdmi_init_info,
};
static struct platform_device fsi_hdmi_device = {
.name = "sh_fsi2_b_hdmi",
.name = "asoc-simple-card",
.id = 1,
.dev = {
.platform_data = &fsi2_hdmi_info,
},
};
static void __init hdmi_init_pm_clock(void)
......@@ -945,17 +964,25 @@ static struct platform_device fsi_device = {
},
};
static struct fsi_ak4642_info fsi2_ak4643_info = {
static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
.fmt = SND_SOC_DAIFMT_LEFT_J,
.codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
.cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
.sysclk = 11289600,
};
static struct asoc_simple_card_info fsi2_ak4643_info = {
.name = "AK4643",
.card = "FSI2A-AK4643",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0013",
.platform = "sh_fsi2",
.id = FSI_PORT_A,
.codec_dai = "ak4642-hifi",
.init = &fsi2_ak4643_init_info,
};
static struct platform_device fsi_ak4643_device = {
.name = "fsi-ak4642-audio",
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4643_info,
},
......
......@@ -55,9 +55,9 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c-dvc", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra20-i2s.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra20-i2s.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra20-das", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
&tegra_ehci1_pdata),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
......
......@@ -124,7 +124,6 @@ static struct platform_device *harmony_devices[] __initdata = {
&tegra_ehci3_device,
&tegra_i2s_device1,
&tegra_das_device,
&tegra_pcm_device,
&harmony_audio_device,
};
......
......@@ -156,7 +156,6 @@ static struct platform_device *seaboard_devices[] __initdata = {
&seaboard_gpio_keys_device,
&tegra_i2s_device1,
&tegra_das_device,
&tegra_pcm_device,
&seaboard_audio_device,
};
......
......@@ -89,7 +89,6 @@ static struct platform_device *trimslice_devices[] __initdata = {
&tegra_sdhci_device4,
&tegra_i2s_device1,
&tegra_das_device,
&tegra_pcm_device,
&trimslice_audio_device,
};
......
......@@ -674,14 +674,14 @@ static struct resource i2s_resource2[] = {
};
struct platform_device tegra_i2s_device1 = {
.name = "tegra-i2s",
.name = "tegra20-i2s",
.id = 0,
.resource = i2s_resource1,
.num_resources = ARRAY_SIZE(i2s_resource1),
};
struct platform_device tegra_i2s_device2 = {
.name = "tegra-i2s",
.name = "tegra20-i2s",
.id = 1,
.resource = i2s_resource2,
.num_resources = ARRAY_SIZE(i2s_resource2),
......@@ -696,13 +696,8 @@ static struct resource tegra_das_resources[] = {
};
struct platform_device tegra_das_device = {
.name = "tegra-das",
.name = "tegra20-das",
.id = -1,
.num_resources = ARRAY_SIZE(tegra_das_resources),
.resource = tegra_das_resources,
};
struct platform_device tegra_pcm_device = {
.name = "tegra-pcm-audio",
.id = -1,
};
......@@ -52,6 +52,5 @@ extern struct platform_device tegra_pmu_device;
extern struct platform_device tegra_i2s_device1;
extern struct platform_device tegra_i2s_device2;
extern struct platform_device tegra_das_device;
extern struct platform_device tegra_pcm_device;
#endif
......@@ -2148,8 +2148,8 @@ static struct clk tegra_list_clks[] = {
PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 108000000, mux_pclk, 0),
PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0),
PERIPH_CLK("i2s1", "tegra-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("i2s2", "tegra-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("i2s1", "tegra20-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("i2s2", "tegra20-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71),
PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
......
......@@ -100,6 +100,7 @@ CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_SOC=y
CONFIG_SND_POWERPC_SOC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_EXT2_FS=y
......
......@@ -141,6 +141,7 @@ CONFIG_SND_INTEL8X0=y
# CONFIG_SND_PPC is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
CONFIG_SND_POWERPC_SOC=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
......
......@@ -143,6 +143,7 @@ CONFIG_SND_INTEL8X0=y
# CONFIG_SND_PPC is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
CONFIG_SND_POWERPC_SOC=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
......
......@@ -54,6 +54,7 @@ config SH_7724_SOLUTION_ENGINE
select SOLUTION_ENGINE
depends on CPU_SUBTYPE_SH7724
select ARCH_REQUIRE_GPIOLIB
select SND_SOC_AK4642 if SND_SIMPLE_CARD
help
Select 7724 SolutionEngine if configuring for a Hitachi SH7724
evaluation board.
......@@ -224,6 +225,7 @@ config SH_ECOVEC
bool "EcoVec"
depends on CPU_SUBTYPE_SH7724
select ARCH_REQUIRE_GPIOLIB
select SND_SOC_DA7210 if SND_SIMPLE_CARD
help
Renesas "R0P7724LC0011/21RL (EcoVec)" support.
......
......@@ -33,6 +33,7 @@
#include <linux/videodev2.h>
#include <video/sh_mobile_lcdc.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
#include <media/sh_mobile_ceu.h>
#include <media/soc_camera.h>
#include <media/tw9910.h>
......@@ -811,6 +812,30 @@ static struct platform_device fsi_device = {
},
};
static struct asoc_simple_dai_init_info fsi_da7210_init_info = {
.fmt = SND_SOC_DAIFMT_I2S,
.codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
.cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
};
static struct asoc_simple_card_info fsi_da7210_info = {
.name = "DA7210",
.card = "FSIB-DA7210",
.cpu_dai = "fsib-dai",
.codec = "da7210.0-001a",
.platform = "sh_fsi.0",
.codec_dai = "da7210-hifi",
.init = &fsi_da7210_init_info,
};
static struct platform_device fsi_da7210_device = {
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi_da7210_info,
},
};
/* IrDA */
static struct resource irda_resources[] = {
[0] = {
......@@ -947,6 +972,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
&camera_devices[1],
&camera_devices[2],
&fsi_device,
&fsi_da7210_device,
&irda_device,
&vou_device,
#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
......
......@@ -29,6 +29,7 @@
#include <video/sh_mobile_lcdc.h>
#include <media/sh_mobile_ceu.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
#include <asm/io.h>
#include <asm/heartbeat.h>
#include <asm/clock.h>
......@@ -305,17 +306,25 @@ static struct platform_device fsi_device = {
},
};
static struct fsi_ak4642_info fsi_ak4642_info = {
static struct asoc_simple_dai_init_info fsi2_ak4642_init_info = {
.fmt = SND_SOC_DAIFMT_LEFT_J,
.codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
.cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
.sysclk = 11289600,
};
static struct asoc_simple_card_info fsi_ak4642_info = {
.name = "AK4642",
.card = "FSIA-AK4642",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0012",
.platform = "sh_fsi.0",
.id = FSI_PORT_A,
.codec_dai = "ak4642-hifi",
.init = &fsi2_ak4642_init_info,
};
static struct platform_device fsi_ak4642_device = {
.name = "fsi-ak4642-audio",
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi_ak4642_info,
},
......
......@@ -813,7 +813,8 @@ static int mc13xxx_probe(struct spi_device *spi)
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
if (mc13xxx->flags & MC13XXX_USE_CODEC)
mc13xxx_add_subdevice(mc13xxx, "%s-codec");
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
pdata->codec, sizeof(*pdata->codec));
if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
......
......@@ -170,6 +170,16 @@ struct mc13xxx_ts_platform_data {
bool atox;
};
enum mc13783_ssi_port {
MC13783_SSI1_PORT,
MC13783_SSI2_PORT,
};
struct mc13xxx_codec_platform_data {
enum mc13783_ssi_port adc_ssi_port;
enum mc13783_ssi_port dac_ssi_port;
};
struct mc13xxx_platform_data {
#define MC13XXX_USE_TOUCHSCREEN (1 << 0)
#define MC13XXX_USE_CODEC (1 << 1)
......@@ -181,6 +191,7 @@ struct mc13xxx_platform_data {
struct mc13xxx_leds_platform_data *leds;
struct mc13xxx_buttons_platform_data *buttons;
struct mc13xxx_ts_platform_data touch;
struct mc13xxx_codec_platform_data *codec;
};
#define MC13XXX_ADC_MODE_TS 1
......
......@@ -68,6 +68,20 @@ struct snd_aes_iec958 {
unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
};
/****************************************************************************
* *
* CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
* *
****************************************************************************/
struct snd_cea_861_aud_if {
unsigned char db1_ct_cc; /* coding type and channel count */
unsigned char db2_sf_ss; /* sample frequency and size */
unsigned char db3; /* not used, all zeros */
unsigned char db4_ca; /* channel allocation code */
unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
};
/****************************************************************************
* *
* Section for driver hardware dependent interface - /dev/snd/hw? *
......
......@@ -170,6 +170,47 @@
#define IEC958_AES5_CON_CGMSA_COPYNOMORE (2<<0) /* condition not be used */
#define IEC958_AES5_CON_CGMSA_COPYNEVER (3<<0) /* no copying is permitted */
/****************************************************************************
* *
* CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
* *
****************************************************************************/
#define CEA861_AUDIO_INFOFRAME_DB1CC (7<<0) /* mask - channel count */
#define CEA861_AUDIO_INFOFRAME_DB1CT (0xf<<4) /* mask - coding type */
#define CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM (0<<4) /* refer to stream */
#define CEA861_AUDIO_INFOFRAME_DB1CT_IEC60958 (1<<4) /* IEC-60958 L-PCM */
#define CEA861_AUDIO_INFOFRAME_DB1CT_AC3 (2<<4) /* AC-3 */
#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG1 (3<<4) /* MPEG1 Layers 1 & 2 */
#define CEA861_AUDIO_INFOFRAME_DB1CT_MP3 (4<<4) /* MPEG1 Layer 3 */
#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG2_MULTICH (5<<4) /* MPEG2 Multichannel */
#define CEA861_AUDIO_INFOFRAME_DB1CT_AAC (6<<4) /* AAC */
#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS (7<<4) /* DTS */
#define CEA861_AUDIO_INFOFRAME_DB1CT_ATRAC (8<<4) /* ATRAC */
#define CEA861_AUDIO_INFOFRAME_DB1CT_ONEBIT (9<<4) /* One Bit Audio */
#define CEA861_AUDIO_INFOFRAME_DB1CT_DOLBY_DIG_PLUS (10<<4) /* Dolby Digital + */
#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS_HD (11<<4) /* DTS-HD */
#define CEA861_AUDIO_INFOFRAME_DB1CT_MAT (12<<4) /* MAT (MLP) */
#define CEA861_AUDIO_INFOFRAME_DB1CT_DST (13<<4) /* DST */
#define CEA861_AUDIO_INFOFRAME_DB1CT_WMA_PRO (14<<4) /* WMA Pro */
#define CEA861_AUDIO_INFOFRAME_DB2SF (7<<2) /* mask - sample frequency */
#define CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM (0<<2) /* refer to stream */
#define CEA861_AUDIO_INFOFRAME_DB2SF_32000 (1<<2) /* 32kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_44100 (2<<2) /* 44.1kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_48000 (3<<2) /* 48kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_88200 (4<<2) /* 88.2kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_96000 (5<<2) /* 96kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_176400 (6<<2) /* 176.4kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SF_192000 (7<<2) /* 192kHz */
#define CEA861_AUDIO_INFOFRAME_DB2SS (3<<0) /* mask - sample size */
#define CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM (0<<0) /* refer to stream */
#define CEA861_AUDIO_INFOFRAME_DB2SS_16BIT (1<<0) /* 16 bits */
#define CEA861_AUDIO_INFOFRAME_DB2SS_20BIT (2<<0) /* 20 bits */
#define CEA861_AUDIO_INFOFRAME_DB2SS_24BIT (3<<0) /* 24 bits */
#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH (1<<7) /* mask - inhibit downmixing */
#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PERMITTED (0<<7) /* stereo downmix permitted */
#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED (1<<7) /* stereo downmis prohibited */
#define CEA861_AUDIO_INFOFRAME_DB5_LSV (0xf<<3) /* mask - level-shift values */
/*****************************************************************************
* *
* MIDI v1.0 interface *
......
/*
* linux/sound/cs42l52.h -- Platform data for CS42L52
*
* Copyright (c) 2012 Cirrus Logic Inc.
*
* 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 __CS42L52_H
#define __CS42L52_H
struct cs42l52_platform_data {
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* MICA mode selection 0=Single 1=Differential */
unsigned int mica_cfg;
/* MICB mode selection 0=Single 1=Differential */
unsigned int micb_cfg;
/* MICA Select 0=MIC1A 1=MIC2A */
unsigned int mica_sel;
/* MICB Select 0=MIC2A 1=MIC2B */
unsigned int micb_sel;
/* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq;
};
#endif /* __CS42L52_H */
......@@ -49,6 +49,18 @@ struct max98095_pdata {
*/
unsigned int digmic_left_mode:1;
unsigned int digmic_right_mode:1;
/* Pin5 is the mechanical method of sensing jack insertion
* but it is something that might not be supported.
* 0 = PIN5 not supported
* 1 = PIN5 supported
*/
unsigned int jack_detect_pin5en:1;
/* Slew amount for jack detection. Calculated as 4 * (delay + 1).
* Default delay is 24 to get a time of 100ms.
*/
unsigned int jack_detect_delay;
};
#endif
......@@ -21,10 +21,11 @@
/*
* flags format
*
* 0x000000BA
* 0x00000CBA
*
* A: inversion
* B: format mode
* C: chip specific
*/
/* A: clock inversion */
......@@ -39,6 +40,9 @@
#define SH_FSI_FMT_DAI (0 << 4)
#define SH_FSI_FMT_SPDIF (1 << 4)
/* C: chip specific */
#define SH_FSI_OPTION_MASK 0x00000F00
#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */
/*
* set_rate return value
......@@ -84,16 +88,4 @@ struct sh_fsi_platform_info {
struct sh_fsi_port_info port_b;
};
/*
* for fsi-ak4642
*/
struct fsi_ak4642_info {
const char *name;
const char *card;
const char *cpu_dai;
const char *codec;
const char *platform;
int id;
};
#endif /* __SOUND_FSI_H */
/*
* ASoC simple sound card support
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* 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 __SIMPLE_CARD_H
#define __SIMPLE_CARD_H
#include <sound/soc.h>
struct asoc_simple_dai_init_info {
unsigned int fmt;
unsigned int cpu_daifmt;
unsigned int codec_daifmt;
unsigned int sysclk;
};
struct asoc_simple_card_info {
const char *name;
const char *card;
const char *cpu_dai;
const char *codec;
const char *platform;
const char *codec_dai;
struct asoc_simple_dai_init_info *init; /* for snd_link.init */
/* used in simple-card.c */
struct snd_soc_dai_link snd_link;
struct snd_soc_card snd_card;
};
#endif /* __SIMPLE_CARD_H */
......@@ -173,6 +173,8 @@ struct snd_soc_dai_ops {
struct snd_soc_dai *);
int (*trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *);
int (*bespoke_trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *);
/*
* For hardware based FIFO caused delay reporting.
* Optional.
......@@ -196,6 +198,7 @@ struct snd_soc_dai_driver {
const char *name;
unsigned int id;
int ac97_control;
unsigned int base;
/* DAI driver callbacks */
int (*probe)(struct snd_soc_dai *dai);
......@@ -241,6 +244,7 @@ struct snd_soc_dai {
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
struct snd_soc_dapm_context dapm;
/* DAI DMA data */
void *playback_dma_data;
......
......@@ -141,10 +141,6 @@ struct device;
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, \
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
......@@ -324,6 +320,8 @@ struct snd_soc_dapm_path;
struct snd_soc_dapm_pin;
struct snd_soc_dapm_route;
struct snd_soc_dapm_context;
struct regulator;
struct snd_soc_dapm_widget_list;
int dapm_reg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
......@@ -359,6 +357,10 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
struct snd_soc_dai *dai);
int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
......@@ -369,8 +371,8 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);
/* dapm events */
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
struct snd_soc_dai *dai, int event);
void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
int event);
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
/* external DAPM widget events */
......@@ -402,6 +404,10 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
/* Mostly internal - should not normally be used */
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
/* dapm path query */
int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
struct snd_soc_dapm_widget_list **list);
/* dapm widget types */
enum snd_soc_dapm_type {
snd_soc_dapm_input = 0, /* input pin */
......@@ -430,6 +436,12 @@ enum snd_soc_dapm_type {
snd_soc_dapm_aif_out, /* audio interface output */
snd_soc_dapm_siggen, /* signal generator */
snd_soc_dapm_dai, /* link to DAI structure */
snd_soc_dapm_dai_link, /* link between two DAI structures */
};
enum snd_soc_dapm_subclass {
SND_SOC_DAPM_CLASS_INIT = 0,
SND_SOC_DAPM_CLASS_RUNTIME = 1,
};
/*
......@@ -482,9 +494,11 @@ struct snd_soc_dapm_widget {
struct snd_soc_dapm_context *dapm;
void *priv; /* widget specific data */
struct regulator *regulator; /* attached regulator */
const struct snd_soc_pcm_stream *params; /* params for dai links */
/* dapm control */
short reg; /* negative reg = no direct dapm */
int reg; /* negative reg = no direct dapm */
unsigned char shift; /* bits to shift */
unsigned int saved_value; /* widget saved value */
unsigned int value; /* widget current value */
......
/*
* linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
*
* Author: Liam Girdwood <lrg@ti.com>
*
* 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 __LINUX_SND_SOC_DPCM_H
#define __LINUX_SND_SOC_DPCM_H
#include <linux/list.h>
#include <sound/pcm.h>
struct snd_soc_pcm_runtime;
/*
* Types of runtime_update to perform. e.g. originated from FE PCM ops
* or audio route changes triggered by muxes/mixers.
*/
enum snd_soc_dpcm_update {
SND_SOC_DPCM_UPDATE_NO = 0,
SND_SOC_DPCM_UPDATE_BE,
SND_SOC_DPCM_UPDATE_FE,
};
/*
* Dynamic PCM Frontend -> Backend link management states.
*/
enum snd_soc_dpcm_link_state {
SND_SOC_DPCM_LINK_STATE_NEW = 0, /* newly created link */
SND_SOC_DPCM_LINK_STATE_FREE, /* link to be dismantled */
};
/*
* Dynamic PCM Frontend -> Backend link PCM states.
*/
enum snd_soc_dpcm_state {
SND_SOC_DPCM_STATE_NEW = 0,
SND_SOC_DPCM_STATE_OPEN,
SND_SOC_DPCM_STATE_HW_PARAMS,
SND_SOC_DPCM_STATE_PREPARE,
SND_SOC_DPCM_STATE_START,
SND_SOC_DPCM_STATE_STOP,
SND_SOC_DPCM_STATE_PAUSED,
SND_SOC_DPCM_STATE_SUSPEND,
SND_SOC_DPCM_STATE_HW_FREE,
SND_SOC_DPCM_STATE_CLOSE,
};
/*
* Dynamic PCM trigger ordering. Triggering flexibility is required as some
* DSPs require triggering before/after their CPU platform and DAIs.
*
* i.e. some clients may want to manually order this call in their PCM
* trigger() whilst others will just use the regular core ordering.
*/
enum snd_soc_dpcm_trigger {
SND_SOC_DPCM_TRIGGER_PRE = 0,
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_BESPOKE,
};
/*
* Dynamic PCM link
* This links together a FE and BE DAI at runtime and stores the link
* state information and the hw_params configuration.
*/
struct snd_soc_dpcm {
/* FE and BE DAIs*/
struct snd_soc_pcm_runtime *be;
struct snd_soc_pcm_runtime *fe;
/* link state */
enum snd_soc_dpcm_link_state state;
/* list of BE and FE for this DPCM link */
struct list_head list_be;
struct list_head list_fe;
/* hw params for this link - may be different for each link */
struct snd_pcm_hw_params hw_params;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_state;
#endif
};
/*
* Dynamic PCM runtime data.
*/
struct snd_soc_dpcm_runtime {
struct list_head be_clients;
struct list_head fe_clients;
int users;
struct snd_pcm_runtime *runtime;
struct snd_pcm_hw_params hw_params;
/* state and update */
enum snd_soc_dpcm_update runtime_update;
enum snd_soc_dpcm_state state;
};
/* can this BE stop and free */
int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream);
/* can this BE perform a hw_params() */
int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream);
/* is the current PCM operation for this FE ? */
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
/* is the current PCM operation for this BE ? */
int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream);
/* get the substream for this BE */
struct snd_pcm_substream *
snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
/* get the BE runtime state */
enum snd_soc_dpcm_state
snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
/* set the BE runtime state */
void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
enum snd_soc_dpcm_state state);
/* internal use only */
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *);
#endif
......@@ -55,6 +55,18 @@
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array),\
.info = snd_soc_info_volsw, \
.get = snd_soc_get_volsw_sx,\
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, \
.shift = xshift, .rshift = xshift, \
.max = xmax, .min = xmin} }
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
......@@ -85,6 +97,18 @@
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
xmax, xinvert) }
#define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.get = snd_soc_get_volsw_sx, \
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xrreg, \
.shift = xshift, .rshift = xshift, \
.max = xmax, .min = xmin} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
......@@ -171,20 +195,6 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&xenum }
#define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\
xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_2r_sx, \
.get = snd_soc_get_volsw_2r_sx, \
.put = snd_soc_put_volsw_2r_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg_left, \
.rreg = xreg_right, .shift = xshift, \
.min = xmin, .max = xmax} }
#define SND_SOC_BYTES(xname, xbase, xregs) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
......@@ -200,6 +210,19 @@
{.base = xbase, .num_regs = xregs, \
.mask = xmask }) }
#define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
xmin, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_xr_sx, .get = snd_soc_get_xr_sx, \
.put = snd_soc_put_xr_sx, \
.private_value = (unsigned long)&(struct soc_mreg_control) \
{.regbase = xregbase, .regcount = xregcount, .nbits = xnbits, \
.invert = xinvert, .min = xmin, .max = xmax} }
#define SOC_SINGLE_STROBE(xname, xreg, xshift, xinvert) \
SOC_SINGLE_EXT(xname, xreg, xshift, 1, xinvert, \
snd_soc_get_strobe, snd_soc_put_strobe)
/*
* Simplified versions of above macros, declaring a struct and calculating
* ARRAY_SIZE internally
......@@ -264,6 +287,7 @@ struct snd_soc_jack_zone;
struct snd_soc_jack_pin;
struct snd_soc_cache_ops;
#include <sound/soc-dapm.h>
#include <sound/soc-dpcm.h>
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio;
......@@ -288,6 +312,11 @@ enum snd_soc_pcm_subclass {
SND_SOC_PCM_CLASS_BE = 1,
};
enum snd_soc_card_subclass {
SND_SOC_CARD_CLASS_INIT = 0,
SND_SOC_CARD_CLASS_RUNTIME = 1,
};
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
......@@ -333,6 +362,11 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
unsigned int reg, unsigned int val);
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
const char *dai_link, int stream);
struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
const char *dai_link);
/* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
......@@ -343,6 +377,9 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms);
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
const struct snd_pcm_hardware *hw);
int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_platform *platform);
/* Jack reporting */
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
struct snd_soc_jack *jack);
......@@ -413,6 +450,10 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#define snd_soc_get_volsw_2r snd_soc_get_volsw
#define snd_soc_put_volsw_2r snd_soc_put_volsw
int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
......@@ -421,19 +462,22 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_limit_volume(struct snd_soc_codec *codec,
const char *name, int max);
int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
/**
* struct snd_soc_reg_access - Describes whether a given register is
......@@ -513,6 +557,7 @@ struct snd_soc_jack_gpio {
#endif
struct snd_soc_jack {
struct mutex mutex;
struct snd_jack *jack;
struct snd_soc_codec *codec;
struct list_head pins;
......@@ -711,6 +756,7 @@ struct snd_soc_platform_driver {
/* platform IO - used for platform DAPM */
unsigned int (*read)(struct snd_soc_platform *, unsigned int);
int (*write)(struct snd_soc_platform *, unsigned int, unsigned int);
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
};
struct snd_soc_platform {
......@@ -746,21 +792,36 @@ struct snd_soc_dai_link {
const char *cpu_dai_name;
const struct device_node *cpu_dai_of_node;
const char *codec_dai_name;
int be_id; /* optional ID for machine driver BE identification */
const struct snd_soc_pcm_stream *params;
unsigned int dai_fmt; /* format to set on init */
enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
/* Keep DAI active over suspend */
unsigned int ignore_suspend:1;
/* Symmetry requirements */
unsigned int symmetric_rates:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1;
/* This DAI link can route to other DAI links at runtime (Frontend)*/
unsigned int dynamic:1;
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_pcm_runtime *rtd);
/* optional hw_params re-writing for BE and FE sync */
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
/* machine stream operations */
struct snd_soc_ops *ops;
};
......@@ -800,6 +861,7 @@ struct snd_soc_card {
struct list_head list;
struct mutex mutex;
struct mutex dapm_mutex;
bool instantiated;
......@@ -889,9 +951,11 @@ struct snd_soc_pcm_runtime {
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops;
unsigned int complete:1;
unsigned int dev_registered:1;
/* Dynamic PCM BE runtime data */
struct snd_soc_dpcm_runtime dpcm[2];
long pmdown_time;
/* runtime devices */
......@@ -902,6 +966,10 @@ struct snd_soc_pcm_runtime {
struct snd_soc_dai *cpu_dai;
struct delayed_work delayed_work;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_dpcm_root;
struct dentry *debugfs_dpcm_state;
#endif
};
/* mixer control */
......@@ -916,6 +984,12 @@ struct soc_bytes {
u32 mask;
};
/* multi register control */
struct soc_mreg_control {
long min, max;
unsigned int regbase, regcount, nbits, invert;
};
/* enumerated kcontrol */
struct soc_enum {
unsigned short reg;
......
......@@ -7,6 +7,8 @@
#include <linux/ktime.h>
#include <linux/tracepoint.h>
#define DAPM_DIRECT "(direct)"
struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_platform;
......@@ -241,6 +243,84 @@ TRACE_EVENT(snd_soc_dapm_walk_done,
(int)__entry->path_checks, (int)__entry->neighbour_checks)
);
TRACE_EVENT(snd_soc_dapm_output_path,
TP_PROTO(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_path *path),
TP_ARGS(widget, path),
TP_STRUCT__entry(
__string( wname, widget->name )
__string( pname, path->name ? path->name : DAPM_DIRECT)
__string( psname, path->sink->name )
__field( int, path_sink )
__field( int, path_connect )
),
TP_fast_assign(
__assign_str(wname, widget->name);
__assign_str(pname, path->name ? path->name : DAPM_DIRECT);
__assign_str(psname, path->sink->name);
__entry->path_connect = path->connect;
__entry->path_sink = (long)path->sink;
),
TP_printk("%c%s -> %s -> %s\n",
(int) __entry->path_sink &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
);
TRACE_EVENT(snd_soc_dapm_input_path,
TP_PROTO(struct snd_soc_dapm_widget *widget,
struct snd_soc_dapm_path *path),
TP_ARGS(widget, path),
TP_STRUCT__entry(
__string( wname, widget->name )
__string( pname, path->name ? path->name : DAPM_DIRECT)
__string( psname, path->source->name )
__field( int, path_source )
__field( int, path_connect )
),
TP_fast_assign(
__assign_str(wname, widget->name);
__assign_str(pname, path->name ? path->name : DAPM_DIRECT);
__assign_str(psname, path->source->name);
__entry->path_connect = path->connect;
__entry->path_source = (long)path->source;
),
TP_printk("%c%s <- %s <- %s\n",
(int) __entry->path_source &&
(int) __entry->path_connect ? '*' : ' ',
__get_str(wname), __get_str(pname), __get_str(psname))
);
TRACE_EVENT(snd_soc_dapm_connected,
TP_PROTO(int paths, int stream),
TP_ARGS(paths, stream),
TP_STRUCT__entry(
__field( int, paths )
__field( int, stream )
),
TP_fast_assign(
__entry->paths = paths;
__entry->stream = stream;
),
TP_printk("%s: found %d paths\n",
__entry->stream ? "capture" : "playback", __entry->paths)
);
TRACE_EVENT(snd_soc_jack_irq,
TP_PROTO(const char *name),
......
......@@ -991,6 +991,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
gpio_direction_output(pdata->reset_pin, 1);
chip->reset_pin = pdata->reset_pin;
}
} else {
chip->reset_pin = -EINVAL;
}
snd_card_set_dev(card, &pdev->dev);
......
......@@ -155,7 +155,7 @@ EXPORT_SYMBOL(snd_jack_new);
* @jack: The jack to configure
* @parent: The device to set as parent for the jack.
*
* Set the parent for the jack input device in the device tree. This
* Set the parent for the jack devices in the device tree. This
* function is only valid prior to registration of the jack. If no
* parent is configured then the parent device will be the sound card.
*/
......@@ -179,6 +179,9 @@ EXPORT_SYMBOL(snd_jack_set_parent);
* mapping is provided but keys are enabled in the jack type then
* BTN_n numeric buttons will be reported.
*
* If jacks are not reporting via the input API this call will have no
* effect.
*
* Note that this is intended to be use by simple devices with small
* numbers of keys that can be reported. It is also possible to
* access the input device directly - devices with complex input
......
......@@ -1894,6 +1894,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
......@@ -1917,13 +1918,12 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
}
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
if (!avail) {
if (nonblock) {
err = -EAGAIN;
......@@ -1971,6 +1971,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
avail -= frames;
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
err = snd_pcm_start(substream);
......@@ -2111,6 +2112,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
......@@ -2141,13 +2143,12 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
}
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_capture_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_capture_avail(runtime);
if (!avail) {
if (runtime->status->state ==
SNDRV_PCM_STATE_DRAINING) {
......@@ -2202,6 +2203,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
avail -= frames;
}
_end_unlock:
runtime->twake = 0;
......
......@@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
substream->runtime->trigger_master = substream;
struct snd_pcm_runtime *runtime = substream->runtime;
switch (runtime->status->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_DISCONNECTED:
case SNDRV_PCM_STATE_SUSPENDED:
return -EBADFD;
}
runtime->trigger_master = substream;
return 0;
}
......@@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
case SNDRV_PCM_STATE_RUNNING:
runtime->status->state = SNDRV_PCM_STATE_DRAINING;
break;
case SNDRV_PCM_STATE_XRUN:
runtime->status->state = SNDRV_PCM_STATE_SETUP;
break;
default:
break;
}
......
......@@ -35,7 +35,7 @@
#include <linux/sound.h>
#include <linux/mutex.h>
#define SNDRV_OSS_MINORS 128
#define SNDRV_OSS_MINORS 256
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
static DEFINE_MUTEX(sound_oss_mutex);
......@@ -111,7 +111,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
int register1 = -1, register2 = -1;
struct device *carddev = snd_card_get_device_link(card);
if (card && card->number >= 8)
if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0; /* ignore silently */
if (minor < 0)
return minor;
......@@ -170,7 +170,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
int track2 = -1;
struct snd_minor *mptr;
if (card && card->number >= 8)
if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0;
if (minor < 0)
return minor;
......
......@@ -117,6 +117,7 @@ struct loopback_pcm {
/* timer stuff */
unsigned int irq_pos; /* fractional IRQ position */
unsigned int period_size_frac;
unsigned int last_drift;
unsigned long last_jiffies;
struct timer_list timer;
};
......@@ -264,6 +265,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
return err;
dpcm->last_jiffies = jiffies;
dpcm->pcm_rate_shift = 0;
dpcm->last_drift = 0;
spin_lock(&cable->lock);
cable->running |= stream;
cable->pause &= ~stream;
......@@ -444,34 +446,30 @@ static void copy_play_buf(struct loopback_pcm *play,
}
}
#define BYTEPOS_UPDATE_POSONLY 0
#define BYTEPOS_UPDATE_CLEAR 1
#define BYTEPOS_UPDATE_COPY 2
static void loopback_bytepos_update(struct loopback_pcm *dpcm,
unsigned int delta,
unsigned int cmd)
static inline unsigned int bytepos_delta(struct loopback_pcm *dpcm,
unsigned int jiffies_delta)
{
unsigned int count;
unsigned long last_pos;
unsigned int delta;
last_pos = byte_pos(dpcm, dpcm->irq_pos);
dpcm->irq_pos += delta * dpcm->pcm_bps;
count = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
if (!count)
return;
if (cmd == BYTEPOS_UPDATE_CLEAR)
clear_capture_buf(dpcm, count);
else if (cmd == BYTEPOS_UPDATE_COPY)
copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE],
count);
dpcm->buf_pos += count;
dpcm->buf_pos %= dpcm->pcm_buffer_size;
dpcm->irq_pos += jiffies_delta * dpcm->pcm_bps;
delta = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
if (delta >= dpcm->last_drift)
delta -= dpcm->last_drift;
dpcm->last_drift = 0;
if (dpcm->irq_pos >= dpcm->period_size_frac) {
dpcm->irq_pos %= dpcm->period_size_frac;
dpcm->period_update_pending = 1;
}
return delta;
}
static inline void bytepos_finish(struct loopback_pcm *dpcm,
unsigned int delta)
{
dpcm->buf_pos += delta;
dpcm->buf_pos %= dpcm->pcm_buffer_size;
}
static unsigned int loopback_pos_update(struct loopback_cable *cable)
......@@ -481,7 +479,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
struct loopback_pcm *dpcm_capt =
cable->streams[SNDRV_PCM_STREAM_CAPTURE];
unsigned long delta_play = 0, delta_capt = 0;
unsigned int running;
unsigned int running, count1, count2;
unsigned long flags;
spin_lock_irqsave(&cable->lock, flags);
......@@ -500,12 +498,13 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
goto unlock;
if (delta_play > delta_capt) {
loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
BYTEPOS_UPDATE_POSONLY);
count1 = bytepos_delta(dpcm_play, delta_play - delta_capt);
bytepos_finish(dpcm_play, count1);
delta_play = delta_capt;
} else if (delta_play < delta_capt) {
loopback_bytepos_update(dpcm_capt, delta_capt - delta_play,
BYTEPOS_UPDATE_CLEAR);
count1 = bytepos_delta(dpcm_capt, delta_capt - delta_play);
clear_capture_buf(dpcm_capt, count1);
bytepos_finish(dpcm_capt, count1);
delta_capt = delta_play;
}
......@@ -513,8 +512,17 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
goto unlock;
/* note delta_capt == delta_play at this moment */
loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
count1 = bytepos_delta(dpcm_play, delta_play);
count2 = bytepos_delta(dpcm_capt, delta_capt);
if (count1 < count2) {
dpcm_capt->last_drift = count2 - count1;
count1 = count2;
} else if (count1 > count2) {
dpcm_play->last_drift = count1 - count2;
}
copy_play_buf(dpcm_play, dpcm_capt, count1);
bytepos_finish(dpcm_play, count1);
bytepos_finish(dpcm_capt, count1);
unlock:
spin_unlock_irqrestore(&cable->lock, flags);
return running;
......
......@@ -31,6 +31,8 @@
#define INTERRUPT_INTERVAL 16
#define QUEUE_LENGTH 48
static void pcm_period_tasklet(unsigned long data);
/**
* amdtp_out_stream_init - initialize an AMDTP output stream structure
* @s: the AMDTP output stream to initialize
......@@ -47,6 +49,7 @@ int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s);
s->packet_index = 0;
return 0;
......@@ -164,6 +167,21 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
}
EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format);
/**
* amdtp_out_stream_pcm_prepare - prepare PCM device for running
* @s: the AMDTP output stream
*
* This function should be called from the PCM device's .prepare callback.
*/
void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
{
tasklet_kill(&s->period_tasklet);
s->pcm_buffer_pointer = 0;
s->pcm_period_pointer = 0;
s->pointer_flush = true;
}
EXPORT_SYMBOL(amdtp_out_stream_pcm_prepare);
static unsigned int calculate_data_blocks(struct amdtp_out_stream *s)
{
unsigned int phase, data_blocks;
......@@ -376,11 +394,21 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
s->pcm_period_pointer += data_blocks;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
snd_pcm_period_elapsed(pcm);
s->pointer_flush = false;
tasklet_hi_schedule(&s->period_tasklet);
}
}
}
static void pcm_period_tasklet(unsigned long data)
{
struct amdtp_out_stream *s = (void *)data;
struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm);
if (pcm)
snd_pcm_period_elapsed(pcm);
}
static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
size_t header_length, void *header, void *data)
{
......@@ -505,6 +533,24 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
}
EXPORT_SYMBOL(amdtp_out_stream_start);
/**
* amdtp_out_stream_pcm_pointer - get the PCM buffer position
* @s: the AMDTP output stream that transports the PCM data
*
* Returns the current buffer position, in frames.
*/
unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
{
/* this optimization is allowed to be racy */
if (s->pointer_flush)
fw_iso_context_flush_completions(s->context);
else
s->pointer_flush = true;
return ACCESS_ONCE(s->pcm_buffer_pointer);
}
EXPORT_SYMBOL(amdtp_out_stream_pcm_pointer);
/**
* amdtp_out_stream_update - update the stream after a bus reset
* @s: the AMDTP output stream
......@@ -532,6 +578,7 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s)
return;
}
tasklet_kill(&s->period_tasklet);
fw_iso_context_stop(s->context);
fw_iso_context_destroy(s->context);
s->context = ERR_PTR(-1);
......
#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
#define SOUND_FIREWIRE_AMDTP_H_INCLUDED
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include "packets-buffer.h"
......@@ -55,6 +56,7 @@ struct amdtp_out_stream {
struct iso_packets_buffer buffer;
struct snd_pcm_substream *pcm;
struct tasklet_struct period_tasklet;
int packet_index;
unsigned int data_block_counter;
......@@ -66,6 +68,7 @@ struct amdtp_out_stream {
unsigned int pcm_buffer_pointer;
unsigned int pcm_period_pointer;
bool pointer_flush;
};
int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
......@@ -81,6 +84,8 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s);
void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
snd_pcm_format_t format);
void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s);
unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s);
void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
/**
......@@ -122,18 +127,6 @@ static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
return s->packet_index < 0;
}
/**
* amdtp_out_stream_pcm_prepare - prepare PCM device for running
* @s: the AMDTP output stream
*
* This function should be called from the PCM device's .prepare callback.
*/
static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
{
s->pcm_buffer_pointer = 0;
s->pcm_period_pointer = 0;
}
/**
* amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device
* @s: the AMDTP output stream
......@@ -149,18 +142,6 @@ static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s,
ACCESS_ONCE(s->pcm) = pcm;
}
/**
* amdtp_out_stream_pcm_pointer - get the PCM buffer position
* @s: the AMDTP output stream that transports the PCM data
*
* Returns the current buffer position, in frames.
*/
static inline unsigned long
amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
{
return ACCESS_ONCE(s->pcm_buffer_pointer);
}
static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
{
return sfc & 1;
......
......@@ -228,7 +228,7 @@ config SND_OXYGEN
Say Y here to include support for sound cards based on the
C-Media CMI8788 (Oxygen HD Audio) chip:
* Asound A-8788
* Asus Xonar DG
* Asus Xonar DG/DGX
* AuzenTech X-Meridian
* AuzenTech X-Meridian 2G
* Bgears b-Enspirer
......
......@@ -1062,17 +1062,4 @@ static struct pci_driver ad1889_pci_driver = {
.remove = __devexit_p(snd_ad1889_remove),
};
static int __init
alsa_ad1889_init(void)
{
return pci_register_driver(&ad1889_pci_driver);
}
static void __exit
alsa_ad1889_fini(void)
{
pci_unregister_driver(&ad1889_pci_driver);
}
module_init(alsa_ad1889_init);
module_exit(alsa_ad1889_fini);
module_pci_driver(ad1889_pci_driver);
......@@ -2294,7 +2294,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver ali5451_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
......@@ -2305,15 +2305,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_ali_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_ali_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_ali_init)
module_exit(alsa_card_ali_exit)
module_pci_driver(ali5451_driver);
......@@ -852,7 +852,7 @@ static int __devinit snd_als300_probe(struct pci_dev *pci,
return 0;
}
static struct pci_driver driver = {
static struct pci_driver als300_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als300_ids,
.probe = snd_als300_probe,
......@@ -863,15 +863,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_als300_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_als300_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_als300_init)
module_exit(alsa_card_als300_exit)
module_pci_driver(als300_driver);
......@@ -1036,7 +1036,7 @@ static int snd_als4000_resume(struct pci_dev *pci)
#endif /* CONFIG_PM */
static struct pci_driver driver = {
static struct pci_driver als4000_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
......@@ -1047,15 +1047,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_als4000_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_als4000_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_als4000_init)
module_exit(alsa_card_als4000_exit)
module_pci_driver(als4000_driver);
......@@ -1700,7 +1700,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver atiixp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
......@@ -1711,16 +1711,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_atiixp_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_atiixp_init)
module_exit(alsa_card_atiixp_exit)
module_pci_driver(atiixp_driver);
......@@ -1331,7 +1331,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver atiixp_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
......@@ -1342,16 +1342,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_atiixp_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_atiixp_init)
module_exit(alsa_card_atiixp_exit)
module_pci_driver(atiixp_modem_driver);
......@@ -375,24 +375,11 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
}
// pci_driver definition
static struct pci_driver driver = {
static struct pci_driver vortex_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
.remove = __devexit_p(snd_vortex_remove),
};
// initialization of the module
static int __init alsa_card_vortex_init(void)
{
return pci_register_driver(&driver);
}
// clean up the module
static void __exit alsa_card_vortex_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_vortex_init)
module_exit(alsa_card_vortex_exit)
module_pci_driver(vortex_driver);
......@@ -112,8 +112,6 @@ struct aw2 {
/*********************************
* FUNCTION DECLARATIONS
********************************/
static int __init alsa_card_aw2_init(void);
static void __exit alsa_card_aw2_exit(void);
static int snd_aw2_dev_free(struct snd_device *device);
static int __devinit snd_aw2_create(struct snd_card *card,
struct pci_dev *pci, struct aw2 **rchip);
......@@ -171,13 +169,15 @@ static DEFINE_PCI_DEVICE_TABLE(snd_aw2_ids) = {
MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
/* pci_driver definition */
static struct pci_driver driver = {
static struct pci_driver aw2_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_aw2_ids,
.probe = snd_aw2_probe,
.remove = __devexit_p(snd_aw2_remove),
};
module_pci_driver(aw2_driver);
/* operators for playback PCM alsa interface */
static struct snd_pcm_ops snd_aw2_playback_ops = {
.open = snd_aw2_pcm_playback_open,
......@@ -217,23 +217,6 @@ static struct snd_kcontrol_new aw2_control __devinitdata = {
* FUNCTION IMPLEMENTATIONS
********************************/
/* initialization of the module */
static int __init alsa_card_aw2_init(void)
{
snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
return pci_register_driver(&driver);
}
/* clean up the module */
static void __exit alsa_card_aw2_exit(void)
{
snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
pci_unregister_driver(&driver);
}
module_init(alsa_card_aw2_init);
module_exit(alsa_card_aw2_exit);
/* component-destructor */
static int snd_aw2_dev_free(struct snd_device *device)
{
......
......@@ -2862,7 +2862,7 @@ snd_azf3328_resume(struct pci_dev *pci)
#endif /* CONFIG_PM */
static struct pci_driver driver = {
static struct pci_driver azf3328_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
......@@ -2873,23 +2873,4 @@ static struct pci_driver driver = {
#endif
};
static int __init
alsa_card_azf3328_init(void)
{
int err;
snd_azf3328_dbgcallenter();
err = pci_register_driver(&driver);
snd_azf3328_dbgcallleave();
return err;
}
static void __exit
alsa_card_azf3328_exit(void)
{
snd_azf3328_dbgcallenter();
pci_unregister_driver(&driver);
snd_azf3328_dbgcallleave();
}
module_init(alsa_card_azf3328_init)
module_exit(alsa_card_azf3328_exit)
module_pci_driver(azf3328_driver);
......@@ -836,8 +836,6 @@ static struct {
{0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
};
static struct pci_driver driver;
/* return the id of the card, or a negative value if it's blacklisted */
static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
{
......@@ -964,24 +962,11 @@ static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = {
{ }
};
static struct pci_driver driver = {
static struct pci_driver bt87x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
.remove = __devexit_p(snd_bt87x_remove),
};
static int __init alsa_card_bt87x_init(void)
{
if (load_all)
driver.id_table = snd_bt87x_default_ids;
return pci_register_driver(&driver);
}
static void __exit alsa_card_bt87x_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_bt87x_init)
module_exit(alsa_card_bt87x_exit)
module_pci_driver(bt87x_driver);
......@@ -1932,7 +1932,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ca0106_ids) = {
MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
// pci_driver definition
static struct pci_driver driver = {
static struct pci_driver ca0106_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
......@@ -1943,17 +1943,4 @@ static struct pci_driver driver = {
#endif
};
// initialization of the module
static int __init alsa_card_ca0106_init(void)
{
return pci_register_driver(&driver);
}
// clean up the module
static void __exit alsa_card_ca0106_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_ca0106_init)
module_exit(alsa_card_ca0106_exit)
module_pci_driver(ca0106_driver);
......@@ -3398,7 +3398,7 @@ static int snd_cmipci_resume(struct pci_dev *pci)
}
#endif /* CONFIG_PM */
static struct pci_driver driver = {
static struct pci_driver cmipci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
......@@ -3409,15 +3409,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_cmipci_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cmipci_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cmipci_init)
module_exit(alsa_card_cmipci_exit)
module_pci_driver(cmipci_driver);
......@@ -2084,7 +2084,7 @@ static int cs4281_resume(struct pci_dev *pci)
}
#endif /* CONFIG_PM */
static struct pci_driver driver = {
static struct pci_driver cs4281_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
......@@ -2095,15 +2095,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_cs4281_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cs4281_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cs4281_init)
module_exit(alsa_card_cs4281_exit)
module_pci_driver(cs4281_driver);
......@@ -161,7 +161,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver cs46xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
......@@ -172,15 +172,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_cs46xx_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cs46xx_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cs46xx_init)
module_exit(alsa_card_cs46xx_exit)
module_pci_driver(cs46xx_driver);
......@@ -291,23 +291,11 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci,
return 0;
}
static struct pci_driver driver = {
static struct pci_driver cs5530_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5530_ids,
.probe = snd_cs5530_probe,
.remove = __devexit_p(snd_cs5530_remove),
};
static int __init alsa_card_cs5530_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cs5530_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cs5530_init)
module_exit(alsa_card_cs5530_exit)
module_pci_driver(cs5530_driver);
......@@ -394,7 +394,7 @@ static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe,
......@@ -405,18 +405,7 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_cs5535audio_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cs5535audio_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cs5535audio_init)
module_exit(alsa_card_cs5535audio_exit)
module_pci_driver(cs5535audio_driver);
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
......
......@@ -154,15 +154,4 @@ static struct pci_driver ct_driver = {
#endif
};
static int __init ct_card_init(void)
{
return pci_register_driver(&ct_driver);
}
static void __exit ct_card_exit(void)
{
pci_unregister_driver(&ct_driver);
}
module_init(ct_card_init)
module_exit(ct_card_exit)
module_pci_driver(ct_driver);
......@@ -2328,7 +2328,7 @@ static void __devexit snd_echo_remove(struct pci_dev *pci)
******************************************************************************/
/* pci_driver definition */
static struct pci_driver driver = {
static struct pci_driver echo_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_echo_ids,
.probe = snd_echo_probe,
......@@ -2339,22 +2339,4 @@ static struct pci_driver driver = {
#endif /* CONFIG_PM */
};
/* initialization of the module */
static int __init alsa_card_echo_init(void)
{
return pci_register_driver(&driver);
}
/* clean up the module */
static void __exit alsa_card_echo_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_echo_init)
module_exit(alsa_card_echo_exit)
module_pci_driver(echo_driver);
......@@ -263,7 +263,7 @@ static int snd_emu10k1_resume(struct pci_dev *pci)
}
#endif
static struct pci_driver driver = {
static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
......@@ -274,15 +274,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_emu10k1_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_emu10k1_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_emu10k1_init)
module_exit(alsa_card_emu10k1_exit)
module_pci_driver(emu10k1_driver);
......@@ -1612,24 +1612,11 @@ static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1x_ids) = {
MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
// pci_driver definition
static struct pci_driver driver = {
static struct pci_driver emu10k1x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
.remove = __devexit_p(snd_emu10k1x_remove),
};
// initialization of the module
static int __init alsa_card_emu10k1x_init(void)
{
return pci_register_driver(&driver);
}
// clean up the module
static void __exit alsa_card_emu10k1x_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_emu10k1x_init)
module_exit(alsa_card_emu10k1x_exit)
module_pci_driver(emu10k1x_driver);
......@@ -2488,7 +2488,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver ens137x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
......@@ -2499,15 +2499,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_ens137x_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_ens137x_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_ens137x_init)
module_exit(alsa_card_ens137x_exit)
module_pci_driver(ens137x_driver);
......@@ -1882,7 +1882,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver es1938_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
......@@ -1893,15 +1893,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_es1938_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_es1938_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_es1938_init)
module_exit(alsa_card_es1938_exit)
module_pci_driver(es1938_driver);
......@@ -2898,7 +2898,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
static struct pci_driver driver = {
static struct pci_driver es1968_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
......@@ -2909,15 +2909,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_es1968_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_es1968_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_es1968_init)
module_exit(alsa_card_es1968_exit)
module_pci_driver(es1968_driver);
......@@ -1416,7 +1416,7 @@ static int snd_fm801_resume(struct pci_dev *pci)
}
#endif
static struct pci_driver driver = {
static struct pci_driver fm801_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
......@@ -1427,15 +1427,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_fm801_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_fm801_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_fm801_init)
module_exit(alsa_card_fm801_exit)
module_pci_driver(fm801_driver);
snd-hda-intel-objs := hda_intel.o
snd-hda-codec-y := hda_codec.o hda_jack.o
snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
......
此差异已折叠。
/*
* BIOS auto-parser helper functions for HD-audio
*
* Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __SOUND_HDA_AUTO_PARSER_H
#define __SOUND_HDA_AUTO_PARSER_H
/*
* Helper for automatic pin configuration
*/
enum {
AUTO_PIN_MIC,
AUTO_PIN_LINE_IN,
AUTO_PIN_CD,
AUTO_PIN_AUX,
AUTO_PIN_LAST
};
enum {
AUTO_PIN_LINE_OUT,
AUTO_PIN_SPEAKER_OUT,
AUTO_PIN_HP_OUT
};
#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
#define AUTO_CFG_MAX_INS 8
struct auto_pin_cfg_item {
hda_nid_t pin;
int type;
};
struct auto_pin_cfg;
const char *hda_get_autocfg_input_label(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
int input);
int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
const struct auto_pin_cfg *cfg,
char *label, int maxlen, int *indexp);
enum {
INPUT_PIN_ATTR_UNUSED, /* pin not connected */
INPUT_PIN_ATTR_INT, /* internal mic/line-in */
INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
};
int snd_hda_get_input_pin_attr(unsigned int def_conf);
struct auto_pin_cfg {
int line_outs;
/* sorted in the order of Front/Surr/CLFE/Side */
hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
int speaker_outs;
hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
int hp_outs;
int line_out_type; /* AUTO_PIN_XXX_OUT */
hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
int num_inputs;
struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
int dig_outs;
hda_nid_t dig_out_pins[2];
hda_nid_t dig_in_pin;
hda_nid_t mono_out_pin;
int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
int dig_in_type; /* HDA_PCM_TYPE_XXX */
};
/* 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 */
int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
struct auto_pin_cfg *cfg,
const hda_nid_t *ignore_nids,
unsigned int cond_flags);
/* older function */
#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
/*
*/
struct hda_gen_spec {
/* fix-up list */
int fixup_id;
const struct hda_fixup *fixup_list;
const char *fixup_name;
/* additional init verbs */
struct snd_array verbs;
};
/*
* Fix-up pin default configurations and add default verbs
*/
struct hda_pintbl {
hda_nid_t nid;
u32 val;
};
struct hda_model_fixup {
const int id;
const char *name;
};
struct hda_fixup {
int type;
bool chained;
int chain_id;
union {
const struct hda_pintbl *pins;
const struct hda_verb *verbs;
void (*func)(struct hda_codec *codec,
const struct hda_fixup *fix,
int action);
} v;
};
/* fixup types */
enum {
HDA_FIXUP_INVALID,
HDA_FIXUP_PINS,
HDA_FIXUP_VERBS,
HDA_FIXUP_FUNC,
};
/* fixup action definitions */
enum {
HDA_FIXUP_ACT_PRE_PROBE,
HDA_FIXUP_ACT_PROBE,
HDA_FIXUP_ACT_INIT,
HDA_FIXUP_ACT_BUILD,
};
int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
const struct hda_verb *list);
void snd_hda_gen_apply_verbs(struct hda_codec *codec);
void snd_hda_apply_pincfgs(struct hda_codec *codec,
const struct hda_pintbl *cfg);
void snd_hda_apply_fixup(struct hda_codec *codec, int action);
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
const struct snd_pci_quirk *quirk,
const struct hda_fixup *fixlist);
#endif /* __SOUND_HDA_AUTO_PARSER_H */
此差异已折叠。
......@@ -704,8 +704,6 @@ struct hda_codec_ops {
unsigned int power_state);
#ifdef CONFIG_PM
int (*suspend)(struct hda_codec *codec, pm_message_t state);
int (*post_suspend)(struct hda_codec *codec);
int (*pre_resume)(struct hda_codec *codec);
int (*resume)(struct hda_codec *codec);
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE
......@@ -829,6 +827,7 @@ struct hda_codec {
struct mutex spdif_mutex;
struct mutex control_mutex;
struct mutex hash_mutex;
struct snd_array spdif_out;
unsigned int spdif_in_enable; /* SPDIF input enable? */
const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
......@@ -861,12 +860,13 @@ struct hda_codec {
unsigned int no_jack_detect:1; /* Machine has no jack-detection */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
unsigned int power_transition :1; /* power-state in transition */
int power_transition; /* power-state in transition */
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
unsigned long power_on_acct;
unsigned long power_off_acct;
unsigned long power_jiffies;
spinlock_t power_lock;
#endif
/* codec-specific additional proc output */
......@@ -911,10 +911,13 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *start_id);
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
static inline int
snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_get_connections(codec, nid, NULL, 0);
}
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
const hda_nid_t **listp);
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
const hda_nid_t *list);
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
......@@ -1051,12 +1054,10 @@ const char *snd_hda_get_jack_location(u32 cfg);
#ifdef CONFIG_SND_HDA_POWER_SAVE
void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
#define snd_hda_codec_needs_resume(codec) codec->power_count
void snd_hda_update_power_acct(struct hda_codec *codec);
#else
static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
#define snd_hda_codec_needs_resume(codec) 1
#endif
#ifdef CONFIG_SND_HDA_PATCH_LOADER
......
......@@ -497,6 +497,7 @@ enum {
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
AZX_DRIVER_CTX,
AZX_DRIVER_CTHDA,
AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
......@@ -518,6 +519,7 @@ enum {
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
......@@ -533,6 +535,9 @@ enum {
(AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
AZX_DCAPS_ALIGN_BUFSIZE)
#define AZX_DCAPS_PRESET_CTHDA \
(AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_4K_BDLE_BOUNDARY)
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
......@@ -546,6 +551,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
[AZX_DRIVER_CTX] = "HDA Creative",
[AZX_DRIVER_CTHDA] = "HDA Creative",
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
......@@ -1285,7 +1291,8 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
/*
* set up a BDL entry
*/
static int setup_bdle(struct snd_pcm_substream *substream,
static int setup_bdle(struct azx *chip,
struct snd_pcm_substream *substream,
struct azx_dev *azx_dev, u32 **bdlp,
int ofs, int size, int with_ioc)
{
......@@ -1304,6 +1311,12 @@ static int setup_bdle(struct snd_pcm_substream *substream,
bdl[1] = cpu_to_le32(upper_32_bits(addr));
/* program the size field of the BDL entry */
chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
/* one BDLE cannot cross 4K boundary on CTHDA chips */
if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) {
u32 remain = 0x1000 - (ofs & 0xfff);
if (chunk > remain)
chunk = remain;
}
bdl[2] = cpu_to_le32(chunk);
/* program the IOC to enable interrupt
* only when the whole fragment is processed
......@@ -1356,7 +1369,7 @@ static int azx_setup_periods(struct azx *chip,
bdl_pos_adj[chip->dev_index]);
pos_adj = 0;
} else {
ofs = setup_bdle(substream, azx_dev,
ofs = setup_bdle(chip, substream, azx_dev,
&bdl, ofs, pos_adj,
!substream->runtime->no_period_wakeup);
if (ofs < 0)
......@@ -1366,10 +1379,10 @@ static int azx_setup_periods(struct azx *chip,
pos_adj = 0;
for (i = 0; i < periods; i++) {
if (i == periods - 1 && pos_adj)
ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,
period_bytes - pos_adj, 0);
else
ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,
period_bytes,
!substream->runtime->no_period_wakeup);
if (ofs < 0)
......@@ -2353,17 +2366,6 @@ static void azx_power_notify(struct hda_bus *bus)
* power management
*/
static int snd_hda_codecs_inuse(struct hda_bus *bus)
{
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
if (snd_hda_codec_needs_resume(codec))
return 1;
}
return 0;
}
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
......@@ -2410,8 +2412,7 @@ static int azx_resume(struct pci_dev *pci)
return -EIO;
azx_init_pci(chip);
if (snd_hda_codecs_inuse(chip->bus))
azx_init_chip(chip, 1);
azx_init_chip(chip, 1);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
......@@ -2565,6 +2566,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
/* forced codec slots */
SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
/* WinFast VP200 H (Teradici) user reported broken communication */
SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
{}
};
......@@ -3130,6 +3133,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#endif
/* CTHDA chips */
{ PCI_DEVICE(0x1102, 0x0010),
.driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
{ PCI_DEVICE(0x1102, 0x0012),
.driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
/* Vortex86MX */
{ PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
/* VMware HDAudio */
......@@ -3148,7 +3156,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
MODULE_DEVICE_TABLE(pci, azx_ids);
/* pci_driver definition */
static struct pci_driver driver = {
static struct pci_driver azx_driver = {
.name = KBUILD_MODNAME,
.id_table = azx_ids,
.probe = azx_probe,
......@@ -3159,15 +3167,4 @@ static struct pci_driver driver = {
#endif
};
static int __init alsa_card_azx_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_azx_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_azx_init)
module_exit(alsa_card_azx_exit)
module_pci_driver(azx_driver);
......@@ -17,6 +17,7 @@
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_jack.h"
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
......
......@@ -12,6 +12,8 @@
#ifndef __SOUND_HDA_JACK_H
#define __SOUND_HDA_JACK_H
struct auto_pin_cfg;
struct hda_jack_tbl {
hda_nid_t nid;
unsigned char action; /* event action (0 = none) */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件已移动
文件已移动
此差异已折叠。
文件已移动
文件已移动
此差异已折叠。
文件已移动
此差异已折叠。
此差异已折叠。
文件已移动
文件已移动
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部