sound updates for 3.14-rc1

It was holiday season, so no wonder that there are little changes in
 framework level, although diffstat shows quite many changes spreaded
 over sound/* directories.  Most of changes are cleanups, code
 refactoring and fixes.
 
 Some highlights:
 
 - Removal of OSS sleep_on usages by Arnd
 
 - Simplified memalloc helper codes, drop obsoleted features;
   now it's built into PCM driver instead of an individual module
 
 - Warn if PCM buffer preallocation fails, which will show page
   allocation issues more clearly
 
 - Compress offload API updates for sample rates by Vinod
 
 - PCM glitch workaround on ctxfi emu20k1 by Sarah
 
 - Drop cs46xx DSP blobs, using firmware loader now
 
 - USB-audio quitks for Plantronics Gamecom 780, Creative VF0420,
   and Focusrite Saffire 6
 
 HD-audio specifics:
 
 - Standardize Kconfigs of HD-audio codec drivers;
   now "make localmodconfig" recognizes configs properly (finally!)
 
 - Parallel PM implementation by Mengdong
 
 - BayleyBay/ValleyView2 board fixups
 
 - Broadwell audio support
 
 - Runtime PM improvement (PantherPoint, etc)
 
 - Quirks: Dell subwooer, Gigabyte mobo jack detection oddity,
   Dell AiO click noise fixes, Dell headset mic fixes, etc
 
 - Automatic bind with HDMI codec parser without generic parser
 
 - More AD codec fixes (since 3.12 regression) including the automatic
   stereo mix support
 
 - Common Thinkpad ACPI helper for Realtek and Conexant codecs
 
 ASoC specifics:
 
 - Update to the generic DMA code to support deferred probe and managed
   resources
 
 - New drivers for BCM2835 (used in Raspberry Pi), Tegra with MAX98090
   and Analog Devices AXI I2S and S/PDIF controller IPs
 
 - Device tree support for the simple card, max98090 and cs42l52
 
 - Conversion of the Samsung drivers to native dmaengine, making them
   multiplatform compatible and hopefully helping keep them more modern
   and up to date.
 
 - More regmap conversions, including a very welcome one for twl6040
   from Peter Ujfalusi
 
 - A big overhaul of the DaVinci drivers also from Peter Ujfalusi
 
 - Lots of DMA updates from Lars-Peter
 
 - Improvements to the constraints handling code from Lars-Peter
 
 - A very helpful conversion of the TWL4030 driver to regmap from Peter
 
 - A new driver for the Freescale ESAI controller from Nicolin Chen
 
 - Conversion of some of the drivers to use params_width()
 
 - Extensions to DPCM for use with compressed audio from Liam
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJS3ocNAAoJEGwxgFQ9KSmkZEcP/3ImC7SrUC8NbCJF51tm31jk
 Ed6eKNEJPcVEbUkZ6QN215w8OkgGCXnxMge1Mhu5VGFJiIjmdtls297DqJAXUL3d
 l3/icCeYK7BN7ocMyaFRnwUipRtSiI0YuuU5cIcdbAoSrI8gtc+yZES82ivjOY4i
 cFs/owDc5nqTNtx414N14a0NQOTJU5gMNjOVqCno8VLsUUUlg3nEY0kyHKiBNe4O
 EqYmHHS2L4xu3tqxmh8pvd82OUnO53rMJXRntU6nuw1sgY7o+4pjmi3k10l1SHpH
 Rv0dB8PunY72AnxPMPORISKHJ3isKPz0QdZVtdj0+WrFUwD1vrFE3Yktq3hYQvwd
 NrOcMoEosQQhDcD74SSt1xfKVpW+gJazN4154VK/O2PKdNHLdc3/4rw95tYA8ywO
 /jnDH+qNlzHSrAdq2Fj21FfTKOYvow8RBB+Rp05RymKESwJ9sk0yLLN1QgDoJXwW
 kNBH6SxMxhaHOch0PzXidErydxnB2+j59i485DmJlI1GsjJTMFZvm8f85OlNstrn
 ad5OsXKfBkS78oT5vBeDkp5uH56hPiyP89lhnd+cE/MgjBHHnQliJ8thLumgUjN+
 vf6VGnpJywacH/VYrA2v8xKj514Q0CgsEydYtq5Z4J6WQVKrECOYlgYgpbJt6dsC
 WE9DYZECRVCp74N8WB+z
 =IWy2
 -----END PGP SIGNATURE-----

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

Pull sound updates from Takashi Iwai:
 "It was holiday season, so no wonder that there are little changes in
  framework level, although diffstat shows quite many changes spreaded
  over sound/* directories.  Most of changes are cleanups, code
  refactoring and fixes.

  Some highlights:
   - Removal of OSS sleep_on usages by Arnd
   - Simplified memalloc helper codes, drop obsoleted features; now it's
     built into PCM driver instead of an individual module
   - Warn if PCM buffer preallocation fails, which will show page
     allocation issues more clearly
   - Compress offload API updates for sample rates by Vinod
   - PCM glitch workaround on ctxfi emu20k1 by Sarah
   - Drop cs46xx DSP blobs, using firmware loader now
   - USB-audio quitks for Plantronics Gamecom 780, Creative VF0420, and
     Focusrite Saffire 6

  HD-audio specifics:
   - Standardize Kconfigs of HD-audio codec drivers; now "make
     localmodconfig" recognizes configs properly (finally!)
   - Parallel PM implementation by Mengdong
   - BayleyBay/ValleyView2 board fixups
   - Broadwell audio support
   - Runtime PM improvement (PantherPoint, etc)
   - Quirks: Dell subwooer, Gigabyte mobo jack detection oddity, Dell
     AiO click noise fixes, Dell headset mic fixes, etc
   - Automatic bind with HDMI codec parser without generic parser
   - More AD codec fixes (since 3.12 regression) including the automatic
     stereo mix support
   - Common Thinkpad ACPI helper for Realtek and Conexant codecs

  ASoC specifics:
   - Update to the generic DMA code to support deferred probe and
     managed resources
   - New drivers for BCM2835 (used in Raspberry Pi), Tegra with MAX98090
     and Analog Devices AXI I2S and S/PDIF controller IPs
   - Device tree support for the simple card, max98090 and cs42l52
   - Conversion of the Samsung drivers to native dmaengine, making them
     multiplatform compatible and hopefully helping keep them more
     modern and up to date.
   - More regmap conversions, including a very welcome one for twl6040
     from Peter Ujfalusi
   - A big overhaul of the DaVinci drivers also from Peter Ujfalusi
   - Lots of DMA updates from Lars-Peter
   - Improvements to the constraints handling code from Lars-Peter
   - A very helpful conversion of the TWL4030 driver to regmap from Peter
   - A new driver for the Freescale ESAI controller from Nicolin Chen
   - Conversion of some of the drivers to use params_width()
   - Extensions to DPCM for use with compressed audio from Liam"

* tag 'sound-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (396 commits)
  ASoC: dapm: Fix double prefix addition
  ASoC: compress: Add suport for DPCM into compressed audio
  ASoC: DPCM: make some DPCM API calls non static for compressed usage
  ASoC: core: Fix possible NULL pointer dereference of pcm->config
  ALSA: hda - add headset mic detect quirks for some Dell machines
  ASoC: tlv320aic32x4: Fix regmap range_min
  ASoC: core: Return -ENOTSUPP from set_sysclk() if no operation provided
  ASoC: dapm: Change prototype of soc_widget_read
  ASoC: samsung: Remove SND_DMAENGINE_PCM_FLAG_NO_RESIDUE flag
  ASoC: axi-{spdif,i2s}: Remove SND_DMAENGINE_PCM_FLAG_NO_RESIDUE flag
  ASoC: generic-dmaengine-pcm: Check DMA residue granularity
  ASoC: generic-dmaengine-pcm: Check NO_RESIDUE flag at runtime
  dma: pl330: Set residue_granularity
  dma: Indicate residue granularity in dma_slave_caps
  ASoC: simple-card: fix one bug to writing to the platform data
  ASoC: pcm: Use snd_pcm_rate_mask_intersect() helper
  ALSA: Add helper function for intersecting two rate masks
  ASoC: s6000: Don't mix SNDRV_PCM_RATE_CONTINUOUS with specific rates
  ASoC: fsl: Don't mix SNDRV_PCM_RATE_CONTINUOUS with specific rates
  ASoC: pcm: Properly initialize hw->rate_max
  ...
This commit is contained in:
Linus Torvalds 2014-01-21 10:26:23 -08:00
commit d4371f94bc
285 changed files with 12080 additions and 10942 deletions

View File

@ -0,0 +1,31 @@
ADI AXI-I2S controller
Required properties:
- compatible : Must be "adi,axi-i2s-1.00.a"
- reg : Must contain I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
The controller expects two clocks, the clock used for the AXI interface and
the clock used as the sampling rate reference clock sample.
- clock-names : "axi" for the clock to the AXI interface, "ref" for the sample
rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channels that are used by
the core. The core expects two dma channels, one for transmit and one for
receive.
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
i2s: i2s@0x77600000 {
compatible = "adi,axi-i2s-1.00.a";
reg = <0x77600000 0x1000>;
clocks = <&clk 15>, <&audio_clock>;
clock-names = "axi", "ref";
dmas = <&ps7_dma 0>, <&ps7_dma 1>;
dma-names = "tx", "rx";
};

View File

@ -0,0 +1,30 @@
ADI AXI-SPDIF controller
Required properties:
- compatible : Must be "adi,axi-spdif-1.00.a"
- reg : Must contain SPDIF core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
The controller expects two clocks, the clock used for the AXI interface and
the clock used as the sampling rate reference clock sample.
- clock-names: "axi" for the clock to the AXI interface, "ref" for the sample
rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channel that is used by
the core. The core expects one dma channel for transmit.
- dma-names : Must be "tx"
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
spdif: spdif@0x77400000 {
compatible = "adi,axi-spdif-tx-1.00.a";
reg = <0x77600000 0x1000>;
clocks = <&clk 15>, <&audio_clock>;
clock-names = "axi", "ref";
dmas = <&ps7_dma 0>;
dma-names = "tx";
};

View File

@ -0,0 +1,25 @@
* Broadcom BCM2835 SoC I2S/PCM module
Required properties:
- compatible: "brcm,bcm2835-i2s"
- reg: A list of base address and size entries:
* The first entry should cover the PCM registers
* The second entry should cover the PCM clock registers
- dmas: List of DMA controller phandle and DMA request line ordered pairs.
- dma-names: Identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
One of the DMA channels will be responsible for transmission (should be
named "tx") and one for reception (should be named "rx").
Example:
bcm2835_i2s: i2s@7e203000 {
compatible = "brcm,bcm2835-i2s";
reg = <0x7e203000 0x20>,
<0x7e101098 0x02>;
dmas = <&dma 2>,
<&dma 3>;
dma-names = "tx", "rx";
};

View File

@ -0,0 +1,46 @@
CS42L52 audio CODEC
Required properties:
- compatible : "cirrus,cs42l52"
- reg : the I2C address of the device for I2C
Optional properties:
- cirrus,reset-gpio : GPIO controller's phandle and the number
of the GPIO used to reset the codec.
- cirrus,chgfreq-divisor : Values used to set the Charge Pump Frequency.
Allowable values of 0x00 through 0x0F. These are raw values written to the
register, not the actual frequency. The frequency is determined by the following.
Frequency = (64xFs)/(N+2)
N = chgfreq_val
Fs = Sample Rate (variable)
- cirrus,mica-differential-cfg : boolean, If present, then the MICA input is configured
as a differential input. If not present then the MICA input is configured as
Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
- cirrus,micb-differential-cfg : boolean, If present, then the MICB input is configured
as a differential input. If not present then the MICB input is configured as
Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
- cirrus,micbias-lvl: Set the output voltage level on the MICBIAS Pin
0 = 0.5 x VA
1 = 0.6 x VA
2 = 0.7 x VA
3 = 0.8 x VA
4 = 0.83 x VA
5 = 0.91 x VA
Example:
codec: codec@4a {
compatible = "cirrus,cs42l52";
reg = <0x4a>;
reset-gpio = <&gpio 10 0>;
cirrus,chgfreq-divisor = <0x05>;
cirrus.mica-differential-cfg;
cirrus,micbias-lvl = <5>;
};

View File

@ -4,7 +4,8 @@ Required properties:
- compatible :
"ti,dm646x-mcasp-audio" : for DM646x platforms
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx)
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
"ti,dra7-mcasp-audio" : for DRA7xx platforms
- reg : Should contain reg specifiers for the entries in the reg-names property.
- reg-names : Should contain:
@ -36,7 +37,8 @@ Optional properties:
- pinctrl-0: Should specify pin control group used for this controller.
- pinctrl-names: Should contain only one value - "default", for more details
please refer to pinctrl-bindings.txt
- fck_parent : Should contain a valid clock name which will be used as parent
for the McASP fck
Example:

View File

@ -0,0 +1,50 @@
Freescale Enhanced Serial Audio Interface (ESAI) Controller
The Enhanced Serial Audio Interface (ESAI) provides a full-duplex serial port
for serial communication with a variety of serial devices, including industry
standard codecs, Sony/Phillips Digital Interface (S/PDIF) transceivers, and
other DSPs. It has up to six transmitters and four receivers.
Required properties:
- compatible : Compatible list, must contain "fsl,imx35-esai".
- reg : Offset and length of the register set for the device.
- interrupts : Contains the spdif interrupt.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
- clocks: Contains an entry for each entry in clock-names.
- clock-names : Includes the following entries:
"core" The core clock used to access registers
"extal" The esai baud clock for esai controller used to derive
HCK, SCK and FS.
"fsys" The system clock derived from ahb clock used to derive
HCK, SCK and FS.
- fsl,fifo-depth: The number of elements in the transmit and receive FIFOs.
This number is the maximum allowed value for TFCR[TFWM] or RFCR[RFWM].
- fsl,esai-synchronous: This is a boolean property. If present, indicating
that ESAI would work in the synchronous mode, which means all the settings
for Receiving would be duplicated from Transmition related registers.
Example:
esai: esai@02024000 {
compatible = "fsl,imx35-esai";
reg = <0x02024000 0x4000>;
interrupts = <0 51 0x04>;
clocks = <&clks 208>, <&clks 118>, <&clks 208>;
clock-names = "core", "extal", "fsys";
dmas = <&sdma 23 21 0>, <&sdma 24 21 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <128>;
fsl,esai-synchronous;
status = "disabled";
};

View File

@ -4,7 +4,12 @@ The SSI is a serial device that communicates with audio codecs. It can
be programmed in AC97, I2S, left-justified, or right-justified modes.
Required properties:
- compatible: Compatible list, contains "fsl,ssi".
- compatible: Compatible list, should contain one of the following
compatibles:
fsl,mpc8610-ssi
fsl,imx51-ssi
fsl,imx35-ssi
fsl,imx21-ssi
- cell-index: The SSI, <0> = SSI1, <1> = SSI2, and so on.
- reg: Offset and length of the register set for the device.
- interrupts: <a b> where a is the interrupt number and b is a

View File

@ -0,0 +1,40 @@
Freescale Synchronous Audio Interface (SAI).
The SAI is based on I2S module that used communicating with audio codecs,
which provides a synchronous audio interface that supports fullduplex
serial interfaces with frame synchronization such as I2S, AC97, TDM, and
codec/DSP interfaces.
Required properties:
- compatible: Compatible list, contains "fsl,vf610-sai".
- reg: Offset and length of the register set for the device.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names : Must include the "sai" entry.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
See ../pinctrl/pinctrl-bindings.txt for details of the property values.
- big-endian-regs: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
device registers.
- big-endian-data: If this property is absent, the little endian mode will
be in use as default, or the big endian mode will be in use for all the
fifo data.
Example:
sai2: sai@40031000 {
compatible = "fsl,vf610-sai";
reg = <0x40031000 0x1000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_SAI2>;
clock-names = "sai";
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
big-endian-regs;
big-endian-data;
};

View File

@ -0,0 +1,17 @@
Device-Tree bindings for dummy HDMI codec
Required properties:
- compatible: should be "linux,hdmi-audio".
CODEC output pins:
* TX
CODEC input pins:
* RX
Example node:
hdmi_audio: hdmi_audio@0 {
compatible = "linux,hdmi-audio";
status = "okay";
};

View File

@ -0,0 +1,43 @@
MAX98090 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "maxim,max98090".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
Pins on the device (for linking into audio routes):
* MIC1
* MIC2
* DMICL
* DMICR
* IN1
* IN2
* IN3
* IN4
* IN5
* IN6
* IN12
* IN34
* IN56
* HPL
* HPR
* SPKL
* SPKR
* RCVL
* RCVR
* MICBIAS
Example:
audio-codec@10 {
compatible = "maxim,max98090";
reg = <0x10>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
};

View File

@ -0,0 +1,51 @@
NVIDIA Tegra audio complex, with MAX98090 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-max98090"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- 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 MAX98090's pins (as documented in its binding), and the jacks
on the board:
* Headphones
* Speakers
* Mic Jack
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
Example:
sound {
compatible = "nvidia,tegra-audio-max98090-venice2",
"nvidia,tegra-audio-max98090";
nvidia,model = "NVIDIA Tegra Venice2";
nvidia,audio-routing =
"Headphones", "HPR",
"Headphones", "HPL",
"Speakers", "SPKR",
"Speakers", "SPKL",
"Mic Jack", "MICBIAS",
"IN34", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&acodec>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};

View File

@ -0,0 +1,77 @@
Simple-Card:
Simple-Card specifies audio DAI connection of SoC <-> codec.
Required properties:
- compatible : "simple-audio-card"
Optional properties:
- simple-audio-card,format : CPU/CODEC common audio format.
"i2s", "right_j", "left_j" , "dsp_a"
"dsp_b", "ac97", "pdm", "msb", "lsb"
- simple-audio-card,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.
Required subnodes:
- simple-audio-card,cpu : CPU sub-node
- simple-audio-card,codec : CODEC sub-node
Required CPU/CODEC subnodes properties:
- sound-dai : phandle and port of CPU/CODEC
Optional CPU/CODEC subnodes properties:
- format : CPU/CODEC specific audio format if needed.
see simple-audio-card,format
- frame-master : bool property. add this if subnode is frame master
- bitclock-master : bool property. add this if subnode is bitclock master
- bitclock-inversion : bool property. add this if subnode has clock inversion
- frame-inversion : bool property. add this if subnode has frame inversion
- clocks / system-clock-frequency : specify subnode's clock if needed.
it can be specified via "clocks" if system has
clock node (= common clock), or "system-clock-frequency"
(if system doens't support common clock)
Example:
sound {
compatible = "simple-audio-card";
simple-audio-card,format = "left_j";
simple-audio-routing =
"MIC_IN", "Mic Jack",
"Headphone Jack", "HP_OUT",
"Ext Spk", "LINE_OUT";
simple-audio-card,cpu {
sound-dai = <&sh_fsi2 0>;
};
simple-audio-card,codec {
sound-dai = <&ak4648>;
bitclock-master;
frame-master;
clocks = <&osc>;
};
};
&i2c0 {
ak4648: ak4648@12 {
#sound-dai-cells = <0>;
compatible = "asahi-kasei,ak4648";
reg = <0x12>;
};
};
sh_fsi2: sh_fsi2@ec230000 {
#sound-dai-cells = <1>;
compatible = "renesas,sh_fsi2";
reg = <0xec230000 0x400>;
interrupt-parent = <&gic>;
interrupts = <0 146 0x4>;
};

View File

@ -6,6 +6,7 @@ Required properties:
- compatible - "string" - One of:
"ti,tlv320aic3x" - Generic TLV320AIC3x device
"ti,tlv320aic32x4" - TLV320AIC32x4
"ti,tlv320aic33" - TLV320AIC33
"ti,tlv320aic3007" - TLV320AIC3007
"ti,tlv320aic3106" - TLV320AIC3106

View File

@ -49,18 +49,23 @@ features :-
* Machine specific controls: Allow machines to add controls to the sound card
(e.g. volume control for speaker amplifier).
To achieve all this, ASoC basically splits an embedded audio system into 3
components :-
To achieve all this, ASoC basically splits an embedded audio system into
multiple re-usable component drivers :-
* Codec driver: The codec driver is platform independent and contains audio
controls, audio interface capabilities, codec DAPM definition and codec IO
functions.
* Codec class drivers: The codec class driver is platform independent and
contains audio controls, audio interface capabilities, codec DAPM
definition and codec IO functions. This class extends to BT, FM and MODEM
ICs if required. Codec class drivers should be generic code that can run
on any architecture and machine.
* Platform driver: The platform driver contains the audio DMA engine and audio
interface drivers (e.g. I2S, AC97, PCM) for that platform.
* Platform class drivers: The platform class driver includes the audio DMA
engine driver, digital audio interface (DAI) drivers (e.g. I2S, AC97, PCM)
and any audio DSP drivers for that platform.
* Machine driver: The machine driver handles any machine specific controls and
audio events (e.g. turning on an amp at start of playback).
* Machine class driver: The machine driver class acts as the glue that
decribes and binds the other component drivers together to form an ALSA
"sound card device". It handles any machine specific controls and
machine level audio events (e.g. turning on an amp at start of playback).
Documentation
@ -84,3 +89,7 @@ machine.txt: Machine driver internals.
pop_clicks.txt: How to minimise audio artifacts.
clocking.txt: ASoC clocking for best power performance.
jack.txt: ASoC jack detection.
DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.

View File

@ -723,6 +723,7 @@ config ARCH_S3C64XX
bool "Samsung S3C64XX"
select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select ARM_AMBA
select ARM_VIC
select CLKDEV_LOOKUP
select CLKSRC_SAMSUNG_PWM

View File

@ -17,9 +17,10 @@ config CPU_S3C6410
help
Enable S3C6410 CPU support
config S3C64XX_DMA
bool "S3C64XX DMA"
select S3C_DMA
config S3C64XX_PL080
bool "S3C64XX DMA using generic PL08x driver"
select AMBA_PL08X
select SAMSUNG_DMADEV
config S3C64XX_SETUP_SDHCI
bool

View File

@ -26,7 +26,7 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle.o
# DMA support
obj-$(CONFIG_S3C64XX_DMA) += dma.o
obj-$(CONFIG_S3C64XX_PL080) += pl080.o
# Device support

View File

@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
static inline int s3c64xx_pm_late_initcall(void) { return 0; }
#endif
#ifdef CONFIG_S3C64XX_PL080
extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
#endif
#endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */

View File

@ -1,762 +0,0 @@
/* linux/arch/arm/plat-s3c64xx/dma.c
*
* Copyright 2009 Openmoko, Inc.
* Copyright 2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C64XX DMA core
*
* 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.
*/
/*
* NOTE: Code in this file is not used when booting with Device Tree support.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/dmapool.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/amba/pl080.h>
#include <linux/of.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include "regs-sys.h"
/* dma channel state information */
struct s3c64xx_dmac {
struct device dev;
struct clk *clk;
void __iomem *regs;
struct s3c2410_dma_chan *channels;
enum dma_ch chanbase;
};
/* pool to provide LLI buffers */
static struct dma_pool *dma_pool;
/* Debug configuration and code */
static unsigned char debug_show_buffs = 0;
static void dbg_showchan(struct s3c2410_dma_chan *chan)
{
pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
chan->number,
readl(chan->regs + PL080_CH_SRC_ADDR),
readl(chan->regs + PL080_CH_DST_ADDR),
readl(chan->regs + PL080_CH_LLI),
readl(chan->regs + PL080_CH_CONTROL),
readl(chan->regs + PL080S_CH_CONTROL2),
readl(chan->regs + PL080S_CH_CONFIG));
}
static void show_lli(struct pl080s_lli *lli)
{
pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
lli, lli->src_addr, lli->dst_addr, lli->next_lli,
lli->control0, lli->control1);
}
static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
{
struct s3c64xx_dma_buff *ptr;
struct s3c64xx_dma_buff *end;
pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
chan->number, chan->next, chan->curr, chan->end);
ptr = chan->next;
end = chan->end;
if (debug_show_buffs) {
for (; ptr != NULL; ptr = ptr->next) {
pr_debug("DMA%d: %08x ",
chan->number, ptr->lli_dma);
show_lli(ptr->lli);
}
}
}
/* End of Debug */
static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
{
struct s3c2410_dma_chan *chan;
unsigned int start, offs;
start = 0;
if (channel >= DMACH_PCM1_TX)
start = 8;
for (offs = 0; offs < 8; offs++) {
chan = &s3c2410_chans[start + offs];
if (!chan->in_use)
goto found;
}
return NULL;
found:
s3c_dma_chan_map[channel] = chan;
return chan;
}
int s3c2410_dma_config(enum dma_ch channel, int xferunit)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
if (chan == NULL)
return -EINVAL;
switch (xferunit) {
case 1:
chan->hw_width = 0;
break;
case 2:
chan->hw_width = 1;
break;
case 4:
chan->hw_width = 2;
break;
default:
printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_config);
static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
struct pl080s_lli *lli,
dma_addr_t data, int size)
{
dma_addr_t src, dst;
u32 control0, control1;
switch (chan->source) {
case DMA_FROM_DEVICE:
src = chan->dev_addr;
dst = data;
control0 = PL080_CONTROL_SRC_AHB2;
control0 |= PL080_CONTROL_DST_INCR;
break;
case DMA_TO_DEVICE:
src = data;
dst = chan->dev_addr;
control0 = PL080_CONTROL_DST_AHB2;
control0 |= PL080_CONTROL_SRC_INCR;
break;
default:
BUG();
}
/* note, we do not currently setup any of the burst controls */
control1 = size >> chan->hw_width; /* size in no of xfers */
control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */
control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */
control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
lli->src_addr = src;
lli->dst_addr = dst;
lli->next_lli = 0;
lli->control0 = control0;
lli->control1 = control1;
}
static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
struct pl080s_lli *lli)
{
void __iomem *regs = chan->regs;
pr_debug("%s: LLI %p => regs\n", __func__, lli);
show_lli(lli);
writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
writel(lli->next_lli, regs + PL080_CH_LLI);
writel(lli->control0, regs + PL080_CH_CONTROL);
writel(lli->control1, regs + PL080S_CH_CONTROL2);
}
static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
{
struct s3c64xx_dmac *dmac = chan->dmac;
u32 config;
u32 bit = chan->bit;
dbg_showchan(chan);
pr_debug("%s: clearing interrupts\n", __func__);
/* clear interrupts */
writel(bit, dmac->regs + PL080_TC_CLEAR);
writel(bit, dmac->regs + PL080_ERR_CLEAR);
pr_debug("%s: starting channel\n", __func__);
config = readl(chan->regs + PL080S_CH_CONFIG);
config |= PL080_CONFIG_ENABLE;
config &= ~PL080_CONFIG_HALT;
pr_debug("%s: writing config %08x\n", __func__, config);
writel(config, chan->regs + PL080S_CH_CONFIG);
return 0;
}
static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
{
u32 config;
int timeout;
pr_debug("%s: stopping channel\n", __func__);
dbg_showchan(chan);
config = readl(chan->regs + PL080S_CH_CONFIG);
config |= PL080_CONFIG_HALT;
writel(config, chan->regs + PL080S_CH_CONFIG);
timeout = 1000;
do {
config = readl(chan->regs + PL080S_CH_CONFIG);
pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
if (config & PL080_CONFIG_ACTIVE)
udelay(10);
else
break;
} while (--timeout > 0);
if (config & PL080_CONFIG_ACTIVE) {
printk(KERN_ERR "%s: channel still active\n", __func__);
return -EFAULT;
}
config = readl(chan->regs + PL080S_CH_CONFIG);
config &= ~PL080_CONFIG_ENABLE;
writel(config, chan->regs + PL080S_CH_CONFIG);
return 0;
}
static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
struct s3c64xx_dma_buff *buf,
enum s3c2410_dma_buffresult result)
{
if (chan->callback_fn != NULL)
(chan->callback_fn)(chan, buf->pw, 0, result);
}
static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
{
dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
kfree(buff);
}
static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
{
struct s3c64xx_dma_buff *buff, *next;
u32 config;
dbg_showchan(chan);
pr_debug("%s: flushing channel\n", __func__);
config = readl(chan->regs + PL080S_CH_CONFIG);
config &= ~PL080_CONFIG_ENABLE;
writel(config, chan->regs + PL080S_CH_CONFIG);
/* dump all the buffers associated with this channel */
for (buff = chan->curr; buff != NULL; buff = next) {
next = buff->next;
pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
s3c64xx_dma_freebuff(buff);
}
chan->curr = chan->next = chan->end = NULL;
return 0;
}
int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
WARN_ON(!chan);
if (!chan)
return -EINVAL;
switch (op) {
case S3C2410_DMAOP_START:
return s3c64xx_dma_start(chan);
case S3C2410_DMAOP_STOP:
return s3c64xx_dma_stop(chan);
case S3C2410_DMAOP_FLUSH:
return s3c64xx_dma_flush(chan);
/* believe PAUSE/RESUME are no-ops */
case S3C2410_DMAOP_PAUSE:
case S3C2410_DMAOP_RESUME:
case S3C2410_DMAOP_STARTED:
case S3C2410_DMAOP_TIMEOUT:
return 0;
}
return -ENOENT;
}
EXPORT_SYMBOL(s3c2410_dma_ctrl);
/* s3c2410_dma_enque
*
*/
int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
dma_addr_t data, int size)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
struct s3c64xx_dma_buff *next;
struct s3c64xx_dma_buff *buff;
struct pl080s_lli *lli;
unsigned long flags;
int ret;
WARN_ON(!chan);
if (!chan)
return -EINVAL;
buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
if (!buff) {
printk(KERN_ERR "%s: no memory for buffer\n", __func__);
return -ENOMEM;
}
lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
if (!lli) {
printk(KERN_ERR "%s: no memory for lli\n", __func__);
ret = -ENOMEM;
goto err_buff;
}
pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
__func__, buff, data, lli, (u32)buff->lli_dma, size);
buff->lli = lli;
buff->pw = id;
s3c64xx_dma_fill_lli(chan, lli, data, size);
local_irq_save(flags);
if ((next = chan->next) != NULL) {
struct s3c64xx_dma_buff *end = chan->end;
struct pl080s_lli *endlli = end->lli;
pr_debug("enquing onto channel\n");
end->next = buff;
endlli->next_lli = buff->lli_dma;
if (chan->flags & S3C2410_DMAF_CIRCULAR) {
struct s3c64xx_dma_buff *curr = chan->curr;
lli->next_lli = curr->lli_dma;
}
if (next == chan->curr) {
writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
chan->next = buff;
}
show_lli(endlli);
chan->end = buff;
} else {
pr_debug("enquing onto empty channel\n");
chan->curr = buff;
chan->next = buff;
chan->end = buff;
s3c64xx_lli_to_regs(chan, lli);
}
local_irq_restore(flags);
show_lli(lli);
dbg_showchan(chan);
dbg_showbuffs(chan);
return 0;
err_buff:
kfree(buff);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_enqueue);
int s3c2410_dma_devconfig(enum dma_ch channel,
enum dma_data_direction source,
unsigned long devaddr)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
u32 peripheral;
u32 config = 0;
pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
__func__, channel, source, devaddr, chan);
WARN_ON(!chan);
if (!chan)
return -EINVAL;
peripheral = (chan->peripheral & 0xf);
chan->source = source;
chan->dev_addr = devaddr;
pr_debug("%s: peripheral %d\n", __func__, peripheral);
switch (source) {
case DMA_FROM_DEVICE:
config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
break;
case DMA_TO_DEVICE:
config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
break;
default:
printk(KERN_ERR "%s: bad source\n", __func__);
return -EINVAL;
}
/* allow TC and ERR interrupts */
config |= PL080_CONFIG_TC_IRQ_MASK;
config |= PL080_CONFIG_ERR_IRQ_MASK;
pr_debug("%s: config %08x\n", __func__, config);
writel(config, chan->regs + PL080S_CH_CONFIG);
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_devconfig);
int s3c2410_dma_getposition(enum dma_ch channel,
dma_addr_t *src, dma_addr_t *dst)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
WARN_ON(!chan);
if (!chan)
return -EINVAL;
if (src != NULL)
*src = readl(chan->regs + PL080_CH_SRC_ADDR);
if (dst != NULL)
*dst = readl(chan->regs + PL080_CH_DST_ADDR);
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_getposition);
/* s3c2410_request_dma
*
* get control of an dma channel
*/
int s3c2410_dma_request(enum dma_ch channel,
struct s3c2410_dma_client *client,
void *dev)
{
struct s3c2410_dma_chan *chan;
unsigned long flags;
pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
channel, client->name, dev);
local_irq_save(flags);
chan = s3c64xx_dma_map_channel(channel);
if (chan == NULL) {
local_irq_restore(flags);
return -EBUSY;
}
dbg_showchan(chan);
chan->client = client;
chan->in_use = 1;
chan->peripheral = channel;
chan->flags = 0;
local_irq_restore(flags);
/* need to setup */
pr_debug("%s: channel initialised, %p\n", __func__, chan);
return chan->number | DMACH_LOW_LEVEL;
}
EXPORT_SYMBOL(s3c2410_dma_request);
/* s3c2410_dma_free
*
* release the given channel back to the system, will stop and flush
* any outstanding transfers, and ensure the channel is ready for the
* next claimant.
*
* Note, although a warning is currently printed if the freeing client
* info is not the same as the registrant's client info, the free is still
* allowed to go through.
*/
int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
unsigned long flags;
if (chan == NULL)
return -EINVAL;
local_irq_save(flags);
if (chan->client != client) {
printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
channel, chan->client, client);
}
/* sort out stopping and freeing the channel */
chan->client = NULL;
chan->in_use = 0;
if (!(channel & DMACH_LOW_LEVEL))
s3c_dma_chan_map[channel] = NULL;
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_free);
static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
{
struct s3c64xx_dmac *dmac = pw;
struct s3c2410_dma_chan *chan;
enum s3c2410_dma_buffresult res;
u32 tcstat, errstat;
u32 bit;
int offs;
tcstat = readl(dmac->regs + PL080_TC_STATUS);
errstat = readl(dmac->regs + PL080_ERR_STATUS);
for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
struct s3c64xx_dma_buff *buff;
if (!(errstat & bit) && !(tcstat & bit))
continue;
chan = dmac->channels + offs;
res = S3C2410_RES_ERR;
if (tcstat & bit) {
writel(bit, dmac->regs + PL080_TC_CLEAR);
res = S3C2410_RES_OK;
}
if (errstat & bit)
writel(bit, dmac->regs + PL080_ERR_CLEAR);
/* 'next' points to the buffer that is next to the
* currently active buffer.
* For CIRCULAR queues, 'next' will be same as 'curr'
* when 'end' is the active buffer.
*/
buff = chan->curr;
while (buff && buff != chan->next
&& buff->next != chan->next)
buff = buff->next;
if (!buff)
BUG();
if (buff == chan->next)
buff = chan->end;
s3c64xx_dma_bufffdone(chan, buff, res);
/* Free the node and update curr, if non-circular queue */
if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
chan->curr = buff->next;
s3c64xx_dma_freebuff(buff);
}
/* Update 'next' */
buff = chan->next;
if (chan->next == chan->end) {
chan->next = chan->curr;
if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
chan->end = NULL;
} else {
chan->next = buff->next;
}
}
return IRQ_HANDLED;
}
static struct bus_type dma_subsys = {
.name = "s3c64xx-dma",
.dev_name = "s3c64xx-dma",
};
static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
int irq, unsigned int base)
{
struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
struct s3c64xx_dmac *dmac;
char clkname[16];
void __iomem *regs;
void __iomem *regptr;
int err, ch;
dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
if (!dmac) {
printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
return -ENOMEM;
}
dmac->dev.id = chno / 8;
dmac->dev.bus = &dma_subsys;
err = device_register(&dmac->dev);
if (err) {
printk(KERN_ERR "%s: failed to register device\n", __func__);
goto err_alloc;
}
regs = ioremap(base, 0x200);
if (!regs) {
printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
err = -ENXIO;
goto err_dev;
}
snprintf(clkname, sizeof(clkname), "dma%d", dmac->dev.id);
dmac->clk = clk_get(NULL, clkname);
if (IS_ERR(dmac->clk)) {
printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
err = PTR_ERR(dmac->clk);
goto err_map;
}
clk_prepare_enable(dmac->clk);
dmac->regs = regs;
dmac->chanbase = chbase;
dmac->channels = chptr;
err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
if (err < 0) {
printk(KERN_ERR "%s: failed to get irq\n", __func__);
goto err_clk;
}
regptr = regs + PL080_Cx_BASE(0);
for (ch = 0; ch < 8; ch++, chptr++) {
pr_debug("%s: registering DMA %d (%p)\n",
__func__, chno + ch, regptr);
chptr->bit = 1 << ch;
chptr->number = chno + ch;
chptr->dmac = dmac;
chptr->regs = regptr;
regptr += PL080_Cx_STRIDE;
}
/* for the moment, permanently enable the controller */
writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n",
irq, regs, chno, chno+8);
return 0;
err_clk:
clk_disable_unprepare(dmac->clk);
clk_put(dmac->clk);
err_map:
iounmap(regs);
err_dev:
device_unregister(&dmac->dev);
err_alloc:
kfree(dmac);
return err;
}
static int __init s3c64xx_dma_init(void)
{
int ret;
/* This driver is not supported when booting with device tree. */
if (of_have_populated_dt())
return -ENODEV;
printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
if (!dma_pool) {
printk(KERN_ERR "%s: failed to create pool\n", __func__);
return -ENOMEM;
}
ret = subsys_system_register(&dma_subsys, NULL);
if (ret) {
printk(KERN_ERR "%s: failed to create subsys\n", __func__);
return -ENOMEM;
}
/* Set all DMA configuration to be DMA, not SDMA */
writel(0xffffff, S3C64XX_SDMA_SEL);
/* Register standard DMA controllers */
s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
return 0;
}
arch_initcall(s3c64xx_dma_init);

View File

@ -11,51 +11,48 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H __FILE__
#define S3C_DMA_CHANNELS (16)
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
/* see mach-s3c2410/dma.h for notes on dma channel numbers */
/* DMA0/SDMA0 */
#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
/* DMA1/SDMA1 */
#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
/* Note, for the S3C64XX architecture we keep the DMACH_
* defines in the order they are allocated to [S]DMA0/[S]DMA1
* so that is easy to do DHACH_ -> DMA controller conversion
*/
enum dma_ch {
/* DMA0/SDMA0 */
DMACH_UART0 = 0,
DMACH_UART0_SRC2,
DMACH_UART1,
DMACH_UART1_SRC2,
DMACH_UART2,
DMACH_UART2_SRC2,
DMACH_UART3,
DMACH_UART3_SRC2,
DMACH_PCM0_TX,
DMACH_PCM0_RX,
DMACH_I2S0_OUT,
DMACH_I2S0_IN,
DMACH_SPI0_TX,
DMACH_SPI0_RX,
DMACH_HSI_I2SV40_TX,
DMACH_HSI_I2SV40_RX,
DMACH_MAX = 32
};
/* DMA1/SDMA1 */
DMACH_PCM1_TX = 16,
DMACH_PCM1_RX,
DMACH_I2S1_OUT,
DMACH_I2S1_IN,
DMACH_SPI1_TX,
DMACH_SPI1_RX,
DMACH_AC97_PCMOUT,
DMACH_AC97_PCMIN,
DMACH_AC97_MICIN,
DMACH_PWM,
DMACH_IRDA,
DMACH_EXTERNAL,
DMACH_RES1,
DMACH_RES2,
DMACH_SECURITY_RX, /* SDMA1 only */
DMACH_SECURITY_TX, /* SDMA1 only */
DMACH_MAX /* the end */
struct s3c2410_dma_client {
char *name;
};
static inline bool samsung_dma_has_circular(void)
@ -65,67 +62,10 @@ static inline bool samsung_dma_has_circular(void)
static inline bool samsung_dma_is_dmadev(void)
{
return false;
return true;
}
#define S3C2410_DMAF_CIRCULAR (1 << 0)
#include <plat/dma.h>
#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
struct s3c64xx_dma_buff;
/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
* @next: Pointer to next buffer in queue or ring.
* @pw: Client provided identifier
* @lli: Pointer to hardware descriptor this buffer is associated with.
* @lli_dma: Hardare address of the descriptor.
*/
struct s3c64xx_dma_buff {
struct s3c64xx_dma_buff *next;
void *pw;
struct pl080s_lli *lli;
dma_addr_t lli_dma;
};
struct s3c64xx_dmac;
struct s3c2410_dma_chan {
unsigned char number; /* number of this dma channel */
unsigned char in_use; /* channel allocated */
unsigned char bit; /* bit for enable/disable/etc */
unsigned char hw_width;
unsigned char peripheral;
unsigned int flags;
enum dma_data_direction source;
dma_addr_t dev_addr;
struct s3c2410_dma_client *client;
struct s3c64xx_dmac *dmac; /* pointer to controller */
void __iomem *regs;
/* cdriver callbacks */
s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
s3c2410_dma_opfn_t op_fn; /* channel op callback */
/* buffer list and information */
struct s3c64xx_dma_buff *curr; /* current dma buffer */
struct s3c64xx_dma_buff *next; /* next buffer to load */
struct s3c64xx_dma_buff *end; /* end of queue */
/* note, when channel is running in circular mode, curr is the
* first buffer enqueued, end is the last and curr is where the
* last buffer-done event is set-at. The buffers are not freed
* and the last buffer hardware descriptor points back to the
* first.
*/
};
#include <plat/dma-core.h>
#include <linux/amba/pl08x.h>
#include <plat/dma-ops.h>
#endif /* __ASM_ARCH_IRQ_H */

View File

@ -0,0 +1,244 @@
/*
* Samsung's S3C64XX generic DMA support using amba-pl08x driver.
*
* Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.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.
*/
#include <linux/kernel.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl080.h>
#include <linux/amba/pl08x.h>
#include <linux/of.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include "regs-sys.h"
static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
{
return cd->min_signal;
}
static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
{
}
/*
* DMA0
*/
static struct pl08x_channel_data s3c64xx_dma0_info[] = {
{
.bus_id = "uart0_tx",
.min_signal = 0,
.max_signal = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart0_rx",
.min_signal = 1,
.max_signal = 1,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_tx",
.min_signal = 2,
.max_signal = 2,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_rx",
.min_signal = 3,
.max_signal = 3,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_tx",
.min_signal = 4,
.max_signal = 4,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_rx",
.min_signal = 5,
.max_signal = 5,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart3_tx",
.min_signal = 6,
.max_signal = 6,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart3_rx",
.min_signal = 7,
.max_signal = 7,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm0_tx",
.min_signal = 8,
.max_signal = 8,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm0_rx",
.min_signal = 9,
.max_signal = 9,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s0_tx",
.min_signal = 10,
.max_signal = 10,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s0_rx",
.min_signal = 11,
.max_signal = 11,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi0_tx",
.min_signal = 12,
.max_signal = 12,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi0_rx",
.min_signal = 13,
.max_signal = 13,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s2_tx",
.min_signal = 14,
.max_signal = 14,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s2_rx",
.min_signal = 15,
.max_signal = 15,
.periph_buses = PL08X_AHB2,
}
};
struct pl08x_platform_data s3c64xx_dma0_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl_memcpy =
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal,
.put_xfer_signal = pl08x_put_xfer_signal,
.slave_channels = s3c64xx_dma0_info,
.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
};
static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
/*
* DMA1
*/
static struct pl08x_channel_data s3c64xx_dma1_info[] = {
{
.bus_id = "pcm1_tx",
.min_signal = 0,
.max_signal = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pcm1_rx",
.min_signal = 1,
.max_signal = 1,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s1_tx",
.min_signal = 2,
.max_signal = 2,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s1_rx",
.min_signal = 3,
.max_signal = 3,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi1_tx",
.min_signal = 4,
.max_signal = 4,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "spi1_rx",
.min_signal = 5,
.max_signal = 5,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_out",
.min_signal = 6,
.max_signal = 6,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_in",
.min_signal = 7,
.max_signal = 7,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ac97_mic",
.min_signal = 8,
.max_signal = 8,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "pwm",
.min_signal = 9,
.max_signal = 9,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "irda",
.min_signal = 10,
.max_signal = 10,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "external",
.min_signal = 11,
.max_signal = 11,
.periph_buses = PL08X_AHB2,
},
};
struct pl08x_platform_data s3c64xx_dma1_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl_memcpy =
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal,
.put_xfer_signal = pl08x_put_xfer_signal,
.slave_channels = s3c64xx_dma1_info,
.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
};
static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
static int __init s3c64xx_pl080_init(void)
{
/* Set all DMA configuration to be DMA, not SDMA */
writel(0xffffff, S3C64XX_SDMA_SEL);
if (of_have_populated_dt())
return 0;
amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
return 0;
}
arch_initcall(s3c64xx_pl080_init);

View File

@ -31,7 +31,7 @@ static struct stedma40_chan_cfg msp0_dma_tx = {
};
struct msp_i2s_platform_data msp0_platform_data = {
.id = MSP_I2S_0,
.id = 0,
.msp_i2s_dma_rx = &msp0_dma_rx,
.msp_i2s_dma_tx = &msp0_dma_tx,
};
@ -49,7 +49,7 @@ static struct stedma40_chan_cfg msp1_dma_tx = {
};
struct msp_i2s_platform_data msp1_platform_data = {
.id = MSP_I2S_1,
.id = 1,
.msp_i2s_dma_rx = NULL,
.msp_i2s_dma_tx = &msp1_dma_tx,
};
@ -69,13 +69,13 @@ static struct stedma40_chan_cfg msp2_dma_tx = {
};
struct msp_i2s_platform_data msp2_platform_data = {
.id = MSP_I2S_2,
.id = 2,
.msp_i2s_dma_rx = &msp2_dma_rx,
.msp_i2s_dma_tx = &msp2_dma_tx,
};
struct msp_i2s_platform_data msp3_platform_data = {
.id = MSP_I2S_3,
.id = 3,
.msp_i2s_dma_rx = &msp1_dma_rx,
.msp_i2s_dma_tx = NULL,
};

View File

@ -1468,6 +1468,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#elif defined(CONFIG_S3C24XX_DMAC)
pd.filter = s3c24xx_dma_filter;
#endif
@ -1509,8 +1511,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
#ifdef CONFIG_PL330_DMA
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
@ -1550,8 +1554,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
#ifdef CONFIG_PL330_DMA
#if defined(CONFIG_PL330_DMA)
pd.filter = pl330_filter;
#elif defined(CONFIG_S3C64XX_PL080)
pd.filter = pl08x_filter_id;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);

View File

@ -18,6 +18,12 @@
#include <mach/dma.h>
#if defined(CONFIG_PL330_DMA)
#define dma_filter pl330_filter
#elif defined(CONFIG_S3C64XX_PL080)
#define dma_filter pl08x_filter_id
#endif
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
struct samsung_dma_req *param,
struct device *dev, char *ch_name)
@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
if (dev->of_node)
return (unsigned)dma_request_slave_channel(dev, ch_name);
else
return (unsigned)dma_request_channel(mask, pl330_filter,
return (unsigned)dma_request_channel(mask, dma_filter,
(void *)dma_ch);
}

View File

@ -331,8 +331,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(HCLK_DMA1, NULL, "dma1"),
ALIAS(HCLK_DMA0, NULL, "dma0"),
ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),

View File

@ -540,6 +540,8 @@ EXPORT_SYMBOL_GPL(dma_get_slave_channel);
* @mask: capabilities that the channel must satisfy
* @fn: optional callback to disposition available channels
* @fn_param: opaque parameter to pass to dma_filter_fn
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param)
@ -591,18 +593,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name)
{
struct dma_chan *chan;
/* If device-tree is present get slave info from here */
if (dev->of_node)
return of_dma_request_slave_channel(dev->of_node, name);
/* If device was enumerated by ACPI get slave info from here */
if (ACPI_HANDLE(dev))
return acpi_dma_request_slave_chan_by_name(dev, name);
if (ACPI_HANDLE(dev)) {
chan = acpi_dma_request_slave_chan_by_name(dev, name);
if (chan)
return chan;
}
return NULL;
return ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
if (IS_ERR(ch))
return NULL;
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);

View File

@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
* @np: device node to get DMA request from
* @name: name of desired channel
*
* Returns pointer to appropriate dma channel on success or NULL on error.
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name)
@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
struct of_dma *ofdma;
struct dma_chan *chan;
int count, i;
int ret_no_channel = -ENODEV;
if (!np || !name) {
pr_err("%s: not enough information provided\n", __func__);
return NULL;
return ERR_PTR(-ENODEV);
}
count = of_property_count_strings(np, "dma-names");
if (count < 0) {
pr_err("%s: dma-names property of node '%s' missing or empty\n",
__func__, np->full_name);
return NULL;
return ERR_PTR(-ENODEV);
}
for (i = 0; i < count; i++) {
@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
mutex_lock(&of_dma_lock);
ofdma = of_dma_find_controller(&dma_spec);
if (ofdma)
if (ofdma) {
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
else
} else {
ret_no_channel = -EPROBE_DEFER;
chan = NULL;
}
mutex_unlock(&of_dma_lock);
@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return chan;
}
return NULL;
return ERR_PTR(ret_no_channel);
}
/**

View File

@ -2884,6 +2884,7 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
caps->cmd_pause = false;
caps->cmd_terminate = true;
caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
return 0;
}

View File

@ -47,6 +47,9 @@
#include <linux/i2c.h>
#include <linux/i2c/twl.h>
/* Register descriptions for audio */
#include <linux/mfd/twl4030-audio.h>
#include "twl-core.h"
/*
@ -200,6 +203,105 @@ static struct twl_mapping twl4030_map[] = {
{ 2, TWL5031_BASEADD_INTERRUPTS },
};
static struct reg_default twl4030_49_defaults[] = {
/* Audio Registers */
{ 0x01, 0x00}, /* CODEC_MODE */
{ 0x02, 0x00}, /* OPTION */
/* 0x03 Unused */
{ 0x04, 0x00}, /* MICBIAS_CTL */
{ 0x05, 0x00}, /* ANAMICL */
{ 0x06, 0x00}, /* ANAMICR */
{ 0x07, 0x00}, /* AVADC_CTL */
{ 0x08, 0x00}, /* ADCMICSEL */
{ 0x09, 0x00}, /* DIGMIXING */
{ 0x0a, 0x0f}, /* ATXL1PGA */
{ 0x0b, 0x0f}, /* ATXR1PGA */
{ 0x0c, 0x0f}, /* AVTXL2PGA */
{ 0x0d, 0x0f}, /* AVTXR2PGA */
{ 0x0e, 0x00}, /* AUDIO_IF */
{ 0x0f, 0x00}, /* VOICE_IF */
{ 0x10, 0x3f}, /* ARXR1PGA */
{ 0x11, 0x3f}, /* ARXL1PGA */
{ 0x12, 0x3f}, /* ARXR2PGA */
{ 0x13, 0x3f}, /* ARXL2PGA */
{ 0x14, 0x25}, /* VRXPGA */
{ 0x15, 0x00}, /* VSTPGA */
{ 0x16, 0x00}, /* VRX2ARXPGA */
{ 0x17, 0x00}, /* AVDAC_CTL */
{ 0x18, 0x00}, /* ARX2VTXPGA */
{ 0x19, 0x32}, /* ARXL1_APGA_CTL*/
{ 0x1a, 0x32}, /* ARXR1_APGA_CTL*/
{ 0x1b, 0x32}, /* ARXL2_APGA_CTL*/
{ 0x1c, 0x32}, /* ARXR2_APGA_CTL*/
{ 0x1d, 0x00}, /* ATX2ARXPGA */
{ 0x1e, 0x00}, /* BT_IF */
{ 0x1f, 0x55}, /* BTPGA */
{ 0x20, 0x00}, /* BTSTPGA */
{ 0x21, 0x00}, /* EAR_CTL */
{ 0x22, 0x00}, /* HS_SEL */
{ 0x23, 0x00}, /* HS_GAIN_SET */
{ 0x24, 0x00}, /* HS_POPN_SET */
{ 0x25, 0x00}, /* PREDL_CTL */
{ 0x26, 0x00}, /* PREDR_CTL */
{ 0x27, 0x00}, /* PRECKL_CTL */
{ 0x28, 0x00}, /* PRECKR_CTL */
{ 0x29, 0x00}, /* HFL_CTL */
{ 0x2a, 0x00}, /* HFR_CTL */
{ 0x2b, 0x05}, /* ALC_CTL */
{ 0x2c, 0x00}, /* ALC_SET1 */
{ 0x2d, 0x00}, /* ALC_SET2 */
{ 0x2e, 0x00}, /* BOOST_CTL */
{ 0x2f, 0x00}, /* SOFTVOL_CTL */
{ 0x30, 0x13}, /* DTMF_FREQSEL */
{ 0x31, 0x00}, /* DTMF_TONEXT1H */
{ 0x32, 0x00}, /* DTMF_TONEXT1L */
{ 0x33, 0x00}, /* DTMF_TONEXT2H */
{ 0x34, 0x00}, /* DTMF_TONEXT2L */
{ 0x35, 0x79}, /* DTMF_TONOFF */
{ 0x36, 0x11}, /* DTMF_WANONOFF */
{ 0x37, 0x00}, /* I2S_RX_SCRAMBLE_H */
{ 0x38, 0x00}, /* I2S_RX_SCRAMBLE_M */
{ 0x39, 0x00}, /* I2S_RX_SCRAMBLE_L */
{ 0x3a, 0x06}, /* APLL_CTL */
{ 0x3b, 0x00}, /* DTMF_CTL */
{ 0x3c, 0x44}, /* DTMF_PGA_CTL2 (0x3C) */
{ 0x3d, 0x69}, /* DTMF_PGA_CTL1 (0x3D) */
{ 0x3e, 0x00}, /* MISC_SET_1 */
{ 0x3f, 0x00}, /* PCMBTMUX */
/* 0x40 - 0x42 Unused */
{ 0x43, 0x00}, /* RX_PATH_SEL */
{ 0x44, 0x32}, /* VDL_APGA_CTL */
{ 0x45, 0x00}, /* VIBRA_CTL */
{ 0x46, 0x00}, /* VIBRA_SET */
{ 0x47, 0x00}, /* VIBRA_PWM_SET */
{ 0x48, 0x00}, /* ANAMIC_GAIN */
{ 0x49, 0x00}, /* MISC_SET_2 */
/* End of Audio Registers */
};
static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case 0:
case 3:
case 40:
case 41:
case 42:
return false;
default:
return true;
}
}
static const struct regmap_range twl4030_49_volatile_ranges[] = {
regmap_reg_range(TWL4030_BASEADD_TEST, 0xff),
};
static const struct regmap_access_table twl4030_49_volatile_table = {
.yes_ranges = twl4030_49_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(twl4030_49_volatile_ranges),
};
static struct regmap_config twl4030_regmap_config[4] = {
{
/* Address 0x48 */
@ -212,6 +314,15 @@ static struct regmap_config twl4030_regmap_config[4] = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
.readable_reg = twl4030_49_nop_reg,
.writeable_reg = twl4030_49_nop_reg,
.volatile_table = &twl4030_49_volatile_table,
.reg_defaults = twl4030_49_defaults,
.num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults),
.cache_type = REGCACHE_RBTREE,
},
{
/* Address 0x4a */
@ -301,6 +412,32 @@ unsigned int twl_rev(void)
}
EXPORT_SYMBOL(twl_rev);
/**
* twl_get_regmap - Get the regmap associated with the given module
* @mod_no: module number
*
* Returns the regmap pointer or NULL in case of failure.
*/
static struct regmap *twl_get_regmap(u8 mod_no)
{
int sid;
struct twl_client *twl;
if (unlikely(!twl_priv || !twl_priv->ready)) {
pr_err("%s: not initialized\n", DRIVER_NAME);
return NULL;
}
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return NULL;
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
return twl->regmap;
}
/**
* twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
* @mod_no: module number
@ -312,25 +449,14 @@ EXPORT_SYMBOL(twl_rev);
*/
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
struct regmap *regmap = twl_get_regmap(mod_no);
int ret;
int sid;
struct twl_client *twl;
if (unlikely(!twl_priv || !twl_priv->ready)) {
pr_err("%s: not initialized\n", DRIVER_NAME);
if (!regmap)
return -EPERM;
}
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
ret = regmap_bulk_write(twl->regmap,
twl_priv->twl_map[mod_no].base + reg, value,
num_bytes);
ret = regmap_bulk_write(regmap, twl_priv->twl_map[mod_no].base + reg,
value, num_bytes);
if (ret)
pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
@ -351,25 +477,14 @@ EXPORT_SYMBOL(twl_i2c_write);
*/
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
struct regmap *regmap = twl_get_regmap(mod_no);
int ret;
int sid;
struct twl_client *twl;
if (unlikely(!twl_priv || !twl_priv->ready)) {
pr_err("%s: not initialized\n", DRIVER_NAME);
if (!regmap)
return -EPERM;
}
if (unlikely(mod_no >= twl_get_last_module())) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
sid = twl_priv->twl_map[mod_no].sid;
twl = &twl_priv->twl_modules[sid];
ret = regmap_bulk_read(twl->regmap,
twl_priv->twl_map[mod_no].base + reg, value,
num_bytes);
ret = regmap_bulk_read(regmap, twl_priv->twl_map[mod_no].base + reg,
value, num_bytes);
if (ret)
pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
@ -379,6 +494,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
}
EXPORT_SYMBOL(twl_i2c_read);
/**
* twl_regcache_bypass - Configure the regcache bypass for the regmap associated
* with the module
* @mod_no: module number
* @enable: Regcache bypass state
*
* Returns 0 else failure.
*/
int twl_set_regcache_bypass(u8 mod_no, bool enable)
{
struct regmap *regmap = twl_get_regmap(mod_no);
if (!regmap)
return -EPERM;
regcache_cache_bypass(regmap, enable);
return 0;
}
EXPORT_SYMBOL(twl_set_regcache_bypass);
/*----------------------------------------------------------------------*/
/**

View File

@ -44,6 +44,54 @@
#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
#define TWL6040_NUM_SUPPLIES (2)
static struct reg_default twl6040_defaults[] = {
{ 0x01, 0x4B }, /* REG_ASICID (ro) */
{ 0x02, 0x00 }, /* REG_ASICREV (ro) */
{ 0x03, 0x00 }, /* REG_INTID */
{ 0x04, 0x00 }, /* REG_INTMR */
{ 0x05, 0x00 }, /* REG_NCPCTRL */
{ 0x06, 0x00 }, /* REG_LDOCTL */
{ 0x07, 0x60 }, /* REG_HPPLLCTL */
{ 0x08, 0x00 }, /* REG_LPPLLCTL */
{ 0x09, 0x4A }, /* REG_LPPLLDIV */
{ 0x0A, 0x00 }, /* REG_AMICBCTL */
{ 0x0B, 0x00 }, /* REG_DMICBCTL */
{ 0x0C, 0x00 }, /* REG_MICLCTL */
{ 0x0D, 0x00 }, /* REG_MICRCTL */
{ 0x0E, 0x00 }, /* REG_MICGAIN */
{ 0x0F, 0x1B }, /* REG_LINEGAIN */
{ 0x10, 0x00 }, /* REG_HSLCTL */
{ 0x11, 0x00 }, /* REG_HSRCTL */
{ 0x12, 0x00 }, /* REG_HSGAIN */
{ 0x13, 0x00 }, /* REG_EARCTL */
{ 0x14, 0x00 }, /* REG_HFLCTL */
{ 0x15, 0x00 }, /* REG_HFLGAIN */
{ 0x16, 0x00 }, /* REG_HFRCTL */
{ 0x17, 0x00 }, /* REG_HFRGAIN */
{ 0x18, 0x00 }, /* REG_VIBCTLL */
{ 0x19, 0x00 }, /* REG_VIBDATL */
{ 0x1A, 0x00 }, /* REG_VIBCTLR */
{ 0x1B, 0x00 }, /* REG_VIBDATR */
{ 0x1C, 0x00 }, /* REG_HKCTL1 */
{ 0x1D, 0x00 }, /* REG_HKCTL2 */
{ 0x1E, 0x00 }, /* REG_GPOCTL */
{ 0x1F, 0x00 }, /* REG_ALB */
{ 0x20, 0x00 }, /* REG_DLB */
/* 0x28, REG_TRIM1 */
/* 0x29, REG_TRIM2 */
/* 0x2A, REG_TRIM3 */
/* 0x2B, REG_HSOTRIM */
/* 0x2C, REG_HFOTRIM */
{ 0x2D, 0x08 }, /* REG_ACCCTL */
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */
};
struct reg_default twl6040_patch[] = {
/* Select I2C bus access to dual access registers */
{ TWL6040_REG_ACCCTL, 0x09 },
};
static bool twl6040_has_vibra(struct device_node *node)
{
#ifdef CONFIG_OF
@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on)
if (twl6040->power_count++)
goto out;
/* Allow writes to the chip */
regcache_cache_only(twl6040->regmap, false);
if (gpio_is_valid(twl6040->audpwron)) {
/* use automatic power-up sequence */
ret = twl6040_power_up_automatic(twl6040);
@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on)
goto out;
}
}
/* Sync with the HW */
regcache_sync(twl6040->regmap);
/* Default PLL configuration after power up */
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
twl6040->sysclk = 19200000;
@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use manual power-down sequence */
twl6040_power_down_manual(twl6040);
}
/* Set regmap to cache only and mark it as dirty */
regcache_cache_only(twl6040->regmap, true);
regcache_mark_dirty(twl6040->regmap);
twl6040->sysclk = 0;
twl6040->mclk = 0;
}
@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case TWL6040_REG_VIBCTLL:
case TWL6040_REG_VIBCTLR:
case TWL6040_REG_INTMR:
case TWL6040_REG_ASICID:
case TWL6040_REG_ASICREV:
case TWL6040_REG_INTID:
case TWL6040_REG_LPPLLCTL:
case TWL6040_REG_HPPLLCTL:
case TWL6040_REG_STATUS:
return true;
default:
return false;
}
}
static bool twl6040_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case TWL6040_REG_ASICID:
case TWL6040_REG_ASICREV:
case TWL6040_REG_STATUS:
return false;
default:
return true;
@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
static struct regmap_config twl6040_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.reg_defaults = twl6040_defaults,
.num_reg_defaults = ARRAY_SIZE(twl6040_defaults),
.max_register = TWL6040_REG_STATUS, /* 0x2e */
.readable_reg = twl6040_readable_reg,
.volatile_reg = twl6040_volatile_reg,
.writeable_reg = twl6040_writeable_reg,
.cache_type = REGCACHE_RBTREE,
};
@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client,
/* dual-access registers controlled by I2C only */
twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
regmap_register_patch(twl6040->regmap, twl6040_patch,
ARRAY_SIZE(twl6040_patch));
/*
* The main functionality of twl6040 to provide audio on OMAP4+ systems.
@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client,
cell->name = "twl6040-gpo";
children++;
/* The chip is powered down so mark regmap to cache only and dirty */
regcache_cache_only(twl6040->regmap, true);
regcache_mark_dirty(twl6040->regmap);
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
NULL, 0, NULL);
if (ret)

View File

@ -14,6 +14,7 @@
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/registers.h>
#include <linux/device.h>
#include "arizona.h"
@ -524,6 +525,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000300, 0x0000 }, /* R768 - Input Enables */
{ 0x00000308, 0x0000 }, /* R776 - Input Rate */
{ 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */
{ 0x0000030C, 0x0002 }, /* R780 - HPF Control */
{ 0x00000310, 0x2080 }, /* R784 - IN1L Control */
{ 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */
{ 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */
@ -545,6 +547,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000328, 0x2000 }, /* R808 - IN4L Control */
{ 0x00000329, 0x0180 }, /* R809 - ADC Digital Volume 4L */
{ 0x0000032A, 0x0000 }, /* R810 - DMIC4L Control */
{ 0x0000032C, 0x0000 }, /* R812 - IN4R Control */
{ 0x0000032D, 0x0180 }, /* R813 - ADC Digital Volume 4R */
{ 0x0000032E, 0x0000 }, /* R814 - DMIC4R Control */
{ 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */
@ -598,6 +601,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x0000043D, 0x0180 }, /* R1085 - DAC Digital Volume 6R */
{ 0x0000043E, 0x0080 }, /* R1086 - DAC Volume Limit 6R */
{ 0x0000043F, 0x0800 }, /* R1087 - Noise Gate Select 6R */
{ 0x00000440, 0x8FFF }, /* R1088 - DRE Enable */
{ 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */
{ 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */
{ 0x00000480, 0x0040 }, /* R1152 - Class W ANC Threshold 1 */
@ -606,6 +610,9 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */
{ 0x00000492, 0x0069 }, /* R1170 - PDM SPK2 CTRL 1 */
{ 0x00000493, 0x0000 }, /* R1171 - PDM SPK2 CTRL 2 */
{ 0x000004A0, 0x3480 }, /* R1184 - HP1 Short Circuit Ctrl */
{ 0x000004A1, 0x3480 }, /* R1185 - HP2 Short Circuit Ctrl */
{ 0x000004A2, 0x3480 }, /* R1186 - HP3 Short Circuit Ctrl */
{ 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */
{ 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */
{ 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */
@ -882,6 +889,38 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */
{ 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */
{ 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */
{ 0x00000750, 0x0000 }, /* R1872 - AIF2TX3MIX Input 1 Source */
{ 0x00000751, 0x0080 }, /* R1873 - AIF2TX3MIX Input 1 Volume */
{ 0x00000752, 0x0000 }, /* R1874 - AIF2TX3MIX Input 2 Source */
{ 0x00000753, 0x0080 }, /* R1875 - AIF2TX3MIX Input 2 Volume */
{ 0x00000754, 0x0000 }, /* R1876 - AIF2TX3MIX Input 3 Source */
{ 0x00000755, 0x0080 }, /* R1877 - AIF2TX3MIX Input 3 Volume */
{ 0x00000756, 0x0000 }, /* R1878 - AIF2TX3MIX Input 4 Source */
{ 0x00000757, 0x0080 }, /* R1879 - AIF2TX3MIX Input 4 Volume */
{ 0x00000758, 0x0000 }, /* R1880 - AIF2TX4MIX Input 1 Source */
{ 0x00000759, 0x0080 }, /* R1881 - AIF2TX4MIX Input 1 Volume */
{ 0x0000075A, 0x0000 }, /* R1882 - AIF2TX4MIX Input 2 Source */
{ 0x0000075B, 0x0080 }, /* R1883 - AIF2TX4MIX Input 2 Volume */
{ 0x0000075C, 0x0000 }, /* R1884 - AIF2TX4MIX Input 3 Source */
{ 0x0000075D, 0x0080 }, /* R1885 - AIF2TX4MIX Input 3 Volume */
{ 0x0000075E, 0x0000 }, /* R1886 - AIF2TX4MIX Input 4 Source */
{ 0x0000075F, 0x0080 }, /* R1887 - AIF2TX4MIX Input 4 Volume */
{ 0x00000760, 0x0000 }, /* R1888 - AIF2TX5MIX Input 1 Source */
{ 0x00000761, 0x0080 }, /* R1889 - AIF2TX5MIX Input 1 Volume */
{ 0x00000762, 0x0000 }, /* R1890 - AIF2TX5MIX Input 2 Source */
{ 0x00000763, 0x0080 }, /* R1891 - AIF2TX5MIX Input 2 Volume */
{ 0x00000764, 0x0000 }, /* R1892 - AIF2TX5MIX Input 3 Source */
{ 0x00000765, 0x0080 }, /* R1893 - AIF2TX5MIX Input 3 Volume */
{ 0x00000766, 0x0000 }, /* R1894 - AIF2TX5MIX Input 4 Source */
{ 0x00000767, 0x0080 }, /* R1895 - AIF2TX5MIX Input 4 Volume */
{ 0x00000768, 0x0000 }, /* R1896 - AIF2TX6MIX Input 1 Source */
{ 0x00000769, 0x0080 }, /* R1897 - AIF2TX6MIX Input 1 Volume */
{ 0x0000076A, 0x0000 }, /* R1898 - AIF2TX6MIX Input 2 Source */
{ 0x0000076B, 0x0080 }, /* R1899 - AIF2TX6MIX Input 2 Volume */
{ 0x0000076C, 0x0000 }, /* R1900 - AIF2TX6MIX Input 3 Source */
{ 0x0000076D, 0x0080 }, /* R1901 - AIF2TX6MIX Input 3 Volume */
{ 0x0000076E, 0x0000 }, /* R1902 - AIF2TX6MIX Input 4 Source */
{ 0x0000076F, 0x0080 }, /* R1903 - AIF2TX6MIX Input 4 Volume */
{ 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */
{ 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */
{ 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */
@ -1342,6 +1381,64 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00001404, 0x0000 }, /* R5124 - DSP4 Status 1 */
};
static bool wm5110_is_rev_b_adsp_memory(unsigned int reg)
{
if ((reg >= 0x100000 && reg < 0x103000) ||
(reg >= 0x180000 && reg < 0x181000) ||
(reg >= 0x190000 && reg < 0x192000) ||
(reg >= 0x1a8000 && reg < 0x1a9000) ||
(reg >= 0x200000 && reg < 0x209000) ||
(reg >= 0x280000 && reg < 0x281000) ||
(reg >= 0x290000 && reg < 0x29a000) ||
(reg >= 0x2a8000 && reg < 0x2aa000) ||
(reg >= 0x300000 && reg < 0x30f000) ||
(reg >= 0x380000 && reg < 0x382000) ||
(reg >= 0x390000 && reg < 0x39e000) ||
(reg >= 0x3a8000 && reg < 0x3b6000) ||
(reg >= 0x400000 && reg < 0x403000) ||
(reg >= 0x480000 && reg < 0x481000) ||
(reg >= 0x490000 && reg < 0x492000) ||
(reg >= 0x4a8000 && reg < 0x4a9000))
return true;
else
return false;
}
static bool wm5110_is_rev_d_adsp_memory(unsigned int reg)
{
if ((reg >= 0x100000 && reg < 0x106000) ||
(reg >= 0x180000 && reg < 0x182000) ||
(reg >= 0x190000 && reg < 0x198000) ||
(reg >= 0x1a8000 && reg < 0x1aa000) ||
(reg >= 0x200000 && reg < 0x20f000) ||
(reg >= 0x280000 && reg < 0x282000) ||
(reg >= 0x290000 && reg < 0x29c000) ||
(reg >= 0x2a6000 && reg < 0x2b4000) ||
(reg >= 0x300000 && reg < 0x30f000) ||
(reg >= 0x380000 && reg < 0x382000) ||
(reg >= 0x390000 && reg < 0x3a2000) ||
(reg >= 0x3a6000 && reg < 0x3b4000) ||
(reg >= 0x400000 && reg < 0x406000) ||
(reg >= 0x480000 && reg < 0x482000) ||
(reg >= 0x490000 && reg < 0x498000) ||
(reg >= 0x4a8000 && reg < 0x4aa000))
return true;
else
return false;
}
static bool wm5110_is_adsp_memory(struct device *dev, unsigned int reg)
{
struct arizona *arizona = dev_get_drvdata(dev);
switch (arizona->rev) {
case 0 ... 2:
return wm5110_is_rev_b_adsp_memory(reg);
default:
return wm5110_is_rev_d_adsp_memory(reg);
}
}
static bool wm5110_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
@ -1460,6 +1557,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INPUT_ENABLES_STATUS:
case ARIZONA_INPUT_RATE:
case ARIZONA_INPUT_VOLUME_RAMP:
case ARIZONA_HPF_CONTROL:
case ARIZONA_IN1L_CONTROL:
case ARIZONA_ADC_DIGITAL_VOLUME_1L:
case ARIZONA_DMIC1L_CONTROL:
@ -1481,6 +1579,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_IN4L_CONTROL:
case ARIZONA_ADC_DIGITAL_VOLUME_4L:
case ARIZONA_DMIC4L_CONTROL:
case ARIZONA_IN4R_CONTROL:
case ARIZONA_ADC_DIGITAL_VOLUME_4R:
case ARIZONA_DMIC4R_CONTROL:
case ARIZONA_OUTPUT_ENABLES_1:
@ -1536,12 +1635,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DAC_DIGITAL_VOLUME_6R:
case ARIZONA_DAC_VOLUME_LIMIT_6R:
case ARIZONA_NOISE_GATE_SELECT_6R:
case ARIZONA_DRE_ENABLE:
case ARIZONA_DAC_AEC_CONTROL_1:
case ARIZONA_NOISE_GATE_CONTROL:
case ARIZONA_PDM_SPK1_CTRL_1:
case ARIZONA_PDM_SPK1_CTRL_2:
case ARIZONA_PDM_SPK2_CTRL_1:
case ARIZONA_PDM_SPK2_CTRL_2:
case ARIZONA_HP1_SHORT_CIRCUIT_CTRL:
case ARIZONA_HP2_SHORT_CIRCUIT_CTRL:
case ARIZONA_HP3_SHORT_CIRCUIT_CTRL:
case ARIZONA_AIF1_BCLK_CTRL:
case ARIZONA_AIF1_TX_PIN_CTRL:
case ARIZONA_AIF1_RX_PIN_CTRL:
@ -1820,6 +1923,38 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME:
case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE:
case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME:
case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE:
case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME:
case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE:
case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME:
case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE:
case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME:
case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE:
case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME:
case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE:
case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME:
case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE:
case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME:
case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE:
case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME:
case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE:
case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME:
case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE:
case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME:
case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE:
case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME:
case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE:
case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME:
case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE:
case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME:
case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE:
case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME:
case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE:
case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME:
case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE:
case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME:
case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE:
case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME:
case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE:
case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME:
case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE:
@ -2331,7 +2466,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP4_SCRATCH_3:
return true;
default:
return false;
return wm5110_is_adsp_memory(dev, reg);
}
}
@ -2407,16 +2542,18 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP4_SCRATCH_3:
return true;
default:
return false;
return wm5110_is_adsp_memory(dev, reg);
}
}
#define WM5110_MAX_REGISTER 0x4a9fff
const struct regmap_config wm5110_spi_regmap = {
.reg_bits = 32,
.pad_bits = 16,
.val_bits = 16,
.max_register = ARIZONA_DSP1_STATUS_2,
.max_register = WM5110_MAX_REGISTER,
.readable_reg = wm5110_readable_register,
.volatile_reg = wm5110_volatile_register,
@ -2430,7 +2567,7 @@ const struct regmap_config wm5110_i2c_regmap = {
.reg_bits = 32,
.val_bits = 16,
.max_register = ARIZONA_DSP1_STATUS_2,
.max_register = WM5110_MAX_REGISTER,
.readable_reg = wm5110_readable_register,
.volatile_reg = wm5110_volatile_register,

View File

@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
depends on PLAT_SAMSUNG
select S3C64XX_DMA if ARCH_S3C64XX
select S3C64XX_PL080 if ARCH_S3C64XX
help
SPI driver for Samsung S3C64XX and newer SoCs.

View File

@ -22,6 +22,7 @@
#define LINUX_DMAENGINE_H
#include <linux/device.h>
#include <linux/err.h>
#include <linux/uio.h>
#include <linux/bug.h>
#include <linux/scatterlist.h>
@ -363,6 +364,32 @@ struct dma_slave_config {
unsigned int slave_id;
};
/**
* enum dma_residue_granularity - Granularity of the reported transfer residue
* @DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. The
* DMA channel is only able to tell whether a descriptor has been completed or
* not, which means residue reporting is not supported by this channel. The
* residue field of the dma_tx_state field will always be 0.
* @DMA_RESIDUE_GRANULARITY_SEGMENT: Residue is updated after each successfully
* completed segment of the transfer (For cyclic transfers this is after each
* period). This is typically implemented by having the hardware generate an
* interrupt after each transferred segment and then the drivers updates the
* outstanding residue by the size of the segment. Another possibility is if
* the hardware supports scatter-gather and the segment descriptor has a field
* which gets set after the segment has been completed. The driver then counts
* the number of segments without the flag set to compute the residue.
* @DMA_RESIDUE_GRANULARITY_BURST: Residue is updated after each transferred
* burst. This is typically only supported if the hardware has a progress
* register of some sort (E.g. a register with the current read/write address
* or a register with the amount of bursts/beats/bytes that have been
* transferred or still need to be transferred).
*/
enum dma_residue_granularity {
DMA_RESIDUE_GRANULARITY_DESCRIPTOR = 0,
DMA_RESIDUE_GRANULARITY_SEGMENT = 1,
DMA_RESIDUE_GRANULARITY_BURST = 2,
};
/* struct dma_slave_caps - expose capabilities of a slave channel only
*
* @src_addr_widths: bit mask of src addr widths the channel supports
@ -373,6 +400,7 @@ struct dma_slave_config {
* should be checked by controller as well
* @cmd_pause: true, if pause and thereby resume is supported
* @cmd_terminate: true, if terminate cmd is supported
* @residue_granularity: granularity of the reported transfer residue
*/
struct dma_slave_caps {
u32 src_addr_widths;
@ -380,6 +408,7 @@ struct dma_slave_caps {
u32 directions;
bool cmd_pause;
bool cmd_terminate;
enum dma_residue_granularity residue_granularity;
};
static inline const char *dma_chan_name(struct dma_chan *chan)
@ -1040,6 +1069,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void);
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param);
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name);
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
void dma_release_channel(struct dma_chan *chan);
#else
@ -1063,6 +1094,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
return NULL;
}
static inline struct dma_chan *dma_request_slave_channel_reason(
struct device *dev, const char *name)
{
return ERR_PTR(-ENODEV);
}
static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{

View File

@ -175,6 +175,9 @@ static inline int twl_class_is_ ##class(void) \
TWL_CLASS_IS(4030, TWL4030_CLASS_ID)
TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
/* Set the regcache bypass for the regmap associated with the nodule */
int twl_set_regcache_bypass(u8 mod_no, bool enable);
/*
* Read and write several 8-bit registers at once.
*/
@ -667,8 +670,6 @@ struct twl4030_codec_data {
unsigned int digimic_delay; /* in ms */
unsigned int ramp_delay_value;
unsigned int offset_cncl_path;
unsigned int check_defaults:1;
unsigned int reset_registers:1;
unsigned int hs_extmute:1;
int hs_extmute_gpio;
};

View File

@ -139,6 +139,7 @@
#define ARIZONA_INPUT_ENABLES_STATUS 0x301
#define ARIZONA_INPUT_RATE 0x308
#define ARIZONA_INPUT_VOLUME_RAMP 0x309
#define ARIZONA_HPF_CONTROL 0x30C
#define ARIZONA_IN1L_CONTROL 0x310
#define ARIZONA_ADC_DIGITAL_VOLUME_1L 0x311
#define ARIZONA_DMIC1L_CONTROL 0x312
@ -160,6 +161,7 @@
#define ARIZONA_IN4L_CONTROL 0x328
#define ARIZONA_ADC_DIGITAL_VOLUME_4L 0x329
#define ARIZONA_DMIC4L_CONTROL 0x32A
#define ARIZONA_IN4R_CONTROL 0x32C
#define ARIZONA_ADC_DIGITAL_VOLUME_4R 0x32D
#define ARIZONA_DMIC4R_CONTROL 0x32E
#define ARIZONA_OUTPUT_ENABLES_1 0x400
@ -224,6 +226,9 @@
#define ARIZONA_PDM_SPK1_CTRL_2 0x491
#define ARIZONA_PDM_SPK2_CTRL_1 0x492
#define ARIZONA_PDM_SPK2_CTRL_2 0x493
#define ARIZONA_HP1_SHORT_CIRCUIT_CTRL 0x4A0
#define ARIZONA_HP2_SHORT_CIRCUIT_CTRL 0x4A1
#define ARIZONA_HP3_SHORT_CIRCUIT_CTRL 0x4A2
#define ARIZONA_SPK_CTRL_2 0x4B5
#define ARIZONA_SPK_CTRL_3 0x4B6
#define ARIZONA_DAC_COMP_1 0x4DC
@ -511,6 +516,38 @@
#define ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME 0x74D
#define ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE 0x74E
#define ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME 0x74F
#define ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE 0x750
#define ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME 0x751
#define ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE 0x752
#define ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME 0x753
#define ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE 0x754
#define ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME 0x755
#define ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE 0x756
#define ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME 0x757
#define ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE 0x758
#define ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME 0x759
#define ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE 0x75A
#define ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME 0x75B
#define ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE 0x75C
#define ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME 0x75D
#define ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE 0x75E
#define ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME 0x75F
#define ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE 0x760
#define ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME 0x761
#define ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE 0x762
#define ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME 0x763
#define ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE 0x764
#define ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME 0x765
#define ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE 0x766
#define ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME 0x767
#define ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE 0x768
#define ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME 0x769
#define ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE 0x76A
#define ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME 0x76B
#define ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE 0x76C
#define ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME 0x76D
#define ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE 0x76E
#define ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME 0x76F
#define ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE 0x780
#define ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME 0x781
#define ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE 0x782
@ -2301,9 +2338,19 @@
#define ARIZONA_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */
#define ARIZONA_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */
/*
* R780 (0x30C) - HPF Control
*/
#define ARIZONA_IN_HPF_CUT_MASK 0x0007 /* IN_HPF_CUT [2:0] */
#define ARIZONA_IN_HPF_CUT_SHIFT 0 /* IN_HPF_CUT [2:0] */
#define ARIZONA_IN_HPF_CUT_WIDTH 3 /* IN_HPF_CUT [2:0] */
/*
* R784 (0x310) - IN1L Control
*/
#define ARIZONA_IN1L_HPF_MASK 0x8000 /* IN1L_HPF - [15] */
#define ARIZONA_IN1L_HPF_SHIFT 15 /* IN1L_HPF - [15] */
#define ARIZONA_IN1L_HPF_WIDTH 1 /* IN1L_HPF - [15] */
#define ARIZONA_IN1_OSR_MASK 0x6000 /* IN1_OSR - [14:13] */
#define ARIZONA_IN1_OSR_SHIFT 13 /* IN1_OSR - [14:13] */
#define ARIZONA_IN1_OSR_WIDTH 2 /* IN1_OSR - [14:13] */
@ -2342,6 +2389,9 @@
/*
* R788 (0x314) - IN1R Control
*/
#define ARIZONA_IN1R_HPF_MASK 0x8000 /* IN1R_HPF - [15] */
#define ARIZONA_IN1R_HPF_SHIFT 15 /* IN1R_HPF - [15] */
#define ARIZONA_IN1R_HPF_WIDTH 1 /* IN1R_HPF - [15] */
#define ARIZONA_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */
#define ARIZONA_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */
#define ARIZONA_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */
@ -2371,6 +2421,9 @@
/*
* R792 (0x318) - IN2L Control
*/
#define ARIZONA_IN2L_HPF_MASK 0x8000 /* IN2L_HPF - [15] */
#define ARIZONA_IN2L_HPF_SHIFT 15 /* IN2L_HPF - [15] */
#define ARIZONA_IN2L_HPF_WIDTH 1 /* IN2L_HPF - [15] */
#define ARIZONA_IN2_OSR_MASK 0x6000 /* IN2_OSR - [14:13] */
#define ARIZONA_IN2_OSR_SHIFT 13 /* IN2_OSR - [14:13] */
#define ARIZONA_IN2_OSR_WIDTH 2 /* IN2_OSR - [14:13] */
@ -2409,6 +2462,9 @@
/*
* R796 (0x31C) - IN2R Control
*/
#define ARIZONA_IN2R_HPF_MASK 0x8000 /* IN2R_HPF - [15] */
#define ARIZONA_IN2R_HPF_SHIFT 15 /* IN2R_HPF - [15] */
#define ARIZONA_IN2R_HPF_WIDTH 1 /* IN2R_HPF - [15] */
#define ARIZONA_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */
#define ARIZONA_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */
#define ARIZONA_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */
@ -2438,6 +2494,9 @@
/*
* R800 (0x320) - IN3L Control
*/
#define ARIZONA_IN3L_HPF_MASK 0x8000 /* IN3L_HPF - [15] */
#define ARIZONA_IN3L_HPF_SHIFT 15 /* IN3L_HPF - [15] */
#define ARIZONA_IN3L_HPF_WIDTH 1 /* IN3L_HPF - [15] */
#define ARIZONA_IN3_OSR_MASK 0x6000 /* IN3_OSR - [14:13] */
#define ARIZONA_IN3_OSR_SHIFT 13 /* IN3_OSR - [14:13] */
#define ARIZONA_IN3_OSR_WIDTH 2 /* IN3_OSR - [14:13] */
@ -2476,6 +2535,9 @@
/*
* R804 (0x324) - IN3R Control
*/
#define ARIZONA_IN3R_HPF_MASK 0x8000 /* IN3R_HPF - [15] */
#define ARIZONA_IN3R_HPF_SHIFT 15 /* IN3R_HPF - [15] */
#define ARIZONA_IN3R_HPF_WIDTH 1 /* IN3R_HPF - [15] */
#define ARIZONA_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */
#define ARIZONA_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */
#define ARIZONA_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */
@ -2505,6 +2567,9 @@
/*
* R808 (0x328) - IN4 Control
*/
#define ARIZONA_IN4L_HPF_MASK 0x8000 /* IN4L_HPF - [15] */
#define ARIZONA_IN4L_HPF_SHIFT 15 /* IN4L_HPF - [15] */
#define ARIZONA_IN4L_HPF_WIDTH 1 /* IN4L_HPF - [15] */
#define ARIZONA_IN4_OSR_MASK 0x6000 /* IN4_OSR - [14:13] */
#define ARIZONA_IN4_OSR_SHIFT 13 /* IN4_OSR - [14:13] */
#define ARIZONA_IN4_OSR_WIDTH 2 /* IN4_OSR - [14:13] */
@ -2534,6 +2599,13 @@
#define ARIZONA_IN4L_DMIC_DLY_SHIFT 0 /* IN4L_DMIC_DLY - [5:0] */
#define ARIZONA_IN4L_DMIC_DLY_WIDTH 6 /* IN4L_DMIC_DLY - [5:0] */
/*
* R812 (0x32C) - IN4R Control
*/
#define ARIZONA_IN4R_HPF_MASK 0x8000 /* IN4R_HPF - [15] */
#define ARIZONA_IN4R_HPF_SHIFT 15 /* IN4R_HPF - [15] */
#define ARIZONA_IN4R_HPF_WIDTH 1 /* IN4R_HPF - [15] */
/*
* R813 (0x32D) - ADC Digital Volume 4R
*/
@ -3147,6 +3219,10 @@
/*
* R1088 (0x440) - DRE Enable
*/
#define ARIZONA_DRE3R_ENA 0x0020 /* DRE3R_ENA */
#define ARIZONA_DRE3R_ENA_MASK 0x0020 /* DRE3R_ENA */
#define ARIZONA_DRE3R_ENA_SHIFT 5 /* DRE3R_ENA */
#define ARIZONA_DRE3R_ENA_WIDTH 1 /* DRE3R_ENA */
#define ARIZONA_DRE3L_ENA 0x0010 /* DRE3L_ENA */
#define ARIZONA_DRE3L_ENA_MASK 0x0010 /* DRE3L_ENA */
#define ARIZONA_DRE3L_ENA_SHIFT 4 /* DRE3L_ENA */
@ -3268,6 +3344,30 @@
#define ARIZONA_SPK2_FMT_SHIFT 0 /* SPK2_FMT */
#define ARIZONA_SPK2_FMT_WIDTH 1 /* SPK2_FMT */
/*
* R1184 (0x4A0) - HP1 Short Circuit Ctrl
*/
#define ARIZONA_HP1_SC_ENA 0x1000 /* HP1_SC_ENA */
#define ARIZONA_HP1_SC_ENA_MASK 0x1000 /* HP1_SC_ENA */
#define ARIZONA_HP1_SC_ENA_SHIFT 12 /* HP1_SC_ENA */
#define ARIZONA_HP1_SC_ENA_WIDTH 1 /* HP1_SC_ENA */
/*
* R1185 (0x4A1) - HP2 Short Circuit Ctrl
*/
#define ARIZONA_HP2_SC_ENA 0x1000 /* HP2_SC_ENA */
#define ARIZONA_HP2_SC_ENA_MASK 0x1000 /* HP2_SC_ENA */
#define ARIZONA_HP2_SC_ENA_SHIFT 12 /* HP2_SC_ENA */
#define ARIZONA_HP2_SC_ENA_WIDTH 1 /* HP2_SC_ENA */
/*
* R1186 (0x4A2) - HP3 Short Circuit Ctrl
*/
#define ARIZONA_HP3_SC_ENA 0x1000 /* HP3_SC_ENA */
#define ARIZONA_HP3_SC_ENA_MASK 0x1000 /* HP3_SC_ENA */
#define ARIZONA_HP3_SC_ENA_SHIFT 12 /* HP3_SC_ENA */
#define ARIZONA_HP3_SC_ENA_WIDTH 1 /* HP3_SC_ENA */
/*
* R1244 (0x4DC) - DAC comp 1
*/
@ -3734,6 +3834,35 @@
#define ARIZONA_AIF2TX2_SLOT_SHIFT 0 /* AIF2TX2_SLOT - [5:0] */
#define ARIZONA_AIF2TX2_SLOT_WIDTH 6 /* AIF2TX2_SLOT - [5:0] */
/*
* R1355 (0x54B) - AIF2 Frame Ctrl 5
*/
#define ARIZONA_AIF2TX3_SLOT_MASK 0x003F /* AIF2TX3_SLOT - [5:0] */
#define ARIZONA_AIF2TX3_SLOT_SHIFT 0 /* AIF2TX3_SLOT - [5:0] */
#define ARIZONA_AIF2TX3_SLOT_WIDTH 6 /* AIF2TX3_SLOT - [5:0] */
/*
* R1356 (0x54C) - AIF2 Frame Ctrl 6
*/
#define ARIZONA_AIF2TX4_SLOT_MASK 0x003F /* AIF2TX4_SLOT - [5:0] */
#define ARIZONA_AIF2TX4_SLOT_SHIFT 0 /* AIF2TX4_SLOT - [5:0] */
#define ARIZONA_AIF2TX4_SLOT_WIDTH 6 /* AIF2TX4_SLOT - [5:0] */
/*
* R1357 (0x54D) - AIF2 Frame Ctrl 7
*/
#define ARIZONA_AIF2TX5_SLOT_MASK 0x003F /* AIF2TX5_SLOT - [5:0] */
#define ARIZONA_AIF2TX5_SLOT_SHIFT 0 /* AIF2TX5_SLOT - [5:0] */
#define ARIZONA_AIF2TX5_SLOT_WIDTH 6 /* AIF2TX5_SLOT - [5:0] */
/*
* R1358 (0x54E) - AIF2 Frame Ctrl 8
*/
#define ARIZONA_AIF2TX6_SLOT_MASK 0x003F /* AIF2TX6_SLOT - [5:0] */
#define ARIZONA_AIF2TX6_SLOT_SHIFT 0 /* AIF2TX6_SLOT - [5:0] */
#define ARIZONA_AIF2TX6_SLOT_WIDTH 6 /* AIF2TX6_SLOT - [5:0] */
/*
* R1361 (0x551) - AIF2 Frame Ctrl 11
*/
@ -3748,9 +3877,53 @@
#define ARIZONA_AIF2RX2_SLOT_SHIFT 0 /* AIF2RX2_SLOT - [5:0] */
#define ARIZONA_AIF2RX2_SLOT_WIDTH 6 /* AIF2RX2_SLOT - [5:0] */
/*
* R1363 (0x553) - AIF2 Frame Ctrl 13
*/
#define ARIZONA_AIF2RX3_SLOT_MASK 0x003F /* AIF2RX3_SLOT - [5:0] */
#define ARIZONA_AIF2RX3_SLOT_SHIFT 0 /* AIF2RX3_SLOT - [5:0] */
#define ARIZONA_AIF2RX3_SLOT_WIDTH 6 /* AIF2RX3_SLOT - [5:0] */
/*
* R1364 (0x554) - AIF2 Frame Ctrl 14
*/
#define ARIZONA_AIF2RX4_SLOT_MASK 0x003F /* AIF2RX4_SLOT - [5:0] */
#define ARIZONA_AIF2RX4_SLOT_SHIFT 0 /* AIF2RX4_SLOT - [5:0] */
#define ARIZONA_AIF2RX4_SLOT_WIDTH 6 /* AIF2RX4_SLOT - [5:0] */
/*
* R1365 (0x555) - AIF2 Frame Ctrl 15
*/
#define ARIZONA_AIF2RX5_SLOT_MASK 0x003F /* AIF2RX5_SLOT - [5:0] */
#define ARIZONA_AIF2RX5_SLOT_SHIFT 0 /* AIF2RX5_SLOT - [5:0] */
#define ARIZONA_AIF2RX5_SLOT_WIDTH 6 /* AIF2RX5_SLOT - [5:0] */
/*
* R1366 (0x556) - AIF2 Frame Ctrl 16
*/
#define ARIZONA_AIF2RX6_SLOT_MASK 0x003F /* AIF2RX6_SLOT - [5:0] */
#define ARIZONA_AIF2RX6_SLOT_SHIFT 0 /* AIF2RX6_SLOT - [5:0] */
#define ARIZONA_AIF2RX6_SLOT_WIDTH 6 /* AIF2RX6_SLOT - [5:0] */
/*
* R1369 (0x559) - AIF2 Tx Enables
*/
#define ARIZONA_AIF2TX6_ENA 0x0020 /* AIF2TX6_ENA */
#define ARIZONA_AIF2TX6_ENA_MASK 0x0020 /* AIF2TX6_ENA */
#define ARIZONA_AIF2TX6_ENA_SHIFT 5 /* AIF2TX6_ENA */
#define ARIZONA_AIF2TX6_ENA_WIDTH 1 /* AIF2TX6_ENA */
#define ARIZONA_AIF2TX5_ENA 0x0010 /* AIF2TX5_ENA */
#define ARIZONA_AIF2TX5_ENA_MASK 0x0010 /* AIF2TX5_ENA */
#define ARIZONA_AIF2TX5_ENA_SHIFT 4 /* AIF2TX5_ENA */
#define ARIZONA_AIF2TX5_ENA_WIDTH 1 /* AIF2TX5_ENA */
#define ARIZONA_AIF2TX4_ENA 0x0008 /* AIF2TX4_ENA */
#define ARIZONA_AIF2TX4_ENA_MASK 0x0008 /* AIF2TX4_ENA */
#define ARIZONA_AIF2TX4_ENA_SHIFT 3 /* AIF2TX4_ENA */
#define ARIZONA_AIF2TX4_ENA_WIDTH 1 /* AIF2TX4_ENA */
#define ARIZONA_AIF2TX3_ENA 0x0004 /* AIF2TX3_ENA */
#define ARIZONA_AIF2TX3_ENA_MASK 0x0004 /* AIF2TX3_ENA */
#define ARIZONA_AIF2TX3_ENA_SHIFT 2 /* AIF2TX3_ENA */
#define ARIZONA_AIF2TX3_ENA_WIDTH 1 /* AIF2TX3_ENA */
#define ARIZONA_AIF2TX2_ENA 0x0002 /* AIF2TX2_ENA */
#define ARIZONA_AIF2TX2_ENA_MASK 0x0002 /* AIF2TX2_ENA */
#define ARIZONA_AIF2TX2_ENA_SHIFT 1 /* AIF2TX2_ENA */
@ -3763,6 +3936,22 @@
/*
* R1370 (0x55A) - AIF2 Rx Enables
*/
#define ARIZONA_AIF2RX6_ENA 0x0020 /* AIF2RX6_ENA */
#define ARIZONA_AIF2RX6_ENA_MASK 0x0020 /* AIF2RX6_ENA */
#define ARIZONA_AIF2RX6_ENA_SHIFT 5 /* AIF2RX6_ENA */
#define ARIZONA_AIF2RX6_ENA_WIDTH 1 /* AIF2RX6_ENA */
#define ARIZONA_AIF2RX5_ENA 0x0010 /* AIF2RX5_ENA */
#define ARIZONA_AIF2RX5_ENA_MASK 0x0010 /* AIF2RX5_ENA */
#define ARIZONA_AIF2RX5_ENA_SHIFT 4 /* AIF2RX5_ENA */
#define ARIZONA_AIF2RX5_ENA_WIDTH 1 /* AIF2RX5_ENA */
#define ARIZONA_AIF2RX4_ENA 0x0008 /* AIF2RX4_ENA */
#define ARIZONA_AIF2RX4_ENA_MASK 0x0008 /* AIF2RX4_ENA */
#define ARIZONA_AIF2RX4_ENA_SHIFT 3 /* AIF2RX4_ENA */
#define ARIZONA_AIF2RX4_ENA_WIDTH 1 /* AIF2RX4_ENA */
#define ARIZONA_AIF2RX3_ENA 0x0004 /* AIF2RX3_ENA */
#define ARIZONA_AIF2RX3_ENA_MASK 0x0004 /* AIF2RX3_ENA */
#define ARIZONA_AIF2RX3_ENA_SHIFT 2 /* AIF2RX3_ENA */
#define ARIZONA_AIF2RX3_ENA_WIDTH 1 /* AIF2RX3_ENA */
#define ARIZONA_AIF2RX2_ENA 0x0002 /* AIF2RX2_ENA */
#define ARIZONA_AIF2RX2_ENA_MASK 0x0002 /* AIF2RX2_ENA */
#define ARIZONA_AIF2RX2_ENA_SHIFT 1 /* AIF2RX2_ENA */

View File

@ -1,6 +1,4 @@
/*
* arch/arm/plat-omap/include/mach/mcbsp.h
*
* Defines for Multi-Channel Buffered Serial Port
*
* Copyright (C) 2002 RidgeRun, Inc.
@ -21,8 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __ASM_ARCH_OMAP_MCBSP_H
#define __ASM_ARCH_OMAP_MCBSP_H
#ifndef __ASOC_TI_MCBSP_H
#define __ASOC_TI_MCBSP_H
#include <linux/spinlock.h>
#include <linux/clk.h>

View File

@ -10,16 +10,9 @@
#include <linux/platform_data/dma-ste-dma40.h>
enum msp_i2s_id {
MSP_I2S_0 = 0,
MSP_I2S_1,
MSP_I2S_2,
MSP_I2S_3,
};
/* Platform data structure for a MSP I2S-device */
struct msp_i2s_platform_data {
enum msp_i2s_id id;
int id;
struct stedma40_chan_cfg *msp_i2s_dma_rx;
struct stedma40_chan_cfg *msp_i2s_dma_tx;
};

View File

@ -92,6 +92,7 @@ enum {
MCASP_VERSION_1 = 0, /* DM646x */
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
MCASP_VERSION_3, /* TI81xx/AM33xx */
MCASP_VERSION_4, /* DRA7xxx */
};
enum mcbsp_clk_input_pin {

View File

@ -16,17 +16,11 @@ struct cs42l52_platform_data {
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* MICA mode selection 0=Single 1=Differential */
unsigned int mica_cfg;
/* MICA mode selection Differential or Single-ended */
bool mica_diff_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;
/* MICB mode selection Differential or Single-ended */
bool micb_diff_cfg;
/* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq;

View File

@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @dma_dev: If set, request DMA channel on this device rather than the DAI
* device.
* @chan_names: If set, these custom DMA channel names will be requested at
* registration time.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;
struct device *dma_dev;
const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
const struct snd_pcm_hardware *pcm_hardware;
unsigned int prealloc_buffer_size;
@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
unsigned int flags);
void snd_dmaengine_pcm_unregister(struct device *dev);
int devm_snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config,
unsigned int flags);
int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);

554
include/sound/hda_verbs.h Normal file
View File

@ -0,0 +1,554 @@
/*
* HD-audio codec verbs
*/
#ifndef __SOUND_HDA_VERBS_H
#define __SOUND_HDA_VERBS_H
/*
* nodes
*/
#define AC_NODE_ROOT 0x00
/*
* function group types
*/
enum {
AC_GRP_AUDIO_FUNCTION = 0x01,
AC_GRP_MODEM_FUNCTION = 0x02,
};
/*
* widget types
*/
enum {
AC_WID_AUD_OUT, /* Audio Out */
AC_WID_AUD_IN, /* Audio In */
AC_WID_AUD_MIX, /* Audio Mixer */
AC_WID_AUD_SEL, /* Audio Selector */
AC_WID_PIN, /* Pin Complex */
AC_WID_POWER, /* Power */
AC_WID_VOL_KNB, /* Volume Knob */
AC_WID_BEEP, /* Beep Generator */
AC_WID_VENDOR = 0x0f /* Vendor specific */
};
/*
* GET verbs
*/
#define AC_VERB_GET_STREAM_FORMAT 0x0a00
#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00
#define AC_VERB_GET_PROC_COEF 0x0c00
#define AC_VERB_GET_COEF_INDEX 0x0d00
#define AC_VERB_PARAMETERS 0x0f00
#define AC_VERB_GET_CONNECT_SEL 0x0f01
#define AC_VERB_GET_CONNECT_LIST 0x0f02
#define AC_VERB_GET_PROC_STATE 0x0f03
#define AC_VERB_GET_SDI_SELECT 0x0f04
#define AC_VERB_GET_POWER_STATE 0x0f05
#define AC_VERB_GET_CONV 0x0f06
#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07
#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08
#define AC_VERB_GET_PIN_SENSE 0x0f09
#define AC_VERB_GET_BEEP_CONTROL 0x0f0a
#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c
#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d
#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
/* f10-f1a: GPIO */
#define AC_VERB_GET_GPIO_DATA 0x0f15
#define AC_VERB_GET_GPIO_MASK 0x0f16
#define AC_VERB_GET_GPIO_DIRECTION 0x0f17
#define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18
#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19
#define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a
#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
/* f20: AFG/MFG */
#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20
#define AC_VERB_GET_CVT_CHAN_COUNT 0x0f2d
#define AC_VERB_GET_HDMI_DIP_SIZE 0x0f2e
#define AC_VERB_GET_HDMI_ELDD 0x0f2f
#define AC_VERB_GET_HDMI_DIP_INDEX 0x0f30
#define AC_VERB_GET_HDMI_DIP_DATA 0x0f31
#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32
#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33
#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34
#define AC_VERB_GET_DEVICE_SEL 0xf35
#define AC_VERB_GET_DEVICE_LIST 0xf36
/*
* SET verbs
*/
#define AC_VERB_SET_STREAM_FORMAT 0x200
#define AC_VERB_SET_AMP_GAIN_MUTE 0x300
#define AC_VERB_SET_PROC_COEF 0x400
#define AC_VERB_SET_COEF_INDEX 0x500
#define AC_VERB_SET_CONNECT_SEL 0x701
#define AC_VERB_SET_PROC_STATE 0x703
#define AC_VERB_SET_SDI_SELECT 0x704
#define AC_VERB_SET_POWER_STATE 0x705
#define AC_VERB_SET_CHANNEL_STREAMID 0x706
#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707
#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708
#define AC_VERB_SET_PIN_SENSE 0x709
#define AC_VERB_SET_BEEP_CONTROL 0x70a
#define AC_VERB_SET_EAPD_BTLENABLE 0x70c
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
#define AC_VERB_SET_GPIO_DATA 0x715
#define AC_VERB_SET_GPIO_MASK 0x716
#define AC_VERB_SET_GPIO_DIRECTION 0x717
#define AC_VERB_SET_GPIO_WAKE_MASK 0x718
#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719
#define AC_VERB_SET_GPIO_STICKY_MASK 0x71a
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f
#define AC_VERB_SET_EAPD 0x788
#define AC_VERB_SET_CODEC_RESET 0x7ff
#define AC_VERB_SET_CVT_CHAN_COUNT 0x72d
#define AC_VERB_SET_HDMI_DIP_INDEX 0x730
#define AC_VERB_SET_HDMI_DIP_DATA 0x731
#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
#define AC_VERB_SET_HDMI_CP_CTRL 0x733
#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
#define AC_VERB_SET_DEVICE_SEL 0x735
/*
* Parameter IDs
*/
#define AC_PAR_VENDOR_ID 0x00
#define AC_PAR_SUBSYSTEM_ID 0x01
#define AC_PAR_REV_ID 0x02
#define AC_PAR_NODE_COUNT 0x04
#define AC_PAR_FUNCTION_TYPE 0x05
#define AC_PAR_AUDIO_FG_CAP 0x08
#define AC_PAR_AUDIO_WIDGET_CAP 0x09
#define AC_PAR_PCM 0x0a
#define AC_PAR_STREAM 0x0b
#define AC_PAR_PIN_CAP 0x0c
#define AC_PAR_AMP_IN_CAP 0x0d
#define AC_PAR_CONNLIST_LEN 0x0e
#define AC_PAR_POWER_STATE 0x0f
#define AC_PAR_PROC_CAP 0x10
#define AC_PAR_GPIO_CAP 0x11
#define AC_PAR_AMP_OUT_CAP 0x12
#define AC_PAR_VOL_KNB_CAP 0x13
#define AC_PAR_DEVLIST_LEN 0x15
#define AC_PAR_HDMI_LPCM_CAP 0x20
/*
* AC_VERB_PARAMETERS results (32bit)
*/
/* Function Group Type */
#define AC_FGT_TYPE (0xff<<0)
#define AC_FGT_TYPE_SHIFT 0
#define AC_FGT_UNSOL_CAP (1<<8)
/* Audio Function Group Capabilities */
#define AC_AFG_OUT_DELAY (0xf<<0)
#define AC_AFG_IN_DELAY (0xf<<8)
#define AC_AFG_BEEP_GEN (1<<16)
/* Audio Widget Capabilities */
#define AC_WCAP_STEREO (1<<0) /* stereo I/O */
#define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */
#define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */
#define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */
#define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */
#define AC_WCAP_STRIPE (1<<5) /* stripe */
#define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */
#define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */
#define AC_WCAP_CONN_LIST (1<<8) /* connection list */
#define AC_WCAP_DIGITAL (1<<9) /* digital I/O */
#define AC_WCAP_POWER (1<<10) /* power control */
#define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */
#define AC_WCAP_CP_CAPS (1<<12) /* content protection */
#define AC_WCAP_CHAN_CNT_EXT (7<<13) /* channel count ext */
#define AC_WCAP_DELAY (0xf<<16)
#define AC_WCAP_DELAY_SHIFT 16
#define AC_WCAP_TYPE (0xf<<20)
#define AC_WCAP_TYPE_SHIFT 20
/* supported PCM rates and bits */
#define AC_SUPPCM_RATES (0xfff << 0)
#define AC_SUPPCM_BITS_8 (1<<16)
#define AC_SUPPCM_BITS_16 (1<<17)
#define AC_SUPPCM_BITS_20 (1<<18)
#define AC_SUPPCM_BITS_24 (1<<19)
#define AC_SUPPCM_BITS_32 (1<<20)
/* supported PCM stream format */
#define AC_SUPFMT_PCM (1<<0)
#define AC_SUPFMT_FLOAT32 (1<<1)
#define AC_SUPFMT_AC3 (1<<2)
/* GP I/O count */
#define AC_GPIO_IO_COUNT (0xff<<0)
#define AC_GPIO_O_COUNT (0xff<<8)
#define AC_GPIO_O_COUNT_SHIFT 8
#define AC_GPIO_I_COUNT (0xff<<16)
#define AC_GPIO_I_COUNT_SHIFT 16
#define AC_GPIO_UNSOLICITED (1<<30)
#define AC_GPIO_WAKE (1<<31)
/* Converter stream, channel */
#define AC_CONV_CHANNEL (0xf<<0)
#define AC_CONV_STREAM (0xf<<4)
#define AC_CONV_STREAM_SHIFT 4
/* Input converter SDI select */
#define AC_SDI_SELECT (0xf<<0)
/* stream format id */
#define AC_FMT_CHAN_SHIFT 0
#define AC_FMT_CHAN_MASK (0x0f << 0)
#define AC_FMT_BITS_SHIFT 4
#define AC_FMT_BITS_MASK (7 << 4)
#define AC_FMT_BITS_8 (0 << 4)
#define AC_FMT_BITS_16 (1 << 4)
#define AC_FMT_BITS_20 (2 << 4)
#define AC_FMT_BITS_24 (3 << 4)
#define AC_FMT_BITS_32 (4 << 4)
#define AC_FMT_DIV_SHIFT 8
#define AC_FMT_DIV_MASK (7 << 8)
#define AC_FMT_MULT_SHIFT 11
#define AC_FMT_MULT_MASK (7 << 11)
#define AC_FMT_BASE_SHIFT 14
#define AC_FMT_BASE_48K (0 << 14)
#define AC_FMT_BASE_44K (1 << 14)
#define AC_FMT_TYPE_SHIFT 15
#define AC_FMT_TYPE_PCM (0 << 15)
#define AC_FMT_TYPE_NON_PCM (1 << 15)
/* Unsolicited response control */
#define AC_UNSOL_TAG (0x3f<<0)
#define AC_UNSOL_ENABLED (1<<7)
#define AC_USRSP_EN AC_UNSOL_ENABLED
/* Unsolicited responses */
#define AC_UNSOL_RES_TAG (0x3f<<26)
#define AC_UNSOL_RES_TAG_SHIFT 26
#define AC_UNSOL_RES_SUBTAG (0x1f<<21)
#define AC_UNSOL_RES_SUBTAG_SHIFT 21
#define AC_UNSOL_RES_DE (0x3f<<15) /* Device Entry
* (for DP1.2 MST)
*/
#define AC_UNSOL_RES_DE_SHIFT 15
#define AC_UNSOL_RES_IA (1<<2) /* Inactive (for DP1.2 MST) */
#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */
#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */
#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */
#define AC_UNSOL_RES_CP_READY (1<<0) /* content protection */
/* Pin widget capabilies */
#define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */
#define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */
#define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */
#define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */
#define AC_PINCAP_OUT (1<<4) /* output capable */
#define AC_PINCAP_IN (1<<5) /* input capable */
#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */
/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
* but is marked reserved in the Intel HDA specification.
*/
#define AC_PINCAP_LR_SWAP (1<<7) /* L/R swap */
/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
* in HD-audio specification
*/
#define AC_PINCAP_HDMI (1<<7) /* HDMI pin */
#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can
* coexist with AC_PINCAP_HDMI
*/
#define AC_PINCAP_VREF (0x37<<8)
#define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */
/* Vref status (used in pin cap) */
#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
#define AC_PINCAP_VREF_50 (1<<1) /* 50% */
#define AC_PINCAP_VREF_GRD (1<<2) /* ground */
#define AC_PINCAP_VREF_80 (1<<4) /* 80% */
#define AC_PINCAP_VREF_100 (1<<5) /* 100% */
/* Amplifier capabilities */
#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */
#define AC_AMPCAP_OFFSET_SHIFT 0
#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */
#define AC_AMPCAP_NUM_STEPS_SHIFT 8
#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB
* in 0.25dB
*/
#define AC_AMPCAP_STEP_SIZE_SHIFT 16
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
/* driver-specific amp-caps: using bits 24-30 */
#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
/* Supported power status */
#define AC_PWRST_D0SUP (1<<0)
#define AC_PWRST_D1SUP (1<<1)
#define AC_PWRST_D2SUP (1<<2)
#define AC_PWRST_D3SUP (1<<3)
#define AC_PWRST_D3COLDSUP (1<<4)
#define AC_PWRST_S3D3COLDSUP (1<<29)
#define AC_PWRST_CLKSTOP (1<<30)
#define AC_PWRST_EPSS (1U<<31)
/* Power state values */
#define AC_PWRST_SETTING (0xf<<0)
#define AC_PWRST_ACTUAL (0xf<<4)
#define AC_PWRST_ACTUAL_SHIFT 4
#define AC_PWRST_D0 0x00
#define AC_PWRST_D1 0x01
#define AC_PWRST_D2 0x02
#define AC_PWRST_D3 0x03
#define AC_PWRST_ERROR (1<<8)
#define AC_PWRST_CLK_STOP_OK (1<<9)
#define AC_PWRST_SETTING_RESET (1<<10)
/* Processing capabilies */
#define AC_PCAP_BENIGN (1<<0)
#define AC_PCAP_NUM_COEF (0xff<<8)
#define AC_PCAP_NUM_COEF_SHIFT 8
/* Volume knobs capabilities */
#define AC_KNBCAP_NUM_STEPS (0x7f<<0)
#define AC_KNBCAP_DELTA (1<<7)
/* HDMI LPCM capabilities */
#define AC_LPCMCAP_48K_CP_CHNS (0x0f<<0) /* max channels w/ CP-on */
#define AC_LPCMCAP_48K_NO_CHNS (0x0f<<4) /* max channels w/o CP-on */
#define AC_LPCMCAP_48K_20BIT (1<<8) /* 20b bitrate supported */
#define AC_LPCMCAP_48K_24BIT (1<<9) /* 24b bitrate supported */
#define AC_LPCMCAP_96K_CP_CHNS (0x0f<<10) /* max channels w/ CP-on */
#define AC_LPCMCAP_96K_NO_CHNS (0x0f<<14) /* max channels w/o CP-on */
#define AC_LPCMCAP_96K_20BIT (1<<18) /* 20b bitrate supported */
#define AC_LPCMCAP_96K_24BIT (1<<19) /* 24b bitrate supported */
#define AC_LPCMCAP_192K_CP_CHNS (0x0f<<20) /* max channels w/ CP-on */
#define AC_LPCMCAP_192K_NO_CHNS (0x0f<<24) /* max channels w/o CP-on */
#define AC_LPCMCAP_192K_20BIT (1<<28) /* 20b bitrate supported */
#define AC_LPCMCAP_192K_24BIT (1<<29) /* 24b bitrate supported */
#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */
#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */
/* Display pin's device list length */
#define AC_DEV_LIST_LEN_MASK 0x3f
#define AC_MAX_DEV_LIST_LEN 64
/*
* Control Parameters
*/
/* Amp gain/mute */
#define AC_AMP_MUTE (1<<7)
#define AC_AMP_GAIN (0x7f)
#define AC_AMP_GET_INDEX (0xf<<0)
#define AC_AMP_GET_LEFT (1<<13)
#define AC_AMP_GET_RIGHT (0<<13)
#define AC_AMP_GET_OUTPUT (1<<15)
#define AC_AMP_GET_INPUT (0<<15)
#define AC_AMP_SET_INDEX (0xf<<8)
#define AC_AMP_SET_INDEX_SHIFT 8
#define AC_AMP_SET_RIGHT (1<<12)
#define AC_AMP_SET_LEFT (1<<13)
#define AC_AMP_SET_INPUT (1<<14)
#define AC_AMP_SET_OUTPUT (1<<15)
/* DIGITAL1 bits */
#define AC_DIG1_ENABLE (1<<0)
#define AC_DIG1_V (1<<1)
#define AC_DIG1_VCFG (1<<2)
#define AC_DIG1_EMPHASIS (1<<3)
#define AC_DIG1_COPYRIGHT (1<<4)
#define AC_DIG1_NONAUDIO (1<<5)
#define AC_DIG1_PROFESSIONAL (1<<6)
#define AC_DIG1_LEVEL (1<<7)
/* DIGITAL2 bits */
#define AC_DIG2_CC (0x7f<<0)
/* DIGITAL3 bits */
#define AC_DIG3_ICT (0xf<<0)
#define AC_DIG3_KAE (1<<7)
/* Pin widget control - 8bit */
#define AC_PINCTL_EPT (0x3<<0)
#define AC_PINCTL_EPT_NATIVE 0
#define AC_PINCTL_EPT_HBR 3
#define AC_PINCTL_VREFEN (0x7<<0)
#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
#define AC_PINCTL_VREF_50 1 /* 50% */
#define AC_PINCTL_VREF_GRD 2 /* ground */
#define AC_PINCTL_VREF_80 4 /* 80% */
#define AC_PINCTL_VREF_100 5 /* 100% */
#define AC_PINCTL_IN_EN (1<<5)
#define AC_PINCTL_OUT_EN (1<<6)
#define AC_PINCTL_HP_EN (1<<7)
/* Pin sense - 32bit */
#define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff)
#define AC_PINSENSE_PRESENCE (1<<31)
#define AC_PINSENSE_ELDV (1<<30) /* ELD valid (HDMI) */
/* EAPD/BTL enable - 32bit */
#define AC_EAPDBTL_BALANCED (1<<0)
#define AC_EAPDBTL_EAPD (1<<1)
#define AC_EAPDBTL_LR_SWAP (1<<2)
/* HDMI ELD data */
#define AC_ELDD_ELD_VALID (1<<31)
#define AC_ELDD_ELD_DATA 0xff
/* HDMI DIP size */
#define AC_DIPSIZE_ELD_BUF (1<<3) /* ELD buf size of packet size */
#define AC_DIPSIZE_PACK_IDX (0x07<<0) /* packet index */
/* HDMI DIP index */
#define AC_DIPIDX_PACK_IDX (0x07<<5) /* packet idnex */
#define AC_DIPIDX_BYTE_IDX (0x1f<<0) /* byte index */
/* HDMI DIP xmit (transmit) control */
#define AC_DIPXMIT_MASK (0x3<<6)
#define AC_DIPXMIT_DISABLE (0x0<<6) /* disable xmit */
#define AC_DIPXMIT_ONCE (0x2<<6) /* xmit once then disable */
#define AC_DIPXMIT_BEST (0x3<<6) /* best effort */
/* HDMI content protection (CP) control */
#define AC_CPCTRL_CES (1<<9) /* current encryption state */
#define AC_CPCTRL_READY (1<<8) /* ready bit */
#define AC_CPCTRL_SUBTAG (0x1f<<3) /* subtag for unsol-resp */
#define AC_CPCTRL_STATE (3<<0) /* current CP request state */
/* Converter channel <-> HDMI slot mapping */
#define AC_CVTMAP_HDMI_SLOT (0xf<<0) /* HDMI slot number */
#define AC_CVTMAP_CHAN (0xf<<4) /* converter channel number */
/* configuration default - 32bit */
#define AC_DEFCFG_SEQUENCE (0xf<<0)
#define AC_DEFCFG_DEF_ASSOC (0xf<<4)
#define AC_DEFCFG_ASSOC_SHIFT 4
#define AC_DEFCFG_MISC (0xf<<8)
#define AC_DEFCFG_MISC_SHIFT 8
#define AC_DEFCFG_MISC_NO_PRESENCE (1<<0)
#define AC_DEFCFG_COLOR (0xf<<12)
#define AC_DEFCFG_COLOR_SHIFT 12
#define AC_DEFCFG_CONN_TYPE (0xf<<16)
#define AC_DEFCFG_CONN_TYPE_SHIFT 16
#define AC_DEFCFG_DEVICE (0xf<<20)
#define AC_DEFCFG_DEVICE_SHIFT 20
#define AC_DEFCFG_LOCATION (0x3f<<24)
#define AC_DEFCFG_LOCATION_SHIFT 24
#define AC_DEFCFG_PORT_CONN (0x3<<30)
#define AC_DEFCFG_PORT_CONN_SHIFT 30
/* Display pin's device list entry */
#define AC_DE_PD (1<<0)
#define AC_DE_ELDV (1<<1)
#define AC_DE_IA (1<<2)
/* device device types (0x0-0xf) */
enum {
AC_JACK_LINE_OUT,
AC_JACK_SPEAKER,
AC_JACK_HP_OUT,
AC_JACK_CD,
AC_JACK_SPDIF_OUT,
AC_JACK_DIG_OTHER_OUT,
AC_JACK_MODEM_LINE_SIDE,
AC_JACK_MODEM_HAND_SIDE,
AC_JACK_LINE_IN,
AC_JACK_AUX,
AC_JACK_MIC_IN,
AC_JACK_TELEPHONY,
AC_JACK_SPDIF_IN,
AC_JACK_DIG_OTHER_IN,
AC_JACK_OTHER = 0xf,
};
/* jack connection types (0x0-0xf) */
enum {
AC_JACK_CONN_UNKNOWN,
AC_JACK_CONN_1_8,
AC_JACK_CONN_1_4,
AC_JACK_CONN_ATAPI,
AC_JACK_CONN_RCA,
AC_JACK_CONN_OPTICAL,
AC_JACK_CONN_OTHER_DIGITAL,
AC_JACK_CONN_OTHER_ANALOG,
AC_JACK_CONN_DIN,
AC_JACK_CONN_XLR,
AC_JACK_CONN_RJ11,
AC_JACK_CONN_COMB,
AC_JACK_CONN_OTHER = 0xf,
};
/* jack colors (0x0-0xf) */
enum {
AC_JACK_COLOR_UNKNOWN,
AC_JACK_COLOR_BLACK,
AC_JACK_COLOR_GREY,
AC_JACK_COLOR_BLUE,
AC_JACK_COLOR_GREEN,
AC_JACK_COLOR_RED,
AC_JACK_COLOR_ORANGE,
AC_JACK_COLOR_YELLOW,
AC_JACK_COLOR_PURPLE,
AC_JACK_COLOR_PINK,
AC_JACK_COLOR_WHITE = 0xe,
AC_JACK_COLOR_OTHER,
};
/* Jack location (0x0-0x3f) */
/* common case */
enum {
AC_JACK_LOC_NONE,
AC_JACK_LOC_REAR,
AC_JACK_LOC_FRONT,
AC_JACK_LOC_LEFT,
AC_JACK_LOC_RIGHT,
AC_JACK_LOC_TOP,
AC_JACK_LOC_BOTTOM,
};
/* bits 4-5 */
enum {
AC_JACK_LOC_EXTERNAL = 0x00,
AC_JACK_LOC_INTERNAL = 0x10,
AC_JACK_LOC_SEPARATE = 0x20,
AC_JACK_LOC_OTHER = 0x30,
};
enum {
/* external on primary chasis */
AC_JACK_LOC_REAR_PANEL = 0x07,
AC_JACK_LOC_DRIVE_BAY,
/* internal */
AC_JACK_LOC_RISER = 0x17,
AC_JACK_LOC_HDMI,
AC_JACK_LOC_ATAPI,
/* others */
AC_JACK_LOC_MOBILE_IN = 0x37,
AC_JACK_LOC_MOBILE_OUT,
};
/* Port connectivity (0-3) */
enum {
AC_JACK_PORT_COMPLEX,
AC_JACK_PORT_NONE,
AC_JACK_PORT_FIXED,
AC_JACK_PORT_BOTH,
};
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS 0x0f
#endif /* __SOUND_HDA_VERBS_H */

View File

@ -149,13 +149,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
struct snd_dma_buffer *dmab);
void snd_dma_free_pages(struct snd_dma_buffer *dmab);
/* buffer-preservation managements */
#define snd_dma_pci_buf_id(pci) (((unsigned int)(pci)->vendor << 16) | (pci)->device)
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
/* basic memory allocation functions */
void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
void snd_free_pages(void *ptr, size_t size);

View File

@ -381,7 +381,6 @@ struct snd_pcm_substream {
struct pm_qos_request latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
size_t dma_max;
/* -- hardware operations -- */
const struct snd_pcm_ops *ops;
@ -901,6 +900,8 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
unsigned int rates_b);
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)

View File

@ -354,4 +354,16 @@ params_period_bytes(const struct snd_pcm_hw_params *p)
params_channels(p)) / 8;
}
static inline int
params_width(const struct snd_pcm_hw_params *p)
{
return snd_pcm_format_width(params_format(p));
}
static inline int
params_physical_width(const struct snd_pcm_hw_params *p)
{
return snd_pcm_format_physical_width(params_format(p));
}
#endif /* __SOUND_PCM_PARAMS_H */

View File

@ -18,7 +18,7 @@
#define RSND_GEN1_ADG 1
#define RSND_GEN1_SSI 2
#define RSND_GEN2_SRU 0
#define RSND_GEN2_SCU 0
#define RSND_GEN2_ADG 1
#define RSND_GEN2_SSIU 2
#define RSND_GEN2_SSI 3
@ -58,6 +58,7 @@ struct rsnd_ssi_platform_info {
struct rsnd_scu_platform_info {
u32 flags;
u32 convert_rate; /* sampling rate convert */
};
/*

View File

@ -123,6 +123,8 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
int direction);
int snd_soc_dai_is_dummy(struct snd_soc_dai *dai);
struct snd_soc_dai_ops {
/*
* DAI clocking configuration, all optional.
@ -220,6 +222,8 @@ struct snd_soc_dai_driver {
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;
@ -244,6 +248,8 @@ struct snd_soc_dai {
unsigned int capture_active:1; /* stream is in use */
unsigned int playback_active:1; /* stream is in use */
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
struct snd_pcm_runtime *runtime;
unsigned int active;
unsigned char probed:1;
@ -258,6 +264,8 @@ struct snd_soc_dai {
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
unsigned int channels;
unsigned int sample_bits;
/* parent platform/codec */
struct snd_soc_platform *platform;

View File

@ -412,6 +412,7 @@ 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);
void snd_soc_dapm_connect_dai_link_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,

View File

@ -11,6 +11,7 @@
#ifndef __LINUX_SND_SOC_DPCM_H
#define __LINUX_SND_SOC_DPCM_H
#include <linux/slab.h>
#include <linux/list.h>
#include <sound/pcm.h>
@ -135,4 +136,25 @@ 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_card *);
int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
int stream, struct snd_soc_dapm_widget_list **list_);
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
int stream, struct snd_soc_dapm_widget_list **list, int new);
int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream);
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
int event);
static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
{
kfree(*list);
}
#endif

View File

@ -334,9 +334,7 @@ struct snd_soc_jack_pin;
#include <sound/soc-dapm.h>
#include <sound/soc-dpcm.h>
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio;
#endif
typedef int (*hw_write_t)(void *,const char* ,int);
@ -446,6 +444,17 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios);
void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios);
#else
static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
return 0;
}
static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
}
#endif
/* codec register bit access */
@ -580,7 +589,6 @@ struct snd_soc_jack_zone {
* to provide more complex checks (eg, reading an
* ADC).
*/
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio {
unsigned int gpio;
const char *name;
@ -594,7 +602,6 @@ struct snd_soc_jack_gpio {
int (*jack_status_check)(void);
};
#endif
struct snd_soc_jack {
struct mutex mutex;
@ -879,6 +886,8 @@ struct snd_soc_dai_link {
/* Symmetry requirements */
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
/* Do not create a PCM for this DAI link (Backend link) */
unsigned int no_pcm:1;
@ -886,6 +895,10 @@ struct snd_soc_dai_link {
/* This DAI link can route to other DAI links at runtime (Frontend)*/
unsigned int dynamic:1;
/* DPCM capture and Playback support */
unsigned int dpcm_capture:1;
unsigned int dpcm_playback:1;
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
@ -1029,6 +1042,7 @@ struct snd_soc_pcm_runtime {
/* Dynamic PCM BE runtime data */
struct snd_soc_dpcm_runtime dpcm[2];
int fe_compr;
long pmdown_time;
unsigned char pop_wait:1;

View File

@ -29,7 +29,6 @@ struct spear_dma_data {
dma_addr_t addr;
u32 max_burst;
enum dma_slave_buswidth addr_width;
bool (*filter)(struct dma_chan *chan, void *slave);
};
#endif /* SPEAR_DMA_H */

View File

@ -57,6 +57,7 @@
#define MAX_NUM_CODECS 32
#define MAX_NUM_CODEC_DESCRIPTORS 32
#define MAX_NUM_BITRATES 32
#define MAX_NUM_SAMPLE_RATES 32
/* Codecs are listed linearly to allow for extensibility */
#define SND_AUDIOCODEC_PCM ((__u32) 0x00000001)
@ -324,7 +325,8 @@ union snd_codec_options {
/** struct snd_codec_desc - description of codec capabilities
* @max_ch: Maximum number of audio channels
* @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
* @sample_rates: Sampling rates in Hz, use values like 48000 for this
* @num_sample_rates: Number of valid values in sample_rates array
* @bit_rate: Indexed array containing supported bit rates
* @num_bitrates: Number of valid values in bit_rate array
* @rate_control: value is specified by SND_RATECONTROLMODE defines.
@ -346,7 +348,8 @@ union snd_codec_options {
struct snd_codec_desc {
__u32 max_ch;
__u32 sample_rates;
__u32 sample_rates[MAX_NUM_SAMPLE_RATES];
__u32 num_sample_rates;
__u32 bit_rate[MAX_NUM_BITRATES];
__u32 num_bitrates;
__u32 rate_control;
@ -364,7 +367,8 @@ struct snd_codec_desc {
* @ch_out: Number of output channels. In case of contradiction between
* this field and the channelMode field, the channelMode field
* overrides.
* @sample_rate: Audio sample rate of input data
* @sample_rate: Audio sample rate of input data in Hz, use values like 48000
* for this.
* @bit_rate: Bitrate of encoded data. May be ignored by decoders
* @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
* Encoders may rely on profiles for quality levels.

View File

@ -753,7 +753,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
* Power Management.
*/
#ifdef CONFIG_PM
static int aaci_do_suspend(struct snd_card *card, unsigned int state)
static int aaci_do_suspend(struct snd_card *card)
{
struct aaci *aaci = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
@ -761,28 +761,28 @@ static int aaci_do_suspend(struct snd_card *card, unsigned int state)
return 0;
}
static int aaci_do_resume(struct snd_card *card, unsigned int state)
static int aaci_do_resume(struct snd_card *card)
{
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
static int aaci_suspend(struct amba_device *dev, pm_message_t state)
static int aaci_suspend(struct device *dev)
{
struct snd_card *card = amba_get_drvdata(dev);
struct snd_card *card = dev_get_drvdata(dev);
return card ? aaci_do_suspend(card) : 0;
}
static int aaci_resume(struct amba_device *dev)
static int aaci_resume(struct device *dev)
{
struct snd_card *card = amba_get_drvdata(dev);
struct snd_card *card = dev_get_drvdata(dev);
return card ? aaci_do_resume(card) : 0;
}
static SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);
#define AACI_DEV_PM_OPS (&aaci_dev_pm_ops)
#else
#define aaci_do_suspend NULL
#define aaci_do_resume NULL
#define aaci_suspend NULL
#define aaci_resume NULL
#define AACI_DEV_PM_OPS NULL
#endif
@ -1100,11 +1100,10 @@ MODULE_DEVICE_TABLE(amba, aaci_ids);
static struct amba_driver aaci_driver = {
.drv = {
.name = DRIVER_NAME,
.pm = AACI_DEV_PM_OPS,
},
.probe = aaci_probe,
.remove = aaci_remove,
.suspend = aaci_suspend,
.resume = aaci_resume,
.id_table = aaci_ids,
};

View File

@ -354,7 +354,7 @@ static int set_sample_rates(struct atmel_abdac *dac)
/* we start at 192 kHz and work our way down to 5112 Hz */
while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
if (new_rate < 0)
if (new_rate <= 0)
break;
/* make sure we are below the ABDAC clock */
if (index < MAX_NUM_RATES &&

View File

@ -10,14 +10,12 @@ snd-$(CONFIG_SND_VMASTER) += vmaster.o
snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
snd-$(CONFIG_SND_JACK) += jack.o
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o
snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o memalloc.o
snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-pcm-dmaengine-objs := pcm_dmaengine.o
snd-page-alloc-y := memalloc.o
snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
snd-hrtimer-objs := hrtimer.o
@ -31,7 +29,7 @@ obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_TIMER) += snd-timer.o
obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o
obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o

View File

@ -501,9 +501,6 @@ static int snd_compress_check_input(struct snd_compr_params *params)
if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
return -EINVAL;
if (!(params->codec.sample_rate & SNDRV_PCM_RATE_8000_192000))
return -EINVAL;
return 0;
}

View File

@ -21,60 +21,18 @@
*
*/
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
#include <linux/genalloc.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <sound/memalloc.h>
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
/*
*/
static DEFINE_MUTEX(list_mutex);
static LIST_HEAD(mem_list_head);
/* buffer preservation list */
struct snd_mem_list {
struct snd_dma_buffer buffer;
unsigned int id;
struct list_head list;
};
/* id for pre-allocated buffers */
#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
/*
*
* Generic memory allocators
*
*/
static long snd_allocated_pages; /* holding the number of allocated pages */
static inline void inc_snd_pages(int order)
{
snd_allocated_pages += 1 << order;
}
static inline void dec_snd_pages(int order)
{
snd_allocated_pages -= 1 << order;
}
/**
* snd_malloc_pages - allocate pages with the given size
* @size: the size to allocate in bytes
@ -87,7 +45,6 @@ static inline void dec_snd_pages(int order)
void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
{
int pg;
void *res;
if (WARN_ON(!size))
return NULL;
@ -95,9 +52,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
return NULL;
gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
pg = get_order(size);
if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
inc_snd_pages(pg);
return res;
return (void *) __get_free_pages(gfp_flags, pg);
}
/**
@ -114,7 +69,6 @@ void snd_free_pages(void *ptr, size_t size)
if (ptr == NULL)
return;
pg = get_order(size);
dec_snd_pages(pg);
free_pages((unsigned long) ptr, pg);
}
@ -129,7 +83,6 @@ void snd_free_pages(void *ptr, size_t size)
static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
{
int pg;
void *res;
gfp_t gfp_flags;
if (WARN_ON(!dma))
@ -139,11 +92,7 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
| __GFP_COMP /* compound page lets parts be mapped */
| __GFP_NORETRY /* don't trigger OOM-killer */
| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
if (res != NULL)
inc_snd_pages(pg);
return res;
return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
}
/* free the coherent DMA pages */
@ -155,7 +104,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
if (ptr == NULL)
return;
pg = get_order(size);
dec_snd_pages(pg);
dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
}
@ -340,256 +288,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
}
}
/**
* snd_dma_get_reserved - get the reserved buffer for the given device
* @dmab: the buffer allocation record to store
* @id: the buffer id
*
* Looks for the reserved-buffer list and re-uses if the same buffer
* is found in the list. When the buffer is found, it's removed from the free list.
*
* Return: The size of buffer if the buffer is found, or zero if not found.
*/
size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
if (WARN_ON(!dmab))
return 0;
mutex_lock(&list_mutex);
list_for_each_entry(mem, &mem_list_head, list) {
if (mem->id == id &&
(mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
struct device *dev = dmab->dev.dev;
list_del(&mem->list);
*dmab = mem->buffer;
if (dmab->dev.dev == NULL)
dmab->dev.dev = dev;
kfree(mem);
mutex_unlock(&list_mutex);
return dmab->bytes;
}
}
mutex_unlock(&list_mutex);
return 0;
}
/**
* snd_dma_reserve_buf - reserve the buffer
* @dmab: the buffer to reserve
* @id: the buffer id
*
* Reserves the given buffer as a reserved buffer.
*
* Return: Zero if successful, or a negative code on error.
*/
int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
if (WARN_ON(!dmab))
return -EINVAL;
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (! mem)
return -ENOMEM;
mutex_lock(&list_mutex);
mem->buffer = *dmab;
mem->id = id;
list_add_tail(&mem->list, &mem_list_head);
mutex_unlock(&list_mutex);
return 0;
}
/*
* purge all reserved buffers
*/
static void free_all_reserved_pages(void)
{
struct list_head *p;
struct snd_mem_list *mem;
mutex_lock(&list_mutex);
while (! list_empty(&mem_list_head)) {
p = mem_list_head.next;
mem = list_entry(p, struct snd_mem_list, list);
list_del(p);
snd_dma_free_pages(&mem->buffer);
kfree(mem);
}
mutex_unlock(&list_mutex);
}
#ifdef CONFIG_PROC_FS
/*
* proc file interface
*/
#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
static struct proc_dir_entry *snd_mem_proc;
static int snd_mem_proc_read(struct seq_file *seq, void *offset)
{
long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
struct snd_mem_list *mem;
int devno;
static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" };
mutex_lock(&list_mutex);
seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n",
pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
devno = 0;
list_for_each_entry(mem, &mem_list_head, list) {
devno++;
seq_printf(seq, "buffer %d : ID %08x : type %s\n",
devno, mem->id, types[mem->buffer.dev.type]);
seq_printf(seq, " addr = 0x%lx, size = %d bytes\n",
(unsigned long)mem->buffer.addr,
(int)mem->buffer.bytes);
}
mutex_unlock(&list_mutex);
return 0;
}
static int snd_mem_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, snd_mem_proc_read, NULL);
}
/* FIXME: for pci only - other bus? */
#ifdef CONFIG_PCI
#define gettoken(bufp) strsep(bufp, " \t\n")
static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
char buf[128];
char *token, *p;
if (count > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
p = buf;
token = gettoken(&p);
if (! token || *token == '#')
return count;
if (strcmp(token, "add") == 0) {
char *endp;
int vendor, device, size, buffers;
long mask;
int i, alloced;
struct pci_dev *pci;
if ((token = gettoken(&p)) == NULL ||
(vendor = simple_strtol(token, NULL, 0)) <= 0 ||
(token = gettoken(&p)) == NULL ||
(device = simple_strtol(token, NULL, 0)) <= 0 ||
(token = gettoken(&p)) == NULL ||
(mask = simple_strtol(token, NULL, 0)) < 0 ||
(token = gettoken(&p)) == NULL ||
(size = memparse(token, &endp)) < 64*1024 ||
size > 16*1024*1024 /* too big */ ||
(token = gettoken(&p)) == NULL ||
(buffers = simple_strtol(token, NULL, 0)) <= 0 ||
buffers > 4) {
printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
return count;
}
vendor &= 0xffff;
device &= 0xffff;
alloced = 0;
pci = NULL;
while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
if (mask > 0 && mask < 0xffffffff) {
if (pci_set_dma_mask(pci, mask) < 0 ||
pci_set_consistent_dma_mask(pci, mask) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
pci_dev_put(pci);
return count;
}
}
for (i = 0; i < buffers; i++) {
struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
pci_dev_put(pci);
return count;
}
snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
}
alloced++;
}
if (! alloced) {
for (i = 0; i < buffers; i++) {
struct snd_dma_buffer dmab;
memset(&dmab, 0, sizeof(dmab));
/* FIXME: We can allocate only in ZONE_DMA
* without a device pointer!
*/
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
break;
}
snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
}
}
} else if (strcmp(token, "erase") == 0)
/* FIXME: need for releasing each buffer chunk? */
free_all_reserved_pages();
else
printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
return count;
}
#endif /* CONFIG_PCI */
static const struct file_operations snd_mem_proc_fops = {
.owner = THIS_MODULE,
.open = snd_mem_proc_open,
.read = seq_read,
#ifdef CONFIG_PCI
.write = snd_mem_proc_write,
#endif
.llseek = seq_lseek,
.release = single_release,
};
#endif /* CONFIG_PROC_FS */
/*
* module entry
*/
static int __init snd_mem_init(void)
{
#ifdef CONFIG_PROC_FS
snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
&snd_mem_proc_fops);
#endif
return 0;
}
static void __exit snd_mem_exit(void)
{
remove_proc_entry(SND_MEM_PROC_FILE, NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
}
module_init(snd_mem_init)
module_exit(snd_mem_exit)
/*
* exports
*/
@ -597,8 +295,5 @@ EXPORT_SYMBOL(snd_dma_alloc_pages);
EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
EXPORT_SYMBOL(snd_dma_free_pages);
EXPORT_SYMBOL(snd_dma_get_reserved_buf);
EXPORT_SYMBOL(snd_dma_reserve_buf);
EXPORT_SYMBOL(snd_malloc_pages);
EXPORT_SYMBOL(snd_free_pages);

View File

@ -51,17 +51,9 @@ static const size_t snd_minimum_buffer = 16384;
static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
{
struct snd_dma_buffer *dmab = &substream->dma_buffer;
size_t orig_size = size;
int err;
/* already reserved? */
if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
if (dmab->bytes >= size)
return 0; /* yes */
/* no, free the reserved block */
snd_dma_free_pages(dmab);
dmab->bytes = 0;
}
do {
if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
size, dmab)) < 0) {
@ -72,6 +64,10 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
size >>= 1;
} while (size >= snd_minimum_buffer);
dmab->bytes = 0; /* tell error */
pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
substream->pcm->card->number, substream->pcm->device,
substream->stream ? 'c' : 'p', substream->number,
substream->pcm->name, orig_size);
return 0;
}
@ -82,10 +78,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
{
if (substream->dma_buffer.area == NULL)
return;
if (substream->dma_buf_id)
snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
else
snd_dma_free_pages(&substream->dma_buffer);
snd_dma_free_pages(&substream->dma_buffer);
substream->dma_buffer.area = NULL;
}
@ -260,11 +253,6 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
*
* Do pre-allocation for the given DMA buffer type.
*
* When substream->dma_buf_id is set, the function tries to look for
* the reserved buffer, and the buffer is not freed but reserved at
* destruction time. The dma_buf_id must be unique for all systems
* (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,

View File

@ -514,3 +514,42 @@ unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
return 0;
}
EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate);
static unsigned int snd_pcm_rate_mask_sanitize(unsigned int rates)
{
if (rates & SNDRV_PCM_RATE_CONTINUOUS)
return SNDRV_PCM_RATE_CONTINUOUS;
else if (rates & SNDRV_PCM_RATE_KNOT)
return SNDRV_PCM_RATE_KNOT;
return rates;
}
/**
* snd_pcm_rate_mask_intersect - computes the intersection between two rate masks
* @rates_a: The first rate mask
* @rates_b: The second rate mask
*
* This function computes the rates that are supported by both rate masks passed
* to the function. It will take care of the special handling of
* SNDRV_PCM_RATE_CONTINUOUS and SNDRV_PCM_RATE_KNOT.
*
* Return: A rate mask containing the rates that are supported by both rates_a
* and rates_b.
*/
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
unsigned int rates_b)
{
rates_a = snd_pcm_rate_mask_sanitize(rates_a);
rates_b = snd_pcm_rate_mask_sanitize(rates_b);
if (rates_a & SNDRV_PCM_RATE_CONTINUOUS)
return rates_b;
else if (rates_b & SNDRV_PCM_RATE_CONTINUOUS)
return rates_a;
else if (rates_a & SNDRV_PCM_RATE_KNOT)
return rates_b;
else if (rates_b & SNDRV_PCM_RATE_KNOT)
return rates_a;
return rates_a & rates_b;
}
EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);

View File

@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/gfp.h>
#include "sound_config.h"
#include "sleep.h"
#define DMAP_FREE_ON_CLOSE 0
#define DMAP_KEEP_ON_CLOSE 1
@ -351,8 +352,7 @@ static void dma_reset_output(int dev)
if (!signal_pending(current) && adev->dmap_out->qlen &&
adev->dmap_out->underrun_count == 0){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
dmabuf_timeout(dmap));
oss_broken_sleep_on(&adev->out_sleeper, dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
@ -446,7 +446,7 @@ int DMAbuf_sync(int dev)
long t = dmabuf_timeout(dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
/* FIXME: not safe may miss events */
t = interruptible_sleep_on_timeout(&adev->out_sleeper, t);
t = oss_broken_sleep_on(&adev->out_sleeper, t);
spin_lock_irqsave(&dmap->lock,flags);
if (!t) {
adev->dmap_out->flags &= ~DMA_SYNCING;
@ -466,7 +466,7 @@ int DMAbuf_sync(int dev)
while (!signal_pending(current) &&
adev->d->local_qlen(dev)){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
oss_broken_sleep_on(&adev->out_sleeper,
dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
@ -587,8 +587,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
timeout = dmabuf_timeout(dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,
timeout);
timeout = oss_broken_sleep_on(&adev->in_sleeper, timeout);
if (!timeout) {
/* FIXME: include device name */
err = -EIO;
@ -768,8 +767,7 @@ static int output_sleep(int dev, int dontblock)
timeout_value = dmabuf_timeout(dmap);
else
timeout_value = MAX_SCHEDULE_TIMEOUT;
timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper,
timeout_value);
timeout_value = oss_broken_sleep_on(&adev->out_sleeper, timeout_value);
if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) {
printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
dma_reset_output(dev);

View File

@ -239,7 +239,6 @@ struct sound_queue {
int busy, syncing, xruns, died;
};
#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
#define WAKE_UP(queue) (wake_up_interruptible(&queue))
extern struct sound_queue dmasound_write_sq;

View File

@ -619,15 +619,27 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
}
while (uLeft) {
DEFINE_WAIT(wait);
while (write_sq.count >= write_sq.max_active) {
prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE);
sq_play();
if (write_sq.non_blocking)
if (write_sq.non_blocking) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EAGAIN;
SLEEP(write_sq.action_queue);
if (signal_pending(current))
}
if (write_sq.count < write_sq.max_active)
break;
schedule_timeout(HZ);
if (signal_pending(current)) {
finish_wait(&write_sq.action_queue, &wait);
return uWritten > 0 ? uWritten : -EINTR;
}
}
finish_wait(&write_sq.action_queue, &wait);
/* Here, we can avoid disabling the interrupt by first
* copying and translating the data, and then updating
* the write_sq variables. Until this is done, the interrupt
@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
if (file->f_flags & O_NONBLOCK)
return rc;
rc = -EINTR;
while (sq->busy) {
SLEEP(sq->open_queue);
if (signal_pending(current))
return rc;
}
if (wait_event_interruptible(sq->open_queue, !sq->busy))
return rc;
rc = 0;
#else
/* OSS manual says we will return EBUSY regardless
@ -844,7 +853,8 @@ static int sq_fsync(void)
sq_play(); /* there may be an incomplete frame waiting */
while (write_sq.active) {
SLEEP(write_sq.sync_queue);
wait_event_interruptible_timeout(write_sq.sync_queue,
!write_sq.active, HZ);
if (signal_pending(current)) {
/* While waiting for audio output to drain, an
* interrupt occurred. Stop audio output immediately

View File

@ -86,9 +86,8 @@ static void drain_midi_queue(int dev)
*/
if (midi_devs[dev]->buffer_status != NULL)
while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev))
interruptible_sleep_on_timeout(&midi_sleeper[dev],
HZ/10);
wait_event_interruptible_timeout(midi_sleeper[dev],
!midi_devs[dev]->buffer_status(dev), HZ/10);
}
static void midi_input_intr(int dev, unsigned char data)
@ -233,8 +232,8 @@ void MIDIbuf_release(int dev, struct file *file)
* devices
*/
while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
interruptible_sleep_on(&midi_sleeper[dev]);
wait_event_interruptible(midi_sleeper[dev],
!DATA_AVAIL(midi_out_buf[dev]));
/*
* Sync
*/
@ -282,8 +281,8 @@ int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
goto out;
}
interruptible_sleep_on(&midi_sleeper[dev]);
if (signal_pending(current))
if (wait_event_interruptible(midi_sleeper[dev],
SPACE_AVAIL(midi_out_buf[dev])))
{
c = -EINTR;
goto out;
@ -325,8 +324,9 @@ int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
c = -EAGAIN;
goto out;
}
interruptible_sleep_on_timeout(&input_sleeper[dev],
parms[dev].prech_timeout);
wait_event_interruptible_timeout(input_sleeper[dev],
DATA_AVAIL(midi_in_buf[dev]),
parms[dev].prech_timeout);
if (signal_pending(current))
c = -EINTR; /* The user is getting restless */

View File

@ -664,12 +664,15 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static void dsp_write_flush(void)
{
int timeout = get_play_delay_jiffies(dev.DAPF.len);
if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags))
return;
set_bit(F_WRITEFLUSH, &dev.flags);
interruptible_sleep_on_timeout(
&dev.writeflush,
get_play_delay_jiffies(dev.DAPF.len));
wait_event_interruptible_timeout(
dev.writeflush,
!test_bit(F_WRITEFLUSH, &dev.flags),
timeout);
clear_bit(F_WRITEFLUSH, &dev.flags);
if (!signal_pending(current)) {
current->state = TASK_INTERRUPTIBLE;
@ -897,6 +900,7 @@ static int dsp_read(char __user *buf, size_t len)
{
int count = len;
char *page = (char *)__get_free_page(GFP_KERNEL);
int timeout = get_rec_delay_jiffies(DAR_BUFF_SIZE);
if (!page)
return -ENOMEM;
@ -936,11 +940,11 @@ static int dsp_read(char __user *buf, size_t len)
if (count > 0) {
set_bit(F_READBLOCK, &dev.flags);
if (!interruptible_sleep_on_timeout(
&dev.readblock,
get_rec_delay_jiffies(DAR_BUFF_SIZE)))
if (wait_event_interruptible_timeout(
dev.readblock,
test_bit(F_READBLOCK, &dev.flags),
timeout) <= 0)
clear_bit(F_READING, &dev.flags);
clear_bit(F_READBLOCK, &dev.flags);
if (signal_pending(current)) {
free_page((unsigned long)page);
return -EINTR;
@ -955,6 +959,7 @@ static int dsp_write(const char __user *buf, size_t len)
{
int count = len;
char *page = (char *)__get_free_page(GFP_KERNEL);
int timeout = get_play_delay_jiffies(DAP_BUFF_SIZE);
if (!page)
return -ENOMEM;
@ -995,10 +1000,10 @@ static int dsp_write(const char __user *buf, size_t len)
if (count > 0) {
set_bit(F_WRITEBLOCK, &dev.flags);
interruptible_sleep_on_timeout(
&dev.writeblock,
get_play_delay_jiffies(DAP_BUFF_SIZE));
clear_bit(F_WRITEBLOCK, &dev.flags);
wait_event_interruptible_timeout(
dev.writeblock,
test_bit(F_WRITEBLOCK, &dev.flags),
timeout);
if (signal_pending(current)) {
free_page((unsigned long)page);
return -EINTR;
@ -1044,7 +1049,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
clear_bit(F_WRITING, &dev.flags);
}
if (test_bit(F_WRITEBLOCK, &dev.flags))
if (test_and_clear_bit(F_WRITEBLOCK, &dev.flags))
wake_up_interruptible(&dev.writeblock);
break;
@ -1055,7 +1060,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
pack_DARQ_to_DARF(dev.last_recbank);
if (test_bit(F_READBLOCK, &dev.flags))
if (test_and_clear_bit(F_READBLOCK, &dev.flags))
wake_up_interruptible(&dev.readblock);
break;

View File

@ -19,6 +19,7 @@
#include "sound_config.h"
#include "midi_ctrl.h"
#include "sleep.h"
static int sequencer_ok;
static struct sound_timer_operations *tmr;
@ -100,8 +101,7 @@ int sequencer_read(int dev, struct file *file, char __user *buf, int count)
return -EAGAIN;
}
interruptible_sleep_on_timeout(&midi_sleeper,
pre_event_timeout);
oss_broken_sleep_on(&midi_sleeper, pre_event_timeout);
spin_lock_irqsave(&lock,flags);
if (!iqlen)
{
@ -343,7 +343,7 @@ static int seq_queue(unsigned char *note, char nonblock)
/*
* Sleep until there is enough space on the queue
*/
interruptible_sleep_on(&seq_sleeper);
oss_broken_sleep_on(&seq_sleeper, MAX_SCHEDULE_TIMEOUT);
}
if (qlen >= SEQ_MAX_QUEUE)
{
@ -1122,8 +1122,7 @@ static void seq_drain_midi_queues(void)
*/
if (n)
interruptible_sleep_on_timeout(&seq_sleeper,
HZ/10);
oss_broken_sleep_on(&seq_sleeper, HZ/10);
}
}
@ -1145,8 +1144,7 @@ void sequencer_release(int dev, struct file *file)
while (!signal_pending(current) && qlen > 0)
{
seq_sync();
interruptible_sleep_on_timeout(&seq_sleeper,
3*HZ);
oss_broken_sleep_on(&seq_sleeper, 3*HZ);
/* Extra delay */
}
}
@ -1201,7 +1199,7 @@ static int seq_sync(void)
seq_startplay();
if (qlen > 0)
interruptible_sleep_on_timeout(&seq_sleeper, HZ);
oss_broken_sleep_on(&seq_sleeper, HZ);
return qlen;
}
@ -1224,7 +1222,7 @@ static void midi_outc(int dev, unsigned char data)
spin_lock_irqsave(&lock,flags);
while (n && !midi_devs[dev]->outputc(dev, data)) {
interruptible_sleep_on_timeout(&seq_sleeper, HZ/25);
oss_broken_sleep_on(&seq_sleeper, HZ/25);
n--;
}
spin_unlock_irqrestore(&lock,flags);

18
sound/oss/sleep.h Normal file
View File

@ -0,0 +1,18 @@
#include <linux/wait.h>
/*
* Do not use. This is a replacement for the old
* "interruptible_sleep_on_timeout" function that has been
* deprecated for ages. All users should instead try to use
* wait_event_interruptible_timeout.
*/
static inline long
oss_broken_sleep_on(wait_queue_head_t *q, long timeout)
{
DEFINE_WAIT(wait);
prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
timeout = schedule_timeout(timeout);
finish_wait(q, &wait);
return timeout;
}

View File

@ -90,6 +90,8 @@
#include <asm/sibyte/sb1250_mac.h>
#include <asm/sibyte/sb1250.h>
#include "sleep.h"
struct cs4297a_state;
static DEFINE_MUTEX(swarm_cs4297a_mutex);
@ -748,7 +750,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data)
/* Since a writer has the DSP open, we have to mux the
request in */
s->reg_request = data;
interruptible_sleep_on(&s->dma_dac.reg_wait);
oss_broken_sleep_on(&s->dma_dac.reg_wait, MAX_SCHEDULE_TIMEOUT);
/* XXXKW how can I deal with the starvation case where
the opener isn't writing? */
} else {
@ -790,7 +792,7 @@ static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset,
if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40)))
return -1;
interruptible_sleep_on(&s->dma_adc.reg_wait);
oss_broken_sleep_on(&s->dma_adc.reg_wait, MAX_SCHEDULE_TIMEOUT);
*value = s->read_value;
CS_DBGOUT(CS_AC97, 2,
printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value));
@ -1740,7 +1742,7 @@ static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count,
start_adc(s);
if (file->f_flags & O_NONBLOCK)
return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_adc.wait);
oss_broken_sleep_on(&s->dma_adc.wait, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
@ -1836,7 +1838,7 @@ static ssize_t cs4297a_write(struct file *file, const char *buffer,
start_dac(s);
if (file->f_flags & O_NONBLOCK)
return ret ? ret : -EAGAIN;
interruptible_sleep_on(&d->wait);
oss_broken_sleep_on(&d->wait, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
@ -2452,7 +2454,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
return -EBUSY;
}
mutex_unlock(&s->open_sem_dac);
interruptible_sleep_on(&s->open_wait_dac);
oss_broken_sleep_on(&s->open_wait_dac, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current)) {
printk("open - sig pending\n");
@ -2469,7 +2471,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
return -EBUSY;
}
mutex_unlock(&s->open_sem_adc);
interruptible_sleep_on(&s->open_wait_adc);
oss_broken_sleep_on(&s->open_wait_adc, MAX_SCHEDULE_TIMEOUT);
if (signal_pending(current)) {
printk("open - sig pending\n");

View File

@ -2921,6 +2921,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
vwsnd_dev_t *devc;
int minor = iminor(inode);
int sw_samplefmt;
DEFINE_WAIT(wait);
DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
@ -2937,21 +2938,26 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
}
mutex_lock(&devc->open_mutex);
while (devc->open_mode & file->f_mode) {
while (1) {
prepare_to_wait(&devc->open_wait, &wait, TASK_INTERRUPTIBLE);
if (!(devc->open_mode & file->f_mode))
break;
mutex_unlock(&devc->open_mutex);
mutex_unlock(&vwsnd_mutex);
if (file->f_flags & O_NONBLOCK) {
DEC_USE_COUNT;
mutex_unlock(&vwsnd_mutex);
return -EBUSY;
}
interruptible_sleep_on(&devc->open_wait);
schedule();
if (signal_pending(current)) {
DEC_USE_COUNT;
mutex_unlock(&vwsnd_mutex);
return -ERESTARTSYS;
}
mutex_lock(&vwsnd_mutex);
mutex_lock(&devc->open_mutex);
}
finish_wait(&devc->open_wait, &wait);
devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
mutex_unlock(&devc->open_mutex);

View File

@ -25,6 +25,7 @@ config SND_ALS300
select SND_PCM
select SND_AC97_CODEC
select SND_OPL3_LIB
select ZONE_DMA
help
Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
@ -49,6 +50,7 @@ config SND_ALI5451
tristate "ALi M5451 PCI Audio Controller"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for the integrated AC97 sound
device on motherboards using the ALi M5451 Audio Controller
@ -153,6 +155,7 @@ config SND_AZT3328
select SND_PCM
select SND_RAWMIDI
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for Aztech AZF3328 (PCI168)
soundcards.
@ -254,6 +257,7 @@ config SND_CS46XX
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
select SND_RAWMIDI
select SND_AC97_CODEC
select FW_LOADER
help
Say Y here to include support for Cirrus Logic CS4610/CS4612/
CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
@ -458,6 +462,7 @@ config SND_EMU10K1
select SND_HWDEP
select SND_RAWMIDI
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y to include support for Sound Blaster PCI 512, Live!,
Audigy and E-mu APS (partially supported) soundcards.
@ -473,6 +478,7 @@ config SND_EMU10K1X
tristate "Emu10k1X (Dell OEM Version)"
select SND_AC97_CODEC
select SND_RAWMIDI
select ZONE_DMA
help
Say Y here to include support for the Dell OEM version of the
Sound Blaster Live!.
@ -506,6 +512,7 @@ config SND_ES1938
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Solo-1
(ES1938, ES1946, ES1969) chips.
@ -517,6 +524,7 @@ config SND_ES1968
tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Maestro
1/2/2E chips.
@ -605,6 +613,7 @@ config SND_ICE1712
select SND_MPU401_UART
select SND_AC97_CODEC
select BITREVERSE
select ZONE_DMA
help
Say Y here to include support for soundcards based on the
ICE1712 (Envy24) chip.
@ -692,6 +701,7 @@ config SND_LX6464ES
config SND_MAESTRO3
tristate "ESS Allegro/Maestro3"
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on ESS Maestro 3
(Allegro) chips.
@ -788,6 +798,7 @@ config SND_SIS7019
tristate "SiS 7019 Audio Accelerator"
depends on X86 && !X86_64
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for the SiS 7019 Audio Accelerator.
@ -799,6 +810,7 @@ config SND_SONICVIBES
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on the S3
SonicVibes chip.
@ -810,6 +822,7 @@ config SND_TRIDENT
tristate "Trident 4D-Wave DX/NX; SiS 7018"
select SND_MPU401_UART
select SND_AC97_CODEC
select ZONE_DMA
help
Say Y here to include support for soundcards based on Trident
4D-Wave DX/NX or SiS 7018 chips.

View File

@ -1716,9 +1716,14 @@ struct snd_cs46xx {
struct snd_pcm *pcm_rear;
struct snd_pcm *pcm_center_lfe;
struct snd_pcm *pcm_iec958;
#define CS46XX_DSP_MODULES 5
struct dsp_module_desc *modules[CS46XX_DSP_MODULES];
#else /* for compatibility */
struct snd_cs46xx_pcm *playback_pcm;
unsigned int play_ctl;
struct ba1_struct *ba1;
#endif
#ifdef CONFIG_PM_SLEEP

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,9 @@
#include <linux/gameport.h>
#include <linux/mutex.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/control.h>
@ -330,13 +332,146 @@ int snd_cs46xx_download(struct snd_cs46xx *chip,
return 0;
}
static inline void memcpy_le32(void *dst, const void *src, unsigned int len)
{
#ifdef __LITTLE_ENDIAN
memcpy(dst, src, len);
#else
u32 *_dst = dst;
const __le32 *_src = src;
len /= 4;
while (len-- > 0)
*_dst++ = le32_to_cpu(*_src++);
#endif
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#include "imgs/cwc4630.h"
#include "imgs/cwcasync.h"
#include "imgs/cwcsnoop.h"
#include "imgs/cwcbinhack.h"
#include "imgs/cwcdma.h"
static const char *module_names[CS46XX_DSP_MODULES] = {
"cwc4630", "cwcasync", "cwcsnoop", "cwcbinhack", "cwcdma"
};
MODULE_FIRMWARE("cs46xx/cwc4630");
MODULE_FIRMWARE("cs46xx/cwcasync");
MODULE_FIRMWARE("cs46xx/cwcsnoop");
MODULE_FIRMWARE("cs46xx/cwcbinhack");
MODULE_FIRMWARE("cs46xx/cwcdma");
static void free_module_desc(struct dsp_module_desc *module)
{
if (!module)
return;
kfree(module->module_name);
kfree(module->symbol_table.symbols);
if (module->segments) {
int i;
for (i = 0; i < module->nsegments; i++)
kfree(module->segments[i].data);
kfree(module->segments);
}
}
/* firmware binary format:
* le32 nsymbols;
* struct {
* le32 address;
* char symbol_name[DSP_MAX_SYMBOL_NAME];
* le32 symbol_type;
* } symbols[nsymbols];
* le32 nsegments;
* struct {
* le32 segment_type;
* le32 offset;
* le32 size;
* le32 data[size];
* } segments[nsegments];
*/
static int load_firmware(struct snd_cs46xx *chip,
struct dsp_module_desc **module_ret,
const char *fw_name)
{
int i, err;
unsigned int nums, fwlen, fwsize;
const __le32 *fwdat;
struct dsp_module_desc *module = NULL;
const struct firmware *fw;
char fw_path[32];
sprintf(fw_path, "cs46xx/%s", fw_name);
err = request_firmware(&fw, fw_path, &chip->pci->dev);
if (err < 0)
return err;
fwsize = fw->size / 4;
if (fwsize < 2) {
err = -EINVAL;
goto error;
}
err = -ENOMEM;
module = kzalloc(sizeof(*module), GFP_KERNEL);
if (!module)
goto error;
module->module_name = kstrdup(fw_name, GFP_KERNEL);
if (!module->module_name)
goto error;
fwlen = 0;
fwdat = (const __le32 *)fw->data;
nums = module->symbol_table.nsymbols = le32_to_cpu(fwdat[fwlen++]);
if (nums >= 40)
goto error_inval;
module->symbol_table.symbols =
kcalloc(nums, sizeof(struct dsp_symbol_entry), GFP_KERNEL);
if (!module->symbol_table.symbols)
goto error;
for (i = 0; i < nums; i++) {
struct dsp_symbol_entry *entry =
&module->symbol_table.symbols[i];
if (fwlen + 2 + DSP_MAX_SYMBOL_NAME / 4 > fwsize)
goto error_inval;
entry->address = le32_to_cpu(fwdat[fwlen++]);
memcpy(entry->symbol_name, &fwdat[fwlen], DSP_MAX_SYMBOL_NAME - 1);
fwlen += DSP_MAX_SYMBOL_NAME / 4;
entry->symbol_type = le32_to_cpu(fwdat[fwlen++]);
}
if (fwlen >= fwsize)
goto error_inval;
nums = module->nsegments = le32_to_cpu(fwdat[fwlen++]);
if (nums > 10)
goto error_inval;
module->segments =
kcalloc(nums, sizeof(struct dsp_segment_desc), GFP_KERNEL);
if (!module->segments)
goto error;
for (i = 0; i < nums; i++) {
struct dsp_segment_desc *entry = &module->segments[i];
if (fwlen + 3 > fwsize)
goto error_inval;
entry->segment_type = le32_to_cpu(fwdat[fwlen++]);
entry->offset = le32_to_cpu(fwdat[fwlen++]);
entry->size = le32_to_cpu(fwdat[fwlen++]);
if (fwlen + entry->size > fwsize)
goto error_inval;
entry->data = kmalloc(entry->size * 4, GFP_KERNEL);
if (!entry->data)
goto error;
memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
fwlen += entry->size;
}
*module_ret = module;
release_firmware(fw);
return 0;
error_inval:
err = -EINVAL;
error:
free_module_desc(module);
release_firmware(fw);
return err;
}
int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
unsigned long offset,
@ -361,20 +496,63 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
#else /* old DSP image */
#include "cs46xx_image.h"
struct ba1_struct {
struct {
u32 offset;
u32 size;
} memory[BA1_MEMORY_COUNT];
u32 map[BA1_DWORD_SIZE];
};
MODULE_FIRMWARE("cs46xx/ba1");
static int load_firmware(struct snd_cs46xx *chip)
{
const struct firmware *fw;
int i, size, err;
err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
if (err < 0)
return err;
if (fw->size != sizeof(*chip->ba1)) {
err = -EINVAL;
goto error;
}
chip->ba1 = vmalloc(sizeof(*chip->ba1));
if (!chip->ba1) {
err = -ENOMEM;
goto error;
}
memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
/* sanity check */
size = 0;
for (i = 0; i < BA1_MEMORY_COUNT; i++)
size += chip->ba1->memory[i].size;
if (size > BA1_DWORD_SIZE * 4)
err = -EINVAL;
error:
release_firmware(fw);
return err;
}
int snd_cs46xx_download_image(struct snd_cs46xx *chip)
{
int idx, err;
unsigned long offset = 0;
unsigned int offset = 0;
struct ba1_struct *ba1 = chip->ba1;
for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
if ((err = snd_cs46xx_download(chip,
&BA1Struct.map[offset],
BA1Struct.memory[idx].offset,
BA1Struct.memory[idx].size)) < 0)
err = snd_cs46xx_download(chip,
&ba1->map[offset],
ba1->memory[idx].offset,
ba1->memory[idx].size);
if (err < 0)
return err;
offset += BA1Struct.memory[idx].size >> 2;
offset += ba1->memory[idx].size >> 2;
}
return 0;
}
@ -2798,6 +2976,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
cs46xx_dsp_spos_destroy(chip);
chip->dsp_spos_instance = NULL;
}
for (idx = 0; idx < CS46XX_DSP_MODULES; idx++)
free_module_desc(chip->modules[idx]);
#else
vfree(chip->ba1);
#endif
#ifdef CONFIG_PM_SLEEP
@ -3067,6 +3249,11 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
{
unsigned int tmp;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
int i;
#endif
int err;
/*
* Reset the processor.
*/
@ -3075,45 +3262,33 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
* Download the image to the processor.
*/
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#if 0
if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
snd_printk(KERN_ERR "image download error\n");
return -EIO;
}
#endif
if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
snd_printk(KERN_ERR "image download error [cwc4630]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcasync]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
return -EIO;
}
if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
snd_printk(KERN_ERR "image download error [cwcdma]\n");
return -EIO;
for (i = 0; i < CS46XX_DSP_MODULES; i++) {
err = load_firmware(chip, &chip->modules[i], module_names[i]);
if (err < 0) {
snd_printk(KERN_ERR "firmware load error [%s]\n",
module_names[i]);
return err;
}
err = cs46xx_dsp_load_module(chip, chip->modules[i]);
if (err < 0) {
snd_printk(KERN_ERR "image download error [%s]\n",
module_names[i]);
return err;
}
}
if (cs46xx_dsp_scb_and_task_init(chip) < 0)
return -EIO;
#else
err = load_firmware(chip);
if (err < 0)
return err;
/* old image */
if (snd_cs46xx_download_image(chip) < 0) {
err = snd_cs46xx_download_image(chip);
if (err < 0) {
snd_printk(KERN_ERR "image download error\n");
return -EIO;
return err;
}
/*

View File

@ -1,320 +0,0 @@
/* generated from cwc4630.osp DO NOT MODIFY */
#ifndef __HEADER_cwc4630_H__
#define __HEADER_cwc4630_H__
static struct dsp_symbol_entry cwc4630_symbols[] = {
{ 0x0000, "BEGINADDRESS",0x00 },
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0070, "SPOSCB",0x02 },
{ 0x0107, "TASKTREETHREAD",0x03 },
{ 0x013c, "TASKTREEHEADERCODE",0x03 },
{ 0x0145, "FGTASKTREEHEADERCODE",0x03 },
{ 0x0169, "NULLALGORITHM",0x03 },
{ 0x016d, "HFGEXECCHILD",0x03 },
{ 0x016e, "HFGEXECCHILD_98",0x03 },
{ 0x0170, "HFGEXECCHILD_PUSH1IND",0x03 },
{ 0x0173, "HFGEXECSIBLING",0x03 },
{ 0x0175, "HFGEXECSIBLING_298",0x03 },
{ 0x0176, "HFGEXECSIBLING_2IND1",0x03 },
{ 0x0179, "S16_CODECOUTPUTTASK",0x03 },
{ 0x0194, "#CODE_END",0x00 },
}; /* cwc4630 symbols */
static u32 cwc4630_code[] = {
/* BEGINADDRESS */
/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003,
/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003,
/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003,
/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003,
/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003,
/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003,
/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003,
/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003,
/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003,
/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040,
/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003,
/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003,
/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003,
/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003,
/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003,
/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003,
/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003,
/* 0040 */ 0x0001a730,0x00001008,0x000e2730,0x00001002,
/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003,
/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000,
/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000,
/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000,
/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000,
/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000,
/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003,
/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003,
/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000,
/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003,
/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000,
/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000,
/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000,
/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000,
/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140,
/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40,
/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00,
/* 007C */ 0x0000002e,0x0009d6c0,0x0002ef8a,0x00000000,
/* 007E */ 0x00040630,0x00001004,0x0004ef0a,0x000eb785,
/* 0080 */ 0x0003fc8a,0x00000000,0x00000000,0x000c70e0,
/* 0082 */ 0x0007d182,0x0002c640,0x00008630,0x00001004,
/* 0084 */ 0x000799b8,0x0002c6c0,0x00031705,0x00092240,
/* 0086 */ 0x00039f05,0x000932c0,0x0003520a,0x00000000,
/* 0088 */ 0x00070731,0x0000100b,0x00010705,0x000b20c0,
/* 008A */ 0x00000000,0x000eba44,0x00032108,0x000c60c4,
/* 008C */ 0x00065208,0x000c2917,0x000486b0,0x00001007,
/* 008E */ 0x00012f05,0x00036880,0x0002818e,0x000c0000,
/* 0090 */ 0x0004410a,0x00000000,0x00048630,0x00001007,
/* 0092 */ 0x00029705,0x000c0000,0x00000000,0x00000000,
/* 0094 */ 0x00003fc1,0x0003fc40,0x000037c1,0x00091b40,
/* 0096 */ 0x00003fc1,0x000911c0,0x000037c1,0x000957c0,
/* 0098 */ 0x00003fc1,0x000951c0,0x000037c1,0x00000000,
/* 009A */ 0x00003fc1,0x000991c0,0x000037c1,0x00000000,
/* 009C */ 0x00003fc1,0x0009d1c0,0x000037c1,0x00000000,
/* 009E */ 0x0001ccc1,0x000915c0,0x0001c441,0x0009d800,
/* 00A0 */ 0x0009cdc1,0x00091240,0x0001c541,0x00091d00,
/* 00A2 */ 0x0009cfc1,0x00095240,0x0001c741,0x00095c80,
/* 00A4 */ 0x000e8ca9,0x00099240,0x000e85ad,0x00095640,
/* 00A6 */ 0x00069ca9,0x00099d80,0x000e952d,0x00099640,
/* 00A8 */ 0x000eaca9,0x0009d6c0,0x000ea5ad,0x00091a40,
/* 00AA */ 0x0006bca9,0x0009de80,0x000eb52d,0x00095a40,
/* 00AC */ 0x000ecca9,0x00099ac0,0x000ec5ad,0x0009da40,
/* 00AE */ 0x000edca9,0x0009d300,0x000a6e0a,0x00001000,
/* 00B0 */ 0x000ed52d,0x00091e40,0x000eeca9,0x00095ec0,
/* 00B2 */ 0x000ee5ad,0x00099e40,0x0006fca9,0x00002500,
/* 00B4 */ 0x000fb208,0x000c59a0,0x000ef52d,0x0009de40,
/* 00B6 */ 0x00068ca9,0x000912c1,0x000683ad,0x00095241,
/* 00B8 */ 0x00020f05,0x000991c1,0x00000000,0x00000000,
/* 00BA */ 0x00086f88,0x00001000,0x0009cf81,0x000b5340,
/* 00BC */ 0x0009c701,0x000b92c0,0x0009de81,0x000bd300,
/* 00BE */ 0x0009d601,0x000b1700,0x0001fd81,0x000b9d80,
/* 00C0 */ 0x0009f501,0x000b57c0,0x000a0f81,0x000bd740,
/* 00C2 */ 0x00020701,0x000b5c80,0x000a1681,0x000b97c0,
/* 00C4 */ 0x00021601,0x00002500,0x000a0701,0x000b9b40,
/* 00C6 */ 0x000a0f81,0x000b1bc0,0x00021681,0x00002d00,
/* 00C8 */ 0x00020f81,0x000bd800,0x000a0701,0x000b5bc0,
/* 00CA */ 0x00021601,0x00003500,0x000a0f81,0x000b5f40,
/* 00CC */ 0x000a0701,0x000bdbc0,0x00021681,0x00003d00,
/* 00CE */ 0x00020f81,0x000b1d00,0x000a0701,0x000b1fc0,
/* 00D0 */ 0x00021601,0x00020500,0x00020f81,0x000b1341,
/* 00D2 */ 0x000a0701,0x000b9fc0,0x00021681,0x00020d00,
/* 00D4 */ 0x00020f81,0x000bde80,0x000a0701,0x000bdfc0,
/* 00D6 */ 0x00021601,0x00021500,0x00020f81,0x000b9341,
/* 00D8 */ 0x00020701,0x000b53c1,0x00021681,0x00021d00,
/* 00DA */ 0x000a0f81,0x000d0380,0x0000b601,0x000b15c0,
/* 00DC */ 0x00007b01,0x00000000,0x00007b81,0x000bd1c0,
/* 00DE */ 0x00007b01,0x00000000,0x00007b81,0x000b91c0,
/* 00E0 */ 0x00007b01,0x000b57c0,0x00007b81,0x000b51c0,
/* 00E2 */ 0x00007b01,0x000b1b40,0x00007b81,0x000b11c0,
/* 00E4 */ 0x00087b01,0x000c3dc0,0x0007e488,0x000d7e45,
/* 00E6 */ 0x00000000,0x000d7a44,0x0007e48a,0x00000000,
/* 00E8 */ 0x00011f05,0x00084080,0x00000000,0x00000000,
/* 00EA */ 0x00001705,0x000b3540,0x00008a01,0x000bf040,
/* 00EC */ 0x00007081,0x000bb5c0,0x00055488,0x00000000,
/* 00EE */ 0x0000d482,0x0003fc40,0x0003fc88,0x00000000,
/* 00F0 */ 0x0001e401,0x000b3a00,0x0001ec81,0x000bd6c0,
/* 00F2 */ 0x0002ef88,0x000e7784,0x00056f08,0x00000000,
/* 00F4 */ 0x000d86b0,0x00001007,0x00008281,0x000bb240,
/* 00F6 */ 0x0000b801,0x000b7140,0x00007888,0x00000000,
/* 00F8 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000,
/* 00FA */ 0x00000000,0x00000000,0x00055288,0x000c555c,
/* 00FC */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
/* 00FE */ 0x0000fa88,0x00000000,0x00000032,0x00001000,
/* 0100 */ 0x0000073d,0x00001000,0x0007f188,0x000c0000,
/* 0102 */ 0x00000000,0x00000000,0x0008c01c,0x00001003,
/* 0104 */ 0x00002705,0x00001008,0x0008b201,0x000c1392,
/* 0106 */ 0x0000ba01,0x00000000,
/* TASKTREETHREAD */
/* 0107 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4,
/* 0109 */ 0x00057488,0x00000000,0x000a6388,0x00001001,
/* 010B */ 0x0008b334,0x000bc141,0x0003020e,0x00000000,
/* 010D */ 0x000986b0,0x00001008,0x00003625,0x000c5dfa,
/* 010F */ 0x000a638a,0x00001001,0x0008020e,0x00001002,
/* 0111 */ 0x0009a6b0,0x00001008,0x0007f301,0x00000000,
/* 0113 */ 0x00000000,0x00000000,0x00002725,0x000a8c40,
/* 0115 */ 0x000000ae,0x00000000,0x000e8630,0x00001008,
/* 0117 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640,
/* 0119 */ 0x000b8630,0x00001008,0x000799b8,0x0002d6c0,
/* 011B */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000,
/* 011D */ 0x00062208,0x000c4117,0x000a0630,0x00001009,
/* 011F */ 0x00000000,0x000c0000,0x0001022e,0x00000000,
/* 0121 */ 0x0006a630,0x00001009,0x00000032,0x00001000,
/* 0123 */ 0x000ca21c,0x00001003,0x00005a02,0x00000000,
/* 0125 */ 0x0001a630,0x00001009,0x00000000,0x000c0000,
/* 0127 */ 0x00000036,0x00001000,0x00000000,0x00000000,
/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 012B */ 0x00000000,0x00000000,0x0003a730,0x00001008,
/* 012D */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
/* 012F */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0131 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0133 */ 0x0003a730,0x00001008,0x00000033,0x00001000,
/* 0135 */ 0x0003a705,0x00001008,0x00007a01,0x000c0000,
/* 0137 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000,
/* 0139 */ 0x00090730,0x0000100a,0x00000000,0x000c0000,
/* 013B */ 0x00000000,0x00000000,
/* TASKTREEHEADERCODE */
/* 013C */ 0x0007aab0,0x00034880,0x000a8fb0,0x0000100b,
/* 013E */ 0x00057488,0x00000000,0x00033b94,0x00081140,
/* 0140 */ 0x000183ae,0x00000000,0x000a86b0,0x0000100b,
/* 0142 */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
/* 0144 */ 0x00042731,0x00001003,
/* FGTASKTREEHEADERCODE */
/* 0145 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100a,
/* 0147 */ 0x00057488,0x00000000,0x00033b94,0x00081140,
/* 0149 */ 0x000183ae,0x00000000,0x000b06b0,0x0000100b,
/* 014B */ 0x00022f05,0x00000000,0x00007401,0x00091140,
/* 014D */ 0x00048f05,0x000951c0,0x00042731,0x00001003,
/* 014F */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
/* 0151 */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003,
/* 0153 */ 0x00000000,0x00000000,0x0008e19c,0x00001003,
/* 0155 */ 0x000083c1,0x00093040,0x00000f41,0x00097140,
/* 0157 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
/* 0159 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
/* 015B */ 0x00000000,0x000fdc44,0x00055208,0x00000000,
/* 015D */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00,
/* 015F */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000,
/* 0161 */ 0x00012f05,0x00036880,0x00065308,0x000c2997,
/* 0163 */ 0x000086b0,0x0000100b,0x0004410a,0x000d40c7,
/* 0165 */ 0x00000000,0x00000000,0x00088730,0x00001004,
/* 0167 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000,
/* NULLALGORITHM */
/* 0169 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
/* 016B */ 0x00080000,0x000bffc7,0x0000273d,0x00001000,
/* HFGEXECCHILD */
/* 016D */ 0x00000000,0x000eba44,
/* HFGEXECCHILD_98 */
/* 016E */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
/* HFGEXECCHILD_PUSH1IND */
/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
/* 0172 */ 0x00006a88,0x000c75c4,
/* HFGEXECSIBLING */
/* 0173 */ 0x00000000,0x000e5084,0x00000000,0x000eba44,
/* HFGEXECSIBLING_298 */
/* 0175 */ 0x00087401,0x000e4782,
/* HFGEXECSIBLING_2IND1 */
/* 0176 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
/* 0178 */ 0x00006a88,0x000c75c4,
/* S16_CODECOUTPUTTASK */
/* 0179 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40,
/* 017B */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80,
/* 017D */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0,
/* 017F */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0,
/* 0181 */ 0x00073fb0,0x00074c80,0x000583a0,0x0000100c,
/* 0183 */ 0x000ee388,0x00042970,0x00008301,0x00021ef2,
/* 0185 */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b,
/* 0187 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916,
/* 0189 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000,
/* 018B */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b,
/* 018D */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956,
/* 018F */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40,
/* 0191 */ 0x00058730,0x00001400,0x000d7488,0x000c3a00,
/* 0193 */ 0x00048f05,0x00000000
};
/* #CODE_END */
static u32 cwc4630_parameter[] = {
/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000,
/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000
}; /* #PARAMETER_END */
static struct dsp_segment_desc cwc4630_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code },
{ SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter },
};
static struct dsp_module_desc cwc4630_module = {
"cwc4630",
{
38,
cwc4630_symbols
},
2,
cwc4630_segments,
};
#endif /* __HEADER_cwc4630_H__ */

View File

@ -1,176 +0,0 @@
/* generated from cwcasync.osp DO NOT MODIFY */
#ifndef __HEADER_cwcasync_H__
#define __HEADER_cwcasync_H__
static struct dsp_symbol_entry cwcasync_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0000, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0000, "SPIOWRITE",0x03 },
{ 0x000d, "S16_ASYNCCODECINPUTTASK",0x03 },
{ 0x0043, "SPDIFITASK",0x03 },
{ 0x007b, "SPDIFOTASK",0x03 },
{ 0x0097, "ASYNCHFGTXCODE",0x03 },
{ 0x00be, "ASYNCHFGRXCODE",0x03 },
{ 0x00db, "#CODE_END",0x00 },
}; /* cwcasync symbols */
static u32 cwcasync_code[] = {
/* OVERLAYBEGINADDRESS */
/* 0000 */ 0x00002731,0x00001400,0x00003725,0x000a8440,
/* 0002 */ 0x000000ae,0x00000000,0x00060630,0x00001000,
/* 0004 */ 0x00000000,0x000c7560,0x00075282,0x0002d640,
/* 0006 */ 0x00021705,0x00000000,0x00072ab8,0x0002d6c0,
/* 0008 */ 0x00020630,0x00001000,0x000c74c2,0x000d4b82,
/* 000A */ 0x000475c2,0x00000000,0x0003430a,0x000c0000,
/* 000C */ 0x00042730,0x00001400,
/* S16_ASYNCCODECINPUTTASK */
/* 000D */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x00000000,
/* 000F */ 0x000fa418,0x0000101f,0x0005d402,0x0001c500,
/* 0011 */ 0x000f0630,0x00001000,0x00004418,0x00001380,
/* 0013 */ 0x000e243d,0x000d394a,0x00049705,0x00000000,
/* 0015 */ 0x0007d530,0x000b4240,0x000e00f2,0x00001000,
/* 0017 */ 0x00009134,0x000ca20a,0x00004c90,0x00001000,
/* 0019 */ 0x0005d705,0x00000000,0x00004f25,0x00098240,
/* 001B */ 0x00004725,0x00000000,0x0000e48a,0x00000000,
/* 001D */ 0x00027295,0x0009c2c0,0x0003df25,0x00000000,
/* 001F */ 0x000e8030,0x00001001,0x0005f718,0x000ac600,
/* 0021 */ 0x0007cf30,0x000c2a01,0x00082630,0x00001001,
/* 0023 */ 0x000504a0,0x00001001,0x00029314,0x000bcb80,
/* 0025 */ 0x0003cf25,0x000b0e00,0x0004f5c0,0x00000000,
/* 0027 */ 0x00049118,0x000d888a,0x0007dd02,0x000c6efa,
/* 0029 */ 0x00000000,0x00000000,0x0004f5c0,0x00069c80,
/* 002B */ 0x0000d402,0x00000000,0x000e8630,0x00001001,
/* 002D */ 0x00079130,0x00000000,0x00049118,0x00090e00,
/* 002F */ 0x0006c10a,0x00000000,0x00000000,0x000c0000,
/* 0031 */ 0x0007cf30,0x00030580,0x00005725,0x00000000,
/* 0033 */ 0x000d84a0,0x00001001,0x00029314,0x000b4780,
/* 0035 */ 0x0003cf25,0x000b8600,0x00000000,0x00000000,
/* 0037 */ 0x00000000,0x000c0000,0x00000000,0x00042c80,
/* 0039 */ 0x0001dec1,0x000e488c,0x00031114,0x00000000,
/* 003B */ 0x0004f5c2,0x00000000,0x0003640a,0x00000000,
/* 003D */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 003F */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0041 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* SPDIFITASK */
/* 0043 */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x000d5384,
/* 0045 */ 0x0007e48a,0x00000000,0x00067718,0x00001000,
/* 0047 */ 0x0007a418,0x00001000,0x0007221a,0x00000000,
/* 0049 */ 0x0005d402,0x00014500,0x000b8630,0x00001002,
/* 004B */ 0x00004418,0x00001780,0x000e243d,0x000d394a,
/* 004D */ 0x00049705,0x00000000,0x0007d530,0x000b4240,
/* 004F */ 0x000ac0f2,0x00001002,0x00014414,0x00000000,
/* 0051 */ 0x00004c90,0x00001000,0x0005d705,0x00000000,
/* 0053 */ 0x00004f25,0x00098240,0x00004725,0x00000000,
/* 0055 */ 0x0000e48a,0x00000000,0x00027295,0x0009c2c0,
/* 0057 */ 0x0007df25,0x00000000,0x000ac030,0x00001003,
/* 0059 */ 0x0005f718,0x000fe798,0x00029314,0x000bcb80,
/* 005B */ 0x00000930,0x000b0e00,0x0004f5c0,0x000de204,
/* 005D */ 0x000884a0,0x00001003,0x0007cf25,0x000e3560,
/* 005F */ 0x00049118,0x00000000,0x00049118,0x000d888a,
/* 0061 */ 0x0007dd02,0x000c6efa,0x0000c434,0x00030040,
/* 0063 */ 0x000fda82,0x000c2312,0x000fdc0e,0x00001001,
/* 0065 */ 0x00083402,0x000c2b92,0x000706b0,0x00001003,
/* 0067 */ 0x00075a82,0x00000000,0x0000d625,0x000b0940,
/* 0069 */ 0x0000840e,0x00001002,0x0000aabc,0x000c511e,
/* 006B */ 0x00078730,0x00001003,0x0000aaf4,0x000e910a,
/* 006D */ 0x0004628a,0x00000000,0x00006aca,0x00000000,
/* 006F */ 0x00000930,0x00000000,0x0004f5c0,0x00069c80,
/* 0071 */ 0x00046ac0,0x00000000,0x0003c40a,0x000fc898,
/* 0073 */ 0x00049118,0x00090e00,0x0006c10a,0x00000000,
/* 0075 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 0077 */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0079 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* SPDIFOTASK */
/* 007B */ 0x0006a108,0x000c0000,0x0004f4c0,0x000c3245,
/* 007D */ 0x0000a418,0x00001000,0x0003a20a,0x00000000,
/* 007F */ 0x00004418,0x00001380,0x000e243d,0x000d394a,
/* 0081 */ 0x000c9705,0x000def92,0x0008c030,0x00001004,
/* 0083 */ 0x0005f718,0x000fe798,0x00000000,0x000c0000,
/* 0085 */ 0x00005725,0x00000000,0x000704a0,0x00001004,
/* 0087 */ 0x00029314,0x000b4780,0x0003cf25,0x000b8600,
/* 0089 */ 0x00000000,0x00000000,0x00000000,0x000c0000,
/* 008B */ 0x00000000,0x00042c80,0x0001dec1,0x000e488c,
/* 008D */ 0x00031114,0x00000000,0x0004f5c2,0x00000000,
/* 008F */ 0x0004a918,0x00098600,0x0006c28a,0x00000000,
/* 0091 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
/* 0093 */ 0x00007001,0x00000000,0x00000734,0x00001000,
/* 0095 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
/* ASYNCHFGTXCODE */
/* 0097 */ 0x0002a880,0x000b4e40,0x00042214,0x000e5548,
/* 0099 */ 0x000542bf,0x00000000,0x00000000,0x000481c0,
/* 009B */ 0x00000000,0x00000000,0x00000000,0x00000030,
/* 009D */ 0x0000072d,0x000fbf8a,0x00077f94,0x000ea7df,
/* 009F */ 0x0002ac95,0x000d3145,0x00002731,0x00001400,
/* 00A1 */ 0x00006288,0x000c71c4,0x00014108,0x000e6044,
/* 00A3 */ 0x00035408,0x00000000,0x00025418,0x000a0ec0,
/* 00A5 */ 0x0001443d,0x000ca21e,0x00046595,0x000d730c,
/* 00A7 */ 0x0006538e,0x00000000,0x00064630,0x00001005,
/* 00A9 */ 0x000e7b0e,0x000df782,0x000746b0,0x00001005,
/* 00AB */ 0x00036f05,0x000c0000,0x00043695,0x000d598c,
/* 00AD */ 0x0005331a,0x000f2185,0x00000000,0x00000000,
/* 00AF */ 0x000007ae,0x000bdb00,0x00040630,0x00001400,
/* 00B1 */ 0x0005e708,0x000c0000,0x0007ef30,0x000b1c00,
/* 00B3 */ 0x000d86a0,0x00001005,0x00066408,0x000c0000,
/* 00B5 */ 0x00000000,0x00000000,0x00021843,0x00000000,
/* 00B7 */ 0x00000cac,0x00062c00,0x00001dac,0x00063400,
/* 00B9 */ 0x00002cac,0x0006cc80,0x000db943,0x000e5ca1,
/* 00BB */ 0x00000000,0x00000000,0x0006680a,0x000f3205,
/* 00BD */ 0x00042730,0x00001400,
/* ASYNCHFGRXCODE */
/* 00BE */ 0x00014108,0x000f2204,0x00025418,0x000a2ec0,
/* 00C0 */ 0x00015dbd,0x00038100,0x00015dbc,0x00000000,
/* 00C2 */ 0x0005e415,0x00034880,0x0001258a,0x000d730c,
/* 00C4 */ 0x0006538e,0x000baa40,0x00060630,0x00001006,
/* 00C6 */ 0x00067b0e,0x000ac380,0x0003ef05,0x00000000,
/* 00C8 */ 0x0000f734,0x0001c300,0x000586b0,0x00001400,
/* 00CA */ 0x000b6f05,0x000c3a00,0x00048f05,0x00000000,
/* 00CC */ 0x0005b695,0x0008c380,0x0002058e,0x00000000,
/* 00CE */ 0x000500b0,0x00001400,0x0002b318,0x000e998d,
/* 00D0 */ 0x0006430a,0x00000000,0x00000000,0x000ef384,
/* 00D2 */ 0x00004725,0x000c0000,0x00000000,0x000f3204,
/* 00D4 */ 0x00004f25,0x000c0000,0x00080000,0x000e5ca1,
/* 00D6 */ 0x000cb943,0x000e5ca1,0x0004b943,0x00000000,
/* 00D8 */ 0x00040730,0x00001400,0x000cb943,0x000e5ca1,
/* 00DA */ 0x0004b943,0x00000000
};
/* #CODE_END */
static struct dsp_segment_desc cwcasync_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
};
static struct dsp_module_desc cwcasync_module = {
"cwcasync",
{
32,
cwcasync_symbols
},
1,
cwcasync_segments,
};
#endif /* __HEADER_cwcasync_H__ */

View File

@ -1,48 +0,0 @@
/* generated by Benny
MODIFY ON YOUR OWN RISK */
#ifndef __HEADER_cwcbinhack_H__
#define __HEADER_cwcbinhack_H__
static struct dsp_symbol_entry cwcbinhack_symbols[] = {
{ 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
{ 0x02c8, "MAGICSNOOPTASK",0x03 },
{ 0x0308, "#CODE_END",0x00 },
}; /* cwcbinhack symbols */
static u32 cwcbinhack_code[] = {
/* 0x02c8 */
0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */
0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */
0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */
0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */
0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */
0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */
0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */
0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */
0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */
0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */
0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */
0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */
0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */
0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */
0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */
0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */
};
/* #CODE_END */
static struct dsp_segment_desc cwcbinhack_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
};
static struct dsp_module_desc cwcbinhack_module = {
"cwcbinhack",
{
3,
cwcbinhack_symbols
},
1,
cwcbinhack_segments,
};
#endif /* __HEADER_cwcbinhack_H__ */

View File

@ -1,170 +0,0 @@
//
// Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
// to compile it you need a tool named SPASM 3.0 and DSP code owned by
// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
// the "ospparser" tool will genereate the cwcdma.h file it's included from
// the cs46xx_lib.c file.
//
//
// The purpose of this code is very simple: make it possible to tranfser
// the samples 'as they are' with no alteration from a PCMreader
// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
// SRC (source rate converters) task always alters the samples in somehow,
// however it's from 48khz -> 48khz.
// The alterations are not audible, but AC3 wont work.
//
// ...
// |
// +---------------+
// | AsynchFGTxSCB |
// +---------------+
// |
// subListPtr
// |
// +--------------+
// | DMAReader |
// +--------------+
// |
// subListPtr
// |
// +-------------+
// | PCMReader |
// +-------------+
// (DMA from host)
//
struct dmaSCB
{
long dma_reserved1[3];
short dma_reserved2:dma_outBufPtr;
short dma_unused1:dma_unused2;
long dma_reserved3[4];
short dma_subListPtr:dma_nextSCB;
short dma_SPBptr:dma_entryPoint;
long dma_strmRsConfig;
long dma_strmBufPtr;
long dma_reserved4;
VolumeControl s2m_volume;
};
#export DMAReader
void DMAReader()
{
execChild();
r2 = r0->dma_subListPtr;
r1 = r0->nextSCB;
rsConfig01 = r2->strmRsConfig;
// Load rsConfig for input buffer
rsDMA01 = r2->basicReq.daw, , tb = Z(0 - rf);
// Load rsDMA in case input buffer is a DMA buffer Test to see if there is any data to transfer
if (tb) goto execSibling_2ind1 after {
r5 = rf + (-1);
r6 = r1->dma_entryPoint; // r6 = entry point of sibling task
r1 = r1->dma_SPBptr, // r1 = pointer to sibling task's SPB
, ind = r6; // Load entry point of sibling task
}
rsConfig23 = r0->dma_strmRsConfig;
// Load rsConfig for output buffer (never a DMA buffer)
r4 = r0->dma_outBufPtr;
rsa0 = r2->strmBufPtr;
// rsa0 = input buffer pointer
for (i = r5; i >= 0; --i)
after {
rsa2 = r4;
// rsa2 = output buffer pointer
nop;
nop;
}
//*****************************
// TODO: cycles to this point *
//*****************************
{
acc0 = (rsd0 = *rsa0++1);
// get sample
nop; // Those "nop"'s are really uggly, but there's
nop; // something with DSP's pipelines which I don't
nop; // understand, resulting this code to fail without
// having those "nop"'s (Benny)
rsa0?reqDMA = r2;
// Trigger DMA transfer on input stream,
// if needed to replenish input buffer
nop;
// Yet another magic "nop" to make stuff work
,,r98 = acc0 $+>> 0;
// store sample in ALU
nop;
// latency on load register.
// (this one is understandable)
*rsa2++1 = r98;
// store sample in output buffer
nop; // The same story
nop; // as above again ...
nop;
}
// TODO: cycles per loop iteration
r2->strmBufPtr = rsa0,, ;
// Update the modified buffer pointers
r4 = rsa2;
// Load output pointer position into r4
r2 = r0->nextSCB;
// Sibling task
goto execSibling_2ind1 // takes 6 cycles
after {
r98 = r2->thisSPB:entryPoint;
// Load child routine entry and data address
r1 = r9;
// r9 is r2->thisSPB
r0->dma_outBufPtr = r4,,
// Store updated output buffer pointer
ind = r8;
// r8 is r2->entryPoint
}
}

View File

@ -1,68 +0,0 @@
/* generated from cwcdma.osp DO NOT MODIFY */
#ifndef __HEADER_cwcdma_H__
#define __HEADER_cwcdma_H__
static struct dsp_symbol_entry cwcdma_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
{ 0x8008, "EXECSIBLING",0x03 },
{ 0x800a, "EXECSIBLING_298",0x03 },
{ 0x800b, "EXECSIBLING_2IND1",0x03 },
{ 0x8010, "TIMINGMASTER",0x03 },
{ 0x804f, "S16_CODECINPUTTASK",0x03 },
{ 0x805e, "PCMSERIALINPUTTASK",0x03 },
{ 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
{ 0x809a, "S16_MIX",0x03 },
{ 0x80bb, "S16_UPSRC",0x03 },
{ 0x813b, "MIX3_EXP",0x03 },
{ 0x8164, "DECIMATEBYPOW2",0x03 },
{ 0x8197, "VARIDECIMATE",0x03 },
{ 0x81f2, "_3DINPUTTASK",0x03 },
{ 0x820a, "_3DPRLGCINPTASK",0x03 },
{ 0x8227, "_3DSTEREOINPUTTASK",0x03 },
{ 0x8242, "_3DOUTPUTTASK",0x03 },
{ 0x82c4, "HRTF_MORPH_TASK",0x03 },
{ 0x82c6, "WAIT4DATA",0x03 },
{ 0x82fa, "PROLOGIC",0x03 },
{ 0x8496, "DECORRELATOR",0x03 },
{ 0x84a4, "STEREO2MONO",0x03 },
{ 0x0000, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0000, "DMAREADER",0x03 },
{ 0x0018, "#CODE_END",0x00 },
}; /* cwcdma symbols */
static u32 cwcdma_code[] = {
/* OVERLAYBEGINADDRESS */
/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300,
/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584,
/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104,
/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000,
/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000,
/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000,
/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000,
/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00,
/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400,
/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100
};
/* #CODE_END */
static struct dsp_segment_desc cwcdma_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
};
static struct dsp_module_desc cwcdma_module = {
"cwcdma",
{
27,
cwcdma_symbols
},
1,
cwcdma_segments,
};
#endif /* __HEADER_cwcdma_H__ */

View File

@ -1,46 +0,0 @@
/* generated from cwcsnoop.osp DO NOT MODIFY */
#ifndef __HEADER_cwcsnoop_H__
#define __HEADER_cwcsnoop_H__
static struct dsp_symbol_entry cwcsnoop_symbols[] = {
{ 0x0500, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0500, "OUTPUTSNOOP",0x03 },
{ 0x051f, "#CODE_END",0x00 },
}; /* cwcsnoop symbols */
static u32 cwcsnoop_code[] = {
/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617,
/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028,
/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000,
/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44,
/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00,
/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293,
/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92,
/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000,
/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000,
/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1,
/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000,
/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000,
/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084,
/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782,
/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880,
/* 001E */ 0x00006a88,0x000c75c4
};
/* #CODE_END */
static struct dsp_segment_desc cwcsnoop_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
};
static struct dsp_module_desc cwcsnoop_module = {
"cwcsnoop",
{
3,
cwcsnoop_symbols
},
1,
cwcsnoop_segments,
};
#endif /* __HEADER_cwcsnoop_H__ */

View File

@ -253,7 +253,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
{
synchronize_irq(cs5535au->irq);
pci_set_power_state(cs5535au->pci, 3);
pci_set_power_state(cs5535au->pci, PCI_D3hot);
if (cs5535au->irq >= 0)
free_irq(cs5535au->irq, cs5535au);

View File

@ -435,6 +435,11 @@ atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
return 0;
position = src->ops->get_ca(src);
if (position < apcm->vm_block->addr) {
snd_printdd("ctxfi: bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n", position, apcm->vm_block->addr, apcm->vm_block->size);
position = apcm->vm_block->addr;
}
size = apcm->vm_block->size;
max_cisz = src->multi * src->rsc.msr;
max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);

View File

@ -1422,7 +1422,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
if (! chip->dma.area)
return;
snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci));
snd_dma_free_pages(&chip->dma);
while ((p = chip->buf_list.next) != &chip->buf_list) {
struct esm_memory *chunk = list_entry(p, struct esm_memory, list);
list_del(p);
@ -1438,20 +1438,18 @@ snd_es1968_init_dmabuf(struct es1968 *chip)
chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) {
err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
chip->total_bufsize, &chip->dma);
if (err < 0 || ! chip->dma.area) {
snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n",
chip->total_bufsize);
return -ENOMEM;
}
if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
snd_dma_free_pages(&chip->dma);
snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n");
return -ENOMEM;
}
err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
chip->total_bufsize, &chip->dma);
if (err < 0 || ! chip->dma.area) {
snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n",
chip->total_bufsize);
return -ENOMEM;
}
if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
snd_dma_free_pages(&chip->dma);
snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&chip->buf_list);

View File

@ -87,69 +87,54 @@ config SND_HDA_PATCH_LOADER
This option turns on hwdep and reconfig features automatically.
config SND_HDA_CODEC_REALTEK
bool "Build Realtek HD-audio codec support"
default y
tristate "Build Realtek HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include Realtek HD-audio codec support in
Say Y or M here to include Realtek HD-audio codec support in
snd-hda-intel driver, such as ALC880.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-realtek.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_REALTEK=m
config SND_HDA_CODEC_ANALOG
bool "Build Analog Device HD-audio codec support"
default y
tristate "Build Analog Device HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include Analog Device HD-audio codec support in
Say Y or M here to include Analog Device HD-audio codec support in
snd-hda-intel driver, such as AD1986A.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-analog.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_ANALOG=m
config SND_HDA_CODEC_SIGMATEL
bool "Build IDT/Sigmatel HD-audio codec support"
default y
tristate "Build IDT/Sigmatel HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include IDT (Sigmatel) HD-audio codec support in
Say Y or M here to include IDT (Sigmatel) HD-audio codec support in
snd-hda-intel driver, such as STAC9200.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-idt.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SIGMATEL=m
config SND_HDA_CODEC_VIA
bool "Build VIA HD-audio codec support"
default y
tristate "Build VIA HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include VIA HD-audio codec support in
Say Y or M here to include VIA HD-audio codec support in
snd-hda-intel driver, such as VT1708.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-via.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_VIA=m
config SND_HDA_CODEC_HDMI
bool "Build HDMI/DisplayPort HD-audio codec support"
default y
tristate "Build HDMI/DisplayPort HD-audio codec support"
help
Say Y here to include HDMI and DisplayPort HD-audio codec
Say Y or M here to include HDMI and DisplayPort HD-audio codec
support in snd-hda-intel driver. This includes all AMD/ATI,
Intel and Nvidia HDMI/DisplayPort codecs.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-hdmi.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_HDMI=m
config SND_HDA_I915
bool
@ -157,55 +142,43 @@ config SND_HDA_I915
depends on DRM_I915
config SND_HDA_CODEC_CIRRUS
bool "Build Cirrus Logic codec support"
default y
tristate "Build Cirrus Logic codec support"
select SND_HDA_GENERIC
help
Say Y here to include Cirrus Logic codec support in
Say Y or M here to include Cirrus Logic codec support in
snd-hda-intel driver, such as CS4206.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-cirrus.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CIRRUS=m
config SND_HDA_CODEC_CONEXANT
bool "Build Conexant HD-audio codec support"
default y
tristate "Build Conexant HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include Conexant HD-audio codec support in
Say Y or M here to include Conexant HD-audio codec support in
snd-hda-intel driver, such as CX20549.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-conexant.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CONEXANT=m
config SND_HDA_CODEC_CA0110
bool "Build Creative CA0110-IBG codec support"
default y
tristate "Build Creative CA0110-IBG codec support"
select SND_HDA_GENERIC
help
Say Y here to include Creative CA0110-IBG codec support in
Say Y or M here to include Creative CA0110-IBG codec support in
snd-hda-intel driver, found on some Creative X-Fi cards.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-ca0110.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0110=m
config SND_HDA_CODEC_CA0132
bool "Build Creative CA0132 codec support"
default y
tristate "Build Creative CA0132 codec support"
help
Say Y here to include Creative CA0132 codec support in
Say Y or M here to include Creative CA0132 codec support in
snd-hda-intel driver.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-ca0132.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0132=m
config SND_HDA_CODEC_CA0132_DSP
bool "Support new DSP code for CA0132 codec"
@ -220,37 +193,33 @@ config SND_HDA_CODEC_CA0132_DSP
(ctefx.bin).
config SND_HDA_CODEC_CMEDIA
bool "Build C-Media HD-audio codec support"
default y
tristate "Build C-Media HD-audio codec support"
select SND_HDA_GENERIC
help
Say Y here to include C-Media HD-audio codec support in
Say Y or M here to include C-Media HD-audio codec support in
snd-hda-intel driver, such as CMI9880.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-cmedia.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CMEDIA=m
config SND_HDA_CODEC_SI3054
bool "Build Silicon Labs 3054 HD-modem codec support"
default y
tristate "Build Silicon Labs 3054 HD-modem codec support"
help
Say Y here to include Silicon Labs 3054 HD-modem codec
Say Y or M here to include Silicon Labs 3054 HD-modem codec
(and compatibles) support in snd-hda-intel driver.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-si3054.
This module is automatically loaded at probing.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SI3054=m
config SND_HDA_GENERIC
bool "Enable generic HD-audio codec parser"
default y
tristate "Enable generic HD-audio codec parser"
help
Say Y here to enable the generic HD-audio codec parser
Say Y or M here to enable the generic HD-audio codec parser
in snd-hda-intel driver.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA_INTEL=y && SND_HDA_GENERIC=m
config SND_HDA_POWER_SAVE_DEFAULT
int "Default time-out for HD-audio power-save mode"
depends on PM

View File

@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.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
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
CFLAGS_hda_codec.o := -I$(src)
CFLAGS_hda_intel.o := -I$(src)
snd-hda-codec-generic-objs := hda_generic.o
snd-hda-codec-realtek-objs := patch_realtek.o
snd-hda-codec-cmedia-objs := patch_cmedia.o
snd-hda-codec-analog-objs := patch_analog.o
@ -27,40 +27,19 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
# common driver
obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
ifdef CONFIG_SND_HDA_CODEC_REALTEK
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o
endif
ifdef CONFIG_SND_HDA_CODEC_CMEDIA
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o
endif
ifdef CONFIG_SND_HDA_CODEC_ANALOG
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o
endif
ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o
endif
ifdef CONFIG_SND_HDA_CODEC_SI3054
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
endif
ifdef CONFIG_SND_HDA_CODEC_CIRRUS
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o
endif
ifdef CONFIG_SND_HDA_CODEC_CA0110
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o
endif
ifdef CONFIG_SND_HDA_CODEC_CA0132
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0132.o
endif
ifdef CONFIG_SND_HDA_CODEC_CONEXANT
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
endif
ifdef CONFIG_SND_HDA_CODEC_VIA
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
endif
ifdef CONFIG_SND_HDA_CODEC_HDMI
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
endif
# codec drivers
obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o
obj-$(CONFIG_SND_HDA_CODEC_REALTEK) += snd-hda-codec-realtek.o
obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
# this must be the last entry after codec drivers;
# otherwise the codec patches won't be hooked before the PCI probe

View File

@ -414,7 +414,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);
EXPORT_SYMBOL_GPL(snd_hda_parse_pin_defcfg);
int snd_hda_get_input_pin_attr(unsigned int def_conf)
{
@ -435,7 +435,7 @@ int snd_hda_get_input_pin_attr(unsigned int def_conf)
return INPUT_PIN_ATTR_FRONT;
return INPUT_PIN_ATTR_NORMAL;
}
EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
EXPORT_SYMBOL_GPL(snd_hda_get_input_pin_attr);
/**
* hda_get_input_pin_label - Give a label for the given input pin
@ -547,7 +547,7 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
cfg->inputs[input].pin,
has_multiple_pins);
}
EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
EXPORT_SYMBOL_GPL(hda_get_autocfg_input_label);
/* return the position of NID in the list, or -1 if not found */
static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
@ -721,7 +721,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
strlcpy(label, name, maxlen);
return 1;
}
EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
int snd_hda_add_verbs(struct hda_codec *codec,
const struct hda_verb *list)
@ -733,7 +733,7 @@ int snd_hda_add_verbs(struct hda_codec *codec,
*v = list;
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_add_verbs);
EXPORT_SYMBOL_GPL(snd_hda_add_verbs);
void snd_hda_apply_verbs(struct hda_codec *codec)
{
@ -743,7 +743,7 @@ void snd_hda_apply_verbs(struct hda_codec *codec)
snd_hda_sequence_write(codec, *v);
}
}
EXPORT_SYMBOL_HDA(snd_hda_apply_verbs);
EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
void snd_hda_apply_pincfgs(struct hda_codec *codec,
const struct hda_pintbl *cfg)
@ -751,7 +751,7 @@ void snd_hda_apply_pincfgs(struct hda_codec *codec,
for (; cfg->nid; cfg++)
snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
}
EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
EXPORT_SYMBOL_GPL(snd_hda_apply_pincfgs);
static void set_pin_targets(struct hda_codec *codec,
const struct hda_pintbl *cfg)
@ -822,7 +822,7 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
if (codec->fixup_list)
apply_fixup(codec, codec->fixup_id, action, 0);
}
EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
@ -880,4 +880,4 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
codec->fixup_name = name;
}
}
EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);

View File

@ -194,7 +194,7 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
}
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device);
EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
@ -231,7 +231,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
void snd_hda_detach_beep_device(struct hda_codec *codec)
{
@ -243,7 +243,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
kfree(beep);
}
}
EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
{
@ -265,7 +265,7 @@ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
}
return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
}
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get_beep);
EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@ -288,4 +288,4 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
return 0;
return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
}
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);

File diff suppressed because it is too large Load Diff

View File

@ -25,552 +25,7 @@
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/hwdep.h>
/*
* nodes
*/
#define AC_NODE_ROOT 0x00
/*
* function group types
*/
enum {
AC_GRP_AUDIO_FUNCTION = 0x01,
AC_GRP_MODEM_FUNCTION = 0x02,
};
/*
* widget types
*/
enum {
AC_WID_AUD_OUT, /* Audio Out */
AC_WID_AUD_IN, /* Audio In */
AC_WID_AUD_MIX, /* Audio Mixer */
AC_WID_AUD_SEL, /* Audio Selector */
AC_WID_PIN, /* Pin Complex */
AC_WID_POWER, /* Power */
AC_WID_VOL_KNB, /* Volume Knob */
AC_WID_BEEP, /* Beep Generator */
AC_WID_VENDOR = 0x0f /* Vendor specific */
};
/*
* GET verbs
*/
#define AC_VERB_GET_STREAM_FORMAT 0x0a00
#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00
#define AC_VERB_GET_PROC_COEF 0x0c00
#define AC_VERB_GET_COEF_INDEX 0x0d00
#define AC_VERB_PARAMETERS 0x0f00
#define AC_VERB_GET_CONNECT_SEL 0x0f01
#define AC_VERB_GET_CONNECT_LIST 0x0f02
#define AC_VERB_GET_PROC_STATE 0x0f03
#define AC_VERB_GET_SDI_SELECT 0x0f04
#define AC_VERB_GET_POWER_STATE 0x0f05
#define AC_VERB_GET_CONV 0x0f06
#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07
#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08
#define AC_VERB_GET_PIN_SENSE 0x0f09
#define AC_VERB_GET_BEEP_CONTROL 0x0f0a
#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c
#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d
#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
/* f10-f1a: GPIO */
#define AC_VERB_GET_GPIO_DATA 0x0f15
#define AC_VERB_GET_GPIO_MASK 0x0f16
#define AC_VERB_GET_GPIO_DIRECTION 0x0f17
#define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18
#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19
#define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a
#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
/* f20: AFG/MFG */
#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20
#define AC_VERB_GET_CVT_CHAN_COUNT 0x0f2d
#define AC_VERB_GET_HDMI_DIP_SIZE 0x0f2e
#define AC_VERB_GET_HDMI_ELDD 0x0f2f
#define AC_VERB_GET_HDMI_DIP_INDEX 0x0f30
#define AC_VERB_GET_HDMI_DIP_DATA 0x0f31
#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32
#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33
#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34
#define AC_VERB_GET_DEVICE_SEL 0xf35
#define AC_VERB_GET_DEVICE_LIST 0xf36
/*
* SET verbs
*/
#define AC_VERB_SET_STREAM_FORMAT 0x200
#define AC_VERB_SET_AMP_GAIN_MUTE 0x300
#define AC_VERB_SET_PROC_COEF 0x400
#define AC_VERB_SET_COEF_INDEX 0x500
#define AC_VERB_SET_CONNECT_SEL 0x701
#define AC_VERB_SET_PROC_STATE 0x703
#define AC_VERB_SET_SDI_SELECT 0x704
#define AC_VERB_SET_POWER_STATE 0x705
#define AC_VERB_SET_CHANNEL_STREAMID 0x706
#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707
#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708
#define AC_VERB_SET_PIN_SENSE 0x709
#define AC_VERB_SET_BEEP_CONTROL 0x70a
#define AC_VERB_SET_EAPD_BTLENABLE 0x70c
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
#define AC_VERB_SET_GPIO_DATA 0x715
#define AC_VERB_SET_GPIO_MASK 0x716
#define AC_VERB_SET_GPIO_DIRECTION 0x717
#define AC_VERB_SET_GPIO_WAKE_MASK 0x718
#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719
#define AC_VERB_SET_GPIO_STICKY_MASK 0x71a
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f
#define AC_VERB_SET_EAPD 0x788
#define AC_VERB_SET_CODEC_RESET 0x7ff
#define AC_VERB_SET_CVT_CHAN_COUNT 0x72d
#define AC_VERB_SET_HDMI_DIP_INDEX 0x730
#define AC_VERB_SET_HDMI_DIP_DATA 0x731
#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
#define AC_VERB_SET_HDMI_CP_CTRL 0x733
#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
#define AC_VERB_SET_DEVICE_SEL 0x735
/*
* Parameter IDs
*/
#define AC_PAR_VENDOR_ID 0x00
#define AC_PAR_SUBSYSTEM_ID 0x01
#define AC_PAR_REV_ID 0x02
#define AC_PAR_NODE_COUNT 0x04
#define AC_PAR_FUNCTION_TYPE 0x05
#define AC_PAR_AUDIO_FG_CAP 0x08
#define AC_PAR_AUDIO_WIDGET_CAP 0x09
#define AC_PAR_PCM 0x0a
#define AC_PAR_STREAM 0x0b
#define AC_PAR_PIN_CAP 0x0c
#define AC_PAR_AMP_IN_CAP 0x0d
#define AC_PAR_CONNLIST_LEN 0x0e
#define AC_PAR_POWER_STATE 0x0f
#define AC_PAR_PROC_CAP 0x10
#define AC_PAR_GPIO_CAP 0x11
#define AC_PAR_AMP_OUT_CAP 0x12
#define AC_PAR_VOL_KNB_CAP 0x13
#define AC_PAR_DEVLIST_LEN 0x15
#define AC_PAR_HDMI_LPCM_CAP 0x20
/*
* AC_VERB_PARAMETERS results (32bit)
*/
/* Function Group Type */
#define AC_FGT_TYPE (0xff<<0)
#define AC_FGT_TYPE_SHIFT 0
#define AC_FGT_UNSOL_CAP (1<<8)
/* Audio Function Group Capabilities */
#define AC_AFG_OUT_DELAY (0xf<<0)
#define AC_AFG_IN_DELAY (0xf<<8)
#define AC_AFG_BEEP_GEN (1<<16)
/* Audio Widget Capabilities */
#define AC_WCAP_STEREO (1<<0) /* stereo I/O */
#define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */
#define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */
#define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */
#define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */
#define AC_WCAP_STRIPE (1<<5) /* stripe */
#define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */
#define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */
#define AC_WCAP_CONN_LIST (1<<8) /* connection list */
#define AC_WCAP_DIGITAL (1<<9) /* digital I/O */
#define AC_WCAP_POWER (1<<10) /* power control */
#define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */
#define AC_WCAP_CP_CAPS (1<<12) /* content protection */
#define AC_WCAP_CHAN_CNT_EXT (7<<13) /* channel count ext */
#define AC_WCAP_DELAY (0xf<<16)
#define AC_WCAP_DELAY_SHIFT 16
#define AC_WCAP_TYPE (0xf<<20)
#define AC_WCAP_TYPE_SHIFT 20
/* supported PCM rates and bits */
#define AC_SUPPCM_RATES (0xfff << 0)
#define AC_SUPPCM_BITS_8 (1<<16)
#define AC_SUPPCM_BITS_16 (1<<17)
#define AC_SUPPCM_BITS_20 (1<<18)
#define AC_SUPPCM_BITS_24 (1<<19)
#define AC_SUPPCM_BITS_32 (1<<20)
/* supported PCM stream format */
#define AC_SUPFMT_PCM (1<<0)
#define AC_SUPFMT_FLOAT32 (1<<1)
#define AC_SUPFMT_AC3 (1<<2)
/* GP I/O count */
#define AC_GPIO_IO_COUNT (0xff<<0)
#define AC_GPIO_O_COUNT (0xff<<8)
#define AC_GPIO_O_COUNT_SHIFT 8
#define AC_GPIO_I_COUNT (0xff<<16)
#define AC_GPIO_I_COUNT_SHIFT 16
#define AC_GPIO_UNSOLICITED (1<<30)
#define AC_GPIO_WAKE (1<<31)
/* Converter stream, channel */
#define AC_CONV_CHANNEL (0xf<<0)
#define AC_CONV_STREAM (0xf<<4)
#define AC_CONV_STREAM_SHIFT 4
/* Input converter SDI select */
#define AC_SDI_SELECT (0xf<<0)
/* stream format id */
#define AC_FMT_CHAN_SHIFT 0
#define AC_FMT_CHAN_MASK (0x0f << 0)
#define AC_FMT_BITS_SHIFT 4
#define AC_FMT_BITS_MASK (7 << 4)
#define AC_FMT_BITS_8 (0 << 4)
#define AC_FMT_BITS_16 (1 << 4)
#define AC_FMT_BITS_20 (2 << 4)
#define AC_FMT_BITS_24 (3 << 4)
#define AC_FMT_BITS_32 (4 << 4)
#define AC_FMT_DIV_SHIFT 8
#define AC_FMT_DIV_MASK (7 << 8)
#define AC_FMT_MULT_SHIFT 11
#define AC_FMT_MULT_MASK (7 << 11)
#define AC_FMT_BASE_SHIFT 14
#define AC_FMT_BASE_48K (0 << 14)
#define AC_FMT_BASE_44K (1 << 14)
#define AC_FMT_TYPE_SHIFT 15
#define AC_FMT_TYPE_PCM (0 << 15)
#define AC_FMT_TYPE_NON_PCM (1 << 15)
/* Unsolicited response control */
#define AC_UNSOL_TAG (0x3f<<0)
#define AC_UNSOL_ENABLED (1<<7)
#define AC_USRSP_EN AC_UNSOL_ENABLED
/* Unsolicited responses */
#define AC_UNSOL_RES_TAG (0x3f<<26)
#define AC_UNSOL_RES_TAG_SHIFT 26
#define AC_UNSOL_RES_SUBTAG (0x1f<<21)
#define AC_UNSOL_RES_SUBTAG_SHIFT 21
#define AC_UNSOL_RES_DE (0x3f<<15) /* Device Entry
* (for DP1.2 MST)
*/
#define AC_UNSOL_RES_DE_SHIFT 15
#define AC_UNSOL_RES_IA (1<<2) /* Inactive (for DP1.2 MST) */
#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */
#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */
#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */
#define AC_UNSOL_RES_CP_READY (1<<0) /* content protection */
/* Pin widget capabilies */
#define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */
#define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */
#define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */
#define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */
#define AC_PINCAP_OUT (1<<4) /* output capable */
#define AC_PINCAP_IN (1<<5) /* input capable */
#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */
/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
* but is marked reserved in the Intel HDA specification.
*/
#define AC_PINCAP_LR_SWAP (1<<7) /* L/R swap */
/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
* in HD-audio specification
*/
#define AC_PINCAP_HDMI (1<<7) /* HDMI pin */
#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can
* coexist with AC_PINCAP_HDMI
*/
#define AC_PINCAP_VREF (0x37<<8)
#define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */
/* Vref status (used in pin cap) */
#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
#define AC_PINCAP_VREF_50 (1<<1) /* 50% */
#define AC_PINCAP_VREF_GRD (1<<2) /* ground */
#define AC_PINCAP_VREF_80 (1<<4) /* 80% */
#define AC_PINCAP_VREF_100 (1<<5) /* 100% */
/* Amplifier capabilities */
#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */
#define AC_AMPCAP_OFFSET_SHIFT 0
#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */
#define AC_AMPCAP_NUM_STEPS_SHIFT 8
#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB
* in 0.25dB
*/
#define AC_AMPCAP_STEP_SIZE_SHIFT 16
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
/* driver-specific amp-caps: using bits 24-30 */
#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
/* Supported power status */
#define AC_PWRST_D0SUP (1<<0)
#define AC_PWRST_D1SUP (1<<1)
#define AC_PWRST_D2SUP (1<<2)
#define AC_PWRST_D3SUP (1<<3)
#define AC_PWRST_D3COLDSUP (1<<4)
#define AC_PWRST_S3D3COLDSUP (1<<29)
#define AC_PWRST_CLKSTOP (1<<30)
#define AC_PWRST_EPSS (1U<<31)
/* Power state values */
#define AC_PWRST_SETTING (0xf<<0)
#define AC_PWRST_ACTUAL (0xf<<4)
#define AC_PWRST_ACTUAL_SHIFT 4
#define AC_PWRST_D0 0x00
#define AC_PWRST_D1 0x01
#define AC_PWRST_D2 0x02
#define AC_PWRST_D3 0x03
#define AC_PWRST_ERROR (1<<8)
#define AC_PWRST_CLK_STOP_OK (1<<9)
#define AC_PWRST_SETTING_RESET (1<<10)
/* Processing capabilies */
#define AC_PCAP_BENIGN (1<<0)
#define AC_PCAP_NUM_COEF (0xff<<8)
#define AC_PCAP_NUM_COEF_SHIFT 8
/* Volume knobs capabilities */
#define AC_KNBCAP_NUM_STEPS (0x7f<<0)
#define AC_KNBCAP_DELTA (1<<7)
/* HDMI LPCM capabilities */
#define AC_LPCMCAP_48K_CP_CHNS (0x0f<<0) /* max channels w/ CP-on */
#define AC_LPCMCAP_48K_NO_CHNS (0x0f<<4) /* max channels w/o CP-on */
#define AC_LPCMCAP_48K_20BIT (1<<8) /* 20b bitrate supported */
#define AC_LPCMCAP_48K_24BIT (1<<9) /* 24b bitrate supported */
#define AC_LPCMCAP_96K_CP_CHNS (0x0f<<10) /* max channels w/ CP-on */
#define AC_LPCMCAP_96K_NO_CHNS (0x0f<<14) /* max channels w/o CP-on */
#define AC_LPCMCAP_96K_20BIT (1<<18) /* 20b bitrate supported */
#define AC_LPCMCAP_96K_24BIT (1<<19) /* 24b bitrate supported */
#define AC_LPCMCAP_192K_CP_CHNS (0x0f<<20) /* max channels w/ CP-on */
#define AC_LPCMCAP_192K_NO_CHNS (0x0f<<24) /* max channels w/o CP-on */
#define AC_LPCMCAP_192K_20BIT (1<<28) /* 20b bitrate supported */
#define AC_LPCMCAP_192K_24BIT (1<<29) /* 24b bitrate supported */
#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */
#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */
/* Display pin's device list length */
#define AC_DEV_LIST_LEN_MASK 0x3f
#define AC_MAX_DEV_LIST_LEN 64
/*
* Control Parameters
*/
/* Amp gain/mute */
#define AC_AMP_MUTE (1<<7)
#define AC_AMP_GAIN (0x7f)
#define AC_AMP_GET_INDEX (0xf<<0)
#define AC_AMP_GET_LEFT (1<<13)
#define AC_AMP_GET_RIGHT (0<<13)
#define AC_AMP_GET_OUTPUT (1<<15)
#define AC_AMP_GET_INPUT (0<<15)
#define AC_AMP_SET_INDEX (0xf<<8)
#define AC_AMP_SET_INDEX_SHIFT 8
#define AC_AMP_SET_RIGHT (1<<12)
#define AC_AMP_SET_LEFT (1<<13)
#define AC_AMP_SET_INPUT (1<<14)
#define AC_AMP_SET_OUTPUT (1<<15)
/* DIGITAL1 bits */
#define AC_DIG1_ENABLE (1<<0)
#define AC_DIG1_V (1<<1)
#define AC_DIG1_VCFG (1<<2)
#define AC_DIG1_EMPHASIS (1<<3)
#define AC_DIG1_COPYRIGHT (1<<4)
#define AC_DIG1_NONAUDIO (1<<5)
#define AC_DIG1_PROFESSIONAL (1<<6)
#define AC_DIG1_LEVEL (1<<7)
/* DIGITAL2 bits */
#define AC_DIG2_CC (0x7f<<0)
/* DIGITAL3 bits */
#define AC_DIG3_ICT (0xf<<0)
#define AC_DIG3_KAE (1<<7)
/* Pin widget control - 8bit */
#define AC_PINCTL_EPT (0x3<<0)
#define AC_PINCTL_EPT_NATIVE 0
#define AC_PINCTL_EPT_HBR 3
#define AC_PINCTL_VREFEN (0x7<<0)
#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
#define AC_PINCTL_VREF_50 1 /* 50% */
#define AC_PINCTL_VREF_GRD 2 /* ground */
#define AC_PINCTL_VREF_80 4 /* 80% */
#define AC_PINCTL_VREF_100 5 /* 100% */
#define AC_PINCTL_IN_EN (1<<5)
#define AC_PINCTL_OUT_EN (1<<6)
#define AC_PINCTL_HP_EN (1<<7)
/* Pin sense - 32bit */
#define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff)
#define AC_PINSENSE_PRESENCE (1<<31)
#define AC_PINSENSE_ELDV (1<<30) /* ELD valid (HDMI) */
/* EAPD/BTL enable - 32bit */
#define AC_EAPDBTL_BALANCED (1<<0)
#define AC_EAPDBTL_EAPD (1<<1)
#define AC_EAPDBTL_LR_SWAP (1<<2)
/* HDMI ELD data */
#define AC_ELDD_ELD_VALID (1<<31)
#define AC_ELDD_ELD_DATA 0xff
/* HDMI DIP size */
#define AC_DIPSIZE_ELD_BUF (1<<3) /* ELD buf size of packet size */
#define AC_DIPSIZE_PACK_IDX (0x07<<0) /* packet index */
/* HDMI DIP index */
#define AC_DIPIDX_PACK_IDX (0x07<<5) /* packet idnex */
#define AC_DIPIDX_BYTE_IDX (0x1f<<0) /* byte index */
/* HDMI DIP xmit (transmit) control */
#define AC_DIPXMIT_MASK (0x3<<6)
#define AC_DIPXMIT_DISABLE (0x0<<6) /* disable xmit */
#define AC_DIPXMIT_ONCE (0x2<<6) /* xmit once then disable */
#define AC_DIPXMIT_BEST (0x3<<6) /* best effort */
/* HDMI content protection (CP) control */
#define AC_CPCTRL_CES (1<<9) /* current encryption state */
#define AC_CPCTRL_READY (1<<8) /* ready bit */
#define AC_CPCTRL_SUBTAG (0x1f<<3) /* subtag for unsol-resp */
#define AC_CPCTRL_STATE (3<<0) /* current CP request state */
/* Converter channel <-> HDMI slot mapping */
#define AC_CVTMAP_HDMI_SLOT (0xf<<0) /* HDMI slot number */
#define AC_CVTMAP_CHAN (0xf<<4) /* converter channel number */
/* configuration default - 32bit */
#define AC_DEFCFG_SEQUENCE (0xf<<0)
#define AC_DEFCFG_DEF_ASSOC (0xf<<4)
#define AC_DEFCFG_ASSOC_SHIFT 4
#define AC_DEFCFG_MISC (0xf<<8)
#define AC_DEFCFG_MISC_SHIFT 8
#define AC_DEFCFG_MISC_NO_PRESENCE (1<<0)
#define AC_DEFCFG_COLOR (0xf<<12)
#define AC_DEFCFG_COLOR_SHIFT 12
#define AC_DEFCFG_CONN_TYPE (0xf<<16)
#define AC_DEFCFG_CONN_TYPE_SHIFT 16
#define AC_DEFCFG_DEVICE (0xf<<20)
#define AC_DEFCFG_DEVICE_SHIFT 20
#define AC_DEFCFG_LOCATION (0x3f<<24)
#define AC_DEFCFG_LOCATION_SHIFT 24
#define AC_DEFCFG_PORT_CONN (0x3<<30)
#define AC_DEFCFG_PORT_CONN_SHIFT 30
/* Display pin's device list entry */
#define AC_DE_PD (1<<0)
#define AC_DE_ELDV (1<<1)
#define AC_DE_IA (1<<2)
/* device device types (0x0-0xf) */
enum {
AC_JACK_LINE_OUT,
AC_JACK_SPEAKER,
AC_JACK_HP_OUT,
AC_JACK_CD,
AC_JACK_SPDIF_OUT,
AC_JACK_DIG_OTHER_OUT,
AC_JACK_MODEM_LINE_SIDE,
AC_JACK_MODEM_HAND_SIDE,
AC_JACK_LINE_IN,
AC_JACK_AUX,
AC_JACK_MIC_IN,
AC_JACK_TELEPHONY,
AC_JACK_SPDIF_IN,
AC_JACK_DIG_OTHER_IN,
AC_JACK_OTHER = 0xf,
};
/* jack connection types (0x0-0xf) */
enum {
AC_JACK_CONN_UNKNOWN,
AC_JACK_CONN_1_8,
AC_JACK_CONN_1_4,
AC_JACK_CONN_ATAPI,
AC_JACK_CONN_RCA,
AC_JACK_CONN_OPTICAL,
AC_JACK_CONN_OTHER_DIGITAL,
AC_JACK_CONN_OTHER_ANALOG,
AC_JACK_CONN_DIN,
AC_JACK_CONN_XLR,
AC_JACK_CONN_RJ11,
AC_JACK_CONN_COMB,
AC_JACK_CONN_OTHER = 0xf,
};
/* jack colors (0x0-0xf) */
enum {
AC_JACK_COLOR_UNKNOWN,
AC_JACK_COLOR_BLACK,
AC_JACK_COLOR_GREY,
AC_JACK_COLOR_BLUE,
AC_JACK_COLOR_GREEN,
AC_JACK_COLOR_RED,
AC_JACK_COLOR_ORANGE,
AC_JACK_COLOR_YELLOW,
AC_JACK_COLOR_PURPLE,
AC_JACK_COLOR_PINK,
AC_JACK_COLOR_WHITE = 0xe,
AC_JACK_COLOR_OTHER,
};
/* Jack location (0x0-0x3f) */
/* common case */
enum {
AC_JACK_LOC_NONE,
AC_JACK_LOC_REAR,
AC_JACK_LOC_FRONT,
AC_JACK_LOC_LEFT,
AC_JACK_LOC_RIGHT,
AC_JACK_LOC_TOP,
AC_JACK_LOC_BOTTOM,
};
/* bits 4-5 */
enum {
AC_JACK_LOC_EXTERNAL = 0x00,
AC_JACK_LOC_INTERNAL = 0x10,
AC_JACK_LOC_SEPARATE = 0x20,
AC_JACK_LOC_OTHER = 0x30,
};
enum {
/* external on primary chasis */
AC_JACK_LOC_REAR_PANEL = 0x07,
AC_JACK_LOC_DRIVE_BAY,
/* internal */
AC_JACK_LOC_RISER = 0x17,
AC_JACK_LOC_HDMI,
AC_JACK_LOC_ATAPI,
/* others */
AC_JACK_LOC_MOBILE_IN = 0x37,
AC_JACK_LOC_MOBILE_OUT,
};
/* Port connectivity (0-3) */
enum {
AC_JACK_PORT_COMPLEX,
AC_JACK_PORT_NONE,
AC_JACK_PORT_FIXED,
AC_JACK_PORT_BOTH,
};
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS 0x0f
#include <sound/hda_verbs.h>
/*
* generic arrays
@ -673,6 +128,7 @@ struct hda_bus {
/* codec linked list */
struct list_head codec_list;
unsigned int num_codecs;
/* link caddr -> codec */
struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
@ -834,6 +290,7 @@ struct hda_codec {
/* detected preset */
const struct hda_codec_preset *preset;
struct module *owner;
int (*parser)(struct hda_codec *codec);
const char *vendor_name; /* codec vendor name */
const char *chip_name; /* codec chip name */
const char *modelname; /* model name for preset */
@ -907,7 +364,7 @@ struct hda_codec {
#ifdef CONFIG_PM
unsigned int power_on :1; /* current (global) power-state */
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
unsigned int pm_down_notified:1; /* PM notified to controller */
unsigned int pm_up_notified:1; /* PM notified to controller */
unsigned int in_pm:1; /* suspend/resume being performed */
int power_transition; /* power-state in transition */
int power_count; /* current (global) power refcount */
@ -936,6 +393,8 @@ struct hda_codec {
struct snd_array jacks;
#endif
int depop_delay; /* depop delay in ms, -1 for default delay time */
/* fix-up list */
int fixup_id;
const struct hda_fixup *fixup_list;
@ -1222,19 +681,6 @@ snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
struct snd_dma_buffer *dmab) {}
#endif
/*
* Codec modularization
*/
/* Export symbols only for communication with codec drivers;
* When built in kernel, all HD-audio drivers are supposed to be statically
* linked to the kernel. Thus, the symbols don't have to (or shouldn't) be
* exported unless it's built as a module.
*/
#ifdef MODULE
#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
#else
#define EXPORT_SYMBOL_HDA(sym)
#endif
#endif /* __SOUND_HDA_CODEC_H */

View File

@ -28,6 +28,7 @@
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include "hda_codec.h"
@ -47,7 +48,7 @@ int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
mutex_init(&spec->pcm_mutex);
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
struct snd_kcontrol_new *
snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
@ -65,7 +66,7 @@ snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
return NULL;
return knew;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
static void free_kctls(struct hda_gen_spec *spec)
{
@ -86,7 +87,7 @@ void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
snd_array_free(&spec->paths);
snd_array_free(&spec->loopback_list);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
EXPORT_SYMBOL_GPL(snd_hda_gen_spec_free);
/*
* store user hints
@ -266,7 +267,7 @@ struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
{
return get_nid_path(codec, from_nid, to_nid, 0);
}
EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
EXPORT_SYMBOL_GPL(snd_hda_get_nid_path);
/* get the index number corresponding to the path instance;
* the index starts from 1, for easier checking the invalid value
@ -284,7 +285,7 @@ int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
return 0;
return idx + 1;
}
EXPORT_SYMBOL_HDA(snd_hda_get_path_idx);
EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
/* get the path instance corresponding to the given index number */
struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
@ -295,7 +296,7 @@ struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
return NULL;
return snd_array_elem(&spec->paths, idx - 1);
}
EXPORT_SYMBOL_HDA(snd_hda_get_path_from_idx);
EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
/* check whether the given DAC is already found in any existing paths */
static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
@ -432,7 +433,7 @@ bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
}
return false;
}
EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
EXPORT_SYMBOL_GPL(snd_hda_parse_nid_path);
/*
* parse the path between the given NIDs and add to the path list.
@ -463,7 +464,7 @@ snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
spec->paths.used--;
return NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
/* clear the given path as invalid so that it won't be picked up later */
static void invalidate_nid_path(struct hda_codec *codec, int idx)
@ -773,7 +774,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
if (enable)
path->active = true;
}
EXPORT_SYMBOL_HDA(snd_hda_activate_path);
EXPORT_SYMBOL_GPL(snd_hda_activate_path);
/* if the given path is inactive, put widgets into D3 (only if suitable) */
static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
@ -1149,7 +1150,7 @@ const struct badness_table hda_main_out_badness = {
.shared_clfe = BAD_SHARED_CLFE,
.shared_surr_main = BAD_SHARED_SURROUND,
};
EXPORT_SYMBOL_HDA(hda_main_out_badness);
EXPORT_SYMBOL_GPL(hda_main_out_badness);
const struct badness_table hda_extra_out_badness = {
.no_primary_dac = BAD_NO_DAC,
@ -1159,7 +1160,7 @@ const struct badness_table hda_extra_out_badness = {
.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
};
EXPORT_SYMBOL_HDA(hda_extra_out_badness);
EXPORT_SYMBOL_GPL(hda_extra_out_badness);
/* get the DAC of the primary output corresponding to the given array index */
static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
@ -2857,9 +2858,11 @@ static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
if (num_conns < idx)
return false;
nid = list[idx];
if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
!is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
!is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
return *mix_val || *mute_val;
@ -3053,6 +3056,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
spec->imux_pins[imux->num_items] = pin;
snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
imux_added = true;
if (spec->dyn_adc_switch)
spec->dyn_adc_idx[imux_idx] = c;
}
}
@ -3150,7 +3155,9 @@ static int create_input_ctls(struct hda_codec *codec)
}
}
if (mixer && spec->add_stereo_mix_input) {
/* add stereo mix when explicitly enabled via hint */
if (mixer && spec->add_stereo_mix_input &&
snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
"Stereo Mix", 0);
if (err < 0)
@ -3916,7 +3923,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
spec->autocfg.line_out_pins, paths, on);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
static void call_update_outputs(struct hda_codec *codec)
{
@ -3949,7 +3956,7 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
return;
call_update_outputs(codec);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
/* standard line-out-automute helper */
void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@ -3969,7 +3976,7 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac
return;
call_update_outputs(codec);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
/* standard mic auto-switch helper */
void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
@ -3992,7 +3999,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
}
mux_select(codec, 0, spec->am_entry[0].idx);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
/* call appropriate hooks */
static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@ -4305,11 +4312,11 @@ static int check_auto_mic_availability(struct hda_codec *codec)
}
/* power_filter hook; make inactive widgets into power down */
static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state)
{
if (power_state != AC_PWRST_D0)
if (power_state != AC_PWRST_D0 || nid == codec->afg)
return power_state;
if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
return power_state;
@ -4317,6 +4324,7 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
return power_state;
return AC_PWRST_D3;
}
EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
/* mute all aamix inputs initially; parse up to the first leaves */
static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
@ -4374,7 +4382,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
spec->no_analog = 1;
goto dig_only;
}
return 0; /* can't find valid BIOS pin config */
if (!cfg->num_inputs && !cfg->dig_in_pin)
return 0; /* can't find valid BIOS pin config */
}
if (!spec->no_primary_hp &&
@ -4442,6 +4451,19 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
if (err < 0)
return err;
/* add stereo mix if available and not enabled yet */
if (!spec->auto_mic && spec->mixer_nid &&
spec->add_stereo_mix_input &&
spec->input_mux.num_items > 1 &&
snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
err = parse_capture_source(codec, spec->mixer_nid,
CFG_IDX_MIX, spec->num_all_adcs,
"Stereo Mix", 0);
if (err < 0)
return err;
}
err = create_capture_mixers(codec);
if (err < 0)
return err;
@ -4494,7 +4516,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
return 1;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
/*
@ -4576,7 +4598,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
/*
@ -5109,7 +5131,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
/*
@ -5183,6 +5205,23 @@ static void init_multi_io(struct hda_codec *codec)
}
}
static void init_aamix_paths(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
if (!spec->have_aamix_ctl)
return;
update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
spec->aamix_out_paths[0],
spec->autocfg.line_out_type);
update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
spec->aamix_out_paths[1],
AUTO_PIN_HP_OUT);
update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
spec->aamix_out_paths[2],
AUTO_PIN_SPEAKER_OUT);
}
/* set up input pins and loopback paths */
static void init_analog_input(struct hda_codec *codec)
{
@ -5285,6 +5324,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
init_multi_out(codec);
init_extra_out(codec);
init_multi_io(codec);
init_aamix_paths(codec);
init_analog_input(codec);
init_input_src(codec);
init_digital(codec);
@ -5302,7 +5342,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
hda_call_check_power_status(codec, 0x01);
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_init);
EXPORT_SYMBOL_GPL(snd_hda_gen_init);
/*
* free the generic spec;
@ -5315,7 +5355,7 @@ void snd_hda_gen_free(struct hda_codec *codec)
kfree(codec->spec);
codec->spec = NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_gen_free);
EXPORT_SYMBOL_GPL(snd_hda_gen_free);
#ifdef CONFIG_PM
/*
@ -5327,7 +5367,7 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
struct hda_gen_spec *spec = codec->spec;
return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
#endif
@ -5372,4 +5412,7 @@ error:
snd_hda_gen_free(codec);
return err;
}
EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
EXPORT_SYMBOL_GPL(snd_hda_parse_generic_codec);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic HD-audio codec parser");

View File

@ -335,5 +335,8 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec);
#ifdef CONFIG_PM
int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
#endif
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);
#endif /* __SOUND_HDA_GENERIC_H */

View File

@ -616,7 +616,7 @@ const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
struct hda_hint *hint = get_hint(codec, key);
return hint ? hint->val : NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_get_hint);
EXPORT_SYMBOL_GPL(snd_hda_get_hint);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
@ -642,7 +642,7 @@ int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
mutex_unlock(&codec->user_mutex);
return ret;
}
EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
{
@ -663,7 +663,7 @@ int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
mutex_unlock(&codec->user_mutex);
return ret;
}
EXPORT_SYMBOL_HDA(snd_hda_get_int_hint);
EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
#endif /* CONFIG_SND_HDA_RECONFIG */
#ifdef CONFIG_SND_HDA_PATCH_LOADER
@ -762,20 +762,50 @@ DEFINE_PARSE_ID_MODE(revision_id);
struct hda_patch_item {
const char *tag;
const char *alias;
void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
int need_codec;
};
static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 },
[LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 },
[LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 },
[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 },
[LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 },
[LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 },
[LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 },
[LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 },
[LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 },
[LINE_MODE_CODEC] = {
.tag = "[codec]",
.parser = parse_codec_mode,
},
[LINE_MODE_MODEL] = {
.tag = "[model]",
.parser = parse_model_mode,
},
[LINE_MODE_VERB] = {
.tag = "[verb]",
.alias = "[init_verbs]",
.parser = parse_verb_mode,
},
[LINE_MODE_PINCFG] = {
.tag = "[pincfg]",
.alias = "[user_pin_configs]",
.parser = parse_pincfg_mode,
},
[LINE_MODE_HINT] = {
.tag = "[hint]",
.alias = "[hints]",
.parser = parse_hint_mode
},
[LINE_MODE_VENDOR_ID] = {
.tag = "[vendor_id]",
.parser = parse_vendor_id_mode,
},
[LINE_MODE_SUBSYSTEM_ID] = {
.tag = "[subsystem_id]",
.parser = parse_subsystem_id_mode,
},
[LINE_MODE_REVISION_ID] = {
.tag = "[revision_id]",
.parser = parse_revision_id_mode,
},
[LINE_MODE_CHIP_NAME] = {
.tag = "[chip_name]",
.parser = parse_chip_name_mode,
},
};
/* check the line starting with '[' -- change the parser mode accodingly */
@ -787,6 +817,8 @@ static int parse_line_mode(char *buf, struct hda_bus *bus)
continue;
if (strmatch(buf, patch_items[i].tag))
return i;
if (patch_items[i].alias && strmatch(buf, patch_items[i].alias))
return i;
}
return LINE_MODE_NONE;
}
@ -846,10 +878,10 @@ int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
if (*buf == '[')
line_mode = parse_line_mode(buf, bus);
else if (patch_items[line_mode].parser &&
(codec || !patch_items[line_mode].need_codec))
(codec || line_mode <= LINE_MODE_CODEC))
patch_items[line_mode].parser(buf, bus, &codec);
}
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_load_patch);
EXPORT_SYMBOL_GPL(snd_hda_load_patch);
#endif /* CONFIG_SND_HDA_PATCH_LOADER */

View File

@ -297,9 +297,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define ULI_NUM_CAPTURE 5
#define ULI_NUM_PLAYBACK 6
/* ATI HDMI has 1 playback and 0 capture */
/* ATI HDMI may have up to 8 playbacks and 0 capture */
#define ATIHDMI_NUM_CAPTURE 0
#define ATIHDMI_NUM_PLAYBACK 1
#define ATIHDMI_NUM_PLAYBACK 8
/* TERA has 4 playback and 3 capture */
#define TERA_NUM_CAPTURE 3
@ -431,6 +431,8 @@ struct azx_dev {
struct timecounter azx_tc;
struct cyclecounter azx_cc;
int delay_negative_threshold;
#ifdef CONFIG_SND_HDA_DSP_LOADER
struct mutex dsp_mutex;
#endif
@ -543,9 +545,7 @@ struct azx {
/* for pending irqs */
struct work_struct irq_pending_work;
#ifdef CONFIG_SND_HDA_I915
struct work_struct probe_work;
#endif
/* reboot notifier (for mysterious hangup problem at power-down) */
struct notifier_block reboot_notifier;
@ -2197,6 +2197,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
goto unlock;
}
/* when LPIB delay correction gives a small negative value,
* we ignore it; currently set the threshold statically to
* 64 frames
*/
if (runtime->period_size > 64)
azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64);
else
azx_dev->delay_negative_threshold = 0;
/* wallclk has 24Mhz clock source */
azx_dev->period_wallclk = (((runtime->period_size * 24000) /
runtime->rate) * 1000);
@ -2449,8 +2458,12 @@ static unsigned int azx_get_position(struct azx *chip,
delay = pos - lpib_pos;
else
delay = lpib_pos - pos;
if (delay < 0)
delay += azx_dev->bufsize;
if (delay < 0) {
if (delay >= azx_dev->delay_negative_threshold)
delay = 0;
else
delay += azx_dev->bufsize;
}
if (delay >= azx_dev->period_bytes) {
snd_printk(KERN_WARNING SFX
"%s: Unstable LPIB (%d >= %d); "
@ -3504,12 +3517,10 @@ static void azx_check_snoop_available(struct azx *chip)
}
}
#ifdef CONFIG_SND_HDA_I915
static void azx_probe_work(struct work_struct *work)
{
azx_probe_continue(container_of(work, struct azx, probe_work));
}
#endif
/*
* constructor
@ -3586,10 +3597,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
#ifdef CONFIG_SND_HDA_I915
/* continue probing in work context as may trigger request module */
INIT_WORK(&chip->probe_work, azx_probe_work);
#endif
*rchip = chip;
@ -3809,7 +3818,7 @@ static int azx_probe(struct pci_dev *pci,
static int dev;
struct snd_card *card;
struct azx *chip;
bool probe_now;
bool schedule_probe;
int err;
if (dev >= SNDRV_CARDS)
@ -3848,7 +3857,7 @@ static int azx_probe(struct pci_dev *pci,
chip->disabled = true;
}
probe_now = !chip->disabled;
schedule_probe = !chip->disabled;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
if (patch[dev] && *patch[dev]) {
@ -3859,25 +3868,17 @@ static int azx_probe(struct pci_dev *pci,
azx_firmware_cb);
if (err < 0)
goto out_free;
probe_now = false; /* continued in azx_firmware_cb() */
schedule_probe = false; /* continued in azx_firmware_cb() */
}
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
/* continue probing in work context, avoid request_module deadlock */
if (probe_now && (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)) {
#ifdef CONFIG_SND_HDA_I915
probe_now = false;
schedule_work(&chip->probe_work);
#else
#ifndef CONFIG_SND_HDA_I915
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n");
#endif
}
if (probe_now) {
err = azx_probe_continue(chip);
if (err < 0)
goto out_free;
}
if (schedule_probe)
schedule_work(&chip->probe_work);
dev++;
if (chip->disabled)
@ -3983,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point */
{ PCI_DEVICE(0x8086, 0x8c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@ -4008,6 +4009,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
{ PCI_DEVICE(0x8086, 0x0d0c),
.driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
/* Broadwell */
{ PCI_DEVICE(0x8086, 0x160c),
.driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
/* 5 Series/3400 */
{ PCI_DEVICE(0x8086, 0x3b56),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },

View File

@ -34,7 +34,7 @@ bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
return false;
return true;
}
EXPORT_SYMBOL_HDA(is_jack_detectable);
EXPORT_SYMBOL_GPL(is_jack_detectable);
/* execute pin sense measurement */
static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
@ -71,7 +71,7 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
return jack;
return NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get);
/**
* snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
@ -89,7 +89,7 @@ snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
return jack;
return NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
/**
* snd_hda_jack_tbl_new - create a jack-table entry for the given NID
@ -108,7 +108,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
jack->tag = codec->jacktbl.used;
return jack;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);
EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new);
void snd_hda_jack_tbl_clear(struct hda_codec *codec)
{
@ -172,7 +172,7 @@ void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
if (jack->nid)
jack->jack_dirty = 1;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);
EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
/**
* snd_hda_pin_sense - execute pin sense measurement
@ -191,7 +191,7 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
}
return read_pin_sense(codec, nid);
}
EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
EXPORT_SYMBOL_GPL(snd_hda_pin_sense);
/**
* snd_hda_jack_detect_state - query pin Presence Detect status
@ -211,7 +211,7 @@ int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
else
return HDA_JACK_NOT_PRESENT;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_state);
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state);
/**
* snd_hda_jack_detect_enable - enable the jack-detection
@ -236,14 +236,14 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | jack->tag);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable_callback);
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
unsigned char action)
{
return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
/**
* snd_hda_jack_set_gating_jack - Set gating jack.
@ -264,7 +264,7 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack);
EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
/**
* snd_hda_jack_report_sync - sync the states of all jacks and report if changed
@ -297,7 +297,7 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
#endif
}
}
EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
#ifdef CONFIG_SND_HDA_INPUT_JACK
/* guess the jack type from the pin-config */
@ -377,7 +377,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
{
return __snd_hda_jack_add_kctl(codec, nid, name, idx, false);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl);
/* get the unique index number for the given kctl name */
static int get_unique_index(struct hda_codec *codec, const char *name, int idx)
@ -493,7 +493,7 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
return err;
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
static void call_jack_callback(struct hda_codec *codec,
struct hda_jack_tbl *jack)
@ -521,7 +521,7 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
call_jack_callback(codec, event);
snd_hda_jack_report_sync(codec);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event);
EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event);
void snd_hda_jack_poll_all(struct hda_codec *codec)
{
@ -542,5 +542,5 @@ void snd_hda_jack_poll_all(struct hda_codec *codec)
if (changes)
snd_hda_jack_report_sync(codec);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all);
EXPORT_SYMBOL_GPL(snd_hda_jack_poll_all);

View File

@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
/*
* generic codec parser
*/
#ifdef CONFIG_SND_HDA_GENERIC
int snd_hda_parse_generic_codec(struct hda_codec *codec);
#else
static inline int snd_hda_parse_generic_codec(struct hda_codec *codec)
{
return -ENODEV;
}
#endif
int snd_hda_parse_hdmi_codec(struct hda_codec *codec);
/*
* generic proc interface

View File

@ -185,7 +185,7 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
};
static int ad198x_parse_auto_config(struct hda_codec *codec)
static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp)
{
struct ad198x_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->gen.autocfg;
@ -195,7 +195,8 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->no_sticky_stream = 1;
spec->gen.indep_hp = 1;
spec->gen.indep_hp = indep_hp;
spec->gen.add_stereo_mix_input = 1;
err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
if (err < 0)
@ -280,11 +281,11 @@ static const struct hda_fixup ad1986a_fixups[] = {
.v.pins = (const struct hda_pintbl[]) {
{ 0x1a, 0x02214021 }, /* headphone */
{ 0x1b, 0x01014011 }, /* front */
{ 0x1c, 0x01013012 }, /* surround */
{ 0x1d, 0x01019015 }, /* clfe */
{ 0x1c, 0x01813030 }, /* line-in */
{ 0x1d, 0x01a19020 }, /* rear mic */
{ 0x1e, 0x411111f0 }, /* N/A */
{ 0x1f, 0x02a190f0 }, /* mic */
{ 0x20, 0x018130f0 }, /* line-in */
{ 0x20, 0x411111f0 }, /* N/A */
{}
},
},
@ -378,7 +379,7 @@ static int patch_ad1986a(struct hda_codec *codec)
ad1986a_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, false);
if (err < 0) {
snd_hda_gen_free(codec);
return err;
@ -480,7 +481,7 @@ static int patch_ad1983(struct hda_codec *codec)
spec->gen.beep_nid = 0x10;
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, false);
if (err < 0)
goto error;
err = ad1983_add_spdif_mux_ctl(codec);
@ -567,7 +568,7 @@ static int patch_ad1981(struct hda_codec *codec)
snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, false);
if (err < 0)
goto error;
err = ad1983_add_spdif_mux_ctl(codec);
@ -893,7 +894,7 @@ static int patch_ad1988(struct hda_codec *codec)
snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, true);
if (err < 0)
goto error;
err = ad1988_add_spdif_mux_ctl(codec);
@ -1070,7 +1071,7 @@ static int patch_ad1884(struct hda_codec *codec)
snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, true);
if (err < 0)
goto error;
err = ad1983_add_spdif_mux_ctl(codec);
@ -1112,7 +1113,7 @@ static int patch_ad1882(struct hda_codec *codec)
spec->gen.mixer_merge_nid = 0x21;
spec->gen.beep_nid = 0x10;
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
err = ad198x_parse_auto_config(codec);
err = ad198x_parse_auto_config(codec, true);
if (err < 0)
goto error;
err = ad1988_add_spdif_mux_ctl(codec);

View File

@ -3240,102 +3240,8 @@ enum {
CXT_FIXUP_THINKPAD_ACPI,
};
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
#include <linux/thinkpad_acpi.h>
#include <acpi/acpi.h>
static int (*led_set_func)(int, bool);
static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
void **rv)
{
bool *found = context;
*found = true;
return AE_OK;
}
static bool is_thinkpad(struct hda_codec *codec)
{
bool found = false;
if (codec->subsystem_id >> 16 != 0x17aa)
return false;
if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
return true;
found = false;
return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
}
static void update_tpacpi_mute_led(void *private_data, int enabled)
{
struct hda_codec *codec = private_data;
struct conexant_spec *spec = codec->spec;
if (spec->dynamic_eapd)
cx_auto_vmaster_hook(private_data, enabled);
if (led_set_func)
led_set_func(TPACPI_LED_MUTE, !enabled);
}
static void update_tpacpi_micmute_led(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
{
if (!ucontrol || !led_set_func)
return;
if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
/* TODO: How do I verify if it's a mono or stereo here? */
bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
led_set_func(TPACPI_LED_MICMUTE, !val);
}
}
static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct conexant_spec *spec = codec->spec;
bool removefunc = false;
if (action == HDA_FIXUP_ACT_PROBE) {
if (!is_thinkpad(codec))
return;
if (!led_set_func)
led_set_func = symbol_request(tpacpi_led_set);
if (!led_set_func) {
snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
return;
}
removefunc = true;
if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
removefunc = false;
}
if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
if (spec->gen.num_adc_nids > 1)
snd_printdd("Skipping micmute LED control due to several ADCs");
else {
spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
removefunc = false;
}
}
}
if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
symbol_put(tpacpi_led_set);
led_set_func = NULL;
}
}
#else
static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
}
#endif
/* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c"
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@ -3492,7 +3398,7 @@ static const struct hda_fixup cxt_fixups[] = {
},
[CXT_FIXUP_THINKPAD_ACPI] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_thinkpad_acpi,
.v.func = hda_fixup_thinkpad_acpi,
},
};

View File

@ -46,6 +46,9 @@ module_param(static_hdmi_pcm, bool, 0644);
MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
#define is_haswell(codec) ((codec)->vendor_id == 0x80862807)
#define is_broadwell(codec) ((codec)->vendor_id == 0x80862808)
#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec))
#define is_valleyview(codec) ((codec)->vendor_id == 0x80862882)
struct hdmi_spec_per_cvt {
@ -1101,7 +1104,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
if (!channels)
return;
if (is_haswell(codec))
if (is_haswell_plus(codec))
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_UNMUTE);
@ -1280,7 +1283,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
struct hdmi_spec *spec = codec->spec;
int err;
if (is_haswell(codec))
if (is_haswell_plus(codec))
haswell_verify_D0(codec, cvt_nid, pin_nid);
err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
@ -1421,7 +1424,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
mux_idx);
/* configure unused pins to choose other converters */
if (is_haswell(codec) || is_valleyview(codec))
if (is_haswell_plus(codec) || is_valleyview(codec))
intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx);
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
@ -1496,11 +1499,14 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
* specification worked this way. Hence, we just ignore the data in
* the unsolicited response to avoid custom WARs.
*/
int present = snd_hda_pin_sense(codec, pin_nid);
int present;
bool update_eld = false;
bool eld_changed = false;
bool ret;
snd_hda_power_up(codec);
present = snd_hda_pin_sense(codec, pin_nid);
mutex_lock(&per_pin->lock);
pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
if (pin_eld->monitor_present)
@ -1573,6 +1579,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
jack->block_report = !ret;
mutex_unlock(&per_pin->lock);
snd_hda_power_down(codec);
return ret;
}
@ -1607,7 +1614,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
return 0;
if (is_haswell(codec))
if (is_haswell_plus(codec))
intel_haswell_fixup_connect_list(codec, pin_nid);
pin_idx = spec->num_pins;
@ -1694,21 +1701,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
}
}
#ifdef CONFIG_PM
/* We're seeing some problems with unsolicited hot plug events on
* PantherPoint after S3, if this is not enabled */
if (codec->vendor_id == 0x80862806)
codec->bus->power_keep_link_on = 1;
/*
* G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
* can be lost and presence sense verb will become inaccurate if the
* HDA link is powered off at hot plug or hw initialization time.
*/
else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
AC_PWRST_EPSS))
codec->bus->power_keep_link_on = 1;
#endif
return 0;
}
@ -2260,18 +2252,22 @@ static int patch_generic_hdmi(struct hda_codec *codec)
codec->spec = spec;
hdmi_array_init(spec, 4);
if (is_haswell(codec)) {
if (is_haswell_plus(codec)) {
intel_haswell_enable_all_pins(codec, true);
intel_haswell_fixup_enable_dp12(codec);
}
if (is_haswell(codec) || is_valleyview(codec)) {
codec->depop_delay = 0;
}
if (hdmi_parse_codec(codec) < 0) {
codec->spec = NULL;
kfree(spec);
return -EINVAL;
}
codec->patch_ops = generic_hdmi_patch_ops;
if (is_haswell(codec)) {
if (is_haswell_plus(codec)) {
codec->patch_ops.set_power_state = haswell_set_power_state;
codec->dp_mst = true;
}
@ -3217,6 +3213,15 @@ static int patch_via_hdmi(struct hda_codec *codec)
return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
}
/*
* called from hda_codec.c for generic HDMI support
*/
int snd_hda_parse_hdmi_codec(struct hda_codec *codec)
{
return patch_generic_hdmi(codec);
}
EXPORT_SYMBOL_GPL(snd_hda_parse_hdmi_codec);
/*
* patch entries
*/
@ -3271,6 +3276,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi },
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
@ -3326,6 +3332,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862804");
MODULE_ALIAS("snd-hda-codec-id:80862805");
MODULE_ALIAS("snd-hda-codec-id:80862806");
MODULE_ALIAS("snd-hda-codec-id:80862807");
MODULE_ALIAS("snd-hda-codec-id:80862808");
MODULE_ALIAS("snd-hda-codec-id:80862880");
MODULE_ALIAS("snd-hda-codec-id:80862882");
MODULE_ALIAS("snd-hda-codec-id:808629fb");

View File

@ -118,7 +118,8 @@ struct alc_spec {
int init_amp;
int codec_variant; /* flag for other variants */
bool has_alc5505_dsp;
unsigned int has_alc5505_dsp:1;
unsigned int no_depop_delay:1;
/* for PLL fix */
hda_nid_t pll_nid;
@ -280,8 +281,11 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
*/
static void alc_eapd_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
alc_auto_setup_eapd(codec, false);
msleep(200);
if (!spec->no_depop_delay)
msleep(200);
snd_hda_shutup_pins(codec);
}
@ -365,6 +369,17 @@ static void alc_fixup_sku_ignore(struct hda_codec *codec,
}
}
static void alc_fixup_no_depop_delay(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PROBE) {
spec->no_depop_delay = 1;
codec->depop_delay = 0;
}
}
static int alc_auto_parse_customize_define(struct hda_codec *codec)
{
unsigned int ass, tmp, i;
@ -454,9 +469,7 @@ static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
* 7 ~ 0 : Assembly ID
* port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
*/
static int alc_subsystem_id(struct hda_codec *codec,
hda_nid_t porta, hda_nid_t porte,
hda_nid_t portd, hda_nid_t porti)
static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
{
unsigned int ass, tmp, i;
unsigned nid;
@ -546,14 +559,7 @@ do_sku:
spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
hda_nid_t nid;
tmp = (ass >> 11) & 0x3; /* HP to chassis */
if (tmp == 0)
nid = porta;
else if (tmp == 1)
nid = porte;
else if (tmp == 2)
nid = portd;
else if (tmp == 3)
nid = porti;
nid = ports[tmp];
if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
spec->gen.autocfg.line_outs))
return 1;
@ -566,7 +572,7 @@ do_sku:
* ports contains an array of 4 pin NIDs for port-A, E, D and I */
static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
{
if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
if (!alc_subsystem_id(codec, ports)) {
struct alc_spec *spec = codec->spec;
snd_printd("realtek: "
"Enable default setup for auto mode as fallback\n");
@ -863,7 +869,10 @@ static int alc_suspend(struct hda_codec *codec)
#ifdef CONFIG_PM
static int alc_resume(struct hda_codec *codec)
{
msleep(150); /* to avoid pop noise */
struct alc_spec *spec = codec->spec;
if (!spec->no_depop_delay)
msleep(150); /* to avoid pop noise */
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
@ -903,7 +912,7 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
}
/*
* Rename codecs appropriately from COEF value
* Rename codecs appropriately from COEF value or subvendor id
*/
struct alc_codec_rename_table {
unsigned int vendor_id;
@ -912,6 +921,13 @@ struct alc_codec_rename_table {
const char *name;
};
struct alc_codec_rename_pci_table {
unsigned int codec_vendor_id;
unsigned short pci_subvendor;
unsigned short pci_subdevice;
const char *name;
};
static struct alc_codec_rename_table rename_tbl[] = {
{ 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
{ 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
@ -931,9 +947,20 @@ static struct alc_codec_rename_table rename_tbl[] = {
{ } /* terminator */
};
static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
{ 0x10ec0280, 0x1028, 0, "ALC3220" },
{ 0x10ec0282, 0x1028, 0, "ALC3221" },
{ 0x10ec0283, 0x1028, 0, "ALC3223" },
{ 0x10ec0292, 0x1028, 0, "ALC3226" },
{ 0x10ec0255, 0x1028, 0, "ALC3234" },
{ 0x10ec0668, 0x1028, 0, "ALC3661" },
{ } /* terminator */
};
static int alc_codec_rename_from_preset(struct hda_codec *codec)
{
const struct alc_codec_rename_table *p;
const struct alc_codec_rename_pci_table *q;
for (p = rename_tbl; p->vendor_id; p++) {
if (p->vendor_id != codec->vendor_id)
@ -941,6 +968,17 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
return alc_codec_rename(codec, p->name);
}
for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
if (q->codec_vendor_id != codec->vendor_id)
continue;
if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
continue;
if (!q->pci_subdevice ||
q->pci_subdevice == codec->bus->pci->subsystem_device)
return alc_codec_rename(codec, q->name);
}
return 0;
}
@ -1763,6 +1801,7 @@ enum {
ALC882_FIXUP_ACER_ASPIRE_7736,
ALC882_FIXUP_ASUS_W90V,
ALC889_FIXUP_CD,
ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
ALC889_FIXUP_VAIO_TT,
ALC888_FIXUP_EEE1601,
ALC882_FIXUP_EAPD,
@ -1980,6 +2019,15 @@ static const struct hda_fixup alc882_fixups[] = {
{ }
}
},
[ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
{ }
},
.chained = true,
.chain_id = ALC889_FIXUP_CD,
},
[ALC889_FIXUP_VAIO_TT] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@ -2211,7 +2259,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@ -2314,6 +2362,7 @@ enum {
ALC262_FIXUP_BENQ,
ALC262_FIXUP_BENQ_T31,
ALC262_FIXUP_INV_DMIC,
ALC262_FIXUP_INTEL_BAYLEYBAY,
};
static const struct hda_fixup alc262_fixups[] = {
@ -2378,6 +2427,10 @@ static const struct hda_fixup alc262_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_inv_dmic_0x12,
},
[ALC262_FIXUP_INTEL_BAYLEYBAY] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_no_depop_delay,
},
};
static const struct snd_pci_quirk alc262_fixup_tbl[] = {
@ -2389,6 +2442,7 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
{}
};
@ -3526,6 +3580,15 @@ static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
alc_fixup_headset_mode(codec, fix, action);
}
static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
struct alc_spec *spec = codec->spec;
spec->gen.auto_mute_via_amp = 1;
}
}
static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@ -3717,101 +3780,18 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
static void alc290_fixup_mono_speakers(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE)
/* Remove DAC node 0x03, as it seems to be
giving mono output */
snd_hda_override_wcaps(codec, 0x03, 0);
}
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
#include <linux/thinkpad_acpi.h>
#include <acpi/acpi.h>
static int (*led_set_func)(int, bool);
static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
void **rv)
{
bool *found = context;
*found = true;
return AE_OK;
}
static bool is_thinkpad(struct hda_codec *codec)
{
bool found = false;
if (codec->subsystem_id >> 16 != 0x17aa)
return false;
if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
return true;
found = false;
return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
}
static void update_tpacpi_mute_led(void *private_data, int enabled)
{
if (led_set_func)
led_set_func(TPACPI_LED_MUTE, !enabled);
}
static void update_tpacpi_micmute_led(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
{
if (!ucontrol || !led_set_func)
return;
if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
/* TODO: How do I verify if it's a mono or stereo here? */
bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
led_set_func(TPACPI_LED_MICMUTE, !val);
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
/* DAC node 0x03 is giving mono output. We therefore want to
make sure 0x14 (front speaker) and 0x15 (headphones) use the
stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
hda_nid_t conn1[2] = { 0x0c };
snd_hda_override_conn_list(codec, 0x14, 1, conn1);
snd_hda_override_conn_list(codec, 0x15, 1, conn1);
}
}
static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
bool removefunc = false;
if (action == HDA_FIXUP_ACT_PROBE) {
if (!is_thinkpad(codec))
return;
if (!led_set_func)
led_set_func = symbol_request(tpacpi_led_set);
if (!led_set_func) {
snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
return;
}
removefunc = true;
if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
removefunc = false;
}
if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
if (spec->gen.num_adc_nids > 1)
snd_printdd("Skipping micmute LED control due to several ADCs");
else {
spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
removefunc = false;
}
}
}
if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
symbol_put(tpacpi_led_set);
led_set_func = NULL;
}
}
#else
static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
}
#endif
/* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c"
enum {
ALC269_FIXUP_SONY_VAIO,
@ -3860,6 +3840,9 @@ enum {
ALC282_FIXUP_ASUS_TX300,
ALC283_FIXUP_INT_MIC,
ALC290_FIXUP_MONO_SPEAKERS,
ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
ALC290_FIXUP_SUBWOOFER,
ALC290_FIXUP_SUBWOOFER_HSJACK,
ALC269_FIXUP_THINKPAD_ACPI,
ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC255_FIXUP_HEADSET_MODE,
@ -4182,15 +4165,37 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
},
[ALC290_FIXUP_SUBWOOFER_HSJACK] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x17, 0x90170112 }, /* subwoofer */
{ }
},
.chained = true,
.chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
},
[ALC290_FIXUP_SUBWOOFER] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x17, 0x90170112 }, /* subwoofer */
{ }
},
.chained = true,
.chain_id = ALC290_FIXUP_MONO_SPEAKERS,
},
[ALC290_FIXUP_MONO_SPEAKERS] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc290_fixup_mono_speakers,
},
[ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc290_fixup_mono_speakers,
.chained = true,
.chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
},
[ALC269_FIXUP_THINKPAD_ACPI] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_thinkpad_acpi,
.v.func = hda_fixup_thinkpad_acpi,
},
[ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
@ -4229,6 +4234,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
@ -4247,16 +4253,23 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x060f, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@ -4502,7 +4515,7 @@ static int patch_alc269(struct hda_codec *codec)
}
if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
spec->has_alc5505_dsp = true;
spec->has_alc5505_dsp = 1;
spec->init_hook = alc5505_dsp_init;
}
@ -4841,6 +4854,7 @@ enum {
ALC662_FIXUP_BASS_CHMAP,
ALC662_FIXUP_BASS_1A,
ALC662_FIXUP_BASS_1A_CHMAP,
ALC668_FIXUP_AUTO_MUTE,
};
static const struct hda_fixup alc662_fixups[] = {
@ -5001,6 +5015,12 @@ static const struct hda_fixup alc662_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_inv_dmic_0x12,
},
[ALC668_FIXUP_AUTO_MUTE] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_auto_mute_via_amp,
.chained = true,
.chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
},
[ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@ -5046,11 +5066,12 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE),
SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE),
SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),

View File

@ -368,6 +368,17 @@ static int stac_vrefout_set(struct hda_codec *codec,
return 1;
}
/* prevent codec AFG to D3 state when vref-out pin is used for mute LED */
/* this hook is set in stac_setup_gpio() */
static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state)
{
if (nid == codec->afg && power_state == AC_PWRST_D3)
return AC_PWRST_D1;
return snd_hda_gen_path_power_filter(codec, nid, power_state);
}
/* update mute-LED accoring to the master switch */
static void stac_update_led_status(struct hda_codec *codec, int enabled)
{
@ -4260,30 +4271,8 @@ static int stac_suspend(struct hda_codec *codec)
stac_shutup(codec);
return 0;
}
static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
{
unsigned int afg_power_state = power_state;
struct sigmatel_spec *spec = codec->spec;
if (power_state == AC_PWRST_D3) {
if (spec->vref_mute_led_nid) {
/* with vref-out pin used for mute led control
* codec AFG is prevented from D3 state
*/
afg_power_state = AC_PWRST_D1;
}
/* this delay seems necessary to avoid click noise at power-down */
msleep(100);
}
snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
afg_power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
#else
#define stac_suspend NULL
#define stac_set_power_state NULL
#endif /* CONFIG_PM */
static const struct hda_codec_ops stac_patch_ops = {
@ -4466,8 +4455,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
spec->gpio_dir |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led;
} else {
codec->patch_ops.set_power_state =
stac_set_power_state;
codec->power_filter = stac_vref_led_power_filter;
}
}

View File

@ -138,6 +138,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
spec->gen.indep_hp = 1;
spec->gen.keep_eapd_on = 1;
spec->gen.pcm_playback_hook = via_playback_pcm_hook;
spec->gen.add_stereo_mix_input = 1;
return spec;
}

View File

@ -0,0 +1,99 @@
/* Helper functions for Thinkpad LED control;
* to be included from codec driver
*/
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
#include <linux/acpi.h>
#include <linux/thinkpad_acpi.h>
static int (*led_set_func)(int, bool);
static void (*old_vmaster_hook)(void *, int);
static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
void **rv)
{
bool *found = context;
*found = true;
return AE_OK;
}
static bool is_thinkpad(struct hda_codec *codec)
{
bool found = false;
if (codec->subsystem_id >> 16 != 0x17aa)
return false;
if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
return true;
found = false;
return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
}
static void update_tpacpi_mute_led(void *private_data, int enabled)
{
if (old_vmaster_hook)
old_vmaster_hook(private_data, enabled);
if (led_set_func)
led_set_func(TPACPI_LED_MUTE, !enabled);
}
static void update_tpacpi_micmute_led(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
{
if (!ucontrol || !led_set_func)
return;
if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
/* TODO: How do I verify if it's a mono or stereo here? */
bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
led_set_func(TPACPI_LED_MICMUTE, !val);
}
}
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct hda_gen_spec *spec = codec->spec;
bool removefunc = false;
if (action == HDA_FIXUP_ACT_PROBE) {
if (!is_thinkpad(codec))
return;
if (!led_set_func)
led_set_func = symbol_request(tpacpi_led_set);
if (!led_set_func) {
snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
return;
}
removefunc = true;
if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
old_vmaster_hook = spec->vmaster_mute.hook;
spec->vmaster_mute.hook = update_tpacpi_mute_led;
removefunc = false;
}
if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
if (spec->num_adc_nids > 1)
snd_printdd("Skipping micmute LED control due to several ADCs");
else {
spec->cap_sync_hook = update_tpacpi_micmute_led;
removefunc = false;
}
}
}
if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
symbol_put(tpacpi_led_set);
led_set_func = NULL;
old_vmaster_hook = NULL;
}
}
#else /* CONFIG_THINKPAD_ACPI */
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
}
#endif /* CONFIG_THINKPAD_ACPI */

View File

@ -584,10 +584,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
{
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
dmab->dev.dev = snd_dma_pci_data(pci);
if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
if (dmab->bytes >= size)
return 0;
}
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, dmab) < 0)
return -ENOMEM;
@ -596,10 +592,8 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
if (dmab->area) {
dmab->dev.dev = NULL; /* make it anonymous */
snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
}
if (dmab->area)
snd_dma_free_pages(dmab);
}

Some files were not shown because too many files have changed in this diff Show More