sound updates for 3.17-rc1
There've been many updates in ASoC side at this time, especially the framework enhancement for multiple CODECs on a single DAI and more componentization works. The only major change in ALSA core is the addition of timestamp type in sw_params field. This should behave in backward compatible way. Other than that, there are lots of small changes and new drivers in wide range, including a large code cut in HD-audio driver for deprecated static quirks. Some highlights are below: ALSA Core: - Add the new timestamp type field to sw_params to choose MONOTONIC_RAW type HD-audio: - Continued conversion to standard printk macros, generic code cleanups - Removal of obsoleted static quirk codes for Conexant and C-Media codecs - Fixups for HP Envy TS, Dell XPS 15, HP and Dell mute/mic LED, Gigabyte BXBT-2807 mobo - Intel Braswell support ASoC: - Support for multiple CODECs attached to a single DAI, enabling systems with for example multiple DAC/speaker drivers on a single link, contributed by Benoit Cousson based on work from Misael Lopez Cruz - Support for byte controls larger than 256 bytes based on the use of TLVs contributed by Omair Mohammed Abdullah - More componentisation work from Lars-Peter Clausen - The remainder of the conversions of CODEC drivers to params_width() by Mark Brown - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments TAS2552 - Lots of updates and fixes, especially to the DaVinci, Intel, Freescale, Realtek, and rcar drivers -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJT4fj0AAoJEGwxgFQ9KSmkXQ0QAIiRmVg40aiJoEdOLGgzNZtq r/nXj69AuB6JSy0hKbFyyijjCcRpyCCGvjDYlogjT75M3c35Npz/m85oZHx2tajD SB5OA+QxO4EQ3C0GjITIRHJROm4MM8/rnbnNYTsWnEGRkobTFTl0rHbSkA85RGFt 0zZqqs1R0s/nO9PMQ+5PA5x9xVFiZs2COeCK0CFA9s2ACf/hbxJBRIqYpIFWOo78 9L41jBOFuC/hIb4qwjgmsCWbKe1KQysTAf+Wty0CKipJ6VhfCbPn1Qn1zXGeUOxc mj4eZ6LpJTrVMr/UN02c5vgPOiaBrQ7fWZo3dVHLlIjC6cEI1tUvNYAin7CMEzx8 DUsvo9p30OheA+ijc9wKaYFY6YmmJZRtpnnMd39i0oPG+bhvoV7vjXjJSB1sLJt1 o82xLpVL4Th8H+DMDVwA7UIBvvZGZBusw1qsNGfcOPrmExi4ScGhA0gSOO6W2y1z VQLRbiXB/HtJGxeqWL6RqJOcLBOlJNmsk4UZMOSCu2OZrWd5I8MuRrNWeHDqhX1H +VDEJVhFmM21vMpnobzEPxWsMgTVIAVf3Thh+WgaPxL4Krh0vkpZsgZk16VVmy/o OJJF3n41FND4n9zSjOe4MkuL8UCOUpKCaBdqj9K1s6UKwOEKuDNslyT/zqutRWK5 x1uApU5y+E4iQT/b7cmA =RL72 -----END PGP SIGNATURE----- Merge tag 'sound-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "There've been many updates in ASoC side at this time, especially the framework enhancement for multiple CODECs on a single DAI and more componentization works. The only major change in ALSA core is the addition of timestamp type in sw_params field. This should behave in backward compatible way. Other than that, there are lots of small changes and new drivers in wide range, including a large code cut in HD-audio driver for deprecated static quirks. Some highlights are below: ALSA Core: - Add the new timestamp type field to sw_params to choose MONOTONIC_RAW type HD-audio: - Continued conversion to standard printk macros, generic code cleanups - Removal of obsoleted static quirk codes for Conexant and C-Media codecs - Fixups for HP Envy TS, Dell XPS 15, HP and Dell mute/mic LED, Gigabyte BXBT-2807 mobo - Intel Braswell support ASoC: - Support for multiple CODECs attached to a single DAI, enabling systems with for example multiple DAC/speaker drivers on a single link, contributed by Benoit Cousson based on work from Misael Lopez Cruz - Support for byte controls larger than 256 bytes based on the use of TLVs contributed by Omair Mohammed Abdullah - More componentisation work from Lars-Peter Clausen - The remainder of the conversions of CODEC drivers to params_width() by Mark Brown - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments TAS2552 - Lots of updates and fixes, especially to the DaVinci, Intel, Freescale, Realtek, and rcar drivers" * tag 'sound-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (402 commits) ALSA: usb-audio: Whitespace cleanups for sound/usb/midi.* ALSA: usb-audio: Respond to suspend and resume callbacks for MIDI input sound/oss/pss: Remove typedefs pss_mixerdata and pss_confdata sound/oss/opl3: Remove typedef opl_devinfo ALSA: fireworks: fix specifiers in format strings for propper output ASoC: imx-audmux: Use uintptr_t for port numbers ASoC: davinci: Enable menuconfig entry for McASP ASoC: fsl_asrc: Don't access members of config before checking it ASoC: fsl_sarc_dma: Check pair before using it ASoC: adau1977: Fix truncation warning on 64 bit architectures ALSA: virtuoso: add Xonar Essence STX II support ALSA: riptide: fix %d confusingly prefixed with 0x in format strings ALSA: fireworks: fix %d confusingly prefixed with 0x in format strings ALSA: hda - add codec ID for Braswell display audio codec ALSA: hda - add PCI IDs for Intel Braswell ALSA: usb-audio: Adjust Gamecom 780 volume level ALSA: usb-audio: improve dmesg source grepability ASoC: rt5670: Fix duplicate const warnings ASoC: rt5670: Staticise non-exported symbols ASoC: Intel: update stream only on stream IPC msgs ...
This commit is contained in:
Коммит
930e0312bc
|
@ -10,10 +10,14 @@ Optional properties:
|
|||
|
||||
- reset-gpio : a GPIO spec for the reset/power down pin.
|
||||
If specified, it will be deasserted at probe time.
|
||||
- va-supply : a regulator spec, providing 5.0V
|
||||
- vd-supply : a regulator spec, providing 3.3V
|
||||
|
||||
Example:
|
||||
|
||||
spdif: ak5386@0 {
|
||||
compatible = "asahi-kasei,ak5386";
|
||||
reset-gpio = <&gpio0 23>;
|
||||
va-supply = <&vdd_5v0_reg>;
|
||||
vd-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
CS4265 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "cirrus,cs4265"
|
||||
|
||||
- reg : the I2C address of the device for I2C. The I2C address depends on
|
||||
the state of the AD0 pin. If AD0 is high, the i2c address is 0x4f.
|
||||
If it is low, the i2c address is 0x4e.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
|
||||
deasserted before communication to the codec starts.
|
||||
|
||||
Examples:
|
||||
|
||||
codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
|
||||
compatible = "cirrus,cs4265";
|
||||
reg = <0x4f>;
|
||||
};
|
||||
|
||||
|
||||
codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
|
||||
compatible = "cirrus,cs4265";
|
||||
reg = <0x4e>;
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
Freescale Asynchronous Sample Rate Converter (ASRC) Controller
|
||||
|
||||
The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
|
||||
signal associated with an input clock into a signal associated with a different
|
||||
output clock. The driver currently works as a Front End of DPCM with other Back
|
||||
Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
|
||||
three substreams within totally 10 channels.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
|
||||
|
||||
- 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 : Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Contains the following entries
|
||||
"mem" Peripheral access clock to access registers.
|
||||
"ipg" Peripheral clock to driver module.
|
||||
"asrck_<0-f>" Clock sources for input and output clock.
|
||||
|
||||
- big-endian : If this property is absent, the little endian mode
|
||||
will be in use as default. Otherwise, the big endian
|
||||
mode will be in use for all the device registers.
|
||||
|
||||
- fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
|
||||
|
||||
- fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
|
||||
|
||||
Example:
|
||||
|
||||
asrc: asrc@02034000 {
|
||||
compatible = "fsl,imx53-asrc";
|
||||
reg = <0x02034000 0x4000>;
|
||||
interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks 107>, <&clks 107>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
|
||||
<&clks 107>, <&clks 0>, <&clks 0>;
|
||||
clock-names = "mem", "ipg", "asrck0",
|
||||
"asrck_1", "asrck_2", "asrck_3", "asrck_4",
|
||||
"asrck_5", "asrck_6", "asrck_7", "asrck_8",
|
||||
"asrck_9", "asrck_a", "asrck_b", "asrck_c",
|
||||
"asrck_d", "asrck_e", "asrck_f";
|
||||
dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
|
||||
<&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
|
||||
dma-names = "rxa", "rxb", "rxc",
|
||||
"txa", "txb", "txc";
|
||||
fsl,asrc-rate = <48000>;
|
||||
fsl,asrc-width = <16>;
|
||||
status = "okay";
|
||||
};
|
|
@ -4,7 +4,7 @@ This device supports I2C only.
|
|||
|
||||
Required properties:
|
||||
|
||||
- compatible : "maxim,max98090".
|
||||
- compatible : "maxim,max98090" or "maxim,max98091".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ Required properties:
|
|||
- rcar_sound,src : Should contain SRC feature.
|
||||
The number of SRC subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,dvc : Should contain DVC feature.
|
||||
The number of DVC subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,dai : DAI contents.
|
||||
The number of DAI subnode should be same as HW.
|
||||
see below for detail.
|
||||
|
@ -21,6 +24,7 @@ SSI subnode properties:
|
|||
- interrupts : Should contain SSI interrupt for PIO transfer
|
||||
- shared-pin : if shared clock pin
|
||||
- pio-transfer : use PIO transfer mode
|
||||
- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
|
||||
|
||||
SRC subnode properties:
|
||||
no properties at this point
|
||||
|
@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
|
|||
<0 0xec540000 0 0x1000>, /* SSIU */
|
||||
<0 0xec541000 0 0x1280>; /* SSI */
|
||||
|
||||
rcar_sound,dvc {
|
||||
dvc0: dvc@0 { };
|
||||
dvc1: dvc@1 { };
|
||||
};
|
||||
|
||||
rcar_sound,src {
|
||||
src0: src@0 { };
|
||||
src1: src@1 { };
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
* Rockchip I2S controller
|
||||
|
||||
The I2S bus (Inter-IC sound bus) is a serial link for digital
|
||||
audio data transfer between devices in the system.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the followings
|
||||
- "rockchip,rk3066-i2s": for rk3066
|
||||
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
|
||||
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the I2S interrupt.
|
||||
- #address-cells: should be 1.
|
||||
- #size-cells: should be 0.
|
||||
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
|
||||
Documentation/devicetree/bindings/dma/dma.txt
|
||||
- dma-names: should include "tx" and "rx".
|
||||
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
|
||||
- clock-names: should contain followings:
|
||||
- "i2s_hclk": clock for I2S BUS
|
||||
- "i2s_clk" : clock for I2S controller
|
||||
|
||||
Example for rk3288 I2S controller:
|
||||
|
||||
i2s@ff890000 {
|
||||
compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
|
||||
reg = <0xff890000 0x10000>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dmas = <&pdma1 0>, <&pdma1 1>;
|
||||
dma-names = "rx", "tx";
|
||||
clock-names = "i2s_hclk", "i2s_clk";
|
||||
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
|
||||
|
||||
Required properties:
|
||||
- compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
|
||||
"samsung,odroidu3-audio" - for Odroid U3 board
|
||||
- samsung,model : the user-visible name of this sound complex
|
||||
- samsung,i2s-controller : the phandle of the I2S controller
|
||||
- samsung,audio-codec : the phandle of the MAX98090 audio codec
|
||||
- samsung,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
|
||||
For Odroid X2:
|
||||
* Headphone Jack
|
||||
* Mic Jack
|
||||
* DMIC
|
||||
|
||||
For Odroid U3:
|
||||
* Headphone Jack
|
||||
* Speakers
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "samsung,odroidu3-audio";
|
||||
samsung,i2s-controller = <&i2s0>;
|
||||
samsung,audio-codec = <&max98090>;
|
||||
samsung,model = "Odroid-X2";
|
||||
samsung,audio-routing =
|
||||
"Headphone Jack", "HPL",
|
||||
"Headphone Jack", "HPR",
|
||||
"IN1", "Mic Jack",
|
||||
"Mic Jack", "MICBIAS";
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
* SiRF SoC USP module
|
||||
|
||||
Required properties:
|
||||
- compatible: "sirf,prima2-usp-pcm"
|
||||
- reg: Base address and size entries:
|
||||
- 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").
|
||||
|
||||
- clocks: USP controller clock source
|
||||
- pinctrl-names: Must contain a "default" entry.
|
||||
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
||||
|
||||
Example:
|
||||
usp0: usp@b0080000 {
|
||||
compatible = "sirf,prima2-usp-pcm";
|
||||
reg = <0xb0080000 0x10000>;
|
||||
clocks = <&clks 28>;
|
||||
dmas = <&dmac1 1>, <&dmac1 2>;
|
||||
dma-names = "rx", "tx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usp0_only_utfs_pins_a>;
|
||||
};
|
||||
|
|
@ -3,15 +3,20 @@ Audio Binding for Snow boards
|
|||
Required properties:
|
||||
- compatible : Can be one of the following,
|
||||
"google,snow-audio-max98090" or
|
||||
"google,snow-audio-max98091" or
|
||||
"google,snow-audio-max98095"
|
||||
- samsung,i2s-controller: The phandle of the Samsung I2S controller
|
||||
- samsung,audio-codec: The phandle of the audio codec
|
||||
|
||||
Optional:
|
||||
- samsung,model: The name of the sound-card
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "google,snow-audio-max98095";
|
||||
|
||||
samsung,model = "Snow-I2S-MAX98095";
|
||||
samsung,i2s-controller = <&i2s0>;
|
||||
samsung,audio-codec = <&max98095>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
Texas Instruments - tas2552 Codec module
|
||||
|
||||
The tas2552 serial control bus communicates through I2C protocols
|
||||
|
||||
Required properties:
|
||||
- compatible - One of:
|
||||
"ti,tas2552" - TAS2552
|
||||
- reg - I2C slave address
|
||||
- supply-*: Required supply regulators are:
|
||||
"vbat" battery voltage
|
||||
"iovdd" I/O Voltage
|
||||
"avdd" Analog DAC Voltage
|
||||
|
||||
Optional properties:
|
||||
- enable-gpio - gpio pin to enable/disable the device
|
||||
|
||||
Example:
|
||||
|
||||
tas2552: tas2552@41 {
|
||||
compatible = "ti,tas2552";
|
||||
reg = <0x41>;
|
||||
enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
For more product information please see the link below:
|
||||
http://www.ti.com/product/TAS2552
|
|
@ -31,6 +31,9 @@ Optional properties:
|
|||
|
||||
Most systems should not set any of these properties.
|
||||
|
||||
- avdd-supply: Power supply for AVDD, providing 3.3V
|
||||
- dvdd-supply: Power supply for DVDD, providing 3.3V
|
||||
|
||||
Examples:
|
||||
|
||||
i2c_bus {
|
||||
|
@ -39,5 +42,7 @@ Examples:
|
|||
reg = <0x1b>;
|
||||
reset-gpio = <&gpio 23 0>;
|
||||
ti,charge-period = <156000>;
|
||||
avdd-supply = <&vdd_3v3_reg>;
|
||||
dvdd-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
WM8904 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
- compatible: "wlf,wm8904"
|
||||
- reg: the I2C address of the device.
|
||||
- clock-names: "mclk"
|
||||
- clocks: reference to
|
||||
<Documentation/devicetree/bindings/clock/clock-bindings.txt>
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1L
|
||||
* IN1R
|
||||
* IN2L
|
||||
* IN2R
|
||||
* IN3L
|
||||
* IN3R
|
||||
* HPOUTL
|
||||
* HPOUTR
|
||||
* LINEOUTL
|
||||
* LINEOUTR
|
||||
* MICBIAS
|
||||
|
||||
Examples:
|
||||
|
||||
codec: wm8904@1a {
|
||||
compatible = "wlf,wm8904";
|
||||
reg = <0x1a>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "mclk";
|
||||
};
|
|
@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
-------------------
|
||||
|
||||
Module for sound cards based on the Asus AV66/AV100/AV200 chips,
|
||||
i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
|
||||
HDAV1.3 (Deluxe), and HDAV1.3 Slim.
|
||||
i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
|
||||
Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
|
||||
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
|
|
|
@ -284,6 +284,11 @@ STAC92HD83*
|
|||
hp-zephyr HP Zephyr
|
||||
hp-led HP with broken BIOS for mute LED
|
||||
hp-inv-led HP with broken BIOS for inverted mute LED
|
||||
hp-mic-led HP with mic-mute LED
|
||||
headset-jack Dell Latitude with a 4-pin headset jack
|
||||
hp-envy-bass Pin fixup for HP Envy bass speaker (NID 0x0f)
|
||||
hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
|
||||
hp-bnb13-eq Hardware equalizer setup for HP laptops
|
||||
auto BIOS setup (default)
|
||||
|
||||
STAC92HD95
|
||||
|
|
|
@ -7526,6 +7526,13 @@ F: drivers/rtc/
|
|||
F: include/linux/rtc.h
|
||||
F: include/uapi/linux/rtc.h
|
||||
|
||||
REALTEK AUDIO CODECS
|
||||
M: Bard Liao <bardliao@realtek.com>
|
||||
M: Oder Chiou <oder_chiou@realtek.com>
|
||||
S: Maintained
|
||||
F: sound/soc/codecs/rt*
|
||||
F: include/sound/rt*.h
|
||||
|
||||
REISERFS FILE SYSTEM
|
||||
L: reiserfs-devel@vger.kernel.org
|
||||
S: Supported
|
||||
|
|
|
@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
|
|||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &fsi_wm8978_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
|
|||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &fsi2_hdmi_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi2_ak4648_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
|
|||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &fsi2_hdmi_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi2_ak4643_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
|
|||
.name = "asoc-simple-card",
|
||||
.dev = {
|
||||
.platform_data = &fsi_da7210_info,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* platform_sst_audio.h: sst audio platform data header file
|
||||
*
|
||||
* Copyright (C) 2012-14 Intel Corporation
|
||||
* Author: Jeeja KP <jeeja.kp@intel.com>
|
||||
* Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
|
||||
* Vinod Koul ,vinod.koul@intel.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; version 2
|
||||
* of the License.
|
||||
*/
|
||||
#ifndef _PLATFORM_SST_AUDIO_H_
|
||||
#define _PLATFORM_SST_AUDIO_H_
|
||||
|
||||
#include <linux/sfi.h>
|
||||
|
||||
enum sst_audio_task_id_mrfld {
|
||||
SST_TASK_ID_NONE = 0,
|
||||
SST_TASK_ID_SBA = 1,
|
||||
SST_TASK_ID_MEDIA = 3,
|
||||
SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
|
||||
};
|
||||
|
||||
/* Device IDs for Merrifield are Pipe IDs,
|
||||
* ref: DSP spec v0.75 */
|
||||
enum sst_audio_device_id_mrfld {
|
||||
/* Output pipeline IDs */
|
||||
PIPE_ID_OUT_START = 0x0,
|
||||
PIPE_CODEC_OUT0 = 0x2,
|
||||
PIPE_CODEC_OUT1 = 0x3,
|
||||
PIPE_SPROT_LOOP_OUT = 0x4,
|
||||
PIPE_MEDIA_LOOP1_OUT = 0x5,
|
||||
PIPE_MEDIA_LOOP2_OUT = 0x6,
|
||||
PIPE_VOIP_OUT = 0xC,
|
||||
PIPE_PCM0_OUT = 0xD,
|
||||
PIPE_PCM1_OUT = 0xE,
|
||||
PIPE_PCM2_OUT = 0xF,
|
||||
PIPE_MEDIA0_OUT = 0x12,
|
||||
PIPE_MEDIA1_OUT = 0x13,
|
||||
/* Input Pipeline IDs */
|
||||
PIPE_ID_IN_START = 0x80,
|
||||
PIPE_CODEC_IN0 = 0x82,
|
||||
PIPE_CODEC_IN1 = 0x83,
|
||||
PIPE_SPROT_LOOP_IN = 0x84,
|
||||
PIPE_MEDIA_LOOP1_IN = 0x85,
|
||||
PIPE_MEDIA_LOOP2_IN = 0x86,
|
||||
PIPE_VOIP_IN = 0x8C,
|
||||
PIPE_PCM0_IN = 0x8D,
|
||||
PIPE_PCM1_IN = 0x8E,
|
||||
PIPE_MEDIA0_IN = 0x8F,
|
||||
PIPE_MEDIA1_IN = 0x90,
|
||||
PIPE_MEDIA2_IN = 0x91,
|
||||
PIPE_RSVD = 0xFF,
|
||||
};
|
||||
|
||||
/* The stream map for each platform consists of an array of the below
|
||||
* stream map structure.
|
||||
*/
|
||||
struct sst_dev_stream_map {
|
||||
u8 dev_num; /* device id */
|
||||
u8 subdev_num; /* substream */
|
||||
u8 direction;
|
||||
u8 device_id; /* fw id */
|
||||
u8 task_id; /* fw task */
|
||||
u8 status;
|
||||
};
|
||||
|
||||
struct sst_platform_data {
|
||||
/* Intel software platform id*/
|
||||
struct sst_dev_stream_map *pdev_strm_map;
|
||||
unsigned int strm_map_size;
|
||||
};
|
||||
|
||||
int add_sst_platform_device(void);
|
||||
#endif
|
||||
|
|
@ -982,6 +982,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
|
|||
|
||||
#define EDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
|
||||
|
||||
static int edma_dma_device_slave_caps(struct dma_chan *dchan,
|
||||
|
|
|
@ -83,16 +83,26 @@ EXPORT_SYMBOL(ssc_free);
|
|||
|
||||
static struct atmel_ssc_platform_data at91rm9200_config = {
|
||||
.use_dma = 0,
|
||||
.has_fslen_ext = 0,
|
||||
};
|
||||
|
||||
static struct atmel_ssc_platform_data at91sam9rl_config = {
|
||||
.use_dma = 0,
|
||||
.has_fslen_ext = 1,
|
||||
};
|
||||
|
||||
static struct atmel_ssc_platform_data at91sam9g45_config = {
|
||||
.use_dma = 1,
|
||||
.has_fslen_ext = 1,
|
||||
};
|
||||
|
||||
static const struct platform_device_id atmel_ssc_devtypes[] = {
|
||||
{
|
||||
.name = "at91rm9200_ssc",
|
||||
.driver_data = (unsigned long) &at91rm9200_config,
|
||||
}, {
|
||||
.name = "at91sam9rl_ssc",
|
||||
.driver_data = (unsigned long) &at91sam9rl_config,
|
||||
}, {
|
||||
.name = "at91sam9g45_ssc",
|
||||
.driver_data = (unsigned long) &at91sam9g45_config,
|
||||
|
@ -106,6 +116,9 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
|
|||
{
|
||||
.compatible = "atmel,at91rm9200-ssc",
|
||||
.data = &at91rm9200_config,
|
||||
}, {
|
||||
.compatible = "atmel,at91sam9rl-ssc",
|
||||
.data = &at91sam9rl_config,
|
||||
}, {
|
||||
.compatible = "atmel,at91sam9g45-ssc",
|
||||
.data = &at91sam9g45_config,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
struct atmel_ssc_platform_data {
|
||||
int use_dma;
|
||||
int has_fslen_ext;
|
||||
};
|
||||
|
||||
struct ssc_device {
|
||||
|
@ -71,6 +72,12 @@ void ssc_free(struct ssc_device *ssc);
|
|||
#define SSC_RFMR_DATNB_OFFSET 8
|
||||
#define SSC_RFMR_FSEDGE_SIZE 1
|
||||
#define SSC_RFMR_FSEDGE_OFFSET 24
|
||||
/*
|
||||
* The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
|
||||
* at91sam9g20, and at91sam9g45 and newer SoCs
|
||||
*/
|
||||
#define SSC_RFMR_FSLEN_EXT_SIZE 4
|
||||
#define SSC_RFMR_FSLEN_EXT_OFFSET 28
|
||||
#define SSC_RFMR_FSLEN_SIZE 4
|
||||
#define SSC_RFMR_FSLEN_OFFSET 16
|
||||
#define SSC_RFMR_FSOS_SIZE 4
|
||||
|
@ -109,6 +116,12 @@ void ssc_free(struct ssc_device *ssc);
|
|||
#define SSC_TFMR_FSDEN_OFFSET 23
|
||||
#define SSC_TFMR_FSEDGE_SIZE 1
|
||||
#define SSC_TFMR_FSEDGE_OFFSET 24
|
||||
/*
|
||||
* The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
|
||||
* at91sam9g20, and at91sam9g45 and newer SoCs
|
||||
*/
|
||||
#define SSC_TFMR_FSLEN_EXT_SIZE 4
|
||||
#define SSC_TFMR_FSLEN_EXT_OFFSET 28
|
||||
#define SSC_TFMR_FSLEN_SIZE 4
|
||||
#define SSC_TFMR_FSLEN_OFFSET 16
|
||||
#define SSC_TFMR_FSOS_SIZE 3
|
||||
|
|
|
@ -299,6 +299,7 @@ enum dma_slave_buswidth {
|
|||
DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
|
||||
DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
|
||||
DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
|
||||
DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
|
||||
DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
|
||||
DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
|
||||
};
|
||||
|
|
|
@ -110,6 +110,12 @@ struct arizona {
|
|||
int clk32k_ref;
|
||||
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
int tdm_width[ARIZONA_MAX_AIF];
|
||||
int tdm_slots[ARIZONA_MAX_AIF];
|
||||
|
||||
uint16_t dac_comp_coeff;
|
||||
uint8_t dac_comp_enabled;
|
||||
};
|
||||
|
||||
int arizona_clk32k_enable(struct arizona *arizona);
|
||||
|
|
|
@ -15,15 +15,6 @@
|
|||
#define S3C64XX_AC97_GPE 1
|
||||
extern void s3c64xx_ac97_setup_gpio(int);
|
||||
|
||||
/*
|
||||
* The machine init code calls s5p*_spdif_setup_gpio with
|
||||
* one of these defines in order to select appropriate bank
|
||||
* of GPIO for S/PDIF pins
|
||||
*/
|
||||
#define S5PC100_SPDIF_GPD 0
|
||||
#define S5PC100_SPDIF_GPG3 1
|
||||
extern void s5pc100_spdif_setup_gpio(int);
|
||||
|
||||
struct samsung_i2s {
|
||||
/* If the Primary DAI has 5.1 Channels */
|
||||
#define QUIRK_PRI_6CHAN (1 << 0)
|
||||
|
|
|
@ -50,6 +50,7 @@ enum imx_dma_prio {
|
|||
|
||||
struct imx_dma_data {
|
||||
int dma_request; /* DMA request line */
|
||||
int dma_request2; /* secondary DMA request line */
|
||||
enum sdma_peripheral_type peripheral_type;
|
||||
int priority;
|
||||
};
|
||||
|
|
|
@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct
|
|||
typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
|
||||
typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
|
||||
typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
|
||||
int op_flag, /* 0=read,1=write,-1=command */
|
||||
int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
|
||||
unsigned int size,
|
||||
unsigned int __user *tlv);
|
||||
|
||||
enum {
|
||||
SNDRV_CTL_TLV_OP_READ = 0,
|
||||
SNDRV_CTL_TLV_OP_WRITE = 1,
|
||||
SNDRV_CTL_TLV_OP_CMD = -1,
|
||||
};
|
||||
|
||||
struct snd_kcontrol_new {
|
||||
snd_ctl_elem_iface_t iface; /* interface identifier */
|
||||
|
|
|
@ -931,10 +931,17 @@ void snd_pcm_timer_done(struct snd_pcm_substream *substream);
|
|||
static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
|
||||
struct timespec *tv)
|
||||
{
|
||||
if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
|
||||
switch (runtime->tstamp_type) {
|
||||
case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
|
||||
ktime_get_ts(tv);
|
||||
else
|
||||
break;
|
||||
case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
|
||||
getrawmonotonic(tv);
|
||||
break;
|
||||
default:
|
||||
getnstimeofday(tv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
* B : SSI direction
|
||||
*/
|
||||
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
|
||||
#define RSND_SSI_NO_BUSIF (1 << 30) /* SSI+DMA without BUSIF */
|
||||
|
||||
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
|
||||
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* linux/sound/rt286.h -- Platform data for RT286
|
||||
*
|
||||
* Copyright 2013 Realtek Microelectronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_RT286_H
|
||||
#define __LINUX_SND_RT286_H
|
||||
|
||||
struct rt286_platform_data {
|
||||
bool cbj_en; /*combo jack enable*/
|
||||
bool gpio2_en; /*GPIO2 enable*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* linux/sound/rt5670.h -- Platform data for RT5670
|
||||
*
|
||||
* Copyright 2014 Realtek Microelectronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_SND_RT5670_H
|
||||
#define __LINUX_SND_RT5670_H
|
||||
|
||||
struct rt5670_platform_data {
|
||||
int jd_mode;
|
||||
bool in2_diff;
|
||||
|
||||
bool dmic_en;
|
||||
unsigned int dmic1_data_pin;
|
||||
/* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/
|
||||
unsigned int dmic2_data_pin;
|
||||
/* 0 = GPIO8; 1 = IN3N; */
|
||||
unsigned int dmic3_data_pin;
|
||||
/* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -257,7 +257,6 @@ struct snd_soc_dai {
|
|||
|
||||
struct snd_soc_dapm_widget *playback_widget;
|
||||
struct snd_soc_dapm_widget *capture_widget;
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
/* DAI DMA data */
|
||||
void *playback_dma_data;
|
||||
|
@ -273,6 +272,10 @@ struct snd_soc_dai {
|
|||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_component *component;
|
||||
|
||||
/* CODEC TDM slot masks and params (for fixup) */
|
||||
unsigned int tx_mask;
|
||||
unsigned int rx_mask;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
|
||||
struct list_head list;
|
||||
|
|
|
@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|||
const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
||||
|
@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
|||
struct snd_soc_dapm_widget_list **list);
|
||||
|
||||
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
|
@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
|
|||
const char *name; /* widget name */
|
||||
const char *sname; /* stream name */
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_platform *platform;
|
||||
struct list_head list;
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
|
@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
|
|||
struct device *dev; /* from parent - for debug */
|
||||
struct snd_soc_component *component; /* parent component */
|
||||
struct snd_soc_codec *codec; /* parent codec */
|
||||
struct snd_soc_platform *platform; /* parent platform */
|
||||
struct snd_soc_card *card; /* parent card */
|
||||
|
||||
/* used during DAPM updates */
|
||||
|
@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
|
|||
struct list_head list;
|
||||
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dapm;
|
||||
|
|
|
@ -248,6 +248,8 @@
|
|||
.info = snd_soc_info_enum_double, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
#define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
|
||||
SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put)
|
||||
|
||||
#define SND_SOC_BYTES(xname, xbase, xregs) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
|
@ -270,7 +272,14 @@
|
|||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&(struct soc_bytes_ext) \
|
||||
{.max = xcount} }
|
||||
|
||||
#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
|
||||
.tlv.c = (snd_soc_bytes_tlv_callback), \
|
||||
.info = snd_soc_info_bytes_ext, \
|
||||
.private_value = (unsigned long)&(struct soc_bytes_ext) \
|
||||
{.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
|
||||
#define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
|
||||
xmin, xmax, xinvert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
|
@ -436,6 +445,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
|
|||
int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_platform *platform);
|
||||
|
||||
int soc_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
|
||||
/* Jack reporting */
|
||||
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
||||
struct snd_soc_jack *jack);
|
||||
|
@ -503,10 +516,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
|
|||
const char *prefix);
|
||||
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
||||
const char *name);
|
||||
int snd_soc_add_component_controls(struct snd_soc_component *component,
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
|
||||
|
@ -552,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *ucontrol);
|
||||
int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
|
||||
unsigned int size, unsigned int __user *tlv);
|
||||
int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
|
||||
|
@ -677,12 +694,17 @@ struct snd_soc_component_driver {
|
|||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
|
||||
int subseq);
|
||||
int (*stream_event)(struct snd_soc_component *, int event);
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const char *name_prefix;
|
||||
struct device *dev;
|
||||
struct snd_soc_card *card;
|
||||
|
||||
unsigned int active;
|
||||
|
||||
|
@ -705,18 +727,18 @@ struct snd_soc_component {
|
|||
int val_bytes;
|
||||
|
||||
struct mutex io_mutex;
|
||||
|
||||
/* Don't use these, use snd_soc_component_get_dapm() */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_context *dapm_ptr;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
const char *name;
|
||||
const char *name_prefix;
|
||||
int id;
|
||||
struct device *dev;
|
||||
const struct snd_soc_codec_driver *driver;
|
||||
|
||||
struct mutex mutex;
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
|
@ -790,9 +812,6 @@ struct snd_soc_codec_driver {
|
|||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
/* codec stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
|
@ -834,9 +853,6 @@ struct snd_soc_platform_driver {
|
|||
/* platform stream compress ops */
|
||||
const struct snd_compr_ops *compr_ops;
|
||||
|
||||
/* platform stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
|
@ -847,23 +863,23 @@ struct snd_soc_platform_driver {
|
|||
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct snd_soc_dai_link_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const struct device_node *of_node;
|
||||
const char *dai_name;
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct device *dev;
|
||||
const struct snd_soc_platform_driver *driver;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
unsigned int probed:1;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
struct snd_soc_component component;
|
||||
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_platform_root;
|
||||
#endif
|
||||
|
@ -896,6 +912,10 @@ struct snd_soc_dai_link {
|
|||
const struct device_node *codec_of_node;
|
||||
/* You MUST specify the DAI name within the codec */
|
||||
const char *codec_dai_name;
|
||||
|
||||
struct snd_soc_dai_link_component *codecs;
|
||||
unsigned int num_codecs;
|
||||
|
||||
/*
|
||||
* You MAY specify the link's platform/PCM/DMA driver, either by
|
||||
* device name, or by DT/OF node, but not both. Some forms of link
|
||||
|
@ -1047,7 +1067,6 @@ struct snd_soc_card {
|
|||
|
||||
/* lists of probed devices belonging to this card */
|
||||
struct list_head codec_dev_list;
|
||||
struct list_head platform_dev_list;
|
||||
|
||||
struct list_head widgets;
|
||||
struct list_head paths;
|
||||
|
@ -1094,6 +1113,9 @@ struct snd_soc_pcm_runtime {
|
|||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
struct snd_soc_dai **codec_dais;
|
||||
unsigned int num_codecs;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dpcm_root;
|
||||
|
@ -1119,6 +1141,9 @@ struct soc_bytes {
|
|||
|
||||
struct soc_bytes_ext {
|
||||
int max;
|
||||
/* used for TLV byte control */
|
||||
int (*get)(unsigned int __user *bytes, unsigned int size);
|
||||
int (*put)(const unsigned int __user *bytes, unsigned int size);
|
||||
};
|
||||
|
||||
/* multi register control */
|
||||
|
@ -1164,6 +1189,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
|
|||
return container_of(component, struct snd_soc_platform, component);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
|
||||
* embedded in
|
||||
* @dapm: The DAPM context to cast to the component
|
||||
*
|
||||
* This function must only be used on DAPM contexts that are known to be part of
|
||||
* a component (e.g. in a component driver). Otherwise the behavior is
|
||||
* undefined.
|
||||
*/
|
||||
static inline struct snd_soc_component *snd_soc_dapm_to_component(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_component, dapm);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
|
||||
* @dapm: The DAPM context to cast to the CODEC
|
||||
|
@ -1188,7 +1228,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
|
|||
static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_platform, dapm);
|
||||
return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
|
||||
* component
|
||||
* @component: The component for which to get the DAPM context
|
||||
*/
|
||||
static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
|
||||
struct snd_soc_component *component)
|
||||
{
|
||||
return component->dapm_ptr;
|
||||
}
|
||||
|
||||
/* codec IO */
|
||||
|
@ -1261,7 +1312,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
|
|||
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
|
||||
{
|
||||
INIT_LIST_HEAD(&card->codec_dev_list);
|
||||
INIT_LIST_HEAD(&card->platform_dev_list);
|
||||
INIT_LIST_HEAD(&card->widgets);
|
||||
INIT_LIST_HEAD(&card->paths);
|
||||
INIT_LIST_HEAD(&card->dapm_list);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* TAS2552 driver platform header
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Inc.
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef TAS2552_PLAT_H
|
||||
#define TAS2552_PLAT_H
|
||||
|
||||
struct tas2552_platform_data {
|
||||
int enable_gpio;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -37,6 +37,7 @@
|
|||
#define WM8962_GPIO_FN_MICSCD 22
|
||||
|
||||
struct wm8962_pdata {
|
||||
struct clk *mclk;
|
||||
int gpio_base;
|
||||
u32 gpio_init[WM8962_MAX_GPIO];
|
||||
|
||||
|
|
|
@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
|
|||
TP_ARGS(codec, type, status),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, codec->name )
|
||||
__string( name, codec->component.name)
|
||||
__string( status, status )
|
||||
__string( type, type )
|
||||
__field( int, id )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, codec->name);
|
||||
__assign_str(name, codec->component.name);
|
||||
__assign_str(status, status);
|
||||
__assign_str(type, type);
|
||||
__entry->id = codec->id;
|
||||
__entry->id = codec->component.id;
|
||||
),
|
||||
|
||||
TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
|
||||
|
|
|
@ -139,7 +139,7 @@ struct snd_hwdep_dsp_image {
|
|||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11)
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 12)
|
||||
|
||||
typedef unsigned long snd_pcm_uframes_t;
|
||||
typedef signed long snd_pcm_sframes_t;
|
||||
|
@ -391,7 +391,9 @@ struct snd_pcm_sw_params {
|
|||
snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
|
||||
snd_pcm_uframes_t silence_size; /* silence block size */
|
||||
snd_pcm_uframes_t boundary; /* pointers wrap point */
|
||||
unsigned char reserved[64]; /* reserved for future */
|
||||
unsigned int proto; /* protocol version */
|
||||
unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */
|
||||
unsigned char reserved[56]; /* reserved for future */
|
||||
};
|
||||
|
||||
struct snd_pcm_channel_info {
|
||||
|
@ -462,7 +464,8 @@ struct snd_xfern {
|
|||
enum {
|
||||
SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
|
||||
SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
|
||||
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
|
||||
SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */
|
||||
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
|
||||
};
|
||||
|
||||
/* channel positions */
|
||||
|
|
|
@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
|
|||
/* We use the PCI APIs for now until the generic one gets fixed
|
||||
* enough or until we get some macio-specific versions
|
||||
*/
|
||||
r->space = dma_alloc_coherent(
|
||||
&macio_get_pci_dev(i2sdev->macio)->dev,
|
||||
r->size,
|
||||
&r->bus_addr,
|
||||
GFP_KERNEL);
|
||||
r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
|
||||
r->size, &r->bus_addr, GFP_KERNEL);
|
||||
if (!r->space)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!r->space) return -ENOMEM;
|
||||
|
||||
memset(r->space, 0, r->size);
|
||||
r->cmds = (void*)DBDMA_ALIGN(r->space);
|
||||
r->bus_cmd_start = r->bus_addr +
|
||||
(dma_addr_t)((char*)r->cmds - (char*)r->space);
|
||||
|
|
|
@ -152,9 +152,9 @@ static inline void pxa_ac97_cold_pxa27x(void)
|
|||
gsr_bits = 0;
|
||||
|
||||
/* PXA27x Developers Manual section 13.5.2.2.1 */
|
||||
clk_enable(ac97conf_clk);
|
||||
clk_prepare_enable(ac97conf_clk);
|
||||
udelay(5);
|
||||
clk_disable(ac97conf_clk);
|
||||
clk_disable_unprepare(ac97conf_clk);
|
||||
GCR = GCR_COLD_RST | GCR_WARM_RST;
|
||||
}
|
||||
#endif
|
||||
|
@ -299,14 +299,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
|
|||
int pxa2xx_ac97_hw_suspend(void)
|
||||
{
|
||||
GCR |= GCR_ACLINK_OFF;
|
||||
clk_disable(ac97_clk);
|
||||
clk_disable_unprepare(ac97_clk);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
|
||||
|
||||
int pxa2xx_ac97_hw_resume(void)
|
||||
{
|
||||
clk_enable(ac97_clk);
|
||||
clk_prepare_enable(ac97_clk);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
|
||||
|
@ -368,7 +368,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = clk_enable(ac97_clk);
|
||||
ret = clk_prepare_enable(ac97_clk);
|
||||
if (ret)
|
||||
goto err_clk2;
|
||||
|
||||
|
@ -403,7 +403,7 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev)
|
|||
clk_put(ac97conf_clk);
|
||||
ac97conf_clk = NULL;
|
||||
}
|
||||
clk_disable(ac97_clk);
|
||||
clk_disable_unprepare(ac97_clk);
|
||||
clk_put(ac97_clk);
|
||||
ac97_clk = NULL;
|
||||
}
|
||||
|
|
|
@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
|
|||
{
|
||||
/* first let's check the buffer parameter's */
|
||||
if (params->buffer.fragment_size == 0 ||
|
||||
params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
|
||||
params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
|
||||
return -EINVAL;
|
||||
|
||||
/* now codec parameters */
|
||||
|
|
|
@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
|||
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
||||
return snd_ctl_subscribe_events(ctl, ip);
|
||||
case SNDRV_CTL_IOCTL_TLV_READ:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, 0);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
|
||||
case SNDRV_CTL_IOCTL_TLV_WRITE:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, 1);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
|
||||
case SNDRV_CTL_IOCTL_TLV_COMMAND:
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, -1);
|
||||
return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
|
||||
case SNDRV_CTL_IOCTL_POWER:
|
||||
return -ENOPROTOOPT;
|
||||
case SNDRV_CTL_IOCTL_POWER_STATE:
|
||||
|
|
|
@ -101,7 +101,9 @@ struct snd_pcm_sw_params32 {
|
|||
u32 silence_threshold;
|
||||
u32 silence_size;
|
||||
u32 boundary;
|
||||
unsigned char reserved[64];
|
||||
u32 proto;
|
||||
u32 tstamp_type;
|
||||
unsigned char reserved[56];
|
||||
};
|
||||
|
||||
/* recalcuate the boundary within 32bit */
|
||||
|
@ -133,7 +135,9 @@ static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
|
|||
get_user(params.start_threshold, &src->start_threshold) ||
|
||||
get_user(params.stop_threshold, &src->stop_threshold) ||
|
||||
get_user(params.silence_threshold, &src->silence_threshold) ||
|
||||
get_user(params.silence_size, &src->silence_size))
|
||||
get_user(params.silence_size, &src->silence_size) ||
|
||||
get_user(params.tstamp_type, &src->tstamp_type) ||
|
||||
get_user(params.proto, &src->proto))
|
||||
return -EFAULT;
|
||||
/*
|
||||
* Check silent_size parameter. Since we have 64bit boundary,
|
||||
|
|
|
@ -65,13 +65,15 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
|
|||
enum dma_slave_buswidth buswidth;
|
||||
int bits;
|
||||
|
||||
bits = snd_pcm_format_physical_width(params_format(params));
|
||||
bits = params_physical_width(params);
|
||||
if (bits < 8 || bits > 64)
|
||||
return -EINVAL;
|
||||
else if (bits == 8)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
else if (bits == 16)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
|
||||
else if (bits == 24)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
|
||||
else if (bits <= 32)
|
||||
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
else
|
||||
|
|
|
@ -543,6 +543,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
|
||||
return -EINVAL;
|
||||
if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
|
||||
params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
|
||||
return -EINVAL;
|
||||
if (params->avail_min == 0)
|
||||
return -EINVAL;
|
||||
if (params->silence_size >= runtime->boundary) {
|
||||
|
@ -557,6 +560,8 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
|
|||
err = 0;
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
runtime->tstamp_mode = params->tstamp_mode;
|
||||
if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
|
||||
runtime->tstamp_type = params->tstamp_type;
|
||||
runtime->period_step = params->period_step;
|
||||
runtime->control->avail_min = params->avail_min;
|
||||
runtime->start_threshold = params->start_threshold;
|
||||
|
@ -2540,9 +2545,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
|
|||
return -EFAULT;
|
||||
if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
|
||||
return -EINVAL;
|
||||
runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
|
||||
if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
|
||||
runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
|
||||
runtime->tstamp_type = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
|
|||
len -= size;
|
||||
}
|
||||
return 0;
|
||||
} if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) {
|
||||
return func(private_data, event->data.ext.ptr, len);
|
||||
}
|
||||
if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
|
||||
return func(private_data, event->data.ext.ptr, len);
|
||||
|
||||
cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
|
||||
for (; len > 0 && cell; cell = cell->next) {
|
||||
|
|
|
@ -83,8 +83,8 @@ config SND_BEBOB
|
|||
* Edirol FA-66/FA-101
|
||||
* PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
|
||||
* BridgeCo RDAudio1/Audio5
|
||||
* Mackie Onyx 1220/1620/1640 (Firewire I/O Card)
|
||||
* Mackie d.2 (Firewire Option)
|
||||
* Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
|
||||
* Mackie d.2 (FireWire Option)
|
||||
* Stanton FinalScratch 2 (ScratchAmp)
|
||||
* Tascam IF-FW/DM
|
||||
* Behringer XENIX UFX 1204/1604
|
||||
|
@ -92,7 +92,7 @@ config SND_BEBOB
|
|||
* Apogee Rosetta 200/400 (X-FireWire card)
|
||||
* Apogee DA/AD/DD-16X (X-FireWire card)
|
||||
* Apogee Ensemble
|
||||
* ESI Quotafire610
|
||||
* ESI QuataFire 610
|
||||
* AcousticReality eARMasterOne
|
||||
* CME MatrixKFW
|
||||
* Phonic Helix Board 12 MkII/18 MkII/24 MkII
|
||||
|
@ -101,13 +101,13 @@ config SND_BEBOB
|
|||
* ICON FireXon
|
||||
* PrismSound Orpheus/ADA-8XR
|
||||
* TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
|
||||
* Terratec EWS MIC2/EWS MIC4
|
||||
* Terratec Aureon 7.1 Firewire
|
||||
* TerraTec EWS MIC2/EWS MIC8
|
||||
* TerraTec Aureon 7.1 FireWire
|
||||
* Yamaha GO44/GO46
|
||||
* Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
|
||||
* M-Audio Firewire410/AudioPhile/Solo
|
||||
* M-Audio FireWire410/AudioPhile/Solo
|
||||
* M-Audio Ozonic/NRV10/ProfireLightBridge
|
||||
* M-Audio Firewire 1814/ProjectMix IO
|
||||
* M-Audio FireWire 1814/ProjectMix IO
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-bebob.
|
||||
|
|
|
@ -64,7 +64,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
|||
hwinfo->phys_in_grp_count);
|
||||
for (i = 0; i < hwinfo->phys_in_grp_count; i++) {
|
||||
snd_iprintf(buffer,
|
||||
"phys in grp[0x%d]: type 0x%d, count 0x%d\n",
|
||||
"phys in grp[%d]: type 0x%X, count 0x%X\n",
|
||||
i, hwinfo->phys_out_grps[i].type,
|
||||
hwinfo->phys_out_grps[i].count);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
|||
hwinfo->phys_out_grp_count);
|
||||
for (i = 0; i < hwinfo->phys_out_grp_count; i++) {
|
||||
snd_iprintf(buffer,
|
||||
"phys out grps[0x%d]: type 0x%d, count 0x%d\n",
|
||||
"phys out grps[%d]: type 0x%X, count 0x%X\n",
|
||||
i, hwinfo->phys_out_grps[i].type,
|
||||
hwinfo->phys_out_grps[i].count);
|
||||
}
|
||||
|
|
|
@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic)
|
|||
case 0xf6:
|
||||
/* printk( "tune_request\n"); */
|
||||
devc->m_state = ST_INIT;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Real time messages
|
||||
|
@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
|
|||
devc->m_busy = 0;
|
||||
devc->m_state = ST_INIT;
|
||||
devc->shared_irq = hw_config->always_detect;
|
||||
devc->irq = hw_config->irq;
|
||||
spin_lock_init(&devc->lock);
|
||||
|
||||
if (devc->irq < 0)
|
||||
|
|
|
@ -52,7 +52,7 @@ struct voice_info
|
|||
int panning; /* 0xffff means not set */
|
||||
};
|
||||
|
||||
typedef struct opl_devinfo
|
||||
struct opl_devinfo
|
||||
{
|
||||
int base;
|
||||
int left_io, right_io;
|
||||
|
@ -73,7 +73,7 @@ typedef struct opl_devinfo
|
|||
unsigned char cmask;
|
||||
|
||||
int is_opl4;
|
||||
} opl_devinfo;
|
||||
};
|
||||
|
||||
static struct opl_devinfo *devc = NULL;
|
||||
|
||||
|
|
|
@ -123,25 +123,25 @@ static bool pss_mixer;
|
|||
#endif
|
||||
|
||||
|
||||
typedef struct pss_mixerdata {
|
||||
struct pss_mixerdata {
|
||||
unsigned int volume_l;
|
||||
unsigned int volume_r;
|
||||
unsigned int bass;
|
||||
unsigned int treble;
|
||||
unsigned int synth;
|
||||
} pss_mixerdata;
|
||||
};
|
||||
|
||||
typedef struct pss_confdata {
|
||||
struct pss_confdata {
|
||||
int base;
|
||||
int irq;
|
||||
int dma;
|
||||
int *osp;
|
||||
pss_mixerdata mixer;
|
||||
struct pss_mixerdata mixer;
|
||||
int ad_mixer_dev;
|
||||
} pss_confdata;
|
||||
};
|
||||
|
||||
static pss_confdata pss_data;
|
||||
static pss_confdata *devc = &pss_data;
|
||||
static struct pss_confdata pss_data;
|
||||
static struct pss_confdata *devc = &pss_data;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
|
||||
static int pss_initialized;
|
||||
|
@ -150,7 +150,7 @@ static int pss_cdrom_port = -1; /* Parameter for the PSS cdrom port */
|
|||
static bool pss_enable_joystick; /* Parameter for enabling the joystick */
|
||||
static coproc_operations pss_coproc_operations;
|
||||
|
||||
static void pss_write(pss_confdata *devc, int data)
|
||||
static void pss_write(struct pss_confdata *devc, int data)
|
||||
{
|
||||
unsigned long i, limit;
|
||||
|
||||
|
@ -206,7 +206,7 @@ static int __init probe_pss(struct address_info *hw_config)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int set_irq(pss_confdata * devc, int dev, int irq)
|
||||
static int set_irq(struct pss_confdata *devc, int dev, int irq)
|
||||
{
|
||||
static unsigned short irq_bits[16] =
|
||||
{
|
||||
|
@ -232,7 +232,7 @@ static int set_irq(pss_confdata * devc, int dev, int irq)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void set_io_base(pss_confdata * devc, int dev, int base)
|
||||
static void set_io_base(struct pss_confdata *devc, int dev, int base)
|
||||
{
|
||||
unsigned short tmp = inw(REG(dev)) & 0x003f;
|
||||
unsigned short bits = (base & 0x0ffc) << 4;
|
||||
|
@ -240,7 +240,7 @@ static void set_io_base(pss_confdata * devc, int dev, int base)
|
|||
outw(bits | tmp, REG(dev));
|
||||
}
|
||||
|
||||
static int set_dma(pss_confdata * devc, int dev, int dma)
|
||||
static int set_dma(struct pss_confdata *devc, int dev, int dma)
|
||||
{
|
||||
static unsigned short dma_bits[8] =
|
||||
{
|
||||
|
@ -264,7 +264,7 @@ static int set_dma(pss_confdata * devc, int dev, int dma)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int pss_reset_dsp(pss_confdata * devc)
|
||||
static int pss_reset_dsp(struct pss_confdata *devc)
|
||||
{
|
||||
unsigned long i, limit = jiffies + HZ/10;
|
||||
|
||||
|
@ -275,7 +275,7 @@ static int pss_reset_dsp(pss_confdata * devc)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int pss_put_dspword(pss_confdata * devc, unsigned short word)
|
||||
static int pss_put_dspword(struct pss_confdata *devc, unsigned short word)
|
||||
{
|
||||
int i, val;
|
||||
|
||||
|
@ -291,7 +291,7 @@ static int pss_put_dspword(pss_confdata * devc, unsigned short word)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
|
||||
static int pss_get_dspword(struct pss_confdata *devc, unsigned short *word)
|
||||
{
|
||||
int i, val;
|
||||
|
||||
|
@ -307,7 +307,8 @@ static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags)
|
||||
static int pss_download_boot(struct pss_confdata *devc, unsigned char *block,
|
||||
int size, int flags)
|
||||
{
|
||||
int i, val, count;
|
||||
unsigned long limit;
|
||||
|
@ -397,7 +398,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
|
|||
}
|
||||
|
||||
/* Mixer */
|
||||
static void set_master_volume(pss_confdata *devc, int left, int right)
|
||||
static void set_master_volume(struct pss_confdata *devc, int left, int right)
|
||||
{
|
||||
static unsigned char log_scale[101] = {
|
||||
0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
|
||||
|
@ -416,7 +417,7 @@ static void set_master_volume(pss_confdata *devc, int left, int right)
|
|||
pss_write(devc, log_scale[right] | 0x0100);
|
||||
}
|
||||
|
||||
static void set_synth_volume(pss_confdata *devc, int volume)
|
||||
static void set_synth_volume(struct pss_confdata *devc, int volume)
|
||||
{
|
||||
int vol = ((0x8000*volume)/100L);
|
||||
pss_write(devc, 0x0080);
|
||||
|
@ -425,21 +426,21 @@ static void set_synth_volume(pss_confdata *devc, int volume)
|
|||
pss_write(devc, vol);
|
||||
}
|
||||
|
||||
static void set_bass(pss_confdata *devc, int level)
|
||||
static void set_bass(struct pss_confdata *devc, int level)
|
||||
{
|
||||
int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
|
||||
pss_write(devc, 0x0010);
|
||||
pss_write(devc, vol | 0x0200);
|
||||
};
|
||||
|
||||
static void set_treble(pss_confdata *devc, int level)
|
||||
static void set_treble(struct pss_confdata *devc, int level)
|
||||
{
|
||||
int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
|
||||
pss_write(devc, 0x0010);
|
||||
pss_write(devc, vol | 0x0300);
|
||||
};
|
||||
|
||||
static void pss_mixer_reset(pss_confdata *devc)
|
||||
static void pss_mixer_reset(struct pss_confdata *devc)
|
||||
{
|
||||
set_master_volume(devc, 33, 33);
|
||||
set_bass(devc, 50);
|
||||
|
@ -499,7 +500,8 @@ static int ret_vol_stereo(int left, int right)
|
|||
return ((right << 8) | left);
|
||||
}
|
||||
|
||||
static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
|
||||
static int call_ad_mixer(struct pss_confdata *devc, unsigned int cmd,
|
||||
void __user *arg)
|
||||
{
|
||||
if (devc->ad_mixer_dev != NO_WSS_MIXER)
|
||||
return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
|
||||
|
@ -509,7 +511,7 @@ static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
|
|||
|
||||
static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
pss_confdata *devc = mixer_devs[dev]->devc;
|
||||
struct pss_confdata *devc = mixer_devs[dev]->devc;
|
||||
int cmdf = cmd & 0xff;
|
||||
|
||||
if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
|
||||
|
|
|
@ -858,8 +858,8 @@ config SND_VIRTUOSO
|
|||
select SND_JACK if INPUT=y || INPUT=SND
|
||||
help
|
||||
Say Y here to include support for sound cards based on the
|
||||
Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
|
||||
Essence ST (Deluxe), and Essence STX.
|
||||
Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX,
|
||||
Essence ST (Deluxe), and Essence STX (II).
|
||||
Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental;
|
||||
for the Xense, missing.
|
||||
|
||||
|
|
|
@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = {
|
|||
static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct echoaudio *chip;
|
||||
|
||||
chip = snd_kcontrol_chip(kcontrol);
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 96;
|
||||
uinfo->value.integer.min = ECHOGAIN_MINOUT;
|
||||
|
@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = {
|
|||
static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct echoaudio *chip;
|
||||
|
||||
chip = snd_kcontrol_chip(kcontrol);
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 6;
|
||||
uinfo->value.integer.min = 0;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* Helper functions for Dell Mic Mute LED control;
|
||||
* to be included from codec driver
|
||||
*/
|
||||
|
||||
#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
|
||||
#include <linux/dell-led.h>
|
||||
|
||||
static int dell_led_value;
|
||||
static int (*dell_led_set_func)(int, int);
|
||||
static void (*dell_old_cap_hook)(struct hda_codec *,
|
||||
struct snd_kcontrol *,
|
||||
struct snd_ctl_elem_value *);
|
||||
|
||||
static void update_dell_wmi_micmute_led(struct hda_codec *codec,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
if (dell_old_cap_hook)
|
||||
dell_old_cap_hook(codec, kcontrol, ucontrol);
|
||||
|
||||
if (!ucontrol || !dell_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? */
|
||||
int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
|
||||
if (val == dell_led_value)
|
||||
return;
|
||||
dell_led_value = val;
|
||||
if (dell_led_set_func)
|
||||
dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void alc_fixup_dell_wmi(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 (!dell_led_set_func)
|
||||
dell_led_set_func = symbol_request(dell_app_wmi_led_set);
|
||||
if (!dell_led_set_func) {
|
||||
codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
|
||||
return;
|
||||
}
|
||||
|
||||
removefunc = true;
|
||||
if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
|
||||
dell_led_value = 0;
|
||||
if (spec->gen.num_adc_nids > 1)
|
||||
codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
|
||||
else {
|
||||
dell_old_cap_hook = spec->gen.cap_sync_hook;
|
||||
spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
|
||||
removefunc = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
|
||||
symbol_put(dell_app_wmi_led_set);
|
||||
dell_led_set_func = NULL;
|
||||
dell_old_cap_hook = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* CONFIG_LEDS_DELL_NETBOOKS */
|
||||
static void alc_fixup_dell_wmi(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LEDS_DELL_NETBOOKS */
|
|
@ -17,8 +17,6 @@
|
|||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
|
||||
#define SFX "hda_codec: "
|
||||
|
||||
/*
|
||||
* Helper for automatic pin configuration
|
||||
*/
|
||||
|
@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
|
|||
{
|
||||
const struct snd_hda_pin_quirk *pq;
|
||||
|
||||
if (codec->fixup_forced)
|
||||
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
|
||||
return;
|
||||
|
||||
for (pq = pin_quirk; pq->subvendor; pq++) {
|
||||
|
@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
const struct hda_fixup *fixlist)
|
||||
{
|
||||
const struct snd_pci_quirk *q;
|
||||
int id = -1;
|
||||
int id = HDA_FIXUP_ID_NOT_SET;
|
||||
const char *name = NULL;
|
||||
|
||||
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
|
||||
return;
|
||||
|
||||
/* when model=nofixup is given, don't pick up any fixups */
|
||||
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
|
||||
codec->fixup_list = NULL;
|
||||
codec->fixup_id = -1;
|
||||
codec->fixup_forced = 1;
|
||||
codec->fixup_name = NULL;
|
||||
codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
codec->fixup_id = models->id;
|
||||
codec->fixup_name = models->name;
|
||||
codec->fixup_list = fixlist;
|
||||
codec->fixup_forced = 1;
|
||||
return;
|
||||
}
|
||||
models++;
|
||||
}
|
||||
}
|
||||
if (id < 0 && quirk) {
|
||||
if (quirk) {
|
||||
q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
|
||||
if (q) {
|
||||
id = q->value;
|
||||
|
@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
codec->fixup_forced = 0;
|
||||
codec->fixup_id = id;
|
||||
if (id >= 0) {
|
||||
codec->fixup_list = fixlist;
|
||||
|
|
|
@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
|
|||
|
||||
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
|
||||
codec->depop_delay = -1;
|
||||
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
spin_lock_init(&codec->power_lock);
|
||||
|
@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
|
||||
typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
|
||||
|
||||
/* apply the function to all matching slave ctls in the mixer list */
|
||||
static int map_slaves(struct hda_codec *codec, const char * const *slaves,
|
||||
|
@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
|
|||
name = tmpname;
|
||||
}
|
||||
if (!strcmp(sctl->id.name, name)) {
|
||||
err = func(data, sctl);
|
||||
err = func(codec, data, sctl);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int check_slave_present(void *data, struct snd_kcontrol *sctl)
|
||||
static int check_slave_present(struct hda_codec *codec,
|
||||
void *data, struct snd_kcontrol *sctl)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* guess the value corresponding to 0dB */
|
||||
static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
|
||||
static int get_kctl_0dB_offset(struct hda_codec *codec,
|
||||
struct snd_kcontrol *kctl, int *step_to_check)
|
||||
{
|
||||
int _tlv[4];
|
||||
const int *tlv = NULL;
|
||||
|
@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
|
|||
if (!step)
|
||||
return -1;
|
||||
if (*step_to_check && *step_to_check != step) {
|
||||
snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
|
||||
codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n",
|
||||
- *step_to_check, step);
|
||||
return -1;
|
||||
}
|
||||
|
@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
|
|||
}
|
||||
|
||||
/* initialize the slave volume with 0dB */
|
||||
static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
|
||||
static int init_slave_0dB(struct hda_codec *codec,
|
||||
void *data, struct snd_kcontrol *slave)
|
||||
{
|
||||
int offset = get_kctl_0dB_offset(slave, data);
|
||||
int offset = get_kctl_0dB_offset(codec, slave, data);
|
||||
if (offset > 0)
|
||||
put_kctl_with_value(slave, offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* unmute the slave */
|
||||
static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
|
||||
static int init_slave_unmute(struct hda_codec *codec,
|
||||
void *data, struct snd_kcontrol *slave)
|
||||
{
|
||||
return put_kctl_with_value(slave, 1);
|
||||
}
|
||||
|
||||
static int add_slave(struct hda_codec *codec,
|
||||
void *data, struct snd_kcontrol *slave)
|
||||
{
|
||||
return snd_ctl_add_slave(data, slave);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_add_vmaster - create a virtual master control and add slaves
|
||||
* @codec: HD-audio codec
|
||||
|
@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = map_slaves(codec, slaves, suffix,
|
||||
(map_slave_func_t)snd_ctl_add_slave, kctl);
|
||||
err = map_slaves(codec, slaves, suffix, add_slave, kctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = {
|
|||
|
||||
/**
|
||||
* snd_hda_calc_stream_format - calculate format bitset
|
||||
* @codec: HD-audio codec
|
||||
* @rate: the sample rate
|
||||
* @channels: the number of channels
|
||||
* @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
|
||||
|
@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = {
|
|||
*
|
||||
* Return zero if invalid.
|
||||
*/
|
||||
unsigned int snd_hda_calc_stream_format(unsigned int rate,
|
||||
unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
|
||||
unsigned int rate,
|
||||
unsigned int channels,
|
||||
unsigned int format,
|
||||
unsigned int maxbps,
|
||||
|
@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
|
|||
break;
|
||||
}
|
||||
if (!rate_bits[i].hz) {
|
||||
snd_printdd("invalid rate %d\n", rate);
|
||||
codec_dbg(codec, "invalid rate %d\n", rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (channels == 0 || channels > 8) {
|
||||
snd_printdd("invalid channels %d\n", channels);
|
||||
codec_dbg(codec, "invalid channels %d\n", channels);
|
||||
return 0;
|
||||
}
|
||||
val |= channels - 1;
|
||||
|
@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
|
|||
val |= AC_FMT_BITS_20;
|
||||
break;
|
||||
default:
|
||||
snd_printdd("invalid format width %d\n",
|
||||
codec_dbg(codec, "invalid format width %d\n",
|
||||
snd_pcm_format_width(format));
|
||||
return 0;
|
||||
}
|
||||
|
@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
|
|||
* suffix is appended to the label. This label index number is stored
|
||||
* to type_idx when non-NULL pointer is given.
|
||||
*/
|
||||
int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
|
||||
int snd_hda_add_imux_item(struct hda_codec *codec,
|
||||
struct hda_input_mux *imux, const char *label,
|
||||
int index, int *type_idx)
|
||||
{
|
||||
int i, label_idx = 0;
|
||||
if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
|
||||
snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
|
||||
codec_err(codec, "hda_codec: Too many imux items!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < imux->num_items; i++) {
|
||||
|
|
|
@ -402,7 +402,6 @@ struct hda_codec {
|
|||
|
||||
/* fix-up list */
|
||||
int fixup_id;
|
||||
unsigned int fixup_forced:1; /* fixup explicitly set by user */
|
||||
const struct hda_fixup *fixup_list;
|
||||
const char *fixup_name;
|
||||
|
||||
|
@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
|
|||
int do_now);
|
||||
#define snd_hda_codec_cleanup_stream(codec, nid) \
|
||||
__snd_hda_codec_cleanup_stream(codec, nid, 0)
|
||||
unsigned int snd_hda_calc_stream_format(unsigned int rate,
|
||||
unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
|
||||
unsigned int rate,
|
||||
unsigned int channels,
|
||||
unsigned int format,
|
||||
unsigned int maxbps,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
#include "hda_priv.h"
|
||||
|
@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
|||
upper_32_bits(azx_dev->bdl.addr));
|
||||
|
||||
/* enable the position buffer */
|
||||
if (chip->position_fix[0] != POS_FIX_LPIB ||
|
||||
chip->position_fix[1] != POS_FIX_LPIB) {
|
||||
if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
|
||||
if (chip->get_position[0] != azx_get_pos_lpib ||
|
||||
chip->get_position[1] != azx_get_pos_lpib) {
|
||||
if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
|
||||
azx_writel(chip, DPLBASE,
|
||||
(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
|
||||
(u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE);
|
||||
}
|
||||
|
||||
/* set the interrupt enable bits in the descriptor control register */
|
||||
|
@ -482,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
}
|
||||
|
||||
azx_stream_reset(chip, azx_dev);
|
||||
format_val = snd_hda_calc_stream_format(runtime->rate,
|
||||
format_val = snd_hda_calc_stream_format(apcm->codec,
|
||||
runtime->rate,
|
||||
runtime->channels,
|
||||
runtime->format,
|
||||
hinfo->maxbps,
|
||||
|
@ -673,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* get the current DMA position with correction on VIA chips */
|
||||
static unsigned int azx_via_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev)
|
||||
unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
|
||||
{
|
||||
unsigned int link_pos, mini_pos, bound_pos;
|
||||
unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
|
||||
unsigned int fifo_size;
|
||||
|
||||
link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
/* Playback, no problem using link position */
|
||||
return link_pos;
|
||||
}
|
||||
|
||||
/* Capture */
|
||||
/* For new chipset,
|
||||
* use mod to get the DMA position just like old chipset
|
||||
*/
|
||||
mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
|
||||
mod_dma_pos %= azx_dev->period_bytes;
|
||||
|
||||
/* azx_dev->fifo_size can't get FIFO size of in stream.
|
||||
* Get from base address + offset.
|
||||
*/
|
||||
fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
|
||||
|
||||
if (azx_dev->insufficient) {
|
||||
/* Link position never gather than FIFO size */
|
||||
if (link_pos <= fifo_size)
|
||||
return 0;
|
||||
|
||||
azx_dev->insufficient = 0;
|
||||
}
|
||||
|
||||
if (link_pos <= fifo_size)
|
||||
mini_pos = azx_dev->bufsize + link_pos - fifo_size;
|
||||
else
|
||||
mini_pos = link_pos - fifo_size;
|
||||
|
||||
/* Find nearest previous boudary */
|
||||
mod_mini_pos = mini_pos % azx_dev->period_bytes;
|
||||
mod_link_pos = link_pos % azx_dev->period_bytes;
|
||||
if (mod_link_pos >= fifo_size)
|
||||
bound_pos = link_pos - mod_link_pos;
|
||||
else if (mod_dma_pos >= mod_mini_pos)
|
||||
bound_pos = mini_pos - mod_mini_pos;
|
||||
else {
|
||||
bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
|
||||
if (bound_pos >= azx_dev->bufsize)
|
||||
bound_pos = 0;
|
||||
}
|
||||
|
||||
/* Calculate real DMA position we want */
|
||||
return bound_pos + mod_dma_pos;
|
||||
return azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
|
||||
|
||||
unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
|
||||
{
|
||||
return le32_to_cpu(*azx_dev->posbuf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
|
||||
|
||||
unsigned int azx_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev,
|
||||
bool with_check)
|
||||
struct azx_dev *azx_dev)
|
||||
{
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||
unsigned int pos;
|
||||
int stream = substream->stream;
|
||||
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
|
||||
int delay = 0;
|
||||
|
||||
switch (chip->position_fix[stream]) {
|
||||
case POS_FIX_LPIB:
|
||||
/* read LPIB */
|
||||
pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
break;
|
||||
case POS_FIX_VIACOMBO:
|
||||
pos = azx_via_get_position(chip, azx_dev);
|
||||
break;
|
||||
default:
|
||||
/* use the position buffer */
|
||||
pos = le32_to_cpu(*azx_dev->posbuf);
|
||||
if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
|
||||
if (!pos || pos == (u32)-1) {
|
||||
dev_info(chip->card->dev,
|
||||
"Invalid position buffer, using LPIB read method instead.\n");
|
||||
chip->position_fix[stream] = POS_FIX_LPIB;
|
||||
pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
} else
|
||||
chip->position_fix[stream] = POS_FIX_POSBUF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (chip->get_position[stream])
|
||||
pos = chip->get_position[stream](chip, azx_dev);
|
||||
else /* use the position buffer as default */
|
||||
pos = azx_get_pos_posbuf(chip, azx_dev);
|
||||
|
||||
if (pos >= azx_dev->bufsize)
|
||||
pos = 0;
|
||||
|
||||
/* calculate runtime delay from LPIB */
|
||||
if (substream->runtime &&
|
||||
chip->position_fix[stream] == POS_FIX_POSBUF &&
|
||||
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
|
||||
unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
delay = pos - lpib_pos;
|
||||
else
|
||||
delay = lpib_pos - pos;
|
||||
if (delay < 0) {
|
||||
if (delay >= azx_dev->delay_negative_threshold)
|
||||
delay = 0;
|
||||
else
|
||||
delay += azx_dev->bufsize;
|
||||
}
|
||||
if (delay >= azx_dev->period_bytes) {
|
||||
dev_info(chip->card->dev,
|
||||
"Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
|
||||
delay, azx_dev->period_bytes);
|
||||
delay = 0;
|
||||
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
|
||||
}
|
||||
delay = bytes_to_frames(substream->runtime, delay);
|
||||
}
|
||||
|
||||
if (substream->runtime) {
|
||||
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
|
||||
|
||||
if (chip->get_delay[stream])
|
||||
delay += chip->get_delay[stream](chip, azx_dev, pos);
|
||||
if (hinfo->ops.get_delay)
|
||||
delay += hinfo->ops.get_delay(hinfo, apcm->codec,
|
||||
substream);
|
||||
|
@ -809,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
|
|||
struct azx *chip = apcm->chip;
|
||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
||||
return bytes_to_frames(substream->runtime,
|
||||
azx_get_position(chip, azx_dev, false));
|
||||
azx_get_position(chip, azx_dev));
|
||||
}
|
||||
|
||||
static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
|
||||
|
@ -1059,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip)
|
|||
azx_writew(chip, CORBWP, 0);
|
||||
|
||||
/* reset the corb hw read pointer */
|
||||
azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
|
||||
azx_writew(chip, CORBRP, AZX_CORBRP_RST);
|
||||
if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
|
||||
for (timeout = 1000; timeout > 0; timeout--) {
|
||||
if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
|
||||
if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
@ -1082,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip)
|
|||
}
|
||||
|
||||
/* enable corb dma */
|
||||
azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
|
||||
azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);
|
||||
|
||||
/* RIRB set up */
|
||||
chip->rirb.addr = chip->rb.addr + 2048;
|
||||
|
@ -1095,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip)
|
|||
/* set the rirb size to 256 entries (ULI requires explicitly) */
|
||||
azx_writeb(chip, RIRBSIZE, 0x02);
|
||||
/* reset the rirb hw write pointer */
|
||||
azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
|
||||
azx_writew(chip, RIRBWP, AZX_RIRBWP_RST);
|
||||
/* set N=1, get RIRB response interrupt for new entry */
|
||||
if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
|
||||
azx_writew(chip, RINTCNT, 0xc0);
|
||||
else
|
||||
azx_writew(chip, RINTCNT, 1);
|
||||
/* enable rirb dma and response irq */
|
||||
azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
|
||||
azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(azx_init_cmd_io);
|
||||
|
@ -1146,7 +1063,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
|
|||
return -EIO;
|
||||
}
|
||||
wp++;
|
||||
wp %= ICH6_MAX_CORB_ENTRIES;
|
||||
wp %= AZX_MAX_CORB_ENTRIES;
|
||||
|
||||
rp = azx_readw(chip, CORBRP);
|
||||
if (wp == rp) {
|
||||
|
@ -1164,7 +1081,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define ICH6_RIRB_EX_UNSOL_EV (1<<4)
|
||||
#define AZX_RIRB_EX_UNSOL_EV (1<<4)
|
||||
|
||||
/* retrieve RIRB entry - called from interrupt handler */
|
||||
static void azx_update_rirb(struct azx *chip)
|
||||
|
@ -1185,7 +1102,7 @@ static void azx_update_rirb(struct azx *chip)
|
|||
|
||||
while (chip->rirb.rp != wp) {
|
||||
chip->rirb.rp++;
|
||||
chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
|
||||
chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES;
|
||||
|
||||
rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
|
||||
res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
|
||||
|
@ -1196,8 +1113,7 @@ static void azx_update_rirb(struct azx *chip)
|
|||
res, res_ex,
|
||||
chip->rirb.rp, wp);
|
||||
snd_BUG();
|
||||
}
|
||||
else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
|
||||
} else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
|
||||
snd_hda_queue_unsol_event(chip->bus, res, res_ex);
|
||||
else if (chip->rirb.cmds[addr]) {
|
||||
chip->rirb.res[addr] = res;
|
||||
|
@ -1305,7 +1221,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
|||
/* release CORB/RIRB */
|
||||
azx_free_cmd_io(chip);
|
||||
/* disable unsolicited responses */
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1326,7 +1242,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
|
|||
|
||||
while (timeout--) {
|
||||
/* check IRV busy bit */
|
||||
if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
|
||||
if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
|
||||
/* reuse rirb.res as the response return value */
|
||||
chip->rirb.res[addr] = azx_readl(chip, IR);
|
||||
return 0;
|
||||
|
@ -1350,13 +1266,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
|
|||
bus->rirb_error = 0;
|
||||
while (timeout--) {
|
||||
/* check ICB busy bit */
|
||||
if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
|
||||
if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
|
||||
/* Clear IRV valid bit */
|
||||
azx_writew(chip, IRS, azx_readw(chip, IRS) |
|
||||
ICH6_IRS_VALID);
|
||||
AZX_IRS_VALID);
|
||||
azx_writel(chip, IC, val);
|
||||
azx_writew(chip, IRS, azx_readw(chip, IRS) |
|
||||
ICH6_IRS_BUSY);
|
||||
AZX_IRS_BUSY);
|
||||
return azx_single_wait_for_response(chip, addr);
|
||||
}
|
||||
udelay(1);
|
||||
|
@ -1585,10 +1501,10 @@ void azx_enter_link_reset(struct azx *chip)
|
|||
unsigned long timeout;
|
||||
|
||||
/* reset controller */
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(100);
|
||||
while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
|
||||
while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) &&
|
||||
time_before(jiffies, timeout))
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
@ -1599,7 +1515,7 @@ static void azx_exit_link_reset(struct azx *chip)
|
|||
{
|
||||
unsigned long timeout;
|
||||
|
||||
azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
|
||||
azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(100);
|
||||
while (!azx_readb(chip, GCTL) &&
|
||||
|
@ -1640,7 +1556,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
|
|||
/* Accept unsolicited responses */
|
||||
if (!chip->single_cmd)
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
|
||||
ICH6_GCTL_UNSOL);
|
||||
AZX_GCTL_UNSOL);
|
||||
|
||||
/* detect codecs */
|
||||
if (!chip->codec_mask) {
|
||||
|
@ -1657,7 +1573,7 @@ static void azx_int_enable(struct azx *chip)
|
|||
{
|
||||
/* enable controller CIE and GIE */
|
||||
azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
|
||||
ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
|
||||
AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
|
||||
}
|
||||
|
||||
/* disable interrupts */
|
||||
|
@ -1678,7 +1594,7 @@ static void azx_int_disable(struct azx *chip)
|
|||
|
||||
/* disable controller CIE and GIE */
|
||||
azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
|
||||
~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
|
||||
~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN));
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
|
@ -1699,7 +1615,7 @@ static void azx_int_clear(struct azx *chip)
|
|||
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
|
||||
|
||||
/* clear int status */
|
||||
azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
|
||||
azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2031,5 +1947,30 @@ int azx_init_stream(struct azx *chip)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(azx_init_stream);
|
||||
|
||||
/*
|
||||
* reboot notifier for hang-up problem at power-down
|
||||
*/
|
||||
static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
|
||||
{
|
||||
struct azx *chip = container_of(nb, struct azx, reboot_notifier);
|
||||
snd_hda_bus_reboot_notify(chip->bus);
|
||||
azx_stop_chip(chip);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
void azx_notifier_register(struct azx *chip)
|
||||
{
|
||||
chip->reboot_notifier.notifier_call = azx_halt;
|
||||
register_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(azx_notifier_register);
|
||||
|
||||
void azx_notifier_unregister(struct azx *chip)
|
||||
{
|
||||
if (chip->reboot_notifier.notifier_call)
|
||||
unregister_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(azx_notifier_unregister);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Common HDA driver funcitons");
|
||||
|
|
|
@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
|
|||
{
|
||||
return substream->runtime->private_data;
|
||||
}
|
||||
unsigned int azx_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev,
|
||||
bool with_check);
|
||||
unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
|
||||
unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
|
||||
unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);
|
||||
|
||||
/* Stream control. */
|
||||
void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
|
||||
|
@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
|
|||
int azx_mixer_create(struct azx *chip);
|
||||
int azx_init_stream(struct azx *chip);
|
||||
|
||||
void azx_notifier_register(struct azx *chip);
|
||||
void azx_notifier_unregister(struct azx *chip);
|
||||
|
||||
#endif /* __SOUND_HDA_CONTROLLER_H */
|
||||
|
|
|
@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
|
|||
(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
|
||||
})
|
||||
|
||||
static void hdmi_update_short_audio_desc(struct cea_sad *a,
|
||||
static void hdmi_update_short_audio_desc(struct hda_codec *codec,
|
||||
struct cea_sad *a,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
|
@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
|
|||
a->format = GRAB_BITS(buf, 0, 3, 4);
|
||||
switch (a->format) {
|
||||
case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
|
||||
snd_printd(KERN_INFO
|
||||
"HDMI: audio coding type 0 not expected\n");
|
||||
codec_info(codec, "HDMI: audio coding type 0 not expected\n");
|
||||
break;
|
||||
|
||||
case AUDIO_CODING_TYPE_LPCM:
|
||||
|
@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
|
|||
a->format = GRAB_BITS(buf, 2, 3, 5);
|
||||
if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
|
||||
a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
|
||||
snd_printd(KERN_INFO
|
||||
"HDMI: audio coding xtype %d not expected\n",
|
||||
a->format);
|
||||
codec_info(codec,
|
||||
"HDMI: audio coding xtype %d not expected\n",
|
||||
a->format);
|
||||
a->format = 0;
|
||||
} else
|
||||
a->format += AUDIO_CODING_TYPE_HE_AAC -
|
||||
|
@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
|
|||
/*
|
||||
* Be careful, ELD buf could be totally rubbish!
|
||||
*/
|
||||
int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
|
||||
int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size)
|
||||
{
|
||||
int mnl;
|
||||
|
@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
|
|||
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
|
||||
if (e->eld_ver != ELD_VER_CEA_861D &&
|
||||
e->eld_ver != ELD_VER_PARTIAL) {
|
||||
snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
|
||||
e->eld_ver);
|
||||
codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
|
@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
|
|||
e->product_id = get_unaligned_le16(buf + 18);
|
||||
|
||||
if (mnl > ELD_MAX_MNL) {
|
||||
snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
|
||||
codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else if (ELD_FIXED_BYTES + mnl > size) {
|
||||
snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
|
||||
codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
|
||||
goto out_fail;
|
||||
} else
|
||||
strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
|
||||
|
||||
for (i = 0; i < e->sad_count; i++) {
|
||||
if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
|
||||
snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
|
||||
codec_info(codec, "HDMI: out of range SAD %d\n", i);
|
||||
goto out_fail;
|
||||
}
|
||||
hdmi_update_short_audio_desc(e->sad + i,
|
||||
hdmi_update_short_audio_desc(codec, e->sad + i,
|
||||
buf + ELD_FIXED_BYTES + mnl + 3 * i);
|
||||
}
|
||||
|
||||
|
@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
|
|||
|
||||
#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
|
||||
|
||||
static void hdmi_show_short_audio_desc(struct cea_sad *a)
|
||||
static void hdmi_show_short_audio_desc(struct hda_codec *codec,
|
||||
struct cea_sad *a)
|
||||
{
|
||||
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
|
||||
char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
|
||||
|
@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a)
|
|||
else
|
||||
buf2[0] = '\0';
|
||||
|
||||
_snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:"
|
||||
" channels = %d, rates =%s%s\n",
|
||||
cea_audio_coding_type_names[a->format],
|
||||
a->channels,
|
||||
buf,
|
||||
buf2);
|
||||
codec_dbg(codec,
|
||||
"HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
|
||||
cea_audio_coding_type_names[a->format],
|
||||
a->channels, buf, buf2);
|
||||
}
|
||||
|
||||
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
|
||||
|
@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
|
|||
buf[j] = '\0'; /* necessary when j == 0 */
|
||||
}
|
||||
|
||||
void snd_hdmi_show_eld(struct parsed_hdmi_eld *e)
|
||||
void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e)
|
||||
{
|
||||
int i;
|
||||
|
||||
_snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n",
|
||||
codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n",
|
||||
e->monitor_name,
|
||||
eld_connection_type_names[e->conn_type]);
|
||||
|
||||
if (e->spk_alloc) {
|
||||
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
||||
snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
|
||||
_snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf);
|
||||
codec_dbg(codec, "HDMI: available speakers:%s\n", buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < e->sad_count; i++)
|
||||
hdmi_show_short_audio_desc(e->sad + i);
|
||||
hdmi_show_short_audio_desc(codec, e->sad + i);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
|
|
@ -350,16 +350,16 @@ static void print_nid_path(struct hda_codec *codec,
|
|||
const char *pfx, struct nid_path *path)
|
||||
{
|
||||
char buf[40];
|
||||
char *pos = buf;
|
||||
int i;
|
||||
|
||||
*pos = 0;
|
||||
for (i = 0; i < path->depth; i++)
|
||||
pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
|
||||
pos != buf ? ":" : "",
|
||||
path->path[i]);
|
||||
|
||||
buf[0] = 0;
|
||||
for (i = 0; i < path->depth; i++) {
|
||||
char tmp[4];
|
||||
sprintf(tmp, ":%02x", path->path[i]);
|
||||
strlcat(buf, tmp, sizeof(buf));
|
||||
}
|
||||
codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf);
|
||||
codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
|
||||
}
|
||||
|
||||
/* called recursively */
|
||||
|
@ -1700,9 +1700,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|||
#define DEBUG_BADNESS
|
||||
|
||||
#ifdef DEBUG_BADNESS
|
||||
#define debug_badness(fmt, args...) codec_dbg(codec, fmt, ##args)
|
||||
#define debug_badness(fmt, ...) \
|
||||
codec_dbg(codec, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debug_badness(...)
|
||||
#define debug_badness(fmt, ...) \
|
||||
do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BADNESS
|
||||
|
@ -3054,7 +3056,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
|
|||
if (spec->hp_mic_pin == pin)
|
||||
spec->hp_mic_mux_idx = imux->num_items;
|
||||
spec->imux_pins[imux->num_items] = pin;
|
||||
snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
|
||||
snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
|
||||
imux_added = true;
|
||||
if (spec->dyn_adc_switch)
|
||||
spec->dyn_adc_idx[imux_idx] = c;
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
* Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
|
||||
* The values will be lost when the display power well is disabled.
|
||||
*/
|
||||
#define ICH6_REG_EM4 0x100c
|
||||
#define ICH6_REG_EM5 0x1010
|
||||
#define AZX_REG_EM4 0x100c
|
||||
#define AZX_REG_EM5 0x1010
|
||||
|
||||
static int (*get_power)(void);
|
||||
static int (*put_power)(void);
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clocksource.h>
|
||||
|
@ -66,6 +65,52 @@
|
|||
#include "hda_priv.h"
|
||||
#include "hda_i915.h"
|
||||
|
||||
/* position fix mode */
|
||||
enum {
|
||||
POS_FIX_AUTO,
|
||||
POS_FIX_LPIB,
|
||||
POS_FIX_POSBUF,
|
||||
POS_FIX_VIACOMBO,
|
||||
POS_FIX_COMBO,
|
||||
};
|
||||
|
||||
/* Defines for ATI HD Audio support in SB450 south bridge */
|
||||
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
|
||||
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
|
||||
|
||||
/* Defines for Nvidia HDA support */
|
||||
#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
|
||||
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
|
||||
#define NVIDIA_HDA_ISTRM_COH 0x4d
|
||||
#define NVIDIA_HDA_OSTRM_COH 0x4c
|
||||
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
|
||||
|
||||
/* Defines for Intel SCH HDA snoop control */
|
||||
#define INTEL_SCH_HDA_DEVC 0x78
|
||||
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
|
||||
|
||||
/* Define IN stream 0 FIFO size offset in VIA controller */
|
||||
#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90
|
||||
/* Define VIA HD Audio Device ID*/
|
||||
#define VIA_HDAC_DEVICE_ID 0x3288
|
||||
|
||||
/* max number of SDs */
|
||||
/* ICH, ATI and VIA have 4 playback and 4 capture */
|
||||
#define ICH6_NUM_CAPTURE 4
|
||||
#define ICH6_NUM_PLAYBACK 4
|
||||
|
||||
/* ULI has 6 playback and 5 capture */
|
||||
#define ULI_NUM_CAPTURE 5
|
||||
#define ULI_NUM_PLAYBACK 6
|
||||
|
||||
/* ATI HDMI may have up to 8 playbacks and 0 capture */
|
||||
#define ATIHDMI_NUM_CAPTURE 0
|
||||
#define ATIHDMI_NUM_PLAYBACK 8
|
||||
|
||||
/* TERA has 4 playback and 3 capture */
|
||||
#define TERA_NUM_CAPTURE 3
|
||||
#define TERA_NUM_PLAYBACK 4
|
||||
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
||||
|
@ -290,8 +335,28 @@ static char *driver_short_names[] = {
|
|||
|
||||
struct hda_intel {
|
||||
struct azx chip;
|
||||
};
|
||||
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
|
||||
/* sync probing */
|
||||
struct completion probe_wait;
|
||||
struct work_struct probe_work;
|
||||
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
|
||||
/* extra flags */
|
||||
unsigned int irq_pending_warned:1;
|
||||
|
||||
/* VGA-switcheroo setup */
|
||||
unsigned int use_vga_switcheroo:1;
|
||||
unsigned int vga_switcheroo_registered:1;
|
||||
unsigned int init_failed:1; /* delayed init failed */
|
||||
|
||||
/* secondary power domain for hdmi audio under vga device */
|
||||
struct dev_pm_domain hdmi_pm_domain;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
|
||||
|
@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip)
|
|||
*/
|
||||
if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
|
||||
dev_dbg(chip->card->dev, "Clearing TCSEL\n");
|
||||
update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
|
||||
update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
|
||||
}
|
||||
|
||||
/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
|
||||
|
@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip)
|
|||
}
|
||||
}
|
||||
|
||||
/* calculate runtime delay from LPIB */
|
||||
static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
|
||||
unsigned int pos)
|
||||
{
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
int stream = substream->stream;
|
||||
unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
|
||||
int delay;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
delay = pos - lpib_pos;
|
||||
else
|
||||
delay = lpib_pos - pos;
|
||||
if (delay < 0) {
|
||||
if (delay >= azx_dev->delay_negative_threshold)
|
||||
delay = 0;
|
||||
else
|
||||
delay += azx_dev->bufsize;
|
||||
}
|
||||
|
||||
if (delay >= azx_dev->period_bytes) {
|
||||
dev_info(chip->card->dev,
|
||||
"Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
|
||||
delay, azx_dev->period_bytes);
|
||||
delay = 0;
|
||||
chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
|
||||
chip->get_delay[stream] = NULL;
|
||||
}
|
||||
|
||||
return bytes_to_frames(substream->runtime, delay);
|
||||
}
|
||||
|
||||
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
|
||||
|
||||
/* called from IRQ */
|
||||
static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
int ok;
|
||||
|
||||
ok = azx_position_ok(chip, azx_dev);
|
||||
|
@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
|
|||
} else if (ok == 0 && chip->bus && chip->bus->workq) {
|
||||
/* bogus IRQ, process it later */
|
||||
azx_dev->irq_pending = 1;
|
||||
queue_work(chip->bus->workq, &chip->irq_pending_work);
|
||||
queue_work(chip->bus->workq, &hda->irq_pending_work);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
|
|||
*/
|
||||
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
|
||||
{
|
||||
struct snd_pcm_substream *substream = azx_dev->substream;
|
||||
int stream = substream->stream;
|
||||
u32 wallclk;
|
||||
unsigned int pos;
|
||||
|
||||
|
@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
|
|||
if (wallclk < (azx_dev->period_wallclk * 2) / 3)
|
||||
return -1; /* bogus (too early) interrupt */
|
||||
|
||||
pos = azx_get_position(chip, azx_dev, true);
|
||||
if (chip->get_position[stream])
|
||||
pos = chip->get_position[stream](chip, azx_dev);
|
||||
else { /* use the position buffer as default */
|
||||
pos = azx_get_pos_posbuf(chip, azx_dev);
|
||||
if (!pos || pos == (u32)-1) {
|
||||
dev_info(chip->card->dev,
|
||||
"Invalid position buffer, using LPIB read method instead.\n");
|
||||
chip->get_position[stream] = azx_get_pos_lpib;
|
||||
pos = azx_get_pos_lpib(chip, azx_dev);
|
||||
chip->get_delay[stream] = NULL;
|
||||
} else {
|
||||
chip->get_position[stream] = azx_get_pos_posbuf;
|
||||
if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
|
||||
chip->get_delay[stream] = azx_get_delay_from_lpib;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= azx_dev->bufsize)
|
||||
pos = 0;
|
||||
|
||||
if (WARN_ONCE(!azx_dev->period_bytes,
|
||||
"hda-intel: zero azx_dev->period_bytes"))
|
||||
|
@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
|
|||
*/
|
||||
static void azx_irq_pending_work(struct work_struct *work)
|
||||
{
|
||||
struct azx *chip = container_of(work, struct azx, irq_pending_work);
|
||||
struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
|
||||
struct azx *chip = &hda->chip;
|
||||
int i, pending, ok;
|
||||
|
||||
if (!chip->irq_pending_warned) {
|
||||
if (!hda->irq_pending_warned) {
|
||||
dev_info(chip->card->dev,
|
||||
"IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
|
||||
chip->card->number);
|
||||
chip->irq_pending_warned = 1;
|
||||
hda->irq_pending_warned = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* get the current DMA position with correction on VIA chips */
|
||||
static unsigned int azx_via_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev)
|
||||
{
|
||||
unsigned int link_pos, mini_pos, bound_pos;
|
||||
unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
|
||||
unsigned int fifo_size;
|
||||
|
||||
link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
|
||||
if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
/* Playback, no problem using link position */
|
||||
return link_pos;
|
||||
}
|
||||
|
||||
/* Capture */
|
||||
/* For new chipset,
|
||||
* use mod to get the DMA position just like old chipset
|
||||
*/
|
||||
mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
|
||||
mod_dma_pos %= azx_dev->period_bytes;
|
||||
|
||||
/* azx_dev->fifo_size can't get FIFO size of in stream.
|
||||
* Get from base address + offset.
|
||||
*/
|
||||
fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
|
||||
|
||||
if (azx_dev->insufficient) {
|
||||
/* Link position never gather than FIFO size */
|
||||
if (link_pos <= fifo_size)
|
||||
return 0;
|
||||
|
||||
azx_dev->insufficient = 0;
|
||||
}
|
||||
|
||||
if (link_pos <= fifo_size)
|
||||
mini_pos = azx_dev->bufsize + link_pos - fifo_size;
|
||||
else
|
||||
mini_pos = link_pos - fifo_size;
|
||||
|
||||
/* Find nearest previous boudary */
|
||||
mod_mini_pos = mini_pos % azx_dev->period_bytes;
|
||||
mod_link_pos = link_pos % azx_dev->period_bytes;
|
||||
if (mod_link_pos >= fifo_size)
|
||||
bound_pos = link_pos - mod_link_pos;
|
||||
else if (mod_dma_pos >= mod_mini_pos)
|
||||
bound_pos = mini_pos - mod_mini_pos;
|
||||
else {
|
||||
bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
|
||||
if (bound_pos >= azx_dev->bufsize)
|
||||
bound_pos = 0;
|
||||
}
|
||||
|
||||
/* Calculate real DMA position we want */
|
||||
return bound_pos + mod_dma_pos;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static DEFINE_MUTEX(card_list_lock);
|
||||
static LIST_HEAD(card_list);
|
||||
|
||||
static void azx_add_card_list(struct azx *chip)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
mutex_lock(&card_list_lock);
|
||||
list_add(&chip->list, &card_list);
|
||||
list_add(&hda->list, &card_list);
|
||||
mutex_unlock(&card_list_lock);
|
||||
}
|
||||
|
||||
static void azx_del_card_list(struct azx *chip)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
mutex_lock(&card_list_lock);
|
||||
list_del_init(&chip->list);
|
||||
list_del_init(&hda->list);
|
||||
mutex_unlock(&card_list_lock);
|
||||
}
|
||||
|
||||
/* trigger power-save check at writing parameter */
|
||||
static int param_set_xint(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
struct hda_intel *hda;
|
||||
struct azx *chip;
|
||||
struct hda_codec *c;
|
||||
int prev = power_save;
|
||||
|
@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
|
|||
return ret;
|
||||
|
||||
mutex_lock(&card_list_lock);
|
||||
list_for_each_entry(chip, &card_list, list) {
|
||||
list_for_each_entry(hda, &card_list, list) {
|
||||
chip = &hda->chip;
|
||||
if (!chip->bus || chip->disabled)
|
||||
continue;
|
||||
list_for_each_entry(c, &chip->bus->codec_list, list)
|
||||
|
@ -593,10 +772,16 @@ static int azx_suspend(struct device *dev)
|
|||
{
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct azx *chip;
|
||||
struct hda_intel *hda;
|
||||
struct azx_pcm *p;
|
||||
|
||||
if (chip->disabled || chip->init_failed)
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
if (chip->disabled || hda->init_failed)
|
||||
return 0;
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
|
||||
|
@ -626,9 +811,15 @@ static int azx_resume(struct device *dev)
|
|||
{
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct azx *chip;
|
||||
struct hda_intel *hda;
|
||||
|
||||
if (chip->disabled || chip->init_failed)
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
if (chip->disabled || hda->init_failed)
|
||||
return 0;
|
||||
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
|
@ -663,9 +854,15 @@ static int azx_resume(struct device *dev)
|
|||
static int azx_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct azx *chip;
|
||||
struct hda_intel *hda;
|
||||
|
||||
if (chip->disabled || chip->init_failed)
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
if (chip->disabled || hda->init_failed)
|
||||
return 0;
|
||||
|
||||
if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
||||
|
@ -687,12 +884,18 @@ static int azx_runtime_suspend(struct device *dev)
|
|||
static int azx_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct azx *chip;
|
||||
struct hda_intel *hda;
|
||||
struct hda_bus *bus;
|
||||
struct hda_codec *codec;
|
||||
int status;
|
||||
|
||||
if (chip->disabled || chip->init_failed)
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
if (chip->disabled || hda->init_failed)
|
||||
return 0;
|
||||
|
||||
if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
||||
|
@ -727,9 +930,15 @@ static int azx_runtime_resume(struct device *dev)
|
|||
static int azx_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct azx *chip;
|
||||
struct hda_intel *hda;
|
||||
|
||||
if (chip->disabled || chip->init_failed)
|
||||
if (!card)
|
||||
return 0;
|
||||
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
if (chip->disabled || hda->init_failed)
|
||||
return 0;
|
||||
|
||||
if (!power_save_controller ||
|
||||
|
@ -753,29 +962,6 @@ static const struct dev_pm_ops azx_pm = {
|
|||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/*
|
||||
* reboot notifier for hang-up problem at power-down
|
||||
*/
|
||||
static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
|
||||
{
|
||||
struct azx *chip = container_of(nb, struct azx, reboot_notifier);
|
||||
snd_hda_bus_reboot_notify(chip->bus);
|
||||
azx_stop_chip(chip);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void azx_notifier_register(struct azx *chip)
|
||||
{
|
||||
chip->reboot_notifier.notifier_call = azx_halt;
|
||||
register_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
|
||||
static void azx_notifier_unregister(struct azx *chip)
|
||||
{
|
||||
if (chip->reboot_notifier.notifier_call)
|
||||
unregister_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
|
||||
static int azx_probe_continue(struct azx *chip);
|
||||
|
||||
#ifdef SUPPORT_VGA_SWITCHEROO
|
||||
|
@ -786,10 +972,11 @@ static void azx_vs_set_state(struct pci_dev *pci,
|
|||
{
|
||||
struct snd_card *card = pci_get_drvdata(pci);
|
||||
struct azx *chip = card->private_data;
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
bool disabled;
|
||||
|
||||
wait_for_completion(&chip->probe_wait);
|
||||
if (chip->init_failed)
|
||||
wait_for_completion(&hda->probe_wait);
|
||||
if (hda->init_failed)
|
||||
return;
|
||||
|
||||
disabled = (state == VGA_SWITCHEROO_OFF);
|
||||
|
@ -803,7 +990,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
|
|||
"Start delayed initialization\n");
|
||||
if (azx_probe_continue(chip) < 0) {
|
||||
dev_err(chip->card->dev, "initialization error\n");
|
||||
chip->init_failed = true;
|
||||
hda->init_failed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -833,9 +1020,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
|
|||
{
|
||||
struct snd_card *card = pci_get_drvdata(pci);
|
||||
struct azx *chip = card->private_data;
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
|
||||
wait_for_completion(&chip->probe_wait);
|
||||
if (chip->init_failed)
|
||||
wait_for_completion(&hda->probe_wait);
|
||||
if (hda->init_failed)
|
||||
return false;
|
||||
if (chip->disabled || !chip->bus)
|
||||
return true;
|
||||
|
@ -847,11 +1035,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
|
|||
|
||||
static void init_vga_switcheroo(struct azx *chip)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
struct pci_dev *p = get_bound_vga(chip->pci);
|
||||
if (p) {
|
||||
dev_info(chip->card->dev,
|
||||
"Handle VGA-switcheroo audio client\n");
|
||||
chip->use_vga_switcheroo = 1;
|
||||
hda->use_vga_switcheroo = 1;
|
||||
pci_dev_put(p);
|
||||
}
|
||||
}
|
||||
|
@ -863,9 +1052,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
|
|||
|
||||
static int register_vga_switcheroo(struct azx *chip)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
int err;
|
||||
|
||||
if (!chip->use_vga_switcheroo)
|
||||
if (!hda->use_vga_switcheroo)
|
||||
return 0;
|
||||
/* FIXME: currently only handling DIS controller
|
||||
* is there any machine with two switchable HDMI audio controllers?
|
||||
|
@ -875,11 +1065,11 @@ static int register_vga_switcheroo(struct azx *chip)
|
|||
chip->bus != NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
chip->vga_switcheroo_registered = 1;
|
||||
hda->vga_switcheroo_registered = 1;
|
||||
|
||||
/* register as an optimus hdmi audio power domain */
|
||||
vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
|
||||
&chip->hdmi_pm_domain);
|
||||
&hda->hdmi_pm_domain);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -895,7 +1085,6 @@ static int azx_free(struct azx *chip)
|
|||
{
|
||||
struct pci_dev *pci = chip->pci;
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
|
||||
int i;
|
||||
|
||||
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
|
||||
|
@ -906,13 +1095,13 @@ static int azx_free(struct azx *chip)
|
|||
|
||||
azx_notifier_unregister(chip);
|
||||
|
||||
chip->init_failed = 1; /* to be sure */
|
||||
complete_all(&chip->probe_wait);
|
||||
hda->init_failed = 1; /* to be sure */
|
||||
complete_all(&hda->probe_wait);
|
||||
|
||||
if (use_vga_switcheroo(chip)) {
|
||||
if (use_vga_switcheroo(hda)) {
|
||||
if (chip->disabled && chip->bus)
|
||||
snd_hda_unlock_devices(chip->bus);
|
||||
if (chip->vga_switcheroo_registered)
|
||||
if (hda->vga_switcheroo_registered)
|
||||
vga_switcheroo_unregister_client(chip->pci);
|
||||
}
|
||||
|
||||
|
@ -1048,6 +1237,30 @@ static int check_position_fix(struct azx *chip, int fix)
|
|||
return POS_FIX_AUTO;
|
||||
}
|
||||
|
||||
static void assign_position_fix(struct azx *chip, int fix)
|
||||
{
|
||||
static azx_get_pos_callback_t callbacks[] = {
|
||||
[POS_FIX_AUTO] = NULL,
|
||||
[POS_FIX_LPIB] = azx_get_pos_lpib,
|
||||
[POS_FIX_POSBUF] = azx_get_pos_posbuf,
|
||||
[POS_FIX_VIACOMBO] = azx_via_get_position,
|
||||
[POS_FIX_COMBO] = azx_get_pos_lpib,
|
||||
};
|
||||
|
||||
chip->get_position[0] = chip->get_position[1] = callbacks[fix];
|
||||
|
||||
/* combo mode uses LPIB only for playback */
|
||||
if (fix == POS_FIX_COMBO)
|
||||
chip->get_position[1] = NULL;
|
||||
|
||||
if (fix == POS_FIX_POSBUF &&
|
||||
(chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
|
||||
chip->get_delay[0] = chip->get_delay[1] =
|
||||
azx_get_delay_from_lpib;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* black-lists for probe_mask
|
||||
*/
|
||||
|
@ -1173,7 +1386,8 @@ static void azx_check_snoop_available(struct azx *chip)
|
|||
|
||||
static void azx_probe_work(struct work_struct *work)
|
||||
{
|
||||
azx_probe_continue(container_of(work, struct azx, probe_work));
|
||||
struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
|
||||
azx_probe_continue(&hda->chip);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1216,19 +1430,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
|
|||
check_msi(chip);
|
||||
chip->dev_index = dev;
|
||||
chip->jackpoll_ms = jackpoll_ms;
|
||||
INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
|
||||
INIT_LIST_HEAD(&chip->pcm_list);
|
||||
INIT_LIST_HEAD(&chip->list);
|
||||
INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
|
||||
INIT_LIST_HEAD(&hda->list);
|
||||
init_vga_switcheroo(chip);
|
||||
init_completion(&chip->probe_wait);
|
||||
init_completion(&hda->probe_wait);
|
||||
|
||||
chip->position_fix[0] = chip->position_fix[1] =
|
||||
check_position_fix(chip, position_fix[dev]);
|
||||
/* combo mode uses LPIB for playback */
|
||||
if (chip->position_fix[0] == POS_FIX_COMBO) {
|
||||
chip->position_fix[0] = POS_FIX_LPIB;
|
||||
chip->position_fix[1] = POS_FIX_AUTO;
|
||||
}
|
||||
assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
|
||||
|
||||
check_probe_mask(chip, dev);
|
||||
|
||||
|
@ -1257,7 +1465,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
|
|||
}
|
||||
|
||||
/* continue probing in work context as may trigger request module */
|
||||
INIT_WORK(&chip->probe_work, azx_probe_work);
|
||||
INIT_WORK(&hda->probe_work, azx_probe_work);
|
||||
|
||||
*rchip = chip;
|
||||
|
||||
|
@ -1315,7 +1523,7 @@ static int azx_first_init(struct azx *chip)
|
|||
NULL);
|
||||
if (p_smbus) {
|
||||
if (p_smbus->revision < 0x30)
|
||||
gcap &= ~ICH6_GCAP_64OK;
|
||||
gcap &= ~AZX_GCAP_64OK;
|
||||
pci_dev_put(p_smbus);
|
||||
}
|
||||
}
|
||||
|
@ -1323,7 +1531,7 @@ static int azx_first_init(struct azx *chip)
|
|||
/* disable 64bit DMA address on some devices */
|
||||
if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
|
||||
dev_dbg(card->dev, "Disabling 64bit DMA\n");
|
||||
gcap &= ~ICH6_GCAP_64OK;
|
||||
gcap &= ~AZX_GCAP_64OK;
|
||||
}
|
||||
|
||||
/* disable buffer size rounding to 128-byte multiples if supported */
|
||||
|
@ -1339,7 +1547,7 @@ static int azx_first_init(struct azx *chip)
|
|||
}
|
||||
|
||||
/* allow 64bit DMA address if supported by H/W */
|
||||
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
|
||||
if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
|
||||
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
|
||||
else {
|
||||
pci_set_dma_mask(pci, DMA_BIT_MASK(32));
|
||||
|
@ -1583,6 +1791,7 @@ static int azx_probe(struct pci_dev *pci,
|
|||
{
|
||||
static int dev;
|
||||
struct snd_card *card;
|
||||
struct hda_intel *hda;
|
||||
struct azx *chip;
|
||||
bool schedule_probe;
|
||||
int err;
|
||||
|
@ -1606,6 +1815,7 @@ static int azx_probe(struct pci_dev *pci,
|
|||
if (err < 0)
|
||||
goto out_free;
|
||||
card->private_data = chip;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
|
||||
pci_set_drvdata(pci, card);
|
||||
|
||||
|
@ -1642,11 +1852,11 @@ static int azx_probe(struct pci_dev *pci,
|
|||
#endif
|
||||
|
||||
if (schedule_probe)
|
||||
schedule_work(&chip->probe_work);
|
||||
schedule_work(&hda->probe_work);
|
||||
|
||||
dev++;
|
||||
if (chip->disabled)
|
||||
complete_all(&chip->probe_wait);
|
||||
complete_all(&hda->probe_wait);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
|
@ -1662,6 +1872,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
|
|||
|
||||
static int azx_probe_continue(struct azx *chip)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
struct pci_dev *pci = chip->pci;
|
||||
int dev = chip->dev_index;
|
||||
int err;
|
||||
|
@ -1735,13 +1946,13 @@ static int azx_probe_continue(struct azx *chip)
|
|||
power_down_all_codecs(chip);
|
||||
azx_notifier_register(chip);
|
||||
azx_add_card_list(chip);
|
||||
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
|
||||
if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo)
|
||||
pm_runtime_put_noidle(&pci->dev);
|
||||
|
||||
out_free:
|
||||
if (err < 0)
|
||||
chip->init_failed = 1;
|
||||
complete_all(&chip->probe_wait);
|
||||
hda->init_failed = 1;
|
||||
complete_all(&hda->probe_wait);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1806,6 +2017,9 @@ static const struct pci_device_id azx_ids[] = {
|
|||
/* BayTrail */
|
||||
{ PCI_DEVICE(0x8086, 0x0f04),
|
||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
|
||||
/* Braswell */
|
||||
{ PCI_DEVICE(0x8086, 0x2284),
|
||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||
/* ICH */
|
||||
{ PCI_DEVICE(0x8086, 0x2668),
|
||||
.driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
|
||||
|
|
|
@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
|
|||
const struct hda_input_mux *imux,
|
||||
struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
|
||||
unsigned int *cur_val);
|
||||
int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
|
||||
int snd_hda_add_imux_item(struct hda_codec *codec,
|
||||
struct hda_input_mux *imux, const char *label,
|
||||
int index, int *type_index_ret);
|
||||
|
||||
/*
|
||||
|
@ -437,6 +438,8 @@ struct snd_hda_pin_quirk {
|
|||
|
||||
#endif
|
||||
|
||||
#define HDA_FIXUP_ID_NOT_SET -1
|
||||
#define HDA_FIXUP_ID_NO_FIXUP -2
|
||||
|
||||
/* fixup types */
|
||||
enum {
|
||||
|
@ -773,9 +776,9 @@ struct hdmi_eld {
|
|||
int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
|
||||
int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned char *buf, int *eld_size);
|
||||
int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
|
||||
int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
|
||||
const unsigned char *buf, int size);
|
||||
void snd_hdmi_show_eld(struct parsed_hdmi_eld *e);
|
||||
void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e);
|
||||
void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
|
||||
struct hda_pcm_stream *hinfo);
|
||||
|
||||
|
|
|
@ -22,107 +22,87 @@
|
|||
/*
|
||||
* registers
|
||||
*/
|
||||
#define ICH6_REG_GCAP 0x00
|
||||
#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */
|
||||
#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */
|
||||
#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */
|
||||
#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */
|
||||
#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */
|
||||
#define ICH6_REG_VMIN 0x02
|
||||
#define ICH6_REG_VMAJ 0x03
|
||||
#define ICH6_REG_OUTPAY 0x04
|
||||
#define ICH6_REG_INPAY 0x06
|
||||
#define ICH6_REG_GCTL 0x08
|
||||
#define ICH6_GCTL_RESET (1 << 0) /* controller reset */
|
||||
#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */
|
||||
#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */
|
||||
#define ICH6_REG_WAKEEN 0x0c
|
||||
#define ICH6_REG_STATESTS 0x0e
|
||||
#define ICH6_REG_GSTS 0x10
|
||||
#define ICH6_GSTS_FSTS (1 << 1) /* flush status */
|
||||
#define ICH6_REG_INTCTL 0x20
|
||||
#define ICH6_REG_INTSTS 0x24
|
||||
#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */
|
||||
#define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */
|
||||
#define ICH6_REG_SSYNC 0x38
|
||||
#define ICH6_REG_CORBLBASE 0x40
|
||||
#define ICH6_REG_CORBUBASE 0x44
|
||||
#define ICH6_REG_CORBWP 0x48
|
||||
#define ICH6_REG_CORBRP 0x4a
|
||||
#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */
|
||||
#define ICH6_REG_CORBCTL 0x4c
|
||||
#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */
|
||||
#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */
|
||||
#define ICH6_REG_CORBSTS 0x4d
|
||||
#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */
|
||||
#define ICH6_REG_CORBSIZE 0x4e
|
||||
#define AZX_REG_GCAP 0x00
|
||||
#define AZX_GCAP_64OK (1 << 0) /* 64bit address support */
|
||||
#define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */
|
||||
#define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */
|
||||
#define AZX_GCAP_ISS (15 << 8) /* # of input streams */
|
||||
#define AZX_GCAP_OSS (15 << 12) /* # of output streams */
|
||||
#define AZX_REG_VMIN 0x02
|
||||
#define AZX_REG_VMAJ 0x03
|
||||
#define AZX_REG_OUTPAY 0x04
|
||||
#define AZX_REG_INPAY 0x06
|
||||
#define AZX_REG_GCTL 0x08
|
||||
#define AZX_GCTL_RESET (1 << 0) /* controller reset */
|
||||
#define AZX_GCTL_FCNTRL (1 << 1) /* flush control */
|
||||
#define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */
|
||||
#define AZX_REG_WAKEEN 0x0c
|
||||
#define AZX_REG_STATESTS 0x0e
|
||||
#define AZX_REG_GSTS 0x10
|
||||
#define AZX_GSTS_FSTS (1 << 1) /* flush status */
|
||||
#define AZX_REG_INTCTL 0x20
|
||||
#define AZX_REG_INTSTS 0x24
|
||||
#define AZX_REG_WALLCLK 0x30 /* 24Mhz source */
|
||||
#define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */
|
||||
#define AZX_REG_SSYNC 0x38
|
||||
#define AZX_REG_CORBLBASE 0x40
|
||||
#define AZX_REG_CORBUBASE 0x44
|
||||
#define AZX_REG_CORBWP 0x48
|
||||
#define AZX_REG_CORBRP 0x4a
|
||||
#define AZX_CORBRP_RST (1 << 15) /* read pointer reset */
|
||||
#define AZX_REG_CORBCTL 0x4c
|
||||
#define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */
|
||||
#define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */
|
||||
#define AZX_REG_CORBSTS 0x4d
|
||||
#define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */
|
||||
#define AZX_REG_CORBSIZE 0x4e
|
||||
|
||||
#define ICH6_REG_RIRBLBASE 0x50
|
||||
#define ICH6_REG_RIRBUBASE 0x54
|
||||
#define ICH6_REG_RIRBWP 0x58
|
||||
#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */
|
||||
#define ICH6_REG_RINTCNT 0x5a
|
||||
#define ICH6_REG_RIRBCTL 0x5c
|
||||
#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */
|
||||
#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */
|
||||
#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */
|
||||
#define ICH6_REG_RIRBSTS 0x5d
|
||||
#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */
|
||||
#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */
|
||||
#define ICH6_REG_RIRBSIZE 0x5e
|
||||
#define AZX_REG_RIRBLBASE 0x50
|
||||
#define AZX_REG_RIRBUBASE 0x54
|
||||
#define AZX_REG_RIRBWP 0x58
|
||||
#define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */
|
||||
#define AZX_REG_RINTCNT 0x5a
|
||||
#define AZX_REG_RIRBCTL 0x5c
|
||||
#define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */
|
||||
#define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */
|
||||
#define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */
|
||||
#define AZX_REG_RIRBSTS 0x5d
|
||||
#define AZX_RBSTS_IRQ (1 << 0) /* response irq */
|
||||
#define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */
|
||||
#define AZX_REG_RIRBSIZE 0x5e
|
||||
|
||||
#define ICH6_REG_IC 0x60
|
||||
#define ICH6_REG_IR 0x64
|
||||
#define ICH6_REG_IRS 0x68
|
||||
#define ICH6_IRS_VALID (1<<1)
|
||||
#define ICH6_IRS_BUSY (1<<0)
|
||||
#define AZX_REG_IC 0x60
|
||||
#define AZX_REG_IR 0x64
|
||||
#define AZX_REG_IRS 0x68
|
||||
#define AZX_IRS_VALID (1<<1)
|
||||
#define AZX_IRS_BUSY (1<<0)
|
||||
|
||||
#define ICH6_REG_DPLBASE 0x70
|
||||
#define ICH6_REG_DPUBASE 0x74
|
||||
#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */
|
||||
#define AZX_REG_DPLBASE 0x70
|
||||
#define AZX_REG_DPUBASE 0x74
|
||||
#define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */
|
||||
|
||||
/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
|
||||
enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
||||
|
||||
/* stream register offsets from stream base */
|
||||
#define ICH6_REG_SD_CTL 0x00
|
||||
#define ICH6_REG_SD_STS 0x03
|
||||
#define ICH6_REG_SD_LPIB 0x04
|
||||
#define ICH6_REG_SD_CBL 0x08
|
||||
#define ICH6_REG_SD_LVI 0x0c
|
||||
#define ICH6_REG_SD_FIFOW 0x0e
|
||||
#define ICH6_REG_SD_FIFOSIZE 0x10
|
||||
#define ICH6_REG_SD_FORMAT 0x12
|
||||
#define ICH6_REG_SD_BDLPL 0x18
|
||||
#define ICH6_REG_SD_BDLPU 0x1c
|
||||
#define AZX_REG_SD_CTL 0x00
|
||||
#define AZX_REG_SD_STS 0x03
|
||||
#define AZX_REG_SD_LPIB 0x04
|
||||
#define AZX_REG_SD_CBL 0x08
|
||||
#define AZX_REG_SD_LVI 0x0c
|
||||
#define AZX_REG_SD_FIFOW 0x0e
|
||||
#define AZX_REG_SD_FIFOSIZE 0x10
|
||||
#define AZX_REG_SD_FORMAT 0x12
|
||||
#define AZX_REG_SD_BDLPL 0x18
|
||||
#define AZX_REG_SD_BDLPU 0x1c
|
||||
|
||||
/* PCI space */
|
||||
#define ICH6_PCIREG_TCSEL 0x44
|
||||
#define AZX_PCIREG_TCSEL 0x44
|
||||
|
||||
/*
|
||||
* other constants
|
||||
*/
|
||||
|
||||
/* max number of SDs */
|
||||
/* ICH, ATI and VIA have 4 playback and 4 capture */
|
||||
#define ICH6_NUM_CAPTURE 4
|
||||
#define ICH6_NUM_PLAYBACK 4
|
||||
|
||||
/* ULI has 6 playback and 5 capture */
|
||||
#define ULI_NUM_CAPTURE 5
|
||||
#define ULI_NUM_PLAYBACK 6
|
||||
|
||||
/* ATI HDMI may have up to 8 playbacks and 0 capture */
|
||||
#define ATIHDMI_NUM_CAPTURE 0
|
||||
#define ATIHDMI_NUM_PLAYBACK 8
|
||||
|
||||
/* TERA has 4 playback and 3 capture */
|
||||
#define TERA_NUM_CAPTURE 3
|
||||
#define TERA_NUM_PLAYBACK 4
|
||||
|
||||
/* this number is statically defined for simplicity */
|
||||
#define MAX_AZX_DEV 16
|
||||
|
||||
/* max number of fragments - we may use more if allocating more pages for BDL */
|
||||
#define BDL_SIZE 4096
|
||||
#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
|
||||
|
@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
|||
#define SD_STS_FIFO_READY 0x20 /* FIFO ready */
|
||||
|
||||
/* INTCTL and INTSTS */
|
||||
#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */
|
||||
#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
|
||||
#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
|
||||
#define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */
|
||||
#define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
|
||||
#define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
|
||||
|
||||
/* below are so far hardcoded - should read registers in future */
|
||||
#define ICH6_MAX_CORB_ENTRIES 256
|
||||
#define ICH6_MAX_RIRB_ENTRIES 256
|
||||
#define AZX_MAX_CORB_ENTRIES 256
|
||||
#define AZX_MAX_RIRB_ENTRIES 256
|
||||
|
||||
/* driver quirks (capabilities) */
|
||||
/* bits 0-7 are used for indicating driver type */
|
||||
|
@ -192,35 +172,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
|||
#define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */
|
||||
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
|
||||
|
||||
/* position fix mode */
|
||||
enum {
|
||||
POS_FIX_AUTO,
|
||||
POS_FIX_LPIB,
|
||||
POS_FIX_POSBUF,
|
||||
POS_FIX_VIACOMBO,
|
||||
POS_FIX_COMBO,
|
||||
};
|
||||
|
||||
/* Defines for ATI HD Audio support in SB450 south bridge */
|
||||
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
|
||||
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
|
||||
|
||||
/* Defines for Nvidia HDA support */
|
||||
#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
|
||||
#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
|
||||
#define NVIDIA_HDA_ISTRM_COH 0x4d
|
||||
#define NVIDIA_HDA_OSTRM_COH 0x4c
|
||||
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
|
||||
|
||||
/* Defines for Intel SCH HDA snoop control */
|
||||
#define INTEL_SCH_HDA_DEVC 0x78
|
||||
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
|
||||
|
||||
/* Define IN stream 0 FIFO size offset in VIA controller */
|
||||
#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90
|
||||
/* Define VIA HD Audio Device ID*/
|
||||
#define VIA_HDAC_DEVICE_ID 0x3288
|
||||
|
||||
/* HD Audio class code */
|
||||
#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
|
||||
|
||||
|
@ -325,6 +276,9 @@ struct azx_pcm {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
|
||||
typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos);
|
||||
|
||||
struct azx {
|
||||
struct snd_card *card;
|
||||
struct pci_dev *pci;
|
||||
|
@ -343,6 +297,10 @@ struct azx {
|
|||
/* Register interaction. */
|
||||
const struct hda_controller_ops *ops;
|
||||
|
||||
/* position adjustment callbacks */
|
||||
azx_get_pos_callback_t get_position[2];
|
||||
azx_get_delay_callback_t get_delay[2];
|
||||
|
||||
/* pci resources */
|
||||
unsigned long addr;
|
||||
void __iomem *remap_addr;
|
||||
|
@ -351,7 +309,6 @@ struct azx {
|
|||
/* locks */
|
||||
spinlock_t reg_lock;
|
||||
struct mutex open_mutex; /* Prevents concurrent open/close operations */
|
||||
struct completion probe_wait;
|
||||
|
||||
/* streams (x num_streams) */
|
||||
struct azx_dev *azx_dev;
|
||||
|
@ -378,7 +335,6 @@ struct azx {
|
|||
#endif
|
||||
|
||||
/* flags */
|
||||
int position_fix[2]; /* for both playback/capture streams */
|
||||
const int *bdl_pos_adj;
|
||||
int poll_count;
|
||||
unsigned int running:1;
|
||||
|
@ -386,46 +342,23 @@ struct azx {
|
|||
unsigned int single_cmd:1;
|
||||
unsigned int polling_mode:1;
|
||||
unsigned int msi:1;
|
||||
unsigned int irq_pending_warned:1;
|
||||
unsigned int probing:1; /* codec probing phase */
|
||||
unsigned int snoop:1;
|
||||
unsigned int align_buffer_size:1;
|
||||
unsigned int region_requested:1;
|
||||
|
||||
/* VGA-switcheroo setup */
|
||||
unsigned int use_vga_switcheroo:1;
|
||||
unsigned int vga_switcheroo_registered:1;
|
||||
unsigned int init_failed:1; /* delayed init failed */
|
||||
unsigned int disabled:1; /* disabled by VGA-switcher */
|
||||
|
||||
/* for debugging */
|
||||
unsigned int last_cmd[AZX_MAX_CODECS];
|
||||
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
|
||||
struct work_struct probe_work;
|
||||
|
||||
/* reboot notifier (for mysterious hangup problem at power-down) */
|
||||
struct notifier_block reboot_notifier;
|
||||
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||
struct azx_dev saved_azx_dev;
|
||||
#endif
|
||||
|
||||
/* secondary power domain for hdmi audio under vga device */
|
||||
struct dev_pm_domain hdmi_pm_domain;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_VERBOSE_PRINTK
|
||||
#define SFX /* nop */
|
||||
#else
|
||||
#define SFX "hda-intel "
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#define azx_snoop(chip) ((chip)->snoop)
|
||||
#else
|
||||
|
@ -437,29 +370,29 @@ struct azx {
|
|||
*/
|
||||
|
||||
#define azx_writel(chip, reg, value) \
|
||||
((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
|
||||
#define azx_readl(chip, reg) \
|
||||
((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg))
|
||||
#define azx_writew(chip, reg, value) \
|
||||
((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg))
|
||||
#define azx_readw(chip, reg) \
|
||||
((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg))
|
||||
#define azx_writeb(chip, reg, value) \
|
||||
((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg))
|
||||
#define azx_readb(chip, reg) \
|
||||
((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg))
|
||||
|
||||
#define azx_sd_writel(chip, dev, reg, value) \
|
||||
((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg))
|
||||
#define azx_sd_readl(chip, dev, reg) \
|
||||
((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg))
|
||||
#define azx_sd_writew(chip, dev, reg, value) \
|
||||
((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg))
|
||||
#define azx_sd_readw(chip, dev, reg) \
|
||||
((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg))
|
||||
#define azx_sd_writeb(chip, dev, reg, value) \
|
||||
((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg))
|
||||
#define azx_sd_readb(chip, dev, reg) \
|
||||
((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg))
|
||||
((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))
|
||||
|
||||
#endif /* __SOUND_HDA_PRIV_H */
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
|
@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev)
|
|||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
|
||||
int status;
|
||||
|
||||
hda_tegra_enable_clocks(hda);
|
||||
|
||||
/* Read STATESTS before controller reset */
|
||||
status = azx_readw(chip, STATESTS);
|
||||
|
||||
hda_tegra_init(hda);
|
||||
|
||||
azx_init_chip(chip, 1);
|
||||
|
@ -294,30 +289,6 @@ static const struct dev_pm_ops hda_tegra_pm = {
|
|||
SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
|
||||
};
|
||||
|
||||
/*
|
||||
* reboot notifier for hang-up problem at power-down
|
||||
*/
|
||||
static int hda_tegra_halt(struct notifier_block *nb, unsigned long event,
|
||||
void *buf)
|
||||
{
|
||||
struct azx *chip = container_of(nb, struct azx, reboot_notifier);
|
||||
snd_hda_bus_reboot_notify(chip->bus);
|
||||
azx_stop_chip(chip);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void hda_tegra_notifier_register(struct azx *chip)
|
||||
{
|
||||
chip->reboot_notifier.notifier_call = hda_tegra_halt;
|
||||
register_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
|
||||
static void hda_tegra_notifier_unregister(struct azx *chip)
|
||||
{
|
||||
if (chip->reboot_notifier.notifier_call)
|
||||
unregister_reboot_notifier(&chip->reboot_notifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* destructor
|
||||
*/
|
||||
|
@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
|
|||
int i;
|
||||
struct azx *chip = device->device_data;
|
||||
|
||||
hda_tegra_notifier_unregister(chip);
|
||||
azx_notifier_unregister(chip);
|
||||
|
||||
if (chip->initialized) {
|
||||
for (i = 0; i < chip->num_streams; i++)
|
||||
|
@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card,
|
|||
chip->driver_type = driver_caps & 0xff;
|
||||
chip->dev_index = 0;
|
||||
INIT_LIST_HEAD(&chip->pcm_list);
|
||||
INIT_LIST_HEAD(&chip->list);
|
||||
|
||||
chip->position_fix[0] = POS_FIX_AUTO;
|
||||
chip->position_fix[1] = POS_FIX_AUTO;
|
||||
chip->codec_probe_mask = -1;
|
||||
|
||||
chip->single_cmd = false;
|
||||
|
@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
|
|||
|
||||
chip->running = 1;
|
||||
power_down_all_codecs(chip);
|
||||
hda_tegra_notifier_register(chip);
|
||||
azx_notifier_register(chip);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -2046,14 +2046,14 @@ enum dma_state {
|
|||
DMA_STATE_RUN = 1
|
||||
};
|
||||
|
||||
static int dma_convert_to_hda_format(
|
||||
static int dma_convert_to_hda_format(struct hda_codec *codec,
|
||||
unsigned int sample_rate,
|
||||
unsigned short channels,
|
||||
unsigned short *hda_format)
|
||||
{
|
||||
unsigned int format_val;
|
||||
|
||||
format_val = snd_hda_calc_stream_format(
|
||||
format_val = snd_hda_calc_stream_format(codec,
|
||||
sample_rate,
|
||||
channels,
|
||||
SNDRV_PCM_FORMAT_S32_LE,
|
||||
|
@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec,
|
|||
}
|
||||
|
||||
dma_engine->codec = codec;
|
||||
dma_convert_to_hda_format(sample_rate, channels, &hda_format);
|
||||
dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format);
|
||||
dma_engine->m_converter_format = hda_format;
|
||||
dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
|
||||
DSP_DMA_WRITE_BUFLEN_INIT) * 2;
|
||||
|
|
|
@ -657,8 +657,10 @@ static void cs4208_fixup_mac(struct hda_codec *codec,
|
|||
{
|
||||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
|
||||
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
|
||||
snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
|
||||
if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO)
|
||||
if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET)
|
||||
codec->fixup_id = CS4208_GPIO0; /* default fixup */
|
||||
snd_hda_apply_fixup(codec, action);
|
||||
}
|
||||
|
|
|
@ -31,549 +31,10 @@
|
|||
#include "hda_jack.h"
|
||||
#include "hda_generic.h"
|
||||
|
||||
#undef ENABLE_CMI_STATIC_QUIRKS
|
||||
|
||||
#ifdef ENABLE_CMI_STATIC_QUIRKS
|
||||
#define NUM_PINS 11
|
||||
|
||||
|
||||
/* board config type */
|
||||
enum {
|
||||
CMI_MINIMAL, /* back 3-jack */
|
||||
CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */
|
||||
CMI_FULL, /* back 6-jack + front-panel 2-jack */
|
||||
CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */
|
||||
CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */
|
||||
CMI_AUTO, /* let driver guess it */
|
||||
CMI_MODELS
|
||||
};
|
||||
#endif /* ENABLE_CMI_STATIC_QUIRKS */
|
||||
|
||||
struct cmi_spec {
|
||||
struct hda_gen_spec gen;
|
||||
|
||||
#ifdef ENABLE_CMI_STATIC_QUIRKS
|
||||
/* below are only for static models */
|
||||
|
||||
int board_config;
|
||||
unsigned int no_line_in: 1; /* no line-in (5-jack) */
|
||||
unsigned int front_panel: 1; /* has front-panel 2-jack */
|
||||
|
||||
/* playback */
|
||||
struct hda_multi_out multiout;
|
||||
hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */
|
||||
int num_dacs;
|
||||
|
||||
/* capture */
|
||||
const hda_nid_t *adc_nids;
|
||||
hda_nid_t dig_in_nid;
|
||||
|
||||
/* capture source */
|
||||
const struct hda_input_mux *input_mux;
|
||||
unsigned int cur_mux[2];
|
||||
|
||||
/* channel mode */
|
||||
int num_channel_modes;
|
||||
const struct hda_channel_mode *channel_modes;
|
||||
|
||||
struct hda_pcm pcm_rec[2]; /* PCM information */
|
||||
|
||||
/* pin default configuration */
|
||||
hda_nid_t pin_nid[NUM_PINS];
|
||||
unsigned int def_conf[NUM_PINS];
|
||||
unsigned int pin_def_confs;
|
||||
|
||||
/* multichannel pins */
|
||||
struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
|
||||
#endif /* ENABLE_CMI_STATIC_QUIRKS */
|
||||
};
|
||||
|
||||
#ifdef ENABLE_CMI_STATIC_QUIRKS
|
||||
/*
|
||||
* input MUX
|
||||
*/
|
||||
static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_input_mux_info(spec->input_mux, uinfo);
|
||||
}
|
||||
|
||||
static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
|
||||
return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
|
||||
spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
|
||||
}
|
||||
|
||||
/*
|
||||
* shared line-in, mic for surrounds
|
||||
*/
|
||||
|
||||
/* 3-stack / 2 channel */
|
||||
static const struct hda_verb cmi9880_ch2_init[] = {
|
||||
/* set line-in PIN for input */
|
||||
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
/* set mic PIN for input, also enable vref */
|
||||
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
/* route front PCM (DAC1) to HP */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
|
||||
{}
|
||||
};
|
||||
|
||||
/* 3-stack / 6 channel */
|
||||
static const struct hda_verb cmi9880_ch6_init[] = {
|
||||
/* set line-in PIN for output */
|
||||
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
/* set mic PIN for output */
|
||||
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
/* route front PCM (DAC1) to HP */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
|
||||
{}
|
||||
};
|
||||
|
||||
/* 3-stack+front / 8 channel */
|
||||
static const struct hda_verb cmi9880_ch8_init[] = {
|
||||
/* set line-in PIN for output */
|
||||
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
/* set mic PIN for output */
|
||||
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
/* route rear-surround PCM (DAC4) to HP */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct hda_channel_mode cmi9880_channel_modes[3] = {
|
||||
{ 2, cmi9880_ch2_init },
|
||||
{ 6, cmi9880_ch6_init },
|
||||
{ 8, cmi9880_ch8_init },
|
||||
};
|
||||
|
||||
static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes,
|
||||
spec->num_channel_modes);
|
||||
}
|
||||
|
||||
static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes,
|
||||
spec->num_channel_modes, spec->multiout.max_channels);
|
||||
}
|
||||
|
||||
static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes,
|
||||
spec->num_channel_modes, &spec->multiout.max_channels);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static const struct snd_kcontrol_new cmi9880_basic_mixer[] = {
|
||||
/* CMI9880 has no playback volumes! */
|
||||
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
|
||||
HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
/* The multiple "Capture Source" controls confuse alsamixer
|
||||
* So call somewhat different..
|
||||
*/
|
||||
/* .name = "Capture Source", */
|
||||
.name = "Input Source",
|
||||
.count = 2,
|
||||
.info = cmi_mux_enum_info,
|
||||
.get = cmi_mux_enum_get,
|
||||
.put = cmi_mux_enum_put,
|
||||
},
|
||||
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
/*
|
||||
* shared I/O pins
|
||||
*/
|
||||
static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Channel Mode",
|
||||
.info = cmi_ch_mode_info,
|
||||
.get = cmi_ch_mode_get,
|
||||
.put = cmi_ch_mode_put,
|
||||
},
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
/* AUD-in selections:
|
||||
* 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
|
||||
*/
|
||||
static const struct hda_input_mux cmi9880_basic_mux = {
|
||||
.num_items = 4,
|
||||
.items = {
|
||||
{ "Front Mic", 0x5 },
|
||||
{ "Rear Mic", 0x2 },
|
||||
{ "Line", 0x1 },
|
||||
{ "CD", 0x7 },
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hda_input_mux cmi9880_no_line_mux = {
|
||||
.num_items = 3,
|
||||
.items = {
|
||||
{ "Front Mic", 0x5 },
|
||||
{ "Rear Mic", 0x2 },
|
||||
{ "CD", 0x7 },
|
||||
}
|
||||
};
|
||||
|
||||
/* front, rear, clfe, rear_surr */
|
||||
static const hda_nid_t cmi9880_dac_nids[4] = {
|
||||
0x03, 0x04, 0x05, 0x06
|
||||
};
|
||||
/* ADC0, ADC1 */
|
||||
static const hda_nid_t cmi9880_adc_nids[2] = {
|
||||
0x08, 0x09
|
||||
};
|
||||
|
||||
#define CMI_DIG_OUT_NID 0x07
|
||||
#define CMI_DIG_IN_NID 0x0a
|
||||
|
||||
/*
|
||||
*/
|
||||
static const struct hda_verb cmi9880_basic_init[] = {
|
||||
/* port-D for line out (rear panel) */
|
||||
{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* port-E for HP out (front panel) */
|
||||
{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* route front PCM to HP */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
|
||||
/* port-A for surround (rear panel) */
|
||||
{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* port-G for CLFE (rear panel) */
|
||||
{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
|
||||
/* port-H for side (rear panel) */
|
||||
{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
|
||||
/* port-C for line-in (rear panel) */
|
||||
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
/* port-B for mic-in (rear panel) with vref */
|
||||
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
/* port-F for mic-in (front panel) with vref */
|
||||
{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
/* CD-in */
|
||||
{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
/* route front mic to ADC1/2 */
|
||||
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
|
||||
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static const struct hda_verb cmi9880_allout_init[] = {
|
||||
/* port-D for line out (rear panel) */
|
||||
{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* port-E for HP out (front panel) */
|
||||
{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* route front PCM to HP */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
|
||||
/* port-A for side (rear panel) */
|
||||
{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* port-G for CLFE (rear panel) */
|
||||
{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
|
||||
/* port-H for side (rear panel) */
|
||||
{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
|
||||
/* port-C for surround (rear panel) */
|
||||
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
|
||||
/* port-B for mic-in (rear panel) with vref */
|
||||
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
/* port-F for mic-in (front panel) with vref */
|
||||
{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
/* CD-in */
|
||||
{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
/* route front mic to ADC1/2 */
|
||||
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
|
||||
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
static int cmi9880_build_controls(struct hda_codec *codec)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
struct snd_kcontrol *kctl;
|
||||
int i, err;
|
||||
|
||||
err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (spec->channel_modes) {
|
||||
err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (spec->multiout.dig_out_nid) {
|
||||
err = snd_hda_create_spdif_out_ctls(codec,
|
||||
spec->multiout.dig_out_nid,
|
||||
spec->multiout.dig_out_nid);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_hda_create_spdif_share_sw(codec,
|
||||
&spec->multiout);
|
||||
if (err < 0)
|
||||
return err;
|
||||
spec->multiout.share_spdif = 1;
|
||||
}
|
||||
if (spec->dig_in_nid) {
|
||||
err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* assign Capture Source enums to NID */
|
||||
kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
|
||||
for (i = 0; kctl && i < kctl->count; i++) {
|
||||
err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmi9880_init(struct hda_codec *codec)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
if (spec->board_config == CMI_ALLOUT)
|
||||
snd_hda_sequence_write(codec, cmi9880_allout_init);
|
||||
else
|
||||
snd_hda_sequence_write(codec, cmi9880_basic_init);
|
||||
if (spec->board_config == CMI_AUTO)
|
||||
snd_hda_sequence_write(codec, spec->multi_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Analog playback callbacks
|
||||
*/
|
||||
static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
|
||||
hinfo);
|
||||
}
|
||||
|
||||
static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
unsigned int stream_tag,
|
||||
unsigned int format,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
|
||||
format, substream);
|
||||
}
|
||||
|
||||
static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Digital out
|
||||
*/
|
||||
static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
|
||||
}
|
||||
|
||||
static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
|
||||
}
|
||||
|
||||
static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
unsigned int stream_tag,
|
||||
unsigned int format,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
|
||||
format, substream);
|
||||
}
|
||||
|
||||
/*
|
||||
* Analog capture
|
||||
*/
|
||||
static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
unsigned int stream_tag,
|
||||
unsigned int format,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
|
||||
snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
|
||||
stream_tag, 0, format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
|
||||
snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
static const struct hda_pcm_stream cmi9880_pcm_analog_playback = {
|
||||
.substreams = 1,
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.nid = 0x03, /* NID to query formats and rates */
|
||||
.ops = {
|
||||
.open = cmi9880_playback_pcm_open,
|
||||
.prepare = cmi9880_playback_pcm_prepare,
|
||||
.cleanup = cmi9880_playback_pcm_cleanup
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_pcm_stream cmi9880_pcm_analog_capture = {
|
||||
.substreams = 2,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.nid = 0x08, /* NID to query formats and rates */
|
||||
.ops = {
|
||||
.prepare = cmi9880_capture_pcm_prepare,
|
||||
.cleanup = cmi9880_capture_pcm_cleanup
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_pcm_stream cmi9880_pcm_digital_playback = {
|
||||
.substreams = 1,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
/* NID is set in cmi9880_build_pcms */
|
||||
.ops = {
|
||||
.open = cmi9880_dig_playback_pcm_open,
|
||||
.close = cmi9880_dig_playback_pcm_close,
|
||||
.prepare = cmi9880_dig_playback_pcm_prepare
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_pcm_stream cmi9880_pcm_digital_capture = {
|
||||
.substreams = 1,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
/* NID is set in cmi9880_build_pcms */
|
||||
};
|
||||
|
||||
static int cmi9880_build_pcms(struct hda_codec *codec)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
struct hda_pcm *info = spec->pcm_rec;
|
||||
|
||||
codec->num_pcms = 1;
|
||||
codec->pcm_info = info;
|
||||
|
||||
info->name = "CMI9880";
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
|
||||
|
||||
if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
|
||||
codec->num_pcms++;
|
||||
info++;
|
||||
info->name = "CMI9880 Digital";
|
||||
info->pcm_type = HDA_PCM_TYPE_SPDIF;
|
||||
if (spec->multiout.dig_out_nid) {
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
|
||||
}
|
||||
if (spec->dig_in_nid) {
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cmi9880_free(struct hda_codec *codec)
|
||||
{
|
||||
kfree(codec->spec);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
static const char * const cmi9880_models[CMI_MODELS] = {
|
||||
[CMI_MINIMAL] = "minimal",
|
||||
[CMI_MIN_FP] = "min_fp",
|
||||
[CMI_FULL] = "full",
|
||||
[CMI_FULL_DIG] = "full_dig",
|
||||
[CMI_ALLOUT] = "allout",
|
||||
[CMI_AUTO] = "auto",
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk cmi9880_cfg_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
|
||||
SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL),
|
||||
SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static const struct hda_codec_ops cmi9880_patch_ops = {
|
||||
.build_controls = cmi9880_build_controls,
|
||||
.build_pcms = cmi9880_build_pcms,
|
||||
.init = cmi9880_init,
|
||||
.free = cmi9880_free,
|
||||
};
|
||||
#endif /* ENABLE_CMI_STATIC_QUIRKS */
|
||||
|
||||
/*
|
||||
* stuff for auto-parser
|
||||
*/
|
||||
|
@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = {
|
|||
.unsol_event = snd_hda_jack_unsol_event,
|
||||
};
|
||||
|
||||
static int cmi_parse_auto_config(struct hda_codec *codec)
|
||||
static int patch_cmi9880(struct hda_codec *codec)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
struct auto_pin_cfg *cfg = &spec->gen.autocfg;
|
||||
struct cmi_spec *spec;
|
||||
struct auto_pin_cfg *cfg;
|
||||
int err;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->spec = spec;
|
||||
cfg = &spec->gen.autocfg;
|
||||
snd_hda_gen_spec_init(&spec->gen);
|
||||
|
||||
err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
|
||||
|
@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int patch_cmi9880(struct hda_codec *codec)
|
||||
{
|
||||
struct cmi_spec *spec;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->spec = spec;
|
||||
#ifdef ENABLE_CMI_STATIC_QUIRKS
|
||||
spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS,
|
||||
cmi9880_models,
|
||||
cmi9880_cfg_tbl);
|
||||
if (spec->board_config < 0) {
|
||||
codec_dbg(codec, "%s: BIOS auto-probing.\n",
|
||||
codec->chip_name);
|
||||
spec->board_config = CMI_AUTO; /* try everything */
|
||||
}
|
||||
|
||||
if (spec->board_config == CMI_AUTO)
|
||||
return cmi_parse_auto_config(codec);
|
||||
|
||||
/* copy default DAC NIDs */
|
||||
memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
|
||||
spec->num_dacs = 4;
|
||||
|
||||
switch (spec->board_config) {
|
||||
case CMI_MINIMAL:
|
||||
case CMI_MIN_FP:
|
||||
spec->channel_modes = cmi9880_channel_modes;
|
||||
if (spec->board_config == CMI_MINIMAL)
|
||||
spec->num_channel_modes = 2;
|
||||
else {
|
||||
spec->front_panel = 1;
|
||||
spec->num_channel_modes = 3;
|
||||
}
|
||||
spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
|
||||
spec->input_mux = &cmi9880_basic_mux;
|
||||
break;
|
||||
case CMI_FULL:
|
||||
case CMI_FULL_DIG:
|
||||
spec->front_panel = 1;
|
||||
spec->multiout.max_channels = 8;
|
||||
spec->input_mux = &cmi9880_basic_mux;
|
||||
if (spec->board_config == CMI_FULL_DIG) {
|
||||
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
|
||||
spec->dig_in_nid = CMI_DIG_IN_NID;
|
||||
}
|
||||
break;
|
||||
case CMI_ALLOUT:
|
||||
default:
|
||||
spec->front_panel = 1;
|
||||
spec->multiout.max_channels = 8;
|
||||
spec->no_line_in = 1;
|
||||
spec->input_mux = &cmi9880_no_line_mux;
|
||||
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
|
||||
break;
|
||||
}
|
||||
|
||||
spec->multiout.num_dacs = spec->num_dacs;
|
||||
spec->multiout.dac_nids = spec->dac_nids;
|
||||
|
||||
spec->adc_nids = cmi9880_adc_nids;
|
||||
|
||||
codec->patch_ops = cmi9880_patch_ops;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return cmi_parse_auto_config(codec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* patch entries
|
||||
*/
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca)
|
|||
*
|
||||
* TODO: it could select the wrong CA from multiple candidates.
|
||||
*/
|
||||
static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
|
||||
static int hdmi_channel_allocation(struct hda_codec *codec,
|
||||
struct hdmi_eld *eld, int channels)
|
||||
{
|
||||
int i;
|
||||
int ca = 0;
|
||||
|
@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
|
|||
}
|
||||
|
||||
snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
|
||||
snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
|
||||
codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
|
||||
ca, channels, buf);
|
||||
|
||||
return ca;
|
||||
|
@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
|||
if (!non_pcm && per_pin->chmap_set)
|
||||
ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
|
||||
else
|
||||
ca = hdmi_channel_allocation(eld, channels);
|
||||
ca = hdmi_channel_allocation(codec, eld, channels);
|
||||
if (ca < 0)
|
||||
ca = 0;
|
||||
|
||||
|
@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
|||
eld->eld_valid = false;
|
||||
else {
|
||||
memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
|
||||
if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer,
|
||||
if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
|
||||
eld->eld_size) < 0)
|
||||
eld->eld_valid = false;
|
||||
}
|
||||
|
||||
if (eld->eld_valid) {
|
||||
snd_hdmi_show_eld(&eld->info);
|
||||
snd_hdmi_show_eld(codec, &eld->info);
|
||||
update_eld = true;
|
||||
}
|
||||
else if (repoll) {
|
||||
|
@ -3355,6 +3356,7 @@ static const struct hda_codec_preset snd_hda_preset_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 = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi },
|
||||
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
|
||||
{} /* terminator */
|
||||
};
|
||||
|
@ -3414,6 +3416,7 @@ 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:80862883");
|
||||
MODULE_ALIAS("snd-hda-codec-id:808629fb");
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -101,6 +101,7 @@ struct alc_spec {
|
|||
/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
|
||||
int mute_led_polarity;
|
||||
hda_nid_t mute_led_nid;
|
||||
hda_nid_t cap_mute_led_nid;
|
||||
|
||||
unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
|
||||
|
||||
|
@ -3402,7 +3403,8 @@ static unsigned int led_power_filter(struct hda_codec *codec,
|
|||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
|
||||
if (power_state != AC_PWRST_D3 || nid == 0 ||
|
||||
(nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
|
||||
return power_state;
|
||||
|
||||
/* Set pin ctl again, it might have just been set to 0 */
|
||||
|
@ -3520,6 +3522,68 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
/* turn on/off mic-mute LED per capture hook */
|
||||
static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
unsigned int pinval, enable, disable;
|
||||
|
||||
pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
|
||||
pinval &= ~AC_PINCTL_VREFEN;
|
||||
enable = pinval | AC_PINCTL_VREF_80;
|
||||
disable = pinval | AC_PINCTL_VREF_HIZ;
|
||||
|
||||
if (!ucontrol)
|
||||
return;
|
||||
|
||||
if (ucontrol->value.integer.value[0] ||
|
||||
ucontrol->value.integer.value[1])
|
||||
pinval = disable;
|
||||
else
|
||||
pinval = enable;
|
||||
|
||||
if (spec->cap_mute_led_nid)
|
||||
snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
|
||||
}
|
||||
|
||||
static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
static const struct hda_verb gpio_init[] = {
|
||||
{ 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
|
||||
{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
|
||||
{}
|
||||
};
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
|
||||
spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
|
||||
spec->gpio_led = 0;
|
||||
spec->cap_mute_led_nid = 0x18;
|
||||
snd_hda_add_verbs(codec, gpio_init);
|
||||
codec->power_filter = led_power_filter;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
|
||||
spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
|
||||
spec->mute_led_polarity = 0;
|
||||
spec->mute_led_nid = 0x1a;
|
||||
spec->cap_mute_led_nid = 0x18;
|
||||
spec->gen.vmaster_mute_enum = 1;
|
||||
codec->power_filter = led_power_filter;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
||||
{
|
||||
int val;
|
||||
|
@ -4231,6 +4295,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
|
|||
/* for hda_fixup_thinkpad_acpi() */
|
||||
#include "thinkpad_helper.c"
|
||||
|
||||
/* for dell wmi mic mute led */
|
||||
#include "dell_wmi_helper.c"
|
||||
|
||||
enum {
|
||||
ALC269_FIXUP_SONY_VAIO,
|
||||
ALC275_FIXUP_SONY_VAIO_GPIO2,
|
||||
|
@ -4255,6 +4322,8 @@ enum {
|
|||
ALC269_FIXUP_HP_MUTE_LED_MIC1,
|
||||
ALC269_FIXUP_HP_MUTE_LED_MIC2,
|
||||
ALC269_FIXUP_HP_GPIO_LED,
|
||||
ALC269_FIXUP_HP_GPIO_MIC1_LED,
|
||||
ALC269_FIXUP_HP_LINE1_MIC1_LED,
|
||||
ALC269_FIXUP_INV_DMIC,
|
||||
ALC269_FIXUP_LENOVO_DOCK,
|
||||
ALC269_FIXUP_NO_SHUTUP,
|
||||
|
@ -4292,6 +4361,8 @@ enum {
|
|||
ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
|
||||
ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
ALC292_FIXUP_TPT440_DOCK,
|
||||
ALC283_FIXUP_BXBT2807_MIC,
|
||||
ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
|
@ -4447,6 +4518,14 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_hp_gpio_led,
|
||||
},
|
||||
[ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_hp_gpio_mic1_led,
|
||||
},
|
||||
[ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_hp_line1_mic1_led,
|
||||
},
|
||||
[ALC269_FIXUP_INV_DMIC] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_inv_dmic_0x12,
|
||||
|
@ -4718,6 +4797,20 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
|
||||
},
|
||||
[ALC283_FIXUP_BXBT2807_MIC] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x19, 0x04a110f0 },
|
||||
{ },
|
||||
},
|
||||
},
|
||||
[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_dell_wmi,
|
||||
.chained_before = true,
|
||||
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
|
@ -4727,7 +4820,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
|
||||
SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||
SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
|
||||
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
|
||||
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
|
||||
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
||||
|
@ -4761,10 +4853,12 @@ 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", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
|
||||
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, 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_DELL_WMI_MIC_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
|
||||
SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||
|
@ -4782,6 +4876,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
|
||||
/* ALC282 */
|
||||
SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
|
@ -4790,6 +4886,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
|
@ -4814,13 +4924,43 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
/* ALC290 */
|
||||
SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
|
@ -4843,7 +4983,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
|
@ -4864,9 +5003,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
|
||||
SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
|
||||
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
|
||||
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
|
||||
|
@ -4891,7 +5030,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
||||
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
|
||||
|
||||
#if 0
|
||||
|
@ -4945,6 +5083,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
|
||||
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
|
||||
SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
|
||||
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct hda_model_fixup alc269_fixup_models[] = {
|
||||
{.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
|
||||
{.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
|
||||
|
@ -5040,6 +5186,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
|||
{0x1d, 0x40700001},
|
||||
{0x1e, 0x411111f0},
|
||||
{0x21, 0x02211040}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
|
||||
{0x12, 0x99a30130},
|
||||
{0x14, 0x90170110},
|
||||
{0x17, 0x40000000},
|
||||
{0x18, 0x411111f0},
|
||||
{0x19, 0x03a11020},
|
||||
{0x1a, 0x411111f0},
|
||||
{0x1b, 0x411111f0},
|
||||
{0x1d, 0x40f41905},
|
||||
{0x1e, 0x411111f0},
|
||||
{0x21, 0x0321101f}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
{0x12, 0x90a60130},
|
||||
{0x14, 0x90170110},
|
||||
|
@ -5162,6 +5319,8 @@ static int patch_alc269(struct hda_codec *codec)
|
|||
snd_hda_pick_fixup(codec, alc269_fixup_models,
|
||||
alc269_fixup_tbl, alc269_fixups);
|
||||
snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
|
||||
snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
|
||||
alc269_fixups);
|
||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
||||
|
||||
alc_auto_parse_customize_define(codec);
|
||||
|
@ -5858,6 +6017,7 @@ 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, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
|
||||
SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
|
||||
SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
|
||||
|
|
|
@ -84,6 +84,7 @@ enum {
|
|||
STAC_DELL_EQ,
|
||||
STAC_ALIENWARE_M17X,
|
||||
STAC_92HD89XX_HP_FRONT_JACK,
|
||||
STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
|
||||
STAC_92HD73XX_MODELS
|
||||
};
|
||||
|
||||
|
@ -103,6 +104,7 @@ enum {
|
|||
STAC_92HD83XXX_HP,
|
||||
STAC_HP_ENVY_BASS,
|
||||
STAC_HP_BNB13_EQ,
|
||||
STAC_HP_ENVY_TS_BASS,
|
||||
STAC_92HD83XXX_MODELS
|
||||
};
|
||||
|
||||
|
@ -1017,7 +1019,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec)
|
|||
for (i = 0; i < num_cons; i++) {
|
||||
if (snd_BUG_ON(!labels[i]))
|
||||
return -EINVAL;
|
||||
snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL);
|
||||
snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL);
|
||||
}
|
||||
|
||||
kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer);
|
||||
|
@ -1809,6 +1811,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = {
|
||||
{ 0x0e, 0x400000f0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
|
@ -1931,6 +1938,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
|
|||
[STAC_92HD89XX_HP_FRONT_JACK] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = stac92hd89xx_hp_front_jack_pin_configs,
|
||||
},
|
||||
[STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1991,6 +2002,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
|
|||
"Alienware M17x", STAC_ALIENWARE_M17X),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
|
||||
"Alienware M17x R3", STAC_DELL_EQ),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927,
|
||||
"HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
|
||||
"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
|
||||
{} /* terminator */
|
||||
|
@ -2668,6 +2681,13 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = STAC_92HD83XXX_HP_MIC_LED,
|
||||
},
|
||||
[STAC_HP_ENVY_TS_BASS] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x10, 0x92170111 },
|
||||
{}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_model_fixup stac92hd83xxx_models[] = {
|
||||
|
@ -2684,6 +2704,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = {
|
|||
{ .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" },
|
||||
{ .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" },
|
||||
{ .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" },
|
||||
{ .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -2739,6 +2760,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
|
|||
"HP bNB13", STAC_HP_BNB13_EQ),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A,
|
||||
"HP bNB13", STAC_HP_BNB13_EQ),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e,
|
||||
"HP ENVY TS", STAC_HP_ENVY_TS_BASS),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940,
|
||||
"HP bNB13", STAC_HP_BNB13_EQ),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941,
|
||||
|
@ -3438,9 +3461,11 @@ static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec,
|
|||
{
|
||||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
|
||||
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
|
||||
snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl,
|
||||
stac922x_fixups);
|
||||
if (codec->fixup_id != STAC_INTEL_MAC_AUTO)
|
||||
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
|
||||
snd_hda_apply_fixup(codec, action);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,14 +41,17 @@
|
|||
#define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x)
|
||||
|
||||
#define ICE1712_REG_CONTROL 0x00 /* byte */
|
||||
#define ICE1712_RESET 0x80 /* reset whole chip */
|
||||
#define ICE1712_SERR_LEVEL 0x04 /* SERR# level otherwise edge */
|
||||
#define ICE1712_RESET 0x80 /* soft reset whole chip */
|
||||
#define ICE1712_SERR_ASSERT_DS_DMA 0x40 /* disabled SERR# assertion for the DS DMA Ch-C irq otherwise enabled */
|
||||
#define ICE1712_DOS_VOL 0x10 /* DOS WT/FM volume control */
|
||||
#define ICE1712_SERR_LEVEL 0x08 /* SERR# level otherwise edge */
|
||||
#define ICE1712_SERR_ASSERT_SB 0x02 /* disabled SERR# assertion for SB irq otherwise enabled */
|
||||
#define ICE1712_NATIVE 0x01 /* native mode otherwise SB */
|
||||
#define ICE1712_REG_IRQMASK 0x01 /* byte */
|
||||
#define ICE1712_IRQ_MPU1 0x80
|
||||
#define ICE1712_IRQ_TIMER 0x40
|
||||
#define ICE1712_IRQ_MPU2 0x20
|
||||
#define ICE1712_IRQ_PROPCM 0x10
|
||||
#define ICE1712_IRQ_MPU1 0x80 /* MIDI irq mask */
|
||||
#define ICE1712_IRQ_TIMER 0x40 /* Timer mask */
|
||||
#define ICE1712_IRQ_MPU2 0x20 /* Secondary MIDI irq mask */
|
||||
#define ICE1712_IRQ_PROPCM 0x10 /* professional multi-track */
|
||||
#define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */
|
||||
#define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */
|
||||
#define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */
|
||||
|
|
|
@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr,
|
|||
{
|
||||
u32 headptr, tailptr;
|
||||
u32 msg_frame_address;
|
||||
int err, i;
|
||||
int i;
|
||||
|
||||
if (snd_BUG_ON(msg->size % 4))
|
||||
return -EINVAL;
|
||||
|
||||
err = 0;
|
||||
|
||||
/* get message frame address */
|
||||
tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
|
||||
headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
|
||||
|
|
|
@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
|
|||
{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
|
||||
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -100,8 +100,8 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Xonar Essence ST (Deluxe)/STX
|
||||
* -----------------------------
|
||||
* Xonar Essence ST (Deluxe)/STX (II)
|
||||
* ----------------------------------
|
||||
*
|
||||
* CMI8788:
|
||||
*
|
||||
|
@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip,
|
|||
chip->model.resume = xonar_stx_resume;
|
||||
chip->model.set_dac_params = set_pcm1796_params;
|
||||
break;
|
||||
case 0x85f4:
|
||||
chip->model = model_xonar_st;
|
||||
/* TODO: daughterboard support */
|
||||
chip->model.shortname = "Xonar STX II";
|
||||
chip->model.init = xonar_stx_init;
|
||||
chip->model.resume = xonar_stx_resume;
|
||||
chip->model.set_dac_params = set_pcm1796_params;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -941,7 +941,7 @@ setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
|
|||
union cmdret rptr = CMDRET_ZERO;
|
||||
int i = 0;
|
||||
|
||||
snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
|
||||
snd_printdd("sent mixer %d: 0x%x 0x%x\n", num, rval, lval);
|
||||
do {
|
||||
SEND_SDGV(cif, num, num, rval, lval);
|
||||
SEND_RDGV(cif, num, num, &rptr);
|
||||
|
@ -1080,7 +1080,7 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval,
|
|||
return -EIO;
|
||||
*rval = rptr.retwords[0];
|
||||
*lval = rptr.retwords[1];
|
||||
snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
|
||||
snd_printdd("got mixer %d: 0x%x 0x%x\n", num, *rval, *lval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi
|
|||
{
|
||||
unsigned long flags;
|
||||
void (*private_free)(struct snd_trident_voice *);
|
||||
void *private_data;
|
||||
|
||||
if (voice == NULL || !voice->use)
|
||||
return;
|
||||
snd_trident_clear_voices(trident, voice->number, voice->number);
|
||||
spin_lock_irqsave(&trident->voice_alloc, flags);
|
||||
private_free = voice->private_free;
|
||||
private_data = voice->private_data;
|
||||
voice->private_free = NULL;
|
||||
voice->private_data = NULL;
|
||||
if (voice->pcm)
|
||||
|
|
|
@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset)
|
|||
static struct snd_util_memblk *
|
||||
search_empty(struct snd_util_memhdr *hdr, int size)
|
||||
{
|
||||
struct snd_util_memblk *blk, *prev;
|
||||
struct snd_util_memblk *blk;
|
||||
int page, psize;
|
||||
struct list_head *p;
|
||||
|
||||
psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1);
|
||||
prev = NULL;
|
||||
page = 0;
|
||||
list_for_each(p, &hdr->block) {
|
||||
blk = list_entry(p, struct snd_util_memblk, list);
|
||||
|
|
|
@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
|
|||
source "sound/soc/intel/Kconfig"
|
||||
source "sound/soc/mxs/Kconfig"
|
||||
source "sound/soc/pxa/Kconfig"
|
||||
source "sound/soc/rockchip/Kconfig"
|
||||
source "sound/soc/samsung/Kconfig"
|
||||
source "sound/soc/s6000/Kconfig"
|
||||
source "sound/soc/sh/Kconfig"
|
||||
|
|
|
@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/
|
|||
obj-$(CONFIG_SND_SOC) += omap/
|
||||
obj-$(CONFIG_SND_SOC) += kirkwood/
|
||||
obj-$(CONFIG_SND_SOC) += pxa/
|
||||
obj-$(CONFIG_SND_SOC) += rockchip/
|
||||
obj-$(CONFIG_SND_SOC) += samsung/
|
||||
obj-$(CONFIG_SND_SOC) += s6000/
|
||||
obj-$(CONFIG_SND_SOC) += sh/
|
||||
|
|
|
@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
u32 tfmr, rfmr, tcmr, rcmr;
|
||||
int start_event;
|
||||
int ret;
|
||||
int fslen, fslen_ext;
|
||||
|
||||
/*
|
||||
* Currently, there is only one set of dma params for
|
||||
|
@ -387,18 +388,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The SSC only supports up to 16-bit samples in I2S format, due
|
||||
* to the size of the Frame Mode Register FSLEN field.
|
||||
*/
|
||||
if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
|
||||
&& bits > 16) {
|
||||
printk(KERN_WARNING
|
||||
"atmel_ssc_dai: sample size %d "
|
||||
"is too large for I2S\n", bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute SSC register settings.
|
||||
*/
|
||||
|
@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
* from the MCK divider, and the BCLK signal
|
||||
* is output on the SSC TK line.
|
||||
*/
|
||||
|
||||
if (bits > 16 && !ssc->pdata->has_fslen_ext) {
|
||||
dev_err(dai->dev,
|
||||
"sample size %d is too large for SSC device\n",
|
||||
bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fslen_ext = (bits - 1) / 16;
|
||||
fslen = (bits - 1) % 16;
|
||||
|
||||
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
|
||||
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
||||
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
|
||||
|
@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
|
||||
|
||||
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
|
||||
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
|
||||
| SSC_BF(RFMR_FSLEN, (bits - 1))
|
||||
| SSC_BF(RFMR_FSLEN, fslen)
|
||||
| SSC_BF(RFMR_DATNB, (channels - 1))
|
||||
| SSC_BIT(RFMR_MSBF)
|
||||
| SSC_BF(RFMR_LOOP, 0)
|
||||
|
@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
|
||||
| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
|
||||
|
||||
tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
|
||||
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
||||
| SSC_BF(TFMR_FSDEN, 0)
|
||||
| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
|
||||
| SSC_BF(TFMR_FSLEN, (bits - 1))
|
||||
| SSC_BF(TFMR_FSLEN, fslen)
|
||||
| SSC_BF(TFMR_DATNB, (channels - 1))
|
||||
| SSC_BIT(TFMR_MSBF)
|
||||
| SSC_BF(TFMR_DATDEF, 0)
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
#include "../codecs/wm8904.h"
|
||||
#include "atmel_ssc_dai.h"
|
||||
|
||||
#define MCLK_RATE 32768
|
||||
|
||||
static struct clk *mclk;
|
||||
|
||||
static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic", NULL),
|
||||
|
@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = {
|
|||
.hw_params = atmel_asoc_wm8904_hw_params,
|
||||
};
|
||||
|
||||
static int atmel_set_bias_level(struct snd_soc_card *card,
|
||||
struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
clk_prepare_enable(mclk);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
clk_disable_unprepare(mclk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
|
||||
.name = "WM8904",
|
||||
.stream_name = "WM8904 PCM",
|
||||
|
@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
|
|||
static struct snd_soc_card atmel_asoc_wm8904_card = {
|
||||
.name = "atmel_asoc_wm8904",
|
||||
.owner = THIS_MODULE,
|
||||
.set_bias_level = atmel_set_bias_level,
|
||||
.dai_link = &atmel_asoc_wm8904_dailink,
|
||||
.num_links = 1,
|
||||
.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
|
||||
|
@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct snd_soc_card *card = &atmel_asoc_wm8904_card;
|
||||
struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
|
||||
struct clk *clk_src;
|
||||
int id, ret;
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
|
@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mclk = clk_get(NULL, "pck0");
|
||||
if (IS_ERR(mclk)) {
|
||||
dev_err(&pdev->dev, "failed to get pck0\n");
|
||||
ret = PTR_ERR(mclk);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
clk_src = clk_get(NULL, "clk32k");
|
||||
if (IS_ERR(clk_src)) {
|
||||
dev_err(&pdev->dev, "failed to get clk32k\n");
|
||||
ret = PTR_ERR(clk_src);
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
ret = clk_set_parent(mclk, clk_src);
|
||||
clk_put(clk_src);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to set MCLK parent\n");
|
||||
goto err_set_audio;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
|
||||
clk_set_rate(mclk, MCLK_RATE);
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed\n");
|
||||
|
|
|
@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
|
|||
unsigned int sample_size = runtime->sample_bits / 8;
|
||||
void *buf = runtime->dma_area;
|
||||
struct bf5xx_i2s_pcm_data *dma_data;
|
||||
unsigned int offset, size;
|
||||
unsigned int offset, samples;
|
||||
|
||||
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
|
||||
if (dma_data->tdm_mode) {
|
||||
offset = pos * 8 * sample_size;
|
||||
size = count * 8 * sample_size;
|
||||
samples = count * 8;
|
||||
} else {
|
||||
offset = frames_to_bytes(runtime, pos);
|
||||
size = frames_to_bytes(runtime, count);
|
||||
samples = count * runtime->channels;
|
||||
}
|
||||
|
||||
snd_pcm_format_set_silence(runtime->format, buf + offset, size);
|
||||
snd_pcm_format_set_silence(runtime->format, buf + offset, samples);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -945,11 +945,11 @@ static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned char inf = 0, mask = 0;
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
inf &= ~PCM_INF2_18WL;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case 18:
|
||||
inf |= PCM_INF2_18WL;
|
||||
break;
|
||||
default:
|
||||
|
@ -1044,11 +1044,11 @@ static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned char inf;
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
inf = 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S18_3LE:
|
||||
case 18:
|
||||
inf = PCM_INF2_18WL;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_CS42L52 if I2C && INPUT
|
||||
select SND_SOC_CS42L56 if I2C && INPUT
|
||||
select SND_SOC_CS42L73 if I2C
|
||||
select SND_SOC_CS4265 if I2C
|
||||
select SND_SOC_CS4270 if I2C
|
||||
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
|
||||
select SND_SOC_CS42XX8_I2C if I2C
|
||||
|
@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_PCM3008
|
||||
select SND_SOC_PCM512x_I2C if I2C
|
||||
select SND_SOC_PCM512x_SPI if SPI_MASTER
|
||||
select SND_SOC_RT286 if I2C
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5640 if I2C
|
||||
select SND_SOC_RT5645 if I2C
|
||||
select SND_SOC_RT5651 if I2C
|
||||
select SND_SOC_RT5670 if I2C
|
||||
select SND_SOC_RT5677 if I2C
|
||||
select SND_SOC_SGTL5000 if I2C
|
||||
select SND_SOC_SI476X if MFD_SI476X_CORE
|
||||
|
@ -91,6 +94,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_STA350 if I2C
|
||||
select SND_SOC_STA529 if I2C
|
||||
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
|
||||
select SND_SOC_TAS2552 if I2C
|
||||
select SND_SOC_TAS5086 if I2C
|
||||
select SND_SOC_TLV320AIC23_I2C if I2C
|
||||
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
|
||||
|
@ -338,6 +342,11 @@ config SND_SOC_CS42L73
|
|||
tristate "Cirrus Logic CS42L73 CODEC"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_CS4265
|
||||
tristate "Cirrus Logic CS4265 CODEC"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
# Cirrus Logic CS4270 Codec
|
||||
config SND_SOC_CS4270
|
||||
tristate "Cirrus Logic CS4270 CODEC"
|
||||
|
@ -445,9 +454,16 @@ config SND_SOC_RL6231
|
|||
default y if SND_SOC_RT5640=y
|
||||
default y if SND_SOC_RT5645=y
|
||||
default y if SND_SOC_RT5651=y
|
||||
default y if SND_SOC_RT5670=y
|
||||
default y if SND_SOC_RT5677=y
|
||||
default m if SND_SOC_RT5640=m
|
||||
default m if SND_SOC_RT5645=m
|
||||
default m if SND_SOC_RT5651=m
|
||||
default m if SND_SOC_RT5670=m
|
||||
default m if SND_SOC_RT5677=m
|
||||
|
||||
config SND_SOC_RT286
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
|
@ -461,6 +477,9 @@ config SND_SOC_RT5645
|
|||
config SND_SOC_RT5651
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5670
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5677
|
||||
tristate
|
||||
|
||||
|
@ -521,6 +540,10 @@ config SND_SOC_STA529
|
|||
config SND_SOC_STAC9766
|
||||
tristate
|
||||
|
||||
config SND_SOC_TAS2552
|
||||
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_TAS5086
|
||||
tristate "Texas Instruments TAS5086 speaker amplifier"
|
||||
depends on I2C
|
||||
|
@ -541,7 +564,9 @@ config SND_SOC_TLV320AIC26
|
|||
depends on SPI
|
||||
|
||||
config SND_SOC_TLV320AIC31XX
|
||||
tristate
|
||||
tristate "Texas Instruments TLV320AIC31xx CODECs"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_TLV320AIC32X4
|
||||
tristate
|
||||
|
|
|
@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
|
|||
snd-soc-cs42l52-objs := cs42l52.o
|
||||
snd-soc-cs42l56-objs := cs42l56.o
|
||||
snd-soc-cs42l73-objs := cs42l73.o
|
||||
snd-soc-cs4265-objs := cs4265.o
|
||||
snd-soc-cs4270-objs := cs4270.o
|
||||
snd-soc-cs4271-objs := cs4271.o
|
||||
snd-soc-cs42xx8-objs := cs42xx8.o
|
||||
|
@ -68,10 +69,12 @@ snd-soc-pcm512x-objs := pcm512x.o
|
|||
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
|
||||
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
|
||||
snd-soc-rl6231-objs := rl6231.o
|
||||
snd-soc-rt286-objs := rt286.o
|
||||
snd-soc-rt5631-objs := rt5631.o
|
||||
snd-soc-rt5640-objs := rt5640.o
|
||||
snd-soc-rt5645-objs := rt5645.o
|
||||
snd-soc-rt5651-objs := rt5651.o
|
||||
snd-soc-rt5670-objs := rt5670.o
|
||||
snd-soc-rt5677-objs := rt5677.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
|
@ -162,6 +165,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
|
|||
# Amp
|
||||
snd-soc-max9877-objs := max9877.o
|
||||
snd-soc-tpa6130a2-objs := tpa6130a2.o
|
||||
snd-soc-tas2552-objs := tas2552.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
|
||||
obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
|
||||
|
@ -204,6 +208,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
|
|||
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
|
||||
obj-$(CONFIG_SND_SOC_CS42L56) += snd-soc-cs42l56.o
|
||||
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
|
||||
obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o
|
||||
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
|
||||
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
|
||||
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
|
||||
|
@ -235,10 +240,12 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
|
|||
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
||||
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
|
||||
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
|
||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
|
||||
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
|
||||
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
|
||||
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
|
||||
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
||||
|
@ -255,6 +262,7 @@ obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
|
|||
obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
|
||||
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
|
||||
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
|
||||
|
|
|
@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
|
|||
int ret;
|
||||
|
||||
/* add codec as bus device for standard ac97 */
|
||||
ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL,
|
||||
&ac97_bus);
|
||||
ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
|
||||
NULL, &ac97_bus);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg,
|
|||
|
||||
*value = 0;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
*value |= recv_buf[i] << (i * 8);
|
||||
for (i = 0; i < size; i++) {
|
||||
*value <<= 8;
|
||||
*value |= recv_buf[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -359,14 +359,14 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
|
|||
if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
|
||||
return 0;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_width(params)) {
|
||||
case 16:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
case 24:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
case 32:
|
||||
val = ADAU17X1_SERIAL_PORT1_DELAY0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
|
|||
if (adau1977->dvdd_reg)
|
||||
power_off_mask = ~0;
|
||||
else
|
||||
power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
|
||||
|
||||
ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
|
||||
power_off_mask, 0x00);
|
||||
|
|
|
@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = {
|
|||
.extended_frequencies = 1,
|
||||
};
|
||||
|
||||
static struct of_device_id ak4642_of_match[];
|
||||
static const struct of_device_id ak4642_of_match[];
|
||||
static int ak4642_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id ak4642_of_match[] = {
|
||||
static const struct of_device_id ak4642_of_match[] = {
|
||||
{ .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
|
||||
{ .compatible = "asahi-kasei,ak4648", .data = &ak4648_drvdata},
|
||||
|
|
|
@ -14,12 +14,18 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
static const char * const supply_names[] = {
|
||||
"va", "vd"
|
||||
};
|
||||
|
||||
struct ak5386_priv {
|
||||
int reset_gpio;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
|
||||
|
@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
|
|||
{ "Capture", NULL, "AINR" },
|
||||
};
|
||||
|
||||
static int ak5386_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
|
||||
static int ak5386_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ak5386_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak5386_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
|
||||
}
|
||||
#else
|
||||
#define ak5386_soc_suspend NULL
|
||||
#define ak5386_soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_ak5386 = {
|
||||
.probe = ak5386_soc_probe,
|
||||
.remove = ak5386_soc_remove,
|
||||
.suspend = ak5386_soc_suspend,
|
||||
.resume = ak5386_soc_resume,
|
||||
.dapm_widgets = ak5386_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
|
||||
.dapm_routes = ak5386_dapm_routes,
|
||||
|
@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ak5386_priv *priv;
|
||||
int ret, i;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
|
|||
priv->reset_gpio = -EINVAL;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
priv->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
|
||||
priv->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
|
||||
priv->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
"reset-gpio", 0);
|
||||
|
|
|
@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_init_spk);
|
||||
|
||||
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
|
||||
{ "OUT1R", NULL, "OUT1L" },
|
||||
{ "OUT2R", NULL, "OUT2L" },
|
||||
{ "OUT3R", NULL, "OUT3L" },
|
||||
{ "OUT4R", NULL, "OUT4L" },
|
||||
{ "OUT5R", NULL, "OUT5L" },
|
||||
{ "OUT6R", NULL, "OUT6L" },
|
||||
};
|
||||
|
||||
int arizona_init_mono(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
|
||||
if (arizona->pdata.out_mono[i])
|
||||
snd_soc_dapm_add_routes(&codec->dapm,
|
||||
&arizona_mono_routes[i], 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_init_mono);
|
||||
|
||||
int arizona_init_gpio(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
|
@ -1127,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream,
|
|||
constraint);
|
||||
}
|
||||
|
||||
static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
|
||||
unsigned int rate)
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
struct reg_default dac_comp[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ ARIZONA_DAC_COMP_1, 0 },
|
||||
{ ARIZONA_DAC_COMP_2, 0 },
|
||||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
mutex_lock(&codec->mutex);
|
||||
|
||||
dac_comp[1].def = arizona->dac_comp_coeff;
|
||||
if (rate >= 176400)
|
||||
dac_comp[2].def = arizona->dac_comp_enabled;
|
||||
|
||||
mutex_unlock(&codec->mutex);
|
||||
|
||||
regmap_multi_reg_write(arizona->regmap,
|
||||
dac_comp,
|
||||
ARRAY_SIZE(dac_comp));
|
||||
}
|
||||
|
||||
static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
|
@ -1153,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
|||
|
||||
switch (dai_priv->clk) {
|
||||
case ARIZONA_CLK_SYSCLK:
|
||||
switch (priv->arizona->type) {
|
||||
case WM5102:
|
||||
arizona_wm5102_set_dac_comp(codec,
|
||||
params_rate(params));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
|
||||
ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
|
||||
if (base)
|
||||
|
@ -1175,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
|
||||
int base, int bclk, int lrclk, int frame)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
|
||||
if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
|
||||
if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
|
||||
return true;
|
||||
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
|
||||
if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
|
@ -1185,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
|||
int base = dai->driver->base;
|
||||
const int *rates;
|
||||
int i, ret, val;
|
||||
int channels = params_channels(params);
|
||||
int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
|
||||
int tdm_width = arizona->tdm_width[dai->id - 1];
|
||||
int tdm_slots = arizona->tdm_slots[dai->id - 1];
|
||||
int bclk, lrclk, wl, frame, bclk_target;
|
||||
bool reconfig;
|
||||
unsigned int aif_tx_state, aif_rx_state;
|
||||
|
||||
if (params_rate(params) % 8000)
|
||||
rates = &arizona_44k1_bclk_rates[0];
|
||||
else
|
||||
rates = &arizona_48k_bclk_rates[0];
|
||||
|
||||
bclk_target = snd_soc_params_to_bclk(params);
|
||||
if (chan_limit && chan_limit < params_channels(params)) {
|
||||
if (tdm_slots) {
|
||||
arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
|
||||
tdm_slots, tdm_width);
|
||||
bclk_target = tdm_slots * tdm_width * params_rate(params);
|
||||
channels = tdm_slots;
|
||||
} else {
|
||||
bclk_target = snd_soc_params_to_bclk(params);
|
||||
}
|
||||
|
||||
if (chan_limit && chan_limit < channels) {
|
||||
arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
|
||||
bclk_target /= params_channels(params);
|
||||
bclk_target /= channels;
|
||||
bclk_target *= chan_limit;
|
||||
}
|
||||
|
||||
/* Force stereo for I2S mode */
|
||||
/* Force multiple of 2 channels for I2S mode */
|
||||
val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
|
||||
if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) {
|
||||
arizona_aif_dbg(dai, "Forcing stereo mode\n");
|
||||
bclk_target *= 2;
|
||||
bclk_target /= channels;
|
||||
bclk_target *= channels + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
|
||||
|
@ -1228,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
|||
wl = snd_pcm_format_width(params_format(params));
|
||||
frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
|
||||
|
||||
reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
|
||||
|
||||
if (reconfig) {
|
||||
/* Save AIF TX/RX state */
|
||||
aif_tx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_TX_ENABLES);
|
||||
aif_rx_state = snd_soc_read(codec,
|
||||
base + ARIZONA_AIF_RX_ENABLES);
|
||||
/* Disable AIF TX/RX before reconfiguring it */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
|
||||
}
|
||||
|
||||
ret = arizona_hw_params_rate(substream, params, dai);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
goto restore_aif;
|
||||
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
if (reconfig) {
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_BCLK_CTRL,
|
||||
ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_BCLK_RATE,
|
||||
ARIZONA_AIF1TX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_BCLK_RATE,
|
||||
ARIZONA_AIF1RX_BCPF_MASK, lrclk);
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_1,
|
||||
ARIZONA_AIF1TX_WL_MASK |
|
||||
ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_FRAME_CTRL_2,
|
||||
ARIZONA_AIF1RX_WL_MASK |
|
||||
ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
restore_aif:
|
||||
if (reconfig) {
|
||||
/* Restore AIF TX/RX state */
|
||||
regmap_update_bits_async(arizona->regmap,
|
||||
base + ARIZONA_AIF_TX_ENABLES,
|
||||
0xff, aif_tx_state);
|
||||
regmap_update_bits(arizona->regmap,
|
||||
base + ARIZONA_AIF_RX_ENABLES,
|
||||
0xff, aif_rx_state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *arizona_dai_clk_str(int clk_id)
|
||||
|
@ -1324,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
|
|||
ARIZONA_AIF1_TRI, reg);
|
||||
}
|
||||
|
||||
static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
|
||||
unsigned int base,
|
||||
int channels, unsigned int mask)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int slot, i;
|
||||
|
||||
for (i = 0; i < channels; ++i) {
|
||||
slot = ffs(mask) - 1;
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
regmap_write(arizona->regmap, base + i, slot);
|
||||
|
||||
mask &= ~(1 << slot);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
arizona_aif_warn(dai, "Too many channels in TDM mask\n");
|
||||
}
|
||||
|
||||
static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots, int slot_width)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
int base = dai->driver->base;
|
||||
int rx_max_chan = dai->driver->playback.channels_max;
|
||||
int tx_max_chan = dai->driver->capture.channels_max;
|
||||
|
||||
/* Only support TDM for the physical AIFs */
|
||||
if (dai->id > ARIZONA_MAX_AIF)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (slots == 0) {
|
||||
tx_mask = (1 << tx_max_chan) - 1;
|
||||
rx_mask = (1 << rx_max_chan) - 1;
|
||||
}
|
||||
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
|
||||
tx_max_chan, tx_mask);
|
||||
arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
|
||||
rx_max_chan, rx_mask);
|
||||
|
||||
arizona->tdm_width[dai->id - 1] = slot_width;
|
||||
arizona->tdm_slots[dai->id - 1] = slots;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct snd_soc_dai_ops arizona_dai_ops = {
|
||||
.startup = arizona_startup,
|
||||
.set_fmt = arizona_set_fmt,
|
||||
.set_tdm_slot = arizona_set_tdm_slot,
|
||||
.hw_params = arizona_hw_params,
|
||||
.set_sysclk = arizona_dai_set_sysclk,
|
||||
.set_tristate = arizona_set_tristate,
|
||||
|
@ -1400,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll,
|
|||
{
|
||||
unsigned int Fvco_min;
|
||||
|
||||
if (fll->fout && Fout != fll->fout) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't change output on active FLL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
|
||||
arizona_fll_err(fll,
|
||||
"Can't scale %dMHz in to <=13.5MHz\n",
|
||||
|
@ -1478,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
while (div <= ARIZONA_FLL_MAX_REFDIV) {
|
||||
for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
ratio++) {
|
||||
if ((ARIZONA_FLL_VCO_CORNER / 2) /
|
||||
(fll->vco_mult * ratio) < Fref)
|
||||
break;
|
||||
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
|
@ -1485,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
|
||||
if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
|
||||
Fref)
|
||||
break;
|
||||
|
||||
for (ratio = init_ratio - 1; ratio > 0; ratio--) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
|
@ -1616,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
|
|||
ARIZONA_FLL1_CTRL_UPD | cfg->n);
|
||||
}
|
||||
|
||||
static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
static int arizona_is_enabled_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
unsigned int reg;
|
||||
|
@ -1632,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
|
|||
return reg & ARIZONA_FLL1_ENA;
|
||||
}
|
||||
|
||||
static void arizona_enable_fll(struct arizona_fll *fll)
|
||||
static int arizona_enable_fll(struct arizona_fll *fll)
|
||||
{
|
||||
struct arizona *arizona = fll->arizona;
|
||||
int ret;
|
||||
bool use_sync = false;
|
||||
int already_enabled = arizona_is_enabled_fll(fll);
|
||||
struct arizona_fll_cfg cfg;
|
||||
|
||||
if (already_enabled < 0)
|
||||
return already_enabled;
|
||||
|
||||
if (already_enabled) {
|
||||
/* Facilitate smooth refclk across the transition */
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7,
|
||||
ARIZONA_FLL1_GAIN_MASK, 0);
|
||||
regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN,
|
||||
ARIZONA_FLL1_FREERUN);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have both REFCLK and SYNCCLK then enable both,
|
||||
* otherwise apply the SYNCCLK settings to REFCLK.
|
||||
|
@ -1666,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
} else {
|
||||
arizona_fll_err(fll, "No clocks provided\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1681,14 +1876,12 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_BW,
|
||||
ARIZONA_FLL1_SYNC_BW);
|
||||
|
||||
if (!arizona_is_enabled_fll(fll))
|
||||
if (!already_enabled)
|
||||
pm_runtime_get(arizona->dev);
|
||||
|
||||
/* Clear any pending completions */
|
||||
try_wait_for_completion(&fll->ok);
|
||||
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
|
||||
if (use_sync)
|
||||
|
@ -1696,10 +1889,16 @@ static void arizona_enable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_SYNC_ENA,
|
||||
ARIZONA_FLL1_SYNC_ENA);
|
||||
|
||||
if (already_enabled)
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
ret = wait_for_completion_timeout(&fll->ok,
|
||||
msecs_to_jiffies(250));
|
||||
if (ret == 0)
|
||||
arizona_fll_warn(fll, "Timed out waiting for lock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arizona_disable_fll(struct arizona_fll *fll)
|
||||
|
@ -1713,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
|||
ARIZONA_FLL1_ENA, 0, &change);
|
||||
regmap_update_bits(arizona->regmap, fll->base + 0x11,
|
||||
ARIZONA_FLL1_SYNC_ENA, 0);
|
||||
regmap_update_bits_async(arizona->regmap, fll->base + 1,
|
||||
ARIZONA_FLL1_FREERUN, 0);
|
||||
|
||||
if (change)
|
||||
pm_runtime_put_autosuspend(arizona->dev);
|
||||
|
@ -1721,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
|
|||
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->ref_src == source && fll->ref_freq == Fref)
|
||||
return 0;
|
||||
|
@ -1736,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
|||
fll->ref_freq = Fref;
|
||||
|
||||
if (fll->fout && Fref > 0) {
|
||||
arizona_enable_fll(fll);
|
||||
ret = arizona_enable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
|
||||
|
||||
int arizona_set_fll(struct arizona_fll *fll, int source,
|
||||
unsigned int Fref, unsigned int Fout)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (fll->sync_src == source &&
|
||||
fll->sync_freq == Fref && fll->fout == Fout)
|
||||
|
@ -1768,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
fll->sync_freq = Fref;
|
||||
fll->fout = Fout;
|
||||
|
||||
if (Fout) {
|
||||
arizona_enable_fll(fll);
|
||||
} else {
|
||||
if (Fout)
|
||||
ret = arizona_enable_fll(fll);
|
||||
else
|
||||
arizona_disable_fll(fll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_set_fll);
|
||||
|
||||
|
|
|
@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
|
|||
|
||||
extern int arizona_init_spk(struct snd_soc_codec *codec);
|
||||
extern int arizona_init_gpio(struct snd_soc_codec *codec);
|
||||
extern int arizona_init_mono(struct snd_soc_codec *codec);
|
||||
|
||||
extern int arizona_init_dai(struct arizona_priv *priv, int dai);
|
||||
|
||||
|
|
|
@ -0,0 +1,682 @@
|
|||
/*
|
||||
* cs4265.c -- CS4265 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2014 Cirrus Logic, Inc.
|
||||
*
|
||||
* Author: Paul Handrigan <paul.handrigan@cirrus.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/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "cs4265.h"
|
||||
|
||||
struct cs4265_private {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *reset_gpio;
|
||||
u8 format;
|
||||
u32 sysclk;
|
||||
};
|
||||
|
||||
static const struct reg_default cs4265_reg_defaults[] = {
|
||||
{ CS4265_PWRCTL, 0x0F },
|
||||
{ CS4265_DAC_CTL, 0x08 },
|
||||
{ CS4265_ADC_CTL, 0x00 },
|
||||
{ CS4265_MCLK_FREQ, 0x00 },
|
||||
{ CS4265_SIG_SEL, 0x40 },
|
||||
{ CS4265_CHB_PGA_CTL, 0x00 },
|
||||
{ CS4265_CHA_PGA_CTL, 0x00 },
|
||||
{ CS4265_ADC_CTL2, 0x19 },
|
||||
{ CS4265_DAC_CHA_VOL, 0x00 },
|
||||
{ CS4265_DAC_CHB_VOL, 0x00 },
|
||||
{ CS4265_DAC_CTL2, 0xC0 },
|
||||
{ CS4265_SPDIF_CTL1, 0x00 },
|
||||
{ CS4265_SPDIF_CTL2, 0x00 },
|
||||
{ CS4265_INT_MASK, 0x00 },
|
||||
{ CS4265_STATUS_MODE_MSB, 0x00 },
|
||||
{ CS4265_STATUS_MODE_LSB, 0x00 },
|
||||
};
|
||||
|
||||
static bool cs4265_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CS4265_PWRCTL:
|
||||
case CS4265_DAC_CTL:
|
||||
case CS4265_ADC_CTL:
|
||||
case CS4265_MCLK_FREQ:
|
||||
case CS4265_SIG_SEL:
|
||||
case CS4265_CHB_PGA_CTL:
|
||||
case CS4265_CHA_PGA_CTL:
|
||||
case CS4265_ADC_CTL2:
|
||||
case CS4265_DAC_CHA_VOL:
|
||||
case CS4265_DAC_CHB_VOL:
|
||||
case CS4265_DAC_CTL2:
|
||||
case CS4265_SPDIF_CTL1:
|
||||
case CS4265_SPDIF_CTL2:
|
||||
case CS4265_INT_MASK:
|
||||
case CS4265_STATUS_MODE_MSB:
|
||||
case CS4265_STATUS_MODE_LSB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool cs4265_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case CS4265_INT_STATUS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0);
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0);
|
||||
|
||||
static const char * const digital_input_mux_text[] = {
|
||||
"SDIN1", "SDIN2"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7,
|
||||
digital_input_mux_text);
|
||||
|
||||
static const struct snd_kcontrol_new digital_input_mux =
|
||||
SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum);
|
||||
|
||||
static const char * const mic_linein_text[] = {
|
||||
"MIC", "LINEIN"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0,
|
||||
mic_linein_text);
|
||||
|
||||
static const char * const cam_mode_text[] = {
|
||||
"One Byte", "Two Byte"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5,
|
||||
cam_mode_text);
|
||||
|
||||
static const char * const cam_mono_stereo_text[] = {
|
||||
"Stereo", "Mono"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2,
|
||||
cam_mono_stereo_text);
|
||||
|
||||
static const char * const mono_select_text[] = {
|
||||
"Channel A", "Channel B"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0,
|
||||
mono_select_text);
|
||||
|
||||
static const struct snd_kcontrol_new mic_linein_mux =
|
||||
SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum);
|
||||
|
||||
static const struct snd_kcontrol_new loopback_ctl =
|
||||
SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new spdif_switch =
|
||||
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0);
|
||||
|
||||
static const struct snd_kcontrol_new dac_switch =
|
||||
SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0);
|
||||
|
||||
static const struct snd_kcontrol_new cs4265_snd_controls[] = {
|
||||
|
||||
SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL,
|
||||
CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv),
|
||||
SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL,
|
||||
CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv),
|
||||
SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6,
|
||||
1, 0),
|
||||
SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7,
|
||||
1, 0),
|
||||
SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1,
|
||||
1, 0),
|
||||
SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3,
|
||||
1, 1),
|
||||
SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7,
|
||||
1, 0),
|
||||
SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
|
||||
6, 1, 0),
|
||||
SOC_ENUM("C Data Access", cam_mode_enum),
|
||||
SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
|
||||
3, 1, 0),
|
||||
SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
|
||||
SOC_SINGLE("MMTLR Data Switch", 0,
|
||||
1, 1, 0),
|
||||
SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
|
||||
SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("LINEINL"),
|
||||
SND_SOC_DAPM_INPUT("LINEINR"),
|
||||
SND_SOC_DAPM_INPUT("MICL"),
|
||||
SND_SOC_DAPM_INPUT("MICR"),
|
||||
|
||||
SND_SOC_DAPM_AIF_OUT("DOUT", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux),
|
||||
|
||||
SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1),
|
||||
SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3,
|
||||
1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM,
|
||||
0, 0, &digital_input_mux),
|
||||
|
||||
SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
|
||||
&loopback_ctl),
|
||||
SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
|
||||
&spdif_switch),
|
||||
SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
|
||||
&dac_switch),
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("DIN1", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("DIN2", NULL, 0,
|
||||
SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("TXIN", NULL, 0,
|
||||
CS4265_SPDIF_CTL2, 5, 1),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTR"),
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route cs4265_audio_map[] = {
|
||||
|
||||
{"DIN1", NULL, "DAI1 Playback"},
|
||||
{"DIN2", NULL, "DAI2 Playback"},
|
||||
{"SDIN1 Input Mixer", NULL, "DIN1"},
|
||||
{"SDIN2 Input Mixer", NULL, "DIN2"},
|
||||
{"Input Mux", "SDIN1", "SDIN1 Input Mixer"},
|
||||
{"Input Mux", "SDIN2", "SDIN2 Input Mixer"},
|
||||
{"DAC", "Switch", "Input Mux"},
|
||||
{"SPDIF", "Switch", "Input Mux"},
|
||||
{"LINEOUTL", NULL, "DAC"},
|
||||
{"LINEOUTR", NULL, "DAC"},
|
||||
{"SPDIFOUT", NULL, "SPDIF"},
|
||||
|
||||
{"ADC Mux", "LINEIN", "LINEINL"},
|
||||
{"ADC Mux", "LINEIN", "LINEINR"},
|
||||
{"ADC Mux", "MIC", "MICL"},
|
||||
{"ADC Mux", "MIC", "MICR"},
|
||||
{"ADC", NULL, "ADC Mux"},
|
||||
{"DOUT", NULL, "ADC"},
|
||||
{"DAI1 Capture", NULL, "DOUT"},
|
||||
{"DAI2 Capture", NULL, "DOUT"},
|
||||
|
||||
/* Loopback */
|
||||
{"Loopback", "Switch", "ADC"},
|
||||
{"DAC", NULL, "Loopback"},
|
||||
};
|
||||
|
||||
struct cs4265_clk_para {
|
||||
u32 mclk;
|
||||
u32 rate;
|
||||
u8 fm_mode; /* values 1, 2, or 4 */
|
||||
u8 mclkdiv;
|
||||
};
|
||||
|
||||
static const struct cs4265_clk_para clk_map_table[] = {
|
||||
/*32k*/
|
||||
{8192000, 32000, 0, 0},
|
||||
{12288000, 32000, 0, 1},
|
||||
{16384000, 32000, 0, 2},
|
||||
{24576000, 32000, 0, 3},
|
||||
{32768000, 32000, 0, 4},
|
||||
|
||||
/*44.1k*/
|
||||
{11289600, 44100, 0, 0},
|
||||
{16934400, 44100, 0, 1},
|
||||
{22579200, 44100, 0, 2},
|
||||
{33868000, 44100, 0, 3},
|
||||
{45158400, 44100, 0, 4},
|
||||
|
||||
/*48k*/
|
||||
{12288000, 48000, 0, 0},
|
||||
{18432000, 48000, 0, 1},
|
||||
{24576000, 48000, 0, 2},
|
||||
{36864000, 48000, 0, 3},
|
||||
{49152000, 48000, 0, 4},
|
||||
|
||||
/*64k*/
|
||||
{8192000, 64000, 1, 0},
|
||||
{1228800, 64000, 1, 1},
|
||||
{1693440, 64000, 1, 2},
|
||||
{2457600, 64000, 1, 3},
|
||||
{3276800, 64000, 1, 4},
|
||||
|
||||
/* 88.2k */
|
||||
{11289600, 88200, 1, 0},
|
||||
{16934400, 88200, 1, 1},
|
||||
{22579200, 88200, 1, 2},
|
||||
{33868000, 88200, 1, 3},
|
||||
{45158400, 88200, 1, 4},
|
||||
|
||||
/* 96k */
|
||||
{12288000, 96000, 1, 0},
|
||||
{18432000, 96000, 1, 1},
|
||||
{24576000, 96000, 1, 2},
|
||||
{36864000, 96000, 1, 3},
|
||||
{49152000, 96000, 1, 4},
|
||||
|
||||
/* 128k */
|
||||
{8192000, 128000, 2, 0},
|
||||
{12288000, 128000, 2, 1},
|
||||
{16934400, 128000, 2, 2},
|
||||
{24576000, 128000, 2, 3},
|
||||
{32768000, 128000, 2, 4},
|
||||
|
||||
/* 176.4k */
|
||||
{11289600, 176400, 2, 0},
|
||||
{16934400, 176400, 2, 1},
|
||||
{22579200, 176400, 2, 2},
|
||||
{33868000, 176400, 2, 3},
|
||||
{49152000, 176400, 2, 4},
|
||||
|
||||
/* 192k */
|
||||
{12288000, 192000, 2, 0},
|
||||
{18432000, 192000, 2, 1},
|
||||
{24576000, 192000, 2, 2},
|
||||
{36864000, 192000, 2, 3},
|
||||
{49152000, 192000, 2, 4},
|
||||
};
|
||||
|
||||
static int cs4265_get_clk_index(int mclk, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
|
||||
if (clk_map_table[i].rate == rate &&
|
||||
clk_map_table[i].mclk == mclk)
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
int i;
|
||||
|
||||
if (clk_id != 0) {
|
||||
dev_err(codec->dev, "Invalid clk_id %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
|
||||
if (clk_map_table[i].mclk == freq) {
|
||||
cs4265->sysclk = freq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
cs4265->sysclk = 0;
|
||||
dev_err(codec->dev, "Invalid freq parameter %d\n", freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 iface = 0;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_MASTER,
|
||||
CS4265_ADC_MASTER);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_MASTER,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* interface format */
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
iface |= SND_SOC_DAIFMT_I2S;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
iface |= SND_SOC_DAIFMT_RIGHT_J;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
iface |= SND_SOC_DAIFMT_LEFT_J;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cs4265->format = iface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
|
||||
if (mute) {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_MUTE,
|
||||
CS4265_DAC_CTL_MUTE);
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_MUTE,
|
||||
CS4265_SPDIF_CTL2_MUTE);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_MUTE,
|
||||
0);
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_MUTE,
|
||||
0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
|
||||
int index;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
|
||||
((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK)
|
||||
== SND_SOC_DAIFMT_RIGHT_J))
|
||||
return -EINVAL;
|
||||
|
||||
index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
|
||||
if (index >= 0) {
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_FM, clk_map_table[index].fm_mode);
|
||||
snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
|
||||
CS4265_MCLK_FREQ_MASK,
|
||||
clk_map_table[index].mclkdiv);
|
||||
|
||||
} else {
|
||||
dev_err(codec->dev, "can't get correct mclk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (1 << 4));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_DIF, (1 << 4));
|
||||
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 6));
|
||||
break;
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
if (params_width(params) == 16) {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (1 << 5));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 7));
|
||||
} else {
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, (3 << 5));
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 7));
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
snd_soc_update_bits(codec, CS4265_DAC_CTL,
|
||||
CS4265_DAC_CTL_DIF, 0);
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_ADC_DIF, 0);
|
||||
snd_soc_update_bits(codec, CS4265_ADC_CTL,
|
||||
CS4265_SPDIF_CTL2_DIF, (1 << 6));
|
||||
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs4265_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN, 0);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN,
|
||||
CS4265_PWRCTL_PDN);
|
||||
break;
|
||||
case SND_SOC_BIAS_OFF:
|
||||
snd_soc_update_bits(codec, CS4265_PWRCTL,
|
||||
CS4265_PWRCTL_PDN,
|
||||
CS4265_PWRCTL_PDN);
|
||||
break;
|
||||
}
|
||||
codec->dapm.bias_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
|
||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
|
||||
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
#define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
|
||||
|
||||
static const struct snd_soc_dai_ops cs4265_ops = {
|
||||
.hw_params = cs4265_pcm_hw_params,
|
||||
.digital_mute = cs4265_digital_mute,
|
||||
.set_fmt = cs4265_set_fmt,
|
||||
.set_sysclk = cs4265_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver cs4265_dai[] = {
|
||||
{
|
||||
.name = "cs4265-dai1",
|
||||
.playback = {
|
||||
.stream_name = "DAI1 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "DAI1 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.ops = &cs4265_ops,
|
||||
},
|
||||
{
|
||||
.name = "cs4265-dai2",
|
||||
.playback = {
|
||||
.stream_name = "DAI2 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "DAI2 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = CS4265_RATES,
|
||||
.formats = CS4265_FORMATS,
|
||||
},
|
||||
.ops = &cs4265_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_codec_driver soc_codec_cs4265 = {
|
||||
.set_bias_level = cs4265_set_bias_level,
|
||||
|
||||
.dapm_widgets = cs4265_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets),
|
||||
.dapm_routes = cs4265_audio_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(cs4265_audio_map),
|
||||
|
||||
.controls = cs4265_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(cs4265_snd_controls),
|
||||
};
|
||||
|
||||
static const struct regmap_config cs4265_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = CS4265_MAX_REGISTER,
|
||||
.reg_defaults = cs4265_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
|
||||
.readable_reg = cs4265_readable_register,
|
||||
.volatile_reg = cs4265_volatile_register,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int cs4265_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs4265_private *cs4265;
|
||||
int ret = 0;
|
||||
unsigned int devid = 0;
|
||||
unsigned int reg;
|
||||
|
||||
cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private),
|
||||
GFP_KERNEL);
|
||||
if (cs4265 == NULL)
|
||||
return -ENOMEM;
|
||||
cs4265->dev = &i2c_client->dev;
|
||||
|
||||
cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap);
|
||||
if (IS_ERR(cs4265->regmap)) {
|
||||
ret = PTR_ERR(cs4265->regmap);
|
||||
dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
|
||||
"reset-gpios");
|
||||
if (IS_ERR(cs4265->reset_gpio)) {
|
||||
ret = PTR_ERR(cs4265->reset_gpio);
|
||||
if (ret != -ENOENT && ret != -ENOSYS)
|
||||
return ret;
|
||||
|
||||
cs4265->reset_gpio = NULL;
|
||||
} else {
|
||||
ret = gpiod_direction_output(cs4265->reset_gpio, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
mdelay(1);
|
||||
gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
|
||||
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs4265);
|
||||
|
||||
ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, ®);
|
||||
devid = reg & CS4265_CHIP_ID_MASK;
|
||||
if (devid != CS4265_CHIP_ID_VAL) {
|
||||
ret = -ENODEV;
|
||||
dev_err(&i2c_client->dev,
|
||||
"CS4265 Device ID (%X). Expected %X\n",
|
||||
devid, CS4265_CHIP_ID);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&i2c_client->dev,
|
||||
"CS4265 Version %x\n",
|
||||
reg & CS4265_REV_ID_MASK);
|
||||
|
||||
regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_cs4265, cs4265_dai,
|
||||
ARRAY_SIZE(cs4265_dai));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs4265_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cs4265_of_match[] = {
|
||||
{ .compatible = "cirrus,cs4265", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs4265_of_match);
|
||||
|
||||
static const struct i2c_device_id cs4265_id[] = {
|
||||
{ "cs4265", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs4265_id);
|
||||
|
||||
static struct i2c_driver cs4265_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs4265",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cs4265_of_match,
|
||||
},
|
||||
.id_table = cs4265_id,
|
||||
.probe = cs4265_i2c_probe,
|
||||
.remove = cs4265_i2c_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(cs4265_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC CS4265 driver");
|
||||
MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* cs4265.h -- CS4265 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2014 Cirrus Logic, Inc.
|
||||
*
|
||||
* Author: Paul Handrigan <paul.handrigan@cirrus.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CS4265_H__
|
||||
#define __CS4265_H__
|
||||
|
||||
#define CS4265_CHIP_ID 0x1
|
||||
#define CS4265_CHIP_ID_VAL 0xD0
|
||||
#define CS4265_CHIP_ID_MASK 0xF0
|
||||
#define CS4265_REV_ID_MASK 0x0F
|
||||
|
||||
#define CS4265_PWRCTL 0x02
|
||||
#define CS4265_PWRCTL_PDN 1
|
||||
|
||||
#define CS4265_DAC_CTL 0x3
|
||||
#define CS4265_DAC_CTL_MUTE (1 << 2)
|
||||
#define CS4265_DAC_CTL_DIF (3 << 4)
|
||||
|
||||
#define CS4265_ADC_CTL 0x4
|
||||
#define CS4265_ADC_MASTER 1
|
||||
#define CS4265_ADC_DIF (1 << 4)
|
||||
#define CS4265_ADC_FM (3 << 6)
|
||||
|
||||
#define CS4265_MCLK_FREQ 0x5
|
||||
#define CS4265_MCLK_FREQ_MASK (7 << 4)
|
||||
|
||||
#define CS4265_SIG_SEL 0x6
|
||||
#define CS4265_SIG_SEL_LOOP (1 << 1)
|
||||
|
||||
#define CS4265_CHB_PGA_CTL 0x7
|
||||
#define CS4265_CHA_PGA_CTL 0x8
|
||||
|
||||
#define CS4265_ADC_CTL2 0x9
|
||||
|
||||
#define CS4265_DAC_CHA_VOL 0xA
|
||||
#define CS4265_DAC_CHB_VOL 0xB
|
||||
|
||||
#define CS4265_DAC_CTL2 0xC
|
||||
|
||||
#define CS4265_INT_STATUS 0xD
|
||||
#define CS4265_INT_MASK 0xE
|
||||
#define CS4265_STATUS_MODE_MSB 0xF
|
||||
#define CS4265_STATUS_MODE_LSB 0x10
|
||||
|
||||
#define CS4265_SPDIF_CTL1 0x11
|
||||
|
||||
#define CS4265_SPDIF_CTL2 0x12
|
||||
#define CS4265_SPDIF_CTL2_MUTE (1 << 4)
|
||||
#define CS4265_SPDIF_CTL2_DIF (3 << 6)
|
||||
|
||||
#define CS4265_C_DATA_BUFF 0x13
|
||||
#define CS4265_MAX_REGISTER 0x2A
|
||||
|
||||
#endif
|
|
@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
|
|||
|
||||
cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
|
||||
GFP_KERNEL);
|
||||
if (!cs4270) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
if (!cs4270)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* get the power supply regulators */
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче