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:
Linus Torvalds 2014-08-06 20:07:24 -07:00
commit 930e0312bc
294 changed files with 17276 additions and 7474 deletions

View file

@ -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>;
};

View file

@ -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>;
};

View file

@ -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";
};

View file

@ -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.

View file

@ -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 { };

View file

@ -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>;
};

View file

@ -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";
};

View file

@ -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>;
};

View file

@ -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>;
};

View file

@ -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

View file

@ -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>;
};
};

View file

@ -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";
};

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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,
};

View file

@ -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);

View file

@ -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)

View file

@ -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;
};

View file

@ -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 */

View file

@ -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;
}
}
/*

View file

@ -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 }

19
include/sound/rt286.h Normal file
View file

@ -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

27
include/sound/rt5670.h Normal file
View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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];

View file

@ -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),

View file

@ -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 */

View file

@ -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);

View file

@ -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;
}

View file

@ -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 */

View file

@ -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:

View file

@ -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,

View file

@ -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

View file

@ -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;
}

View file

@ -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) {

View file

@ -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.

View file

@ -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);
}

View file

@ -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)

View file

@ -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;

View file

@ -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) &&

View file

@ -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.

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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++) {

View file

@ -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,

View file

@ -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");

View file

@ -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 */

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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 |

View file

@ -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);

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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
*/

File diff suppressed because it is too large Load diff

View file

@ -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");

View file

@ -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),

View file

@ -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);
}

View file

@ -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 */

View file

@ -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));

View file

@ -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 },
{ }
};

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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);

View file

@ -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"

View file

@ -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/

View file

@ -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)

View file

@ -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");

View file

@ -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;
}

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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:

View file

@ -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);

View file

@ -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},

View file

@ -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);

View file

@ -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);

View file

@ -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);

682
sound/soc/codecs/cs4265.c Normal file
View file

@ -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, &reg);
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");

64
sound/soc/codecs/cs4265.h Normal file
View file

@ -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

View file

@ -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++)

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