diff options
299 files changed, 10340 insertions, 3841 deletions
diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt new file mode 100644 index 000000000000..0e295c9d8937 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/arizona.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | Wolfson Arizona class audio SoCs | ||
2 | |||
3 | These devices are audio SoCs with extensive digital capabilites and a range | ||
4 | of analogue I/O. | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : one of the following chip-specific strings: | ||
9 | "wlf,wm5102" | ||
10 | "wlf,wm5110" | ||
11 | - reg : I2C slave address when connected using I2C, chip select number when | ||
12 | using SPI. | ||
13 | |||
14 | - interrupts : The interrupt line the /IRQ signal for the device is | ||
15 | connected to. | ||
16 | - interrupt-controller : Arizona class devices contain interrupt controllers | ||
17 | and may provide interrupt services to other devices. | ||
18 | - interrupt-parent : The parent interrupt controller. | ||
19 | - #interrupt-cells: the number of cells to describe an IRQ, this should be 2. | ||
20 | The first cell is the IRQ number. | ||
21 | The second cell is the flags, encoded as the trigger masks from | ||
22 | Documentation/devicetree/bindings/interrupts.txt | ||
23 | |||
24 | - gpio-controller : Indicates this device is a GPIO controller. | ||
25 | - #gpio-cells : Must be 2. The first cell is the pin number and the | ||
26 | second cell is used to specify optional parameters (currently unused). | ||
27 | |||
28 | - AVDD1-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply, | ||
29 | SPKVDDL-supply, SPKVDDR-supply : power supplies for the device, as covered | ||
30 | in Documentation/devicetree/bindings/regulator/regulator.txt | ||
31 | |||
32 | Optional properties: | ||
33 | |||
34 | - wlf,reset : GPIO specifier for the GPIO controlling /RESET | ||
35 | - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA | ||
36 | |||
37 | - wlf,gpio-defaults : A list of GPIO configuration register values. If | ||
38 | absent, no configuration of these registers is performed. If any | ||
39 | entry has a value that is out of range for a 16 bit register then | ||
40 | the chip default will be used. If present exactly five values must | ||
41 | be specified. | ||
42 | |||
43 | Example: | ||
44 | |||
45 | codec: wm5102@1a { | ||
46 | compatible = "wlf,wm5102"; | ||
47 | reg = <0x1a>; | ||
48 | interrupts = <347>; | ||
49 | #interrupt-cells = <2>; | ||
50 | interrupt-parent = <&gic>; | ||
51 | |||
52 | gpio-controller; | ||
53 | #gpio-cells = <2>; | ||
54 | |||
55 | wlf,gpio-defaults = < | ||
56 | 0x00000000, /* AIF1TXLRCLK */ | ||
57 | 0xffffffff, | ||
58 | 0xffffffff, | ||
59 | 0xffffffff, | ||
60 | 0xffffffff, | ||
61 | >; | ||
62 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt b/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt new file mode 100644 index 000000000000..f49450a87890 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | Freescale i.MX audio complex with WM8962 codec | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "fsl,imx-audio-wm8962" | ||
5 | - model : The user-visible name of this sound complex | ||
6 | - ssi-controller : The phandle of the i.MX SSI controller | ||
7 | - audio-codec : The phandle of the WM8962 audio codec | ||
8 | - audio-routing : A list of the connections between audio components. | ||
9 | Each entry is a pair of strings, the first being the connection's sink, | ||
10 | the second being the connection's source. Valid names could be power | ||
11 | supplies, WM8962 pins, and the jacks on the board: | ||
12 | |||
13 | Power supplies: | ||
14 | * Mic Bias | ||
15 | |||
16 | Board connectors: | ||
17 | * Mic Jack | ||
18 | * Headphone Jack | ||
19 | * Ext Spk | ||
20 | |||
21 | - mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) | ||
22 | - mux-ext-port : The external port of the i.MX audio muxer | ||
23 | |||
24 | Note: The AUDMUX port numbering should start at 1, which is consistent with | ||
25 | hardware manual. | ||
26 | |||
27 | Example: | ||
28 | |||
29 | sound { | ||
30 | compatible = "fsl,imx6q-sabresd-wm8962", | ||
31 | "fsl,imx-audio-wm8962"; | ||
32 | model = "wm8962-audio"; | ||
33 | ssi-controller = <&ssi2>; | ||
34 | audio-codec = <&codec>; | ||
35 | audio-routing = | ||
36 | "Headphone Jack", "HPOUTL", | ||
37 | "Headphone Jack", "HPOUTR", | ||
38 | "Ext Spk", "SPKOUTL", | ||
39 | "Ext Spk", "SPKOUTR", | ||
40 | "MICBIAS", "AMIC", | ||
41 | "IN3R", "MICBIAS", | ||
42 | "DMIC", "MICBIAS", | ||
43 | "DMICDAT", "DMIC"; | ||
44 | mux-int-port = <2>; | ||
45 | mux-ext-port = <3>; | ||
46 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/mxs-saif.txt b/Documentation/devicetree/bindings/sound/mxs-saif.txt index c37ba6143d9b..7ba07a118e37 100644 --- a/Documentation/devicetree/bindings/sound/mxs-saif.txt +++ b/Documentation/devicetree/bindings/sound/mxs-saif.txt | |||
@@ -3,8 +3,11 @@ | |||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Should be "fsl,<chip>-saif" | 4 | - compatible: Should be "fsl,<chip>-saif" |
5 | - reg: Should contain registers location and length | 5 | - reg: Should contain registers location and length |
6 | - interrupts: Should contain ERROR and DMA interrupts | 6 | - interrupts: Should contain ERROR interrupt number |
7 | - fsl,saif-dma-channel: APBX DMA channel for the SAIF | 7 | - dmas: DMA specifier, consisting of a phandle to DMA controller node |
8 | and SAIF DMA channel ID. | ||
9 | Refer to dma.txt and fsl-mxs-dma.txt for details. | ||
10 | - dma-names: Must be "rx-tx". | ||
8 | 11 | ||
9 | Optional properties: | 12 | Optional properties: |
10 | - fsl,saif-master: phandle to the master SAIF. It's only required for | 13 | - fsl,saif-master: phandle to the master SAIF. It's only required for |
@@ -23,14 +26,16 @@ aliases { | |||
23 | saif0: saif@80042000 { | 26 | saif0: saif@80042000 { |
24 | compatible = "fsl,imx28-saif"; | 27 | compatible = "fsl,imx28-saif"; |
25 | reg = <0x80042000 2000>; | 28 | reg = <0x80042000 2000>; |
26 | interrupts = <59 80>; | 29 | interrupts = <59>; |
27 | fsl,saif-dma-channel = <4>; | 30 | dmas = <&dma_apbx 4>; |
31 | dma-names = "rx-tx"; | ||
28 | }; | 32 | }; |
29 | 33 | ||
30 | saif1: saif@80046000 { | 34 | saif1: saif@80046000 { |
31 | compatible = "fsl,imx28-saif"; | 35 | compatible = "fsl,imx28-saif"; |
32 | reg = <0x80046000 2000>; | 36 | reg = <0x80046000 2000>; |
33 | interrupts = <58 81>; | 37 | interrupts = <58>; |
34 | fsl,saif-dma-channel = <5>; | 38 | dmas = <&dma_apbx 5>; |
39 | dma-names = "rx-tx"; | ||
35 | fsl,saif-master = <&saif0>; | 40 | fsl,saif-master = <&saif0>; |
36 | }; | 41 | }; |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt new file mode 100644 index 000000000000..d130818700b2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt | |||
@@ -0,0 +1,71 @@ | |||
1 | NVIDIA Tegra audio complex, with RT5640 CODEC | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "nvidia,tegra-audio-rt5640" | ||
5 | - clocks : Must contain an entry for each entry in clock-names. | ||
6 | - clock-names : Must include the following entries: | ||
7 | "pll_a" (The Tegra clock of that name), | ||
8 | "pll_a_out0" (The Tegra clock of that name), | ||
9 | "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk) | ||
10 | - nvidia,model : The user-visible name of this sound complex. | ||
11 | - nvidia,audio-routing : A list of the connections between audio components. | ||
12 | Each entry is a pair of strings, the first being the connection's sink, | ||
13 | the second being the connection's source. Valid names for sources and | ||
14 | sinks are the RT5640's pins, and the jacks on the board: | ||
15 | |||
16 | RT5640 pins: | ||
17 | |||
18 | * DMIC1 | ||
19 | * DMIC2 | ||
20 | * MICBIAS1 | ||
21 | * IN1P | ||
22 | * IN1R | ||
23 | * IN2P | ||
24 | * IN2R | ||
25 | * HPOL | ||
26 | * HPOR | ||
27 | * LOUTL | ||
28 | * LOUTR | ||
29 | * MONOP | ||
30 | * MONON | ||
31 | * SPOLP | ||
32 | * SPOLN | ||
33 | * SPORP | ||
34 | * SPORN | ||
35 | |||
36 | Board connectors: | ||
37 | |||
38 | * Headphones | ||
39 | * Speakers | ||
40 | |||
41 | - nvidia,i2s-controller : The phandle of the Tegra I2S controller that's | ||
42 | connected to the CODEC. | ||
43 | - nvidia,audio-codec : The phandle of the RT5640 audio codec. This binding | ||
44 | assumes that AIF1 on the CODEC is connected to Tegra. | ||
45 | |||
46 | Optional properties: | ||
47 | - nvidia,hp-det-gpios : The GPIO that detects headphones are plugged in | ||
48 | |||
49 | Example: | ||
50 | |||
51 | sound { | ||
52 | compatible = "nvidia,tegra-audio-rt5640-dalmore", | ||
53 | "nvidia,tegra-audio-rt5640"; | ||
54 | nvidia,model = "NVIDIA Tegra Dalmore"; | ||
55 | |||
56 | nvidia,audio-routing = | ||
57 | "Headphones", "HPOR", | ||
58 | "Headphones", "HPOL", | ||
59 | "Speakers", "SPORP", | ||
60 | "Speakers", "SPORN", | ||
61 | "Speakers", "SPOLP", | ||
62 | "Speakers", "SPOLN"; | ||
63 | |||
64 | nvidia,i2s-controller = <&tegra_i2s1>; | ||
65 | nvidia,audio-codec = <&rt5640>; | ||
66 | |||
67 | nvidia,hp-det-gpios = <&gpio 143 0>; /* GPIO PR7 */ | ||
68 | |||
69 | clocks = <&tegra_car 216>, <&tegra_car 217>, <&tegra_car 120>; | ||
70 | clock-names = "pll_a", "pll_a_out0", "mclk"; | ||
71 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt new file mode 100644 index 000000000000..005bcb24d72d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5640.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | RT5640 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "realtek,rt5640". | ||
8 | |||
9 | - reg : The I2C address of the device. | ||
10 | |||
11 | - interrupts : The CODEC's interrupt output. | ||
12 | |||
13 | Optional properties: | ||
14 | |||
15 | - realtek,in1-differential | ||
16 | - realtek,in2-differential | ||
17 | Boolean. Indicate MIC1/2 input are differential, rather than single-ended. | ||
18 | |||
19 | - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. | ||
20 | |||
21 | Example: | ||
22 | |||
23 | rt5640 { | ||
24 | compatible = "realtek,rt5640"; | ||
25 | reg = <0x1c>; | ||
26 | interrupt-parent = <&gpio>; | ||
27 | interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>; | ||
28 | realtek,ldo1-en-gpios = | ||
29 | <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; | ||
30 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt index 9cc44449508d..955df60a118c 100644 --- a/Documentation/devicetree/bindings/sound/sgtl5000.txt +++ b/Documentation/devicetree/bindings/sound/sgtl5000.txt | |||
@@ -5,9 +5,12 @@ Required properties: | |||
5 | 5 | ||
6 | - reg : the I2C address of the device | 6 | - reg : the I2C address of the device |
7 | 7 | ||
8 | - clocks : the clock provider of SYS_MCLK | ||
9 | |||
8 | Example: | 10 | Example: |
9 | 11 | ||
10 | codec: sgtl5000@0a { | 12 | codec: sgtl5000@0a { |
11 | compatible = "fsl,sgtl5000"; | 13 | compatible = "fsl,sgtl5000"; |
12 | reg = <0x0a>; | 14 | reg = <0x0a>; |
15 | clocks = <&clks 150>; | ||
13 | }; | 16 | }; |
diff --git a/Documentation/devicetree/bindings/sound/spdif-receiver.txt b/Documentation/devicetree/bindings/sound/spdif-receiver.txt new file mode 100644 index 000000000000..80f807bf8a1d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/spdif-receiver.txt | |||
@@ -0,0 +1,10 @@ | |||
1 | Device-Tree bindings for dummy spdif receiver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "linux,spdif-dir". | ||
5 | |||
6 | Example node: | ||
7 | |||
8 | codec: spdif-receiver { | ||
9 | compatible = "linux,spdif-dir"; | ||
10 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/spdif-transmitter.txt b/Documentation/devicetree/bindings/sound/spdif-transmitter.txt new file mode 100644 index 000000000000..55a85841dd85 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/spdif-transmitter.txt | |||
@@ -0,0 +1,10 @@ | |||
1 | Device-Tree bindings for dummy spdif transmitter | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "linux,spdif-dit". | ||
5 | |||
6 | Example node: | ||
7 | |||
8 | codec: spdif-transmitter { | ||
9 | compatible = "linux,spdif-dit"; | ||
10 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/ssm2518.txt b/Documentation/devicetree/bindings/sound/ssm2518.txt new file mode 100644 index 000000000000..59381a778c79 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ssm2518.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | SSM2518 audio amplifier | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible : Must be "adi,ssm2518" | ||
7 | - reg : the I2C address of the device. This will either be 0x34 (ADDR pin low) | ||
8 | or 0x35 (ADDR pin high) | ||
9 | |||
10 | Optional properties: | ||
11 | - gpios : GPIO connected to the nSD pin. If the property is not present it is | ||
12 | assumed that the nSD pin is hardwired to always on. | ||
13 | |||
14 | Example: | ||
15 | |||
16 | ssm2518: ssm2518@34 { | ||
17 | compatible = "adi,ssm2518"; | ||
18 | reg = <0x34>; | ||
19 | gpios = <&gpio 5 0>; | ||
20 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8962.txt b/Documentation/devicetree/bindings/sound/wm8962.txt index dceb3b1c2bb7..7f82b59ec8f9 100644 --- a/Documentation/devicetree/bindings/sound/wm8962.txt +++ b/Documentation/devicetree/bindings/sound/wm8962.txt | |||
@@ -8,9 +8,32 @@ Required properties: | |||
8 | 8 | ||
9 | - reg : the I2C address of the device. | 9 | - reg : the I2C address of the device. |
10 | 10 | ||
11 | Optional properties: | ||
12 | - spk-mono: This is a boolean property. If present, the SPK_MONO bit | ||
13 | of R51 (Class D Control 2) gets set, indicating that the speaker is | ||
14 | in mono mode. | ||
15 | |||
16 | - mic-cfg : Default register value for R48 (Additional Control 4). | ||
17 | If absent, the default should be the register default. | ||
18 | |||
19 | - gpio-cfg : A list of GPIO configuration register values. The list must | ||
20 | be 6 entries long. If absent, no configuration of these registers is | ||
21 | performed. And note that only the value within [0x0, 0xffff] is valid. | ||
22 | Any other value is regarded as setting the GPIO register by its reset | ||
23 | value 0x0. | ||
24 | |||
11 | Example: | 25 | Example: |
12 | 26 | ||
13 | codec: wm8962@1a { | 27 | codec: wm8962@1a { |
14 | compatible = "wlf,wm8962"; | 28 | compatible = "wlf,wm8962"; |
15 | reg = <0x1a>; | 29 | reg = <0x1a>; |
30 | |||
31 | gpio-cfg = < | ||
32 | 0x0000 /* 0:Default */ | ||
33 | 0x0000 /* 1:Default */ | ||
34 | 0x0013 /* 2:FN_DMICCLK */ | ||
35 | 0x0000 /* 3:Default */ | ||
36 | 0x8014 /* 4:FN_DMICCDAT */ | ||
37 | 0x0000 /* 5:Default */ | ||
38 | >; | ||
16 | }; | 39 | }; |
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 77d68e23b247..809d72b8eff1 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
@@ -21,41 +21,41 @@ ALC267/268 | |||
21 | ========== | 21 | ========== |
22 | inv-dmic Inverted internal mic workaround | 22 | inv-dmic Inverted internal mic workaround |
23 | 23 | ||
24 | ALC269/270/275/276/280/282 | 24 | ALC269/270/275/276/28x/29x |
25 | ====== | 25 | ====== |
26 | laptop-amic Laptops with analog-mic input | 26 | laptop-amic Laptops with analog-mic input |
27 | laptop-dmic Laptops with digital-mic input | 27 | laptop-dmic Laptops with digital-mic input |
28 | alc269-dmic Enable ALC269(VA) digital mic workaround | 28 | alc269-dmic Enable ALC269(VA) digital mic workaround |
29 | alc271-dmic Enable ALC271X digital mic workaround | 29 | alc271-dmic Enable ALC271X digital mic workaround |
30 | inv-dmic Inverted internal mic workaround | 30 | inv-dmic Inverted internal mic workaround |
31 | lenovo-dock Enables docking station I/O for some Lenovos | 31 | lenovo-dock Enables docking station I/O for some Lenovos |
32 | dell-headset-multi Headset jack, which can also be used as mic-in | 32 | dell-headset-multi Headset jack, which can also be used as mic-in |
33 | dell-headset-dock Headset jack (without mic-in), and also dock I/O | 33 | dell-headset-dock Headset jack (without mic-in), and also dock I/O |
34 | 34 | ||
35 | ALC662/663/272 | 35 | ALC66x/67x/892 |
36 | ============== | 36 | ============== |
37 | mario Chromebook mario model fixup | 37 | mario Chromebook mario model fixup |
38 | asus-mode1 ASUS | 38 | asus-mode1 ASUS |
39 | asus-mode2 ASUS | 39 | asus-mode2 ASUS |
40 | asus-mode3 ASUS | 40 | asus-mode3 ASUS |
41 | asus-mode4 ASUS | 41 | asus-mode4 ASUS |
42 | asus-mode5 ASUS | 42 | asus-mode5 ASUS |
43 | asus-mode6 ASUS | 43 | asus-mode6 ASUS |
44 | asus-mode7 ASUS | 44 | asus-mode7 ASUS |
45 | asus-mode8 ASUS | 45 | asus-mode8 ASUS |
46 | inv-dmic Inverted internal mic workaround | 46 | inv-dmic Inverted internal mic workaround |
47 | dell-headset-multi Headset jack, which can also be used as mic-in | 47 | dell-headset-multi Headset jack, which can also be used as mic-in |
48 | 48 | ||
49 | ALC680 | 49 | ALC680 |
50 | ====== | 50 | ====== |
51 | N/A | 51 | N/A |
52 | 52 | ||
53 | ALC882/883/885/888/889 | 53 | ALC88x/898/1150 |
54 | ====================== | 54 | ====================== |
55 | acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G | 55 | acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G |
56 | acer-aspire-8930g Acer Aspire 8330G/6935G | 56 | acer-aspire-8930g Acer Aspire 8330G/6935G |
57 | acer-aspire Acer Aspire others | 57 | acer-aspire Acer Aspire others |
58 | inv-dmic Inverted internal mic workaround | 58 | inv-dmic Inverted internal mic workaround |
59 | no-primary-hp VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC) | 59 | no-primary-hp VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC) |
60 | 60 | ||
61 | ALC861/660 | 61 | ALC861/660 |
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c index d58f50e5aa4b..1e7be62fccb6 100644 --- a/arch/blackfin/mach-bf527/boards/ad7160eval.c +++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c | |||
@@ -283,14 +283,6 @@ static struct platform_device bfin_i2s = { | |||
283 | }; | 283 | }; |
284 | #endif | 284 | #endif |
285 | 285 | ||
286 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
287 | static struct platform_device bfin_tdm = { | ||
288 | .name = "bfin-tdm", | ||
289 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
290 | /* TODO: add platform data here */ | ||
291 | }; | ||
292 | #endif | ||
293 | |||
294 | static struct spi_board_info bfin_spi_board_info[] __initdata = { | 286 | static struct spi_board_info bfin_spi_board_info[] __initdata = { |
295 | #if defined(CONFIG_MTD_M25P80) \ | 287 | #if defined(CONFIG_MTD_M25P80) \ |
296 | || defined(CONFIG_MTD_M25P80_MODULE) | 288 | || defined(CONFIG_MTD_M25P80_MODULE) |
@@ -800,10 +792,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
800 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) | 792 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) |
801 | &bfin_i2s, | 793 | &bfin_i2s, |
802 | #endif | 794 | #endif |
803 | |||
804 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
805 | &bfin_tdm, | ||
806 | #endif | ||
807 | }; | 795 | }; |
808 | 796 | ||
809 | static int __init ad7160eval_init(void) | 797 | static int __init ad7160eval_init(void) |
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 29f16e5c37b9..d0a0c5e527cd 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c | |||
@@ -493,8 +493,7 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = { | |||
493 | }; | 493 | }; |
494 | #endif | 494 | #endif |
495 | 495 | ||
496 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ | 496 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) |
497 | defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
498 | 497 | ||
499 | static const u16 bfin_snd_pin[][7] = { | 498 | static const u16 bfin_snd_pin[][7] = { |
500 | {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, | 499 | {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, |
@@ -549,13 +548,6 @@ static struct platform_device bfin_i2s_pcm = { | |||
549 | }; | 548 | }; |
550 | #endif | 549 | #endif |
551 | 550 | ||
552 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
553 | static struct platform_device bfin_tdm_pcm = { | ||
554 | .name = "bfin-tdm-pcm-audio", | ||
555 | .id = -1, | ||
556 | }; | ||
557 | #endif | ||
558 | |||
559 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 551 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
560 | static struct platform_device bfin_ac97_pcm = { | 552 | static struct platform_device bfin_ac97_pcm = { |
561 | .name = "bfin-ac97-pcm-audio", | 553 | .name = "bfin-ac97-pcm-audio", |
@@ -575,22 +567,10 @@ static struct platform_device bfin_i2s = { | |||
575 | }; | 567 | }; |
576 | #endif | 568 | #endif |
577 | 569 | ||
578 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
579 | static struct platform_device bfin_tdm = { | ||
580 | .name = "bfin-tdm", | ||
581 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
582 | .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), | ||
583 | .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], | ||
584 | .dev = { | ||
585 | .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], | ||
586 | }, | ||
587 | }; | ||
588 | #endif | ||
589 | |||
590 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | 570 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ |
591 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 571 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
592 | static const char * const ad1836_link[] = { | 572 | static const char * const ad1836_link[] = { |
593 | "bfin-tdm.0", | 573 | "bfin-i2s.0", |
594 | "spi0.4", | 574 | "spi0.4", |
595 | }; | 575 | }; |
596 | static struct platform_device bfin_ad1836_machine = { | 576 | static struct platform_device bfin_ad1836_machine = { |
@@ -1269,10 +1249,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
1269 | &bfin_i2s_pcm, | 1249 | &bfin_i2s_pcm, |
1270 | #endif | 1250 | #endif |
1271 | 1251 | ||
1272 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
1273 | &bfin_tdm_pcm, | ||
1274 | #endif | ||
1275 | |||
1276 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 1252 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
1277 | &bfin_ac97_pcm, | 1253 | &bfin_ac97_pcm, |
1278 | #endif | 1254 | #endif |
@@ -1281,10 +1257,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
1281 | &bfin_i2s, | 1257 | &bfin_i2s, |
1282 | #endif | 1258 | #endif |
1283 | 1259 | ||
1284 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
1285 | &bfin_tdm, | ||
1286 | #endif | ||
1287 | |||
1288 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | 1260 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ |
1289 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 1261 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
1290 | &bfin_ad1836_machine, | 1262 | &bfin_ad1836_machine, |
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 07811c209b9d..90fb0d14b147 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c | |||
@@ -450,14 +450,6 @@ static struct platform_device bfin_i2s = { | |||
450 | }; | 450 | }; |
451 | #endif | 451 | #endif |
452 | 452 | ||
453 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
454 | static struct platform_device bfin_tdm = { | ||
455 | .name = "bfin-tdm", | ||
456 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
457 | /* TODO: add platform data here */ | ||
458 | }; | ||
459 | #endif | ||
460 | |||
461 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 453 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
462 | static struct platform_device bfin_ac97 = { | 454 | static struct platform_device bfin_ac97 = { |
463 | .name = "bfin-ac97", | 455 | .name = "bfin-ac97", |
@@ -516,10 +508,6 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
516 | &bfin_i2s, | 508 | &bfin_i2s, |
517 | #endif | 509 | #endif |
518 | 510 | ||
519 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
520 | &bfin_tdm, | ||
521 | #endif | ||
522 | |||
523 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 511 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
524 | &bfin_ac97, | 512 | &bfin_ac97, |
525 | #endif | 513 | #endif |
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 6fca8698bf3b..4a8c2e3fd7e5 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c | |||
@@ -542,8 +542,7 @@ static struct platform_device bfin_dpmc = { | |||
542 | }; | 542 | }; |
543 | 543 | ||
544 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ | 544 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ |
545 | defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) \ | 545 | defined(CONFIG_SND_BF5XX_AC97) || \ |
546 | || defined(CONFIG_SND_BF5XX_AC97) || \ | ||
547 | defined(CONFIG_SND_BF5XX_AC97_MODULE) | 546 | defined(CONFIG_SND_BF5XX_AC97_MODULE) |
548 | 547 | ||
549 | #include <asm/bfin_sport.h> | 548 | #include <asm/bfin_sport.h> |
@@ -603,13 +602,6 @@ static struct platform_device bfin_i2s_pcm = { | |||
603 | }; | 602 | }; |
604 | #endif | 603 | #endif |
605 | 604 | ||
606 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
607 | static struct platform_device bfin_tdm_pcm = { | ||
608 | .name = "bfin-tdm-pcm-audio", | ||
609 | .id = -1, | ||
610 | }; | ||
611 | #endif | ||
612 | |||
613 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 605 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
614 | static struct platform_device bfin_ac97_pcm = { | 606 | static struct platform_device bfin_ac97_pcm = { |
615 | .name = "bfin-ac97-pcm-audio", | 607 | .name = "bfin-ac97-pcm-audio", |
@@ -620,7 +612,7 @@ static struct platform_device bfin_ac97_pcm = { | |||
620 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | 612 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ |
621 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 613 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
622 | static const char * const ad1836_link[] = { | 614 | static const char * const ad1836_link[] = { |
623 | "bfin-tdm.0", | 615 | "bfin-i2s.0", |
624 | "spi0.4", | 616 | "spi0.4", |
625 | }; | 617 | }; |
626 | static struct platform_device bfin_ad1836_machine = { | 618 | static struct platform_device bfin_ad1836_machine = { |
@@ -675,20 +667,6 @@ static struct platform_device bfin_i2s = { | |||
675 | }; | 667 | }; |
676 | #endif | 668 | #endif |
677 | 669 | ||
678 | #if defined(CONFIG_SND_BF5XX_SOC_TDM) || \ | ||
679 | defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) | ||
680 | static struct platform_device bfin_tdm = { | ||
681 | .name = "bfin-tdm", | ||
682 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
683 | .num_resources = | ||
684 | ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), | ||
685 | .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], | ||
686 | .dev = { | ||
687 | .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], | ||
688 | }, | ||
689 | }; | ||
690 | #endif | ||
691 | |||
692 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || \ | 670 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || \ |
693 | defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) | 671 | defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) |
694 | static struct platform_device bfin_ac97 = { | 672 | static struct platform_device bfin_ac97 = { |
@@ -761,10 +739,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
761 | &bfin_i2s_pcm, | 739 | &bfin_i2s_pcm, |
762 | #endif | 740 | #endif |
763 | 741 | ||
764 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
765 | &bfin_tdm_pcm, | ||
766 | #endif | ||
767 | |||
768 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 742 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
769 | &bfin_ac97_pcm, | 743 | &bfin_ac97_pcm, |
770 | #endif | 744 | #endif |
@@ -792,11 +766,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
792 | &bfin_i2s, | 766 | &bfin_i2s, |
793 | #endif | 767 | #endif |
794 | 768 | ||
795 | #if defined(CONFIG_SND_BF5XX_SOC_TDM) || \ | ||
796 | defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) | ||
797 | &bfin_tdm, | ||
798 | #endif | ||
799 | |||
800 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || \ | 769 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || \ |
801 | defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) | 770 | defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) |
802 | &bfin_ac97, | 771 | &bfin_ac97, |
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 6a3a14bcd3a1..44fd1d4682ac 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c | |||
@@ -2570,7 +2570,6 @@ static struct platform_device bfin_dpmc = { | |||
2570 | }; | 2570 | }; |
2571 | 2571 | ||
2572 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ | 2572 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ |
2573 | defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ | ||
2574 | defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 2573 | defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
2575 | 2574 | ||
2576 | #define SPORT_REQ(x) \ | 2575 | #define SPORT_REQ(x) \ |
@@ -2628,13 +2627,6 @@ static struct platform_device bfin_i2s_pcm = { | |||
2628 | }; | 2627 | }; |
2629 | #endif | 2628 | #endif |
2630 | 2629 | ||
2631 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
2632 | static struct platform_device bfin_tdm_pcm = { | ||
2633 | .name = "bfin-tdm-pcm-audio", | ||
2634 | .id = -1, | ||
2635 | }; | ||
2636 | #endif | ||
2637 | |||
2638 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 2630 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
2639 | static struct platform_device bfin_ac97_pcm = { | 2631 | static struct platform_device bfin_ac97_pcm = { |
2640 | .name = "bfin-ac97-pcm-audio", | 2632 | .name = "bfin-ac97-pcm-audio", |
@@ -2645,7 +2637,7 @@ static struct platform_device bfin_ac97_pcm = { | |||
2645 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | 2637 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ |
2646 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 2638 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
2647 | static const char * const ad1836_link[] = { | 2639 | static const char * const ad1836_link[] = { |
2648 | "bfin-tdm.0", | 2640 | "bfin-i2s.0", |
2649 | "spi0.4", | 2641 | "spi0.4", |
2650 | }; | 2642 | }; |
2651 | static struct platform_device bfin_ad1836_machine = { | 2643 | static struct platform_device bfin_ad1836_machine = { |
@@ -2699,18 +2691,6 @@ static struct platform_device bfin_i2s = { | |||
2699 | }; | 2691 | }; |
2700 | #endif | 2692 | #endif |
2701 | 2693 | ||
2702 | #if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) | ||
2703 | static struct platform_device bfin_tdm = { | ||
2704 | .name = "bfin-tdm", | ||
2705 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
2706 | .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), | ||
2707 | .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], | ||
2708 | .dev = { | ||
2709 | .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], | ||
2710 | }, | ||
2711 | }; | ||
2712 | #endif | ||
2713 | |||
2714 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) | 2694 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) |
2715 | static struct platform_device bfin_ac97 = { | 2695 | static struct platform_device bfin_ac97 = { |
2716 | .name = "bfin-ac97", | 2696 | .name = "bfin-ac97", |
@@ -2935,10 +2915,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
2935 | &bfin_i2s_pcm, | 2915 | &bfin_i2s_pcm, |
2936 | #endif | 2916 | #endif |
2937 | 2917 | ||
2938 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
2939 | &bfin_tdm_pcm, | ||
2940 | #endif | ||
2941 | |||
2942 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 2918 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
2943 | &bfin_ac97_pcm, | 2919 | &bfin_ac97_pcm, |
2944 | #endif | 2920 | #endif |
@@ -2961,10 +2937,6 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
2961 | &bfin_i2s, | 2937 | &bfin_i2s, |
2962 | #endif | 2938 | #endif |
2963 | 2939 | ||
2964 | #if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) | ||
2965 | &bfin_tdm, | ||
2966 | #endif | ||
2967 | |||
2968 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) | 2940 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) |
2969 | &bfin_ac97, | 2941 | &bfin_ac97, |
2970 | #endif | 2942 | #endif |
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index c4d07f040947..372eb54944ef 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c | |||
@@ -1393,7 +1393,6 @@ static struct platform_device bfin_dpmc = { | |||
1393 | }; | 1393 | }; |
1394 | 1394 | ||
1395 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ | 1395 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \ |
1396 | defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \ | ||
1397 | defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 1396 | defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
1398 | 1397 | ||
1399 | #define SPORT_REQ(x) \ | 1398 | #define SPORT_REQ(x) \ |
@@ -1461,13 +1460,6 @@ static struct platform_device bfin_i2s_pcm = { | |||
1461 | }; | 1460 | }; |
1462 | #endif | 1461 | #endif |
1463 | 1462 | ||
1464 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
1465 | static struct platform_device bfin_tdm_pcm = { | ||
1466 | .name = "bfin-tdm-pcm-audio", | ||
1467 | .id = -1, | ||
1468 | }; | ||
1469 | #endif | ||
1470 | |||
1471 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 1463 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
1472 | static struct platform_device bfin_ac97_pcm = { | 1464 | static struct platform_device bfin_ac97_pcm = { |
1473 | .name = "bfin-ac97-pcm-audio", | 1465 | .name = "bfin-ac97-pcm-audio", |
@@ -1501,18 +1493,6 @@ static struct platform_device bfin_i2s = { | |||
1501 | }; | 1493 | }; |
1502 | #endif | 1494 | #endif |
1503 | 1495 | ||
1504 | #if defined(CONFIG_SND_BF5XX_SOC_TDM) || defined(CONFIG_SND_BF5XX_SOC_TDM_MODULE) | ||
1505 | static struct platform_device bfin_tdm = { | ||
1506 | .name = "bfin-tdm", | ||
1507 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
1508 | .num_resources = ARRAY_SIZE(bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM]), | ||
1509 | .resource = bfin_snd_resources[CONFIG_SND_BF5XX_SPORT_NUM], | ||
1510 | .dev = { | ||
1511 | .platform_data = &bfin_snd_data[CONFIG_SND_BF5XX_SPORT_NUM], | ||
1512 | }, | ||
1513 | }; | ||
1514 | #endif | ||
1515 | |||
1516 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) | 1496 | #if defined(CONFIG_SND_BF5XX_SOC_AC97) || defined(CONFIG_SND_BF5XX_SOC_AC97_MODULE) |
1517 | static struct platform_device bfin_ac97 = { | 1497 | static struct platform_device bfin_ac97 = { |
1518 | .name = "bfin-ac97", | 1498 | .name = "bfin-ac97", |
@@ -1646,9 +1626,7 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
1646 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) | 1626 | #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) |
1647 | &bfin_i2s_pcm, | 1627 | &bfin_i2s_pcm, |
1648 | #endif | 1628 | #endif |
1649 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | 1629 | |
1650 | &bfin_tdm_pcm, | ||
1651 | #endif | ||
1652 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 1630 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
1653 | &bfin_ac97_pcm, | 1631 | &bfin_ac97_pcm, |
1654 | #endif | 1632 | #endif |
@@ -1661,10 +1639,6 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
1661 | &bfin_i2s, | 1639 | &bfin_i2s, |
1662 | #endif | 1640 | #endif |
1663 | 1641 | ||
1664 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
1665 | &bfin_tdm, | ||
1666 | #endif | ||
1667 | |||
1668 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 1642 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
1669 | &bfin_ac97, | 1643 | &bfin_ac97, |
1670 | #endif | 1644 | #endif |
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 551f866172cf..92938e79b9e3 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c | |||
@@ -523,14 +523,6 @@ static struct platform_device bfin_i2s = { | |||
523 | }; | 523 | }; |
524 | #endif | 524 | #endif |
525 | 525 | ||
526 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
527 | static struct platform_device bfin_tdm = { | ||
528 | .name = "bfin-tdm", | ||
529 | .id = CONFIG_SND_BF5XX_SPORT_NUM, | ||
530 | /* TODO: add platform data here */ | ||
531 | }; | ||
532 | #endif | ||
533 | |||
534 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 526 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
535 | static struct platform_device bfin_ac97 = { | 527 | static struct platform_device bfin_ac97 = { |
536 | .name = "bfin-ac97", | 528 | .name = "bfin-ac97", |
@@ -542,7 +534,7 @@ static struct platform_device bfin_ac97 = { | |||
542 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | 534 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ |
543 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 535 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
544 | static const char * const ad1836_link[] = { | 536 | static const char * const ad1836_link[] = { |
545 | "bfin-tdm.0", | 537 | "bfin-i2s.0", |
546 | "spi0.4", | 538 | "spi0.4", |
547 | }; | 539 | }; |
548 | static struct platform_device bfin_ad1836_machine = { | 540 | static struct platform_device bfin_ad1836_machine = { |
@@ -611,10 +603,6 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
611 | &bfin_i2s, | 603 | &bfin_i2s, |
612 | #endif | 604 | #endif |
613 | 605 | ||
614 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | ||
615 | &bfin_tdm, | ||
616 | #endif | ||
617 | |||
618 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 606 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
619 | &bfin_ac97, | 607 | &bfin_ac97, |
620 | #endif | 608 | #endif |
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index 97d701639585..bba40aed4273 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c | |||
@@ -821,7 +821,7 @@ static struct platform_device bfin_i2s = { | |||
821 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | 821 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ |
822 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | 822 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) |
823 | static const char * const ad1836_link[] = { | 823 | static const char * const ad1836_link[] = { |
824 | "bfin-tdm.0", | 824 | "bfin-i2s.0", |
825 | "spi0.76", | 825 | "spi0.76", |
826 | }; | 826 | }; |
827 | static struct platform_device bfin_ad1836_machine = { | 827 | static struct platform_device bfin_ad1836_machine = { |
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 6ab03043fd60..74b4481754fd 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
@@ -16,9 +16,13 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/mfd/core.h> | 17 | #include <linux/mfd/core.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/of.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/of_gpio.h> | ||
19 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
20 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
21 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/regulator/machine.h> | ||
22 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
23 | 27 | ||
24 | #include <linux/mfd/arizona/core.h> | 28 | #include <linux/mfd/arizona/core.h> |
@@ -344,6 +348,17 @@ static int arizona_runtime_resume(struct device *dev) | |||
344 | 348 | ||
345 | switch (arizona->type) { | 349 | switch (arizona->type) { |
346 | case WM5102: | 350 | case WM5102: |
351 | if (arizona->external_dcvdd) { | ||
352 | ret = regmap_update_bits(arizona->regmap, | ||
353 | ARIZONA_ISOLATION_CONTROL, | ||
354 | ARIZONA_ISOLATE_DCVDD1, 0); | ||
355 | if (ret != 0) { | ||
356 | dev_err(arizona->dev, | ||
357 | "Failed to connect DCVDD: %d\n", ret); | ||
358 | goto err; | ||
359 | } | ||
360 | } | ||
361 | |||
347 | ret = wm5102_patch(arizona); | 362 | ret = wm5102_patch(arizona); |
348 | if (ret != 0) { | 363 | if (ret != 0) { |
349 | dev_err(arizona->dev, "Failed to apply patch: %d\n", | 364 | dev_err(arizona->dev, "Failed to apply patch: %d\n", |
@@ -365,6 +380,28 @@ static int arizona_runtime_resume(struct device *dev) | |||
365 | goto err; | 380 | goto err; |
366 | } | 381 | } |
367 | 382 | ||
383 | if (arizona->external_dcvdd) { | ||
384 | ret = regmap_update_bits(arizona->regmap, | ||
385 | ARIZONA_ISOLATION_CONTROL, | ||
386 | ARIZONA_ISOLATE_DCVDD1, 0); | ||
387 | if (ret != 0) { | ||
388 | dev_err(arizona->dev, | ||
389 | "Failed to connect DCVDD: %d\n", ret); | ||
390 | goto err; | ||
391 | } | ||
392 | } | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | switch (arizona->type) { | ||
397 | case WM5102: | ||
398 | ret = wm5102_patch(arizona); | ||
399 | if (ret != 0) { | ||
400 | dev_err(arizona->dev, "Failed to apply patch: %d\n", | ||
401 | ret); | ||
402 | goto err; | ||
403 | } | ||
404 | default: | ||
368 | break; | 405 | break; |
369 | } | 406 | } |
370 | 407 | ||
@@ -385,9 +422,22 @@ err: | |||
385 | static int arizona_runtime_suspend(struct device *dev) | 422 | static int arizona_runtime_suspend(struct device *dev) |
386 | { | 423 | { |
387 | struct arizona *arizona = dev_get_drvdata(dev); | 424 | struct arizona *arizona = dev_get_drvdata(dev); |
425 | int ret; | ||
388 | 426 | ||
389 | dev_dbg(arizona->dev, "Entering AoD mode\n"); | 427 | dev_dbg(arizona->dev, "Entering AoD mode\n"); |
390 | 428 | ||
429 | if (arizona->external_dcvdd) { | ||
430 | ret = regmap_update_bits(arizona->regmap, | ||
431 | ARIZONA_ISOLATION_CONTROL, | ||
432 | ARIZONA_ISOLATE_DCVDD1, | ||
433 | ARIZONA_ISOLATE_DCVDD1); | ||
434 | if (ret != 0) { | ||
435 | dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", | ||
436 | ret); | ||
437 | return ret; | ||
438 | } | ||
439 | } | ||
440 | |||
391 | regulator_disable(arizona->dcvdd); | 441 | regulator_disable(arizona->dcvdd); |
392 | regcache_cache_only(arizona->regmap, true); | 442 | regcache_cache_only(arizona->regmap, true); |
393 | regcache_mark_dirty(arizona->regmap); | 443 | regcache_mark_dirty(arizona->regmap); |
@@ -397,6 +447,26 @@ static int arizona_runtime_suspend(struct device *dev) | |||
397 | #endif | 447 | #endif |
398 | 448 | ||
399 | #ifdef CONFIG_PM_SLEEP | 449 | #ifdef CONFIG_PM_SLEEP |
450 | static int arizona_suspend(struct device *dev) | ||
451 | { | ||
452 | struct arizona *arizona = dev_get_drvdata(dev); | ||
453 | |||
454 | dev_dbg(arizona->dev, "Suspend, disabling IRQ\n"); | ||
455 | disable_irq(arizona->irq); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int arizona_suspend_late(struct device *dev) | ||
461 | { | ||
462 | struct arizona *arizona = dev_get_drvdata(dev); | ||
463 | |||
464 | dev_dbg(arizona->dev, "Late suspend, reenabling IRQ\n"); | ||
465 | enable_irq(arizona->irq); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
400 | static int arizona_resume_noirq(struct device *dev) | 470 | static int arizona_resume_noirq(struct device *dev) |
401 | { | 471 | { |
402 | struct arizona *arizona = dev_get_drvdata(dev); | 472 | struct arizona *arizona = dev_get_drvdata(dev); |
@@ -422,13 +492,78 @@ const struct dev_pm_ops arizona_pm_ops = { | |||
422 | SET_RUNTIME_PM_OPS(arizona_runtime_suspend, | 492 | SET_RUNTIME_PM_OPS(arizona_runtime_suspend, |
423 | arizona_runtime_resume, | 493 | arizona_runtime_resume, |
424 | NULL) | 494 | NULL) |
425 | SET_SYSTEM_SLEEP_PM_OPS(NULL, arizona_resume) | 495 | SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) |
426 | #ifdef CONFIG_PM_SLEEP | 496 | #ifdef CONFIG_PM_SLEEP |
497 | .suspend_late = arizona_suspend_late, | ||
427 | .resume_noirq = arizona_resume_noirq, | 498 | .resume_noirq = arizona_resume_noirq, |
428 | #endif | 499 | #endif |
429 | }; | 500 | }; |
430 | EXPORT_SYMBOL_GPL(arizona_pm_ops); | 501 | EXPORT_SYMBOL_GPL(arizona_pm_ops); |
431 | 502 | ||
503 | #ifdef CONFIG_OF | ||
504 | int arizona_of_get_type(struct device *dev) | ||
505 | { | ||
506 | const struct of_device_id *id = of_match_device(arizona_of_match, dev); | ||
507 | |||
508 | if (id) | ||
509 | return (int)id->data; | ||
510 | else | ||
511 | return 0; | ||
512 | } | ||
513 | EXPORT_SYMBOL_GPL(arizona_of_get_type); | ||
514 | |||
515 | static int arizona_of_get_core_pdata(struct arizona *arizona) | ||
516 | { | ||
517 | int ret, i; | ||
518 | |||
519 | arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, | ||
520 | "wlf,reset", 0); | ||
521 | if (arizona->pdata.reset < 0) | ||
522 | arizona->pdata.reset = 0; | ||
523 | |||
524 | arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node, | ||
525 | "wlf,ldoena", 0); | ||
526 | if (arizona->pdata.ldoena < 0) | ||
527 | arizona->pdata.ldoena = 0; | ||
528 | |||
529 | ret = of_property_read_u32_array(arizona->dev->of_node, | ||
530 | "wlf,gpio-defaults", | ||
531 | arizona->pdata.gpio_defaults, | ||
532 | ARRAY_SIZE(arizona->pdata.gpio_defaults)); | ||
533 | if (ret >= 0) { | ||
534 | /* | ||
535 | * All values are literal except out of range values | ||
536 | * which are chip default, translate into platform | ||
537 | * data which uses 0 as chip default and out of range | ||
538 | * as zero. | ||
539 | */ | ||
540 | for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { | ||
541 | if (arizona->pdata.gpio_defaults[i] > 0xffff) | ||
542 | arizona->pdata.gpio_defaults[i] = 0; | ||
543 | if (arizona->pdata.gpio_defaults[i] == 0) | ||
544 | arizona->pdata.gpio_defaults[i] = 0x10000; | ||
545 | } | ||
546 | } else { | ||
547 | dev_err(arizona->dev, "Failed to parse GPIO defaults: %d\n", | ||
548 | ret); | ||
549 | } | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | const struct of_device_id arizona_of_match[] = { | ||
555 | { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, | ||
556 | { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, | ||
557 | {}, | ||
558 | }; | ||
559 | EXPORT_SYMBOL_GPL(arizona_of_match); | ||
560 | #else | ||
561 | static inline int arizona_of_get_core_pdata(struct arizona *arizona) | ||
562 | { | ||
563 | return 0; | ||
564 | } | ||
565 | #endif | ||
566 | |||
432 | static struct mfd_cell early_devs[] = { | 567 | static struct mfd_cell early_devs[] = { |
433 | { .name = "arizona-ldo1" }, | 568 | { .name = "arizona-ldo1" }, |
434 | }; | 569 | }; |
@@ -462,6 +597,8 @@ int arizona_dev_init(struct arizona *arizona) | |||
462 | dev_set_drvdata(arizona->dev, arizona); | 597 | dev_set_drvdata(arizona->dev, arizona); |
463 | mutex_init(&arizona->clk_lock); | 598 | mutex_init(&arizona->clk_lock); |
464 | 599 | ||
600 | arizona_of_get_core_pdata(arizona); | ||
601 | |||
465 | if (dev_get_platdata(arizona->dev)) | 602 | if (dev_get_platdata(arizona->dev)) |
466 | memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), | 603 | memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), |
467 | sizeof(arizona->pdata)); | 604 | sizeof(arizona->pdata)); |
@@ -536,51 +673,22 @@ int arizona_dev_init(struct arizona *arizona) | |||
536 | 673 | ||
537 | regcache_cache_only(arizona->regmap, false); | 674 | regcache_cache_only(arizona->regmap, false); |
538 | 675 | ||
676 | /* Verify that this is a chip we know about */ | ||
539 | ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); | 677 | ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); |
540 | if (ret != 0) { | 678 | if (ret != 0) { |
541 | dev_err(dev, "Failed to read ID register: %d\n", ret); | 679 | dev_err(dev, "Failed to read ID register: %d\n", ret); |
542 | goto err_reset; | 680 | goto err_reset; |
543 | } | 681 | } |
544 | 682 | ||
545 | ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, | ||
546 | &arizona->rev); | ||
547 | if (ret != 0) { | ||
548 | dev_err(dev, "Failed to read revision register: %d\n", ret); | ||
549 | goto err_reset; | ||
550 | } | ||
551 | arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; | ||
552 | |||
553 | switch (reg) { | 683 | switch (reg) { |
554 | #ifdef CONFIG_MFD_WM5102 | ||
555 | case 0x5102: | 684 | case 0x5102: |
556 | type_name = "WM5102"; | ||
557 | if (arizona->type != WM5102) { | ||
558 | dev_err(arizona->dev, "WM5102 registered as %d\n", | ||
559 | arizona->type); | ||
560 | arizona->type = WM5102; | ||
561 | } | ||
562 | apply_patch = wm5102_patch; | ||
563 | arizona->rev &= 0x7; | ||
564 | break; | ||
565 | #endif | ||
566 | #ifdef CONFIG_MFD_WM5110 | ||
567 | case 0x5110: | 685 | case 0x5110: |
568 | type_name = "WM5110"; | ||
569 | if (arizona->type != WM5110) { | ||
570 | dev_err(arizona->dev, "WM5110 registered as %d\n", | ||
571 | arizona->type); | ||
572 | arizona->type = WM5110; | ||
573 | } | ||
574 | apply_patch = wm5110_patch; | ||
575 | break; | 686 | break; |
576 | #endif | ||
577 | default: | 687 | default: |
578 | dev_err(arizona->dev, "Unknown device ID %x\n", reg); | 688 | dev_err(arizona->dev, "Unknown device ID: %x\n", reg); |
579 | goto err_reset; | 689 | goto err_reset; |
580 | } | 690 | } |
581 | 691 | ||
582 | dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); | ||
583 | |||
584 | /* If we have a /RESET GPIO we'll already be reset */ | 692 | /* If we have a /RESET GPIO we'll already be reset */ |
585 | if (!arizona->pdata.reset) { | 693 | if (!arizona->pdata.reset) { |
586 | regcache_mark_dirty(arizona->regmap); | 694 | regcache_mark_dirty(arizona->regmap); |
@@ -600,6 +708,7 @@ int arizona_dev_init(struct arizona *arizona) | |||
600 | } | 708 | } |
601 | } | 709 | } |
602 | 710 | ||
711 | /* Ensure device startup is complete */ | ||
603 | switch (arizona->type) { | 712 | switch (arizona->type) { |
604 | case WM5102: | 713 | case WM5102: |
605 | ret = regmap_read(arizona->regmap, 0x19, &val); | 714 | ret = regmap_read(arizona->regmap, 0x19, &val); |
@@ -620,6 +729,52 @@ int arizona_dev_init(struct arizona *arizona) | |||
620 | break; | 729 | break; |
621 | } | 730 | } |
622 | 731 | ||
732 | /* Read the device ID information & do device specific stuff */ | ||
733 | ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); | ||
734 | if (ret != 0) { | ||
735 | dev_err(dev, "Failed to read ID register: %d\n", ret); | ||
736 | goto err_reset; | ||
737 | } | ||
738 | |||
739 | ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, | ||
740 | &arizona->rev); | ||
741 | if (ret != 0) { | ||
742 | dev_err(dev, "Failed to read revision register: %d\n", ret); | ||
743 | goto err_reset; | ||
744 | } | ||
745 | arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; | ||
746 | |||
747 | switch (reg) { | ||
748 | #ifdef CONFIG_MFD_WM5102 | ||
749 | case 0x5102: | ||
750 | type_name = "WM5102"; | ||
751 | if (arizona->type != WM5102) { | ||
752 | dev_err(arizona->dev, "WM5102 registered as %d\n", | ||
753 | arizona->type); | ||
754 | arizona->type = WM5102; | ||
755 | } | ||
756 | apply_patch = wm5102_patch; | ||
757 | arizona->rev &= 0x7; | ||
758 | break; | ||
759 | #endif | ||
760 | #ifdef CONFIG_MFD_WM5110 | ||
761 | case 0x5110: | ||
762 | type_name = "WM5110"; | ||
763 | if (arizona->type != WM5110) { | ||
764 | dev_err(arizona->dev, "WM5110 registered as %d\n", | ||
765 | arizona->type); | ||
766 | arizona->type = WM5110; | ||
767 | } | ||
768 | apply_patch = wm5110_patch; | ||
769 | break; | ||
770 | #endif | ||
771 | default: | ||
772 | dev_err(arizona->dev, "Unknown device ID %x\n", reg); | ||
773 | goto err_reset; | ||
774 | } | ||
775 | |||
776 | dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); | ||
777 | |||
623 | if (apply_patch) { | 778 | if (apply_patch) { |
624 | ret = apply_patch(arizona); | 779 | ret = apply_patch(arizona); |
625 | if (ret != 0) { | 780 | if (ret != 0) { |
@@ -651,6 +806,14 @@ int arizona_dev_init(struct arizona *arizona) | |||
651 | arizona->pdata.gpio_defaults[i]); | 806 | arizona->pdata.gpio_defaults[i]); |
652 | } | 807 | } |
653 | 808 | ||
809 | /* | ||
810 | * LDO1 can only be used to supply DCVDD so if it has no | ||
811 | * consumers then DCVDD is supplied externally. | ||
812 | */ | ||
813 | if (arizona->pdata.ldo1 && | ||
814 | arizona->pdata.ldo1->num_consumer_supplies == 0) | ||
815 | arizona->external_dcvdd = true; | ||
816 | |||
654 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); | 817 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); |
655 | pm_runtime_use_autosuspend(arizona->dev); | 818 | pm_runtime_use_autosuspend(arizona->dev); |
656 | pm_runtime_enable(arizona->dev); | 819 | pm_runtime_enable(arizona->dev); |
@@ -697,7 +860,7 @@ int arizona_dev_init(struct arizona *arizona) | |||
697 | if (arizona->pdata.micbias[i].discharge) | 860 | if (arizona->pdata.micbias[i].discharge) |
698 | val |= ARIZONA_MICB1_DISCH; | 861 | val |= ARIZONA_MICB1_DISCH; |
699 | 862 | ||
700 | if (arizona->pdata.micbias[i].fast_start) | 863 | if (arizona->pdata.micbias[i].soft_start) |
701 | val |= ARIZONA_MICB1_RATE; | 864 | val |= ARIZONA_MICB1_RATE; |
702 | 865 | ||
703 | if (arizona->pdata.micbias[i].bypass) | 866 | if (arizona->pdata.micbias[i].bypass) |
@@ -809,6 +972,11 @@ int arizona_dev_exit(struct arizona *arizona) | |||
809 | arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona); | 972 | arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona); |
810 | pm_runtime_disable(arizona->dev); | 973 | pm_runtime_disable(arizona->dev); |
811 | arizona_irq_exit(arizona); | 974 | arizona_irq_exit(arizona); |
975 | if (arizona->pdata.reset) | ||
976 | gpio_set_value_cansleep(arizona->pdata.reset, 0); | ||
977 | regulator_disable(arizona->dcvdd); | ||
978 | regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies), | ||
979 | arizona->core_supplies); | ||
812 | return 0; | 980 | return 0; |
813 | } | 981 | } |
814 | EXPORT_SYMBOL_GPL(arizona_dev_exit); | 982 | EXPORT_SYMBOL_GPL(arizona_dev_exit); |
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 44a1bb969841..deb267ebf84e 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c | |||
@@ -27,9 +27,14 @@ static int arizona_i2c_probe(struct i2c_client *i2c, | |||
27 | { | 27 | { |
28 | struct arizona *arizona; | 28 | struct arizona *arizona; |
29 | const struct regmap_config *regmap_config; | 29 | const struct regmap_config *regmap_config; |
30 | int ret; | 30 | int ret, type; |
31 | 31 | ||
32 | switch (id->driver_data) { | 32 | if (i2c->dev.of_node) |
33 | type = arizona_of_get_type(&i2c->dev); | ||
34 | else | ||
35 | type = id->driver_data; | ||
36 | |||
37 | switch (type) { | ||
33 | #ifdef CONFIG_MFD_WM5102 | 38 | #ifdef CONFIG_MFD_WM5102 |
34 | case WM5102: | 39 | case WM5102: |
35 | regmap_config = &wm5102_i2c_regmap; | 40 | regmap_config = &wm5102_i2c_regmap; |
@@ -84,6 +89,7 @@ static struct i2c_driver arizona_i2c_driver = { | |||
84 | .name = "arizona", | 89 | .name = "arizona", |
85 | .owner = THIS_MODULE, | 90 | .owner = THIS_MODULE, |
86 | .pm = &arizona_pm_ops, | 91 | .pm = &arizona_pm_ops, |
92 | .of_match_table = of_match_ptr(arizona_of_match), | ||
87 | }, | 93 | }, |
88 | .probe = arizona_i2c_probe, | 94 | .probe = arizona_i2c_probe, |
89 | .remove = arizona_i2c_remove, | 95 | .remove = arizona_i2c_remove, |
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index b57e642d2b4a..47be7b35b5c5 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c | |||
@@ -27,9 +27,14 @@ static int arizona_spi_probe(struct spi_device *spi) | |||
27 | const struct spi_device_id *id = spi_get_device_id(spi); | 27 | const struct spi_device_id *id = spi_get_device_id(spi); |
28 | struct arizona *arizona; | 28 | struct arizona *arizona; |
29 | const struct regmap_config *regmap_config; | 29 | const struct regmap_config *regmap_config; |
30 | int ret; | 30 | int ret, type; |
31 | 31 | ||
32 | switch (id->driver_data) { | 32 | if (spi->dev.of_node) |
33 | type = arizona_of_get_type(&spi->dev); | ||
34 | else | ||
35 | type = id->driver_data; | ||
36 | |||
37 | switch (type) { | ||
33 | #ifdef CONFIG_MFD_WM5102 | 38 | #ifdef CONFIG_MFD_WM5102 |
34 | case WM5102: | 39 | case WM5102: |
35 | regmap_config = &wm5102_spi_regmap; | 40 | regmap_config = &wm5102_spi_regmap; |
@@ -84,6 +89,7 @@ static struct spi_driver arizona_spi_driver = { | |||
84 | .name = "arizona", | 89 | .name = "arizona", |
85 | .owner = THIS_MODULE, | 90 | .owner = THIS_MODULE, |
86 | .pm = &arizona_pm_ops, | 91 | .pm = &arizona_pm_ops, |
92 | .of_match_table = of_match_ptr(arizona_of_match), | ||
87 | }, | 93 | }, |
88 | .probe = arizona_spi_probe, | 94 | .probe = arizona_spi_probe, |
89 | .remove = arizona_spi_remove, | 95 | .remove = arizona_spi_remove, |
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h index 9798ae5da67b..db55d9854a55 100644 --- a/drivers/mfd/arizona.h +++ b/drivers/mfd/arizona.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #ifndef _WM5102_H | 13 | #ifndef _WM5102_H |
14 | #define _WM5102_H | 14 | #define _WM5102_H |
15 | 15 | ||
16 | #include <linux/of.h> | ||
16 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
18 | 19 | ||
@@ -26,6 +27,8 @@ extern const struct regmap_config wm5110_spi_regmap; | |||
26 | 27 | ||
27 | extern const struct dev_pm_ops arizona_pm_ops; | 28 | extern const struct dev_pm_ops arizona_pm_ops; |
28 | 29 | ||
30 | extern const struct of_device_id arizona_of_match[]; | ||
31 | |||
29 | extern const struct regmap_irq_chip wm5102_aod; | 32 | extern const struct regmap_irq_chip wm5102_aod; |
30 | extern const struct regmap_irq_chip wm5102_irq; | 33 | extern const struct regmap_irq_chip wm5102_irq; |
31 | 34 | ||
@@ -37,4 +40,13 @@ int arizona_dev_exit(struct arizona *arizona); | |||
37 | int arizona_irq_init(struct arizona *arizona); | 40 | int arizona_irq_init(struct arizona *arizona); |
38 | int arizona_irq_exit(struct arizona *arizona); | 41 | int arizona_irq_exit(struct arizona *arizona); |
39 | 42 | ||
43 | #ifdef CONFIG_OF | ||
44 | int arizona_of_get_type(struct device *dev); | ||
45 | #else | ||
46 | static inline int arizona_of_get_type(struct device *dev) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
50 | #endif | ||
51 | |||
40 | #endif | 52 | #endif |
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 155c4a1a6a99..802dd3cb18cf 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c | |||
@@ -65,7 +65,8 @@ static const struct reg_default wm5102_revb_patch[] = { | |||
65 | { 0x418, 0xa080 }, | 65 | { 0x418, 0xa080 }, |
66 | { 0x420, 0xa080 }, | 66 | { 0x420, 0xa080 }, |
67 | { 0x428, 0xe000 }, | 67 | { 0x428, 0xe000 }, |
68 | { 0x443, 0xDC1A }, | 68 | { 0x442, 0x3F0A }, |
69 | { 0x443, 0xDC1F }, | ||
69 | { 0x4B0, 0x0066 }, | 70 | { 0x4B0, 0x0066 }, |
70 | { 0x458, 0x000b }, | 71 | { 0x458, 0x000b }, |
71 | { 0x212, 0x0000 }, | 72 | { 0x212, 0x0000 }, |
@@ -424,6 +425,9 @@ static const struct reg_default wm5102_reg_default[] = { | |||
424 | { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ | 425 | { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ |
425 | { 0x00000436, 0x0081 }, /* R1078 - DAC Volume Limit 5R */ | 426 | { 0x00000436, 0x0081 }, /* R1078 - DAC Volume Limit 5R */ |
426 | { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ | 427 | { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ |
428 | { 0x00000440, 0x8FFF }, /* R1088 - DRE Enable */ | ||
429 | { 0x00000442, 0x3F0A }, /* R1090 - DRE Control 2 */ | ||
430 | { 0x00000443, 0xDC1F }, /* R1090 - DRE Control 3 */ | ||
427 | { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ | 431 | { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ |
428 | { 0x00000458, 0x000B }, /* R1112 - Noise Gate Control */ | 432 | { 0x00000458, 0x000B }, /* R1112 - Noise Gate Control */ |
429 | { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ | 433 | { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ |
@@ -1197,6 +1201,9 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) | |||
1197 | case ARIZONA_DAC_DIGITAL_VOLUME_5R: | 1201 | case ARIZONA_DAC_DIGITAL_VOLUME_5R: |
1198 | case ARIZONA_DAC_VOLUME_LIMIT_5R: | 1202 | case ARIZONA_DAC_VOLUME_LIMIT_5R: |
1199 | case ARIZONA_NOISE_GATE_SELECT_5R: | 1203 | case ARIZONA_NOISE_GATE_SELECT_5R: |
1204 | case ARIZONA_DRE_ENABLE: | ||
1205 | case ARIZONA_DRE_CONTROL_2: | ||
1206 | case ARIZONA_DRE_CONTROL_3: | ||
1200 | case ARIZONA_DAC_AEC_CONTROL_1: | 1207 | case ARIZONA_DAC_AEC_CONTROL_1: |
1201 | case ARIZONA_NOISE_GATE_CONTROL: | 1208 | case ARIZONA_NOISE_GATE_CONTROL: |
1202 | case ARIZONA_PDM_SPK1_CTRL_1: | 1209 | case ARIZONA_PDM_SPK1_CTRL_1: |
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index c41599815299..2a7972349159 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c | |||
@@ -2273,18 +2273,22 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) | |||
2273 | case ARIZONA_DSP1_CLOCKING_1: | 2273 | case ARIZONA_DSP1_CLOCKING_1: |
2274 | case ARIZONA_DSP1_STATUS_1: | 2274 | case ARIZONA_DSP1_STATUS_1: |
2275 | case ARIZONA_DSP1_STATUS_2: | 2275 | case ARIZONA_DSP1_STATUS_2: |
2276 | case ARIZONA_DSP1_STATUS_3: | ||
2276 | case ARIZONA_DSP2_CONTROL_1: | 2277 | case ARIZONA_DSP2_CONTROL_1: |
2277 | case ARIZONA_DSP2_CLOCKING_1: | 2278 | case ARIZONA_DSP2_CLOCKING_1: |
2278 | case ARIZONA_DSP2_STATUS_1: | 2279 | case ARIZONA_DSP2_STATUS_1: |
2279 | case ARIZONA_DSP2_STATUS_2: | 2280 | case ARIZONA_DSP2_STATUS_2: |
2281 | case ARIZONA_DSP2_STATUS_3: | ||
2280 | case ARIZONA_DSP3_CONTROL_1: | 2282 | case ARIZONA_DSP3_CONTROL_1: |
2281 | case ARIZONA_DSP3_CLOCKING_1: | 2283 | case ARIZONA_DSP3_CLOCKING_1: |
2282 | case ARIZONA_DSP3_STATUS_1: | 2284 | case ARIZONA_DSP3_STATUS_1: |
2283 | case ARIZONA_DSP3_STATUS_2: | 2285 | case ARIZONA_DSP3_STATUS_2: |
2286 | case ARIZONA_DSP3_STATUS_3: | ||
2284 | case ARIZONA_DSP4_CONTROL_1: | 2287 | case ARIZONA_DSP4_CONTROL_1: |
2285 | case ARIZONA_DSP4_CLOCKING_1: | 2288 | case ARIZONA_DSP4_CLOCKING_1: |
2286 | case ARIZONA_DSP4_STATUS_1: | 2289 | case ARIZONA_DSP4_STATUS_1: |
2287 | case ARIZONA_DSP4_STATUS_2: | 2290 | case ARIZONA_DSP4_STATUS_2: |
2291 | case ARIZONA_DSP4_STATUS_3: | ||
2288 | return true; | 2292 | return true; |
2289 | default: | 2293 | default: |
2290 | return false; | 2294 | return false; |
@@ -2334,12 +2338,16 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) | |||
2334 | case ARIZONA_DSP1_CLOCKING_1: | 2338 | case ARIZONA_DSP1_CLOCKING_1: |
2335 | case ARIZONA_DSP1_STATUS_1: | 2339 | case ARIZONA_DSP1_STATUS_1: |
2336 | case ARIZONA_DSP1_STATUS_2: | 2340 | case ARIZONA_DSP1_STATUS_2: |
2341 | case ARIZONA_DSP1_STATUS_3: | ||
2337 | case ARIZONA_DSP2_STATUS_1: | 2342 | case ARIZONA_DSP2_STATUS_1: |
2338 | case ARIZONA_DSP2_STATUS_2: | 2343 | case ARIZONA_DSP2_STATUS_2: |
2344 | case ARIZONA_DSP2_STATUS_3: | ||
2339 | case ARIZONA_DSP3_STATUS_1: | 2345 | case ARIZONA_DSP3_STATUS_1: |
2340 | case ARIZONA_DSP3_STATUS_2: | 2346 | case ARIZONA_DSP3_STATUS_2: |
2347 | case ARIZONA_DSP3_STATUS_3: | ||
2341 | case ARIZONA_DSP4_STATUS_1: | 2348 | case ARIZONA_DSP4_STATUS_1: |
2342 | case ARIZONA_DSP4_STATUS_2: | 2349 | case ARIZONA_DSP4_STATUS_2: |
2350 | case ARIZONA_DSP4_STATUS_3: | ||
2343 | return true; | 2351 | return true; |
2344 | default: | 2352 | default: |
2345 | return false; | 2353 | return false; |
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 1abd5ad59925..f7b90661e321 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
@@ -58,7 +58,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num) | |||
58 | ssc->user++; | 58 | ssc->user++; |
59 | spin_unlock(&user_lock); | 59 | spin_unlock(&user_lock); |
60 | 60 | ||
61 | clk_enable(ssc->clk); | 61 | clk_prepare_enable(ssc->clk); |
62 | 62 | ||
63 | return ssc; | 63 | return ssc; |
64 | } | 64 | } |
@@ -69,7 +69,7 @@ void ssc_free(struct ssc_device *ssc) | |||
69 | spin_lock(&user_lock); | 69 | spin_lock(&user_lock); |
70 | if (ssc->user) { | 70 | if (ssc->user) { |
71 | ssc->user--; | 71 | ssc->user--; |
72 | clk_disable(ssc->clk); | 72 | clk_disable_unprepare(ssc->clk); |
73 | } else { | 73 | } else { |
74 | dev_dbg(&ssc->pdev->dev, "device already free\n"); | 74 | dev_dbg(&ssc->pdev->dev, "device already free\n"); |
75 | } | 75 | } |
@@ -167,10 +167,10 @@ static int ssc_probe(struct platform_device *pdev) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | /* disable all interrupts */ | 169 | /* disable all interrupts */ |
170 | clk_enable(ssc->clk); | 170 | clk_prepare_enable(ssc->clk); |
171 | ssc_writel(ssc->regs, IDR, -1); | 171 | ssc_writel(ssc->regs, IDR, -1); |
172 | ssc_readl(ssc->regs, SR); | 172 | ssc_readl(ssc->regs, SR); |
173 | clk_disable(ssc->clk); | 173 | clk_disable_unprepare(ssc->clk); |
174 | 174 | ||
175 | ssc->irq = platform_get_irq(pdev, 0); | 175 | ssc->irq = platform_get_irq(pdev, 0); |
176 | if (!ssc->irq) { | 176 | if (!ssc->irq) { |
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index cc281368dc55..f797bb9b8b56 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h | |||
@@ -95,6 +95,8 @@ struct arizona { | |||
95 | 95 | ||
96 | struct arizona_pdata pdata; | 96 | struct arizona_pdata pdata; |
97 | 97 | ||
98 | unsigned int external_dcvdd:1; | ||
99 | |||
98 | int irq; | 100 | int irq; |
99 | struct irq_domain *virq; | 101 | struct irq_domain *virq; |
100 | struct regmap_irq_chip_data *aod_irq_chip; | 102 | struct regmap_irq_chip_data *aod_irq_chip; |
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index 80dead1f7100..12a5c135c746 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h | |||
@@ -77,7 +77,7 @@ struct arizona_micbias { | |||
77 | int mV; /** Regulated voltage */ | 77 | int mV; /** Regulated voltage */ |
78 | unsigned int ext_cap:1; /** External capacitor fitted */ | 78 | unsigned int ext_cap:1; /** External capacitor fitted */ |
79 | unsigned int discharge:1; /** Actively discharge */ | 79 | unsigned int discharge:1; /** Actively discharge */ |
80 | unsigned int fast_start:1; /** Enable aggressive startup ramp rate */ | 80 | unsigned int soft_start:1; /** Disable aggressive startup ramp rate */ |
81 | unsigned int bypass:1; /** Use bypass mode */ | 81 | unsigned int bypass:1; /** Use bypass mode */ |
82 | }; | 82 | }; |
83 | 83 | ||
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index 715b6ba3d52a..4706d3d46e56 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h | |||
@@ -215,6 +215,9 @@ | |||
215 | #define ARIZONA_DAC_DIGITAL_VOLUME_6R 0x43D | 215 | #define ARIZONA_DAC_DIGITAL_VOLUME_6R 0x43D |
216 | #define ARIZONA_DAC_VOLUME_LIMIT_6R 0x43E | 216 | #define ARIZONA_DAC_VOLUME_LIMIT_6R 0x43E |
217 | #define ARIZONA_NOISE_GATE_SELECT_6R 0x43F | 217 | #define ARIZONA_NOISE_GATE_SELECT_6R 0x43F |
218 | #define ARIZONA_DRE_ENABLE 0x440 | ||
219 | #define ARIZONA_DRE_CONTROL_2 0x442 | ||
220 | #define ARIZONA_DRE_CONTROL_3 0x443 | ||
218 | #define ARIZONA_DAC_AEC_CONTROL_1 0x450 | 221 | #define ARIZONA_DAC_AEC_CONTROL_1 0x450 |
219 | #define ARIZONA_NOISE_GATE_CONTROL 0x458 | 222 | #define ARIZONA_NOISE_GATE_CONTROL 0x458 |
220 | #define ARIZONA_PDM_SPK1_CTRL_1 0x490 | 223 | #define ARIZONA_PDM_SPK1_CTRL_1 0x490 |
@@ -1002,6 +1005,7 @@ | |||
1002 | #define ARIZONA_DSP2_CLOCKING_1 0x1201 | 1005 | #define ARIZONA_DSP2_CLOCKING_1 0x1201 |
1003 | #define ARIZONA_DSP2_STATUS_1 0x1204 | 1006 | #define ARIZONA_DSP2_STATUS_1 0x1204 |
1004 | #define ARIZONA_DSP2_STATUS_2 0x1205 | 1007 | #define ARIZONA_DSP2_STATUS_2 0x1205 |
1008 | #define ARIZONA_DSP2_STATUS_3 0x1206 | ||
1005 | #define ARIZONA_DSP2_SCRATCH_0 0x1240 | 1009 | #define ARIZONA_DSP2_SCRATCH_0 0x1240 |
1006 | #define ARIZONA_DSP2_SCRATCH_1 0x1241 | 1010 | #define ARIZONA_DSP2_SCRATCH_1 0x1241 |
1007 | #define ARIZONA_DSP2_SCRATCH_2 0x1242 | 1011 | #define ARIZONA_DSP2_SCRATCH_2 0x1242 |
@@ -1010,6 +1014,7 @@ | |||
1010 | #define ARIZONA_DSP3_CLOCKING_1 0x1301 | 1014 | #define ARIZONA_DSP3_CLOCKING_1 0x1301 |
1011 | #define ARIZONA_DSP3_STATUS_1 0x1304 | 1015 | #define ARIZONA_DSP3_STATUS_1 0x1304 |
1012 | #define ARIZONA_DSP3_STATUS_2 0x1305 | 1016 | #define ARIZONA_DSP3_STATUS_2 0x1305 |
1017 | #define ARIZONA_DSP3_STATUS_3 0x1306 | ||
1013 | #define ARIZONA_DSP3_SCRATCH_0 0x1340 | 1018 | #define ARIZONA_DSP3_SCRATCH_0 0x1340 |
1014 | #define ARIZONA_DSP3_SCRATCH_1 0x1341 | 1019 | #define ARIZONA_DSP3_SCRATCH_1 0x1341 |
1015 | #define ARIZONA_DSP3_SCRATCH_2 0x1342 | 1020 | #define ARIZONA_DSP3_SCRATCH_2 0x1342 |
@@ -1018,6 +1023,7 @@ | |||
1018 | #define ARIZONA_DSP4_CLOCKING_1 0x1401 | 1023 | #define ARIZONA_DSP4_CLOCKING_1 0x1401 |
1019 | #define ARIZONA_DSP4_STATUS_1 0x1404 | 1024 | #define ARIZONA_DSP4_STATUS_1 0x1404 |
1020 | #define ARIZONA_DSP4_STATUS_2 0x1405 | 1025 | #define ARIZONA_DSP4_STATUS_2 0x1405 |
1026 | #define ARIZONA_DSP4_STATUS_3 0x1406 | ||
1021 | #define ARIZONA_DSP4_SCRATCH_0 0x1440 | 1027 | #define ARIZONA_DSP4_SCRATCH_0 0x1440 |
1022 | #define ARIZONA_DSP4_SCRATCH_1 0x1441 | 1028 | #define ARIZONA_DSP4_SCRATCH_1 0x1441 |
1023 | #define ARIZONA_DSP4_SCRATCH_2 0x1442 | 1029 | #define ARIZONA_DSP4_SCRATCH_2 0x1442 |
@@ -3130,6 +3136,47 @@ | |||
3130 | #define ARIZONA_OUT6R_NGATE_SRC_WIDTH 12 /* OUT6R_NGATE_SRC - [11:0] */ | 3136 | #define ARIZONA_OUT6R_NGATE_SRC_WIDTH 12 /* OUT6R_NGATE_SRC - [11:0] */ |
3131 | 3137 | ||
3132 | /* | 3138 | /* |
3139 | * R1088 (0x440) - DRE Enable | ||
3140 | */ | ||
3141 | #define ARIZONA_DRE3L_ENA 0x0010 /* DRE3L_ENA */ | ||
3142 | #define ARIZONA_DRE3L_ENA_MASK 0x0010 /* DRE3L_ENA */ | ||
3143 | #define ARIZONA_DRE3L_ENA_SHIFT 4 /* DRE3L_ENA */ | ||
3144 | #define ARIZONA_DRE3L_ENA_WIDTH 1 /* DRE3L_ENA */ | ||
3145 | #define ARIZONA_DRE2R_ENA 0x0008 /* DRE2R_ENA */ | ||
3146 | #define ARIZONA_DRE2R_ENA_MASK 0x0008 /* DRE2R_ENA */ | ||
3147 | #define ARIZONA_DRE2R_ENA_SHIFT 3 /* DRE2R_ENA */ | ||
3148 | #define ARIZONA_DRE2R_ENA_WIDTH 1 /* DRE2R_ENA */ | ||
3149 | #define ARIZONA_DRE2L_ENA 0x0004 /* DRE2L_ENA */ | ||
3150 | #define ARIZONA_DRE2L_ENA_MASK 0x0004 /* DRE2L_ENA */ | ||
3151 | #define ARIZONA_DRE2L_ENA_SHIFT 2 /* DRE2L_ENA */ | ||
3152 | #define ARIZONA_DRE2L_ENA_WIDTH 1 /* DRE2L_ENA */ | ||
3153 | #define ARIZONA_DRE1R_ENA 0x0002 /* DRE1R_ENA */ | ||
3154 | #define ARIZONA_DRE1R_ENA_MASK 0x0002 /* DRE1R_ENA */ | ||
3155 | #define ARIZONA_DRE1R_ENA_SHIFT 1 /* DRE1R_ENA */ | ||
3156 | #define ARIZONA_DRE1R_ENA_WIDTH 1 /* DRE1R_ENA */ | ||
3157 | #define ARIZONA_DRE1L_ENA 0x0001 /* DRE1L_ENA */ | ||
3158 | #define ARIZONA_DRE1L_ENA_MASK 0x0001 /* DRE1L_ENA */ | ||
3159 | #define ARIZONA_DRE1L_ENA_SHIFT 0 /* DRE1L_ENA */ | ||
3160 | #define ARIZONA_DRE1L_ENA_WIDTH 1 /* DRE1L_ENA */ | ||
3161 | |||
3162 | /* | ||
3163 | * R1090 (0x442) - DRE Control 2 | ||
3164 | */ | ||
3165 | #define ARIZONA_DRE_T_LOW_MASK 0x3F00 /* DRE_T_LOW - [13:8] */ | ||
3166 | #define ARIZONA_DRE_T_LOW_SHIFT 8 /* DRE_T_LOW - [13:8] */ | ||
3167 | #define ARIZONA_DRE_T_LOW_WIDTH 6 /* DRE_T_LOW - [13:8] */ | ||
3168 | |||
3169 | /* | ||
3170 | * R1091 (0x443) - DRE Control 3 | ||
3171 | */ | ||
3172 | #define ARIZONA_DRE_GAIN_SHIFT_MASK 0xC000 /* DRE_GAIN_SHIFT - [15:14] */ | ||
3173 | #define ARIZONA_DRE_GAIN_SHIFT_SHIFT 14 /* DRE_GAIN_SHIFT - [15:14] */ | ||
3174 | #define ARIZONA_DRE_GAIN_SHIFT_WIDTH 2 /* DRE_GAIN_SHIFT - [15:14] */ | ||
3175 | #define ARIZONA_DRE_LOW_LEVEL_ABS_MASK 0x000F /* LOW_LEVEL_ABS - [3:0] */ | ||
3176 | #define ARIZONA_DRE_LOW_LEVEL_ABS_SHIFT 0 /* LOW_LEVEL_ABS - [3:0] */ | ||
3177 | #define ARIZONA_DRE_LOW_LEVEL_ABS_WIDTH 4 /* LOW_LEVEL_ABS - [3:0] */ | ||
3178 | |||
3179 | /* | ||
3133 | * R1104 (0x450) - DAC AEC Control 1 | 3180 | * R1104 (0x450) - DAC AEC Control 1 |
3134 | */ | 3181 | */ |
3135 | #define ARIZONA_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */ | 3182 | #define ARIZONA_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */ |
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 68e776594889..b5046f6313a9 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h | |||
@@ -182,6 +182,11 @@ struct wm8994_pdata { | |||
182 | */ | 182 | */ |
183 | int micdet_delay; | 183 | int micdet_delay; |
184 | 184 | ||
185 | /* Delay between microphone detect completing and reporting on | ||
186 | * insert (specified in ms) | ||
187 | */ | ||
188 | int mic_id_delay; | ||
189 | |||
185 | /* IRQ for microphone detection if brought out directly as a | 190 | /* IRQ for microphone detection if brought out directly as a |
186 | * signal. | 191 | * signal. |
187 | */ | 192 | */ |
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h index 053548961c15..db8cef3d5321 100644 --- a/include/linux/mfd/wm8994/registers.h +++ b/include/linux/mfd/wm8994/registers.h | |||
@@ -2668,6 +2668,10 @@ | |||
2668 | /* | 2668 | /* |
2669 | * R772 (0x304) - AIF1ADC LRCLK | 2669 | * R772 (0x304) - AIF1ADC LRCLK |
2670 | */ | 2670 | */ |
2671 | #define WM8958_AIF1_LRCLK_INV 0x1000 /* AIF1_LRCLK_INV */ | ||
2672 | #define WM8958_AIF1_LRCLK_INV_MASK 0x1000 /* AIF1_LRCLK_INV */ | ||
2673 | #define WM8958_AIF1_LRCLK_INV_SHIFT 12 /* AIF1_LRCLK_INV */ | ||
2674 | #define WM8958_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */ | ||
2671 | #define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */ | 2675 | #define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */ |
2672 | #define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */ | 2676 | #define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */ |
2673 | #define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */ | 2677 | #define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */ |
@@ -2679,6 +2683,10 @@ | |||
2679 | /* | 2683 | /* |
2680 | * R773 (0x305) - AIF1DAC LRCLK | 2684 | * R773 (0x305) - AIF1DAC LRCLK |
2681 | */ | 2685 | */ |
2686 | #define WM8958_AIF1_LRCLK_INV 0x1000 /* AIF1_LRCLK_INV */ | ||
2687 | #define WM8958_AIF1_LRCLK_INV_MASK 0x1000 /* AIF1_LRCLK_INV */ | ||
2688 | #define WM8958_AIF1_LRCLK_INV_SHIFT 12 /* AIF1_LRCLK_INV */ | ||
2689 | #define WM8958_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */ | ||
2682 | #define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */ | 2690 | #define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */ |
2683 | #define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */ | 2691 | #define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */ |
2684 | #define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */ | 2692 | #define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */ |
diff --git a/include/linux/platform_data/ssm2518.h b/include/linux/platform_data/ssm2518.h new file mode 100644 index 000000000000..9a8e3ea287e3 --- /dev/null +++ b/include/linux/platform_data/ssm2518.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * SSM2518 amplifier audio driver | ||
3 | * | ||
4 | * Copyright 2013 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #ifndef __LINUX_PLATFORM_DATA_SSM2518_H__ | ||
11 | #define __LINUX_PLATFORM_DATA_SSM2518_H__ | ||
12 | |||
13 | /** | ||
14 | * struct ssm2518_platform_data - Platform data for the ssm2518 driver | ||
15 | * @enable_gpio: GPIO connected to the nSD pin. Set to -1 if the nSD pin is | ||
16 | * hardwired. | ||
17 | */ | ||
18 | struct ssm2518_platform_data { | ||
19 | int enable_gpio; | ||
20 | }; | ||
21 | |||
22 | #endif | ||
diff --git a/include/sound/control.h b/include/sound/control.h index 34bc93d80d55..5358892b1b39 100644 --- a/include/sound/control.h +++ b/include/sound/control.h | |||
@@ -233,7 +233,8 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master, | |||
233 | int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, | 233 | int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, |
234 | void (*hook)(void *private_data, int), | 234 | void (*hook)(void *private_data, int), |
235 | void *private_data); | 235 | void *private_data); |
236 | void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl); | 236 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); |
237 | #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) | ||
237 | 238 | ||
238 | /* | 239 | /* |
239 | * Helper functions for jack-detection controls | 240 | * Helper functions for jack-detection controls |
diff --git a/include/sound/core.h b/include/sound/core.h index 5bfe5136441c..c586617cfa0d 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | /* number of supported soundcards */ | 31 | /* number of supported soundcards */ |
32 | #ifdef CONFIG_SND_DYNAMIC_MINORS | 32 | #ifdef CONFIG_SND_DYNAMIC_MINORS |
33 | #define SNDRV_CARDS 32 | 33 | #define SNDRV_CARDS CONFIG_SND_MAX_CARDS |
34 | #else | 34 | #else |
35 | #define SNDRV_CARDS 8 /* don't change - minor numbers */ | 35 | #define SNDRV_CARDS 8 /* don't change - minor numbers */ |
36 | #endif | 36 | #endif |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b48792fe386b..84b10f9a2832 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -384,7 +384,7 @@ struct snd_pcm_substream { | |||
384 | unsigned int dma_buf_id; | 384 | unsigned int dma_buf_id; |
385 | size_t dma_max; | 385 | size_t dma_max; |
386 | /* -- hardware operations -- */ | 386 | /* -- hardware operations -- */ |
387 | struct snd_pcm_ops *ops; | 387 | const struct snd_pcm_ops *ops; |
388 | /* -- runtime information -- */ | 388 | /* -- runtime information -- */ |
389 | struct snd_pcm_runtime *runtime; | 389 | struct snd_pcm_runtime *runtime; |
390 | /* -- timer section -- */ | 390 | /* -- timer section -- */ |
@@ -871,7 +871,8 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); | |||
871 | int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); | 871 | int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); |
872 | snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsigned, int big_endian); | 872 | snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsigned, int big_endian); |
873 | 873 | ||
874 | void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops); | 874 | void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, |
875 | const struct snd_pcm_ops *ops); | ||
875 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); | 876 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); |
876 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); | 877 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); |
877 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | 878 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, |
diff --git a/include/sound/rt5640.h b/include/sound/rt5640.h new file mode 100644 index 000000000000..27cc75ed67f8 --- /dev/null +++ b/include/sound/rt5640.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * linux/sound/rt5640.h -- Platform data for RT5640 | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __LINUX_SND_RT5640_H | ||
12 | #define __LINUX_SND_RT5640_H | ||
13 | |||
14 | struct rt5640_platform_data { | ||
15 | /* IN1 & IN2 can optionally be differential */ | ||
16 | bool in1_diff; | ||
17 | bool in2_diff; | ||
18 | |||
19 | int ldo1_en; /* GPIO for LDO1_EN */ | ||
20 | }; | ||
21 | |||
22 | #endif | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 385c6329a967..3e479f4e15f5 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -311,6 +311,8 @@ struct device; | |||
311 | #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */ | 311 | #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */ |
312 | #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */ | 312 | #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */ |
313 | #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */ | 313 | #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */ |
314 | #define SND_SOC_DAPM_WILL_PMU 0x40 /* called at start of sequence */ | ||
315 | #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ | ||
314 | #define SND_SOC_DAPM_PRE_POST_PMD \ | 316 | #define SND_SOC_DAPM_PRE_POST_PMD \ |
315 | (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) | 317 | (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) |
316 | 318 | ||
@@ -479,7 +481,6 @@ struct snd_soc_dapm_route { | |||
479 | /* dapm audio path between two widgets */ | 481 | /* dapm audio path between two widgets */ |
480 | struct snd_soc_dapm_path { | 482 | struct snd_soc_dapm_path { |
481 | const char *name; | 483 | const char *name; |
482 | const char *long_name; | ||
483 | 484 | ||
484 | /* source (input) and sink (output) widgets */ | 485 | /* source (input) and sink (output) widgets */ |
485 | struct snd_soc_dapm_widget *source; | 486 | struct snd_soc_dapm_widget *source; |
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index e3983d508272..041203f20f6d 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h | |||
@@ -817,6 +817,8 @@ typedef int __bitwise snd_ctl_elem_iface_t; | |||
817 | #define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ | 817 | #define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ |
818 | #define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ | 818 | #define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ |
819 | 819 | ||
820 | #define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 | ||
821 | |||
820 | struct snd_ctl_elem_id { | 822 | struct snd_ctl_elem_id { |
821 | unsigned int numid; /* numeric identifier, zero = invalid */ | 823 | unsigned int numid; /* numeric identifier, zero = invalid */ |
822 | snd_ctl_elem_iface_t iface; /* interface identifier */ | 824 | snd_ctl_elem_iface_t iface; /* interface identifier */ |
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index aa5d8034890b..1ca8dc2ccb89 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -1076,8 +1076,6 @@ static int aaci_remove(struct amba_device *dev) | |||
1076 | { | 1076 | { |
1077 | struct snd_card *card = amba_get_drvdata(dev); | 1077 | struct snd_card *card = amba_get_drvdata(dev); |
1078 | 1078 | ||
1079 | amba_set_drvdata(dev, NULL); | ||
1080 | |||
1081 | if (card) { | 1079 | if (card) { |
1082 | struct aaci *aaci = card->private_data; | 1080 | struct aaci *aaci = card->private_data; |
1083 | writel(0, aaci->base + AACI_MAINCR); | 1081 | writel(0, aaci->base + AACI_MAINCR); |
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index ec54be4efff0..ce431e6e07cf 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -230,7 +230,6 @@ static int pxa2xx_ac97_remove(struct platform_device *dev) | |||
230 | 230 | ||
231 | if (card) { | 231 | if (card) { |
232 | snd_card_free(card); | 232 | snd_card_free(card); |
233 | platform_set_drvdata(dev, NULL); | ||
234 | pxa2xx_ac97_hw_remove(dev); | 233 | pxa2xx_ac97_hw_remove(dev); |
235 | } | 234 | } |
236 | 235 | ||
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index b413ed05e74d..c0c2f57a0d6f 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -157,6 +157,15 @@ config SND_DYNAMIC_MINORS | |||
157 | 157 | ||
158 | If you are unsure about this, say N here. | 158 | If you are unsure about this, say N here. |
159 | 159 | ||
160 | config SND_MAX_CARDS | ||
161 | int "Max number of sound cards" | ||
162 | range 4 256 | ||
163 | default 32 | ||
164 | depends on SND_DYNAMIC_MINORS | ||
165 | help | ||
166 | Specify the max number of sound cards that can be assigned | ||
167 | on a single machine. | ||
168 | |||
160 | config SND_SUPPORT_OLD_API | 169 | config SND_SUPPORT_OLD_API |
161 | bool "Support old ALSA API" | 170 | bool "Support old ALSA API" |
162 | default y | 171 | default y |
diff --git a/sound/core/init.c b/sound/core/init.c index 6ef06400dfc8..6b9087115da2 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -46,7 +46,8 @@ static LIST_HEAD(shutdown_files); | |||
46 | 46 | ||
47 | static const struct file_operations snd_shutdown_f_ops; | 47 | static const struct file_operations snd_shutdown_f_ops; |
48 | 48 | ||
49 | static unsigned int snd_cards_lock; /* locked for registering/using */ | 49 | /* locked for registering/using */ |
50 | static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS); | ||
50 | struct snd_card *snd_cards[SNDRV_CARDS]; | 51 | struct snd_card *snd_cards[SNDRV_CARDS]; |
51 | EXPORT_SYMBOL(snd_cards); | 52 | EXPORT_SYMBOL(snd_cards); |
52 | 53 | ||
@@ -167,29 +168,35 @@ int snd_card_create(int idx, const char *xid, | |||
167 | err = 0; | 168 | err = 0; |
168 | mutex_lock(&snd_card_mutex); | 169 | mutex_lock(&snd_card_mutex); |
169 | if (idx < 0) { | 170 | if (idx < 0) { |
170 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) | 171 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) { |
171 | /* idx == -1 == 0xffff means: take any free slot */ | 172 | /* idx == -1 == 0xffff means: take any free slot */ |
172 | if (~snd_cards_lock & idx & 1<<idx2) { | 173 | if (idx2 < sizeof(int) && !(idx & (1U << idx2))) |
174 | continue; | ||
175 | if (!test_bit(idx2, snd_cards_lock)) { | ||
173 | if (module_slot_match(module, idx2)) { | 176 | if (module_slot_match(module, idx2)) { |
174 | idx = idx2; | 177 | idx = idx2; |
175 | break; | 178 | break; |
176 | } | 179 | } |
177 | } | 180 | } |
181 | } | ||
178 | } | 182 | } |
179 | if (idx < 0) { | 183 | if (idx < 0) { |
180 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) | 184 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) { |
181 | /* idx == -1 == 0xffff means: take any free slot */ | 185 | /* idx == -1 == 0xffff means: take any free slot */ |
182 | if (~snd_cards_lock & idx & 1<<idx2) { | 186 | if (idx2 < sizeof(int) && !(idx & (1U << idx2))) |
187 | continue; | ||
188 | if (!test_bit(idx2, snd_cards_lock)) { | ||
183 | if (!slots[idx2] || !*slots[idx2]) { | 189 | if (!slots[idx2] || !*slots[idx2]) { |
184 | idx = idx2; | 190 | idx = idx2; |
185 | break; | 191 | break; |
186 | } | 192 | } |
187 | } | 193 | } |
194 | } | ||
188 | } | 195 | } |
189 | if (idx < 0) | 196 | if (idx < 0) |
190 | err = -ENODEV; | 197 | err = -ENODEV; |
191 | else if (idx < snd_ecards_limit) { | 198 | else if (idx < snd_ecards_limit) { |
192 | if (snd_cards_lock & (1 << idx)) | 199 | if (test_bit(idx, snd_cards_lock)) |
193 | err = -EBUSY; /* invalid */ | 200 | err = -EBUSY; /* invalid */ |
194 | } else if (idx >= SNDRV_CARDS) | 201 | } else if (idx >= SNDRV_CARDS) |
195 | err = -ENODEV; | 202 | err = -ENODEV; |
@@ -199,7 +206,7 @@ int snd_card_create(int idx, const char *xid, | |||
199 | idx, snd_ecards_limit - 1, err); | 206 | idx, snd_ecards_limit - 1, err); |
200 | goto __error; | 207 | goto __error; |
201 | } | 208 | } |
202 | snd_cards_lock |= 1 << idx; /* lock it */ | 209 | set_bit(idx, snd_cards_lock); /* lock it */ |
203 | if (idx >= snd_ecards_limit) | 210 | if (idx >= snd_ecards_limit) |
204 | snd_ecards_limit = idx + 1; /* increase the limit */ | 211 | snd_ecards_limit = idx + 1; /* increase the limit */ |
205 | mutex_unlock(&snd_card_mutex); | 212 | mutex_unlock(&snd_card_mutex); |
@@ -249,7 +256,7 @@ int snd_card_locked(int card) | |||
249 | int locked; | 256 | int locked; |
250 | 257 | ||
251 | mutex_lock(&snd_card_mutex); | 258 | mutex_lock(&snd_card_mutex); |
252 | locked = snd_cards_lock & (1 << card); | 259 | locked = test_bit(card, snd_cards_lock); |
253 | mutex_unlock(&snd_card_mutex); | 260 | mutex_unlock(&snd_card_mutex); |
254 | return locked; | 261 | return locked; |
255 | } | 262 | } |
@@ -361,7 +368,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
361 | /* phase 1: disable fops (user space) operations for ALSA API */ | 368 | /* phase 1: disable fops (user space) operations for ALSA API */ |
362 | mutex_lock(&snd_card_mutex); | 369 | mutex_lock(&snd_card_mutex); |
363 | snd_cards[card->number] = NULL; | 370 | snd_cards[card->number] = NULL; |
364 | snd_cards_lock &= ~(1 << card->number); | 371 | clear_bit(card->number, snd_cards_lock); |
365 | mutex_unlock(&snd_card_mutex); | 372 | mutex_unlock(&snd_card_mutex); |
366 | 373 | ||
367 | /* phase 2: replace file->f_op with special dummy operations */ | 374 | /* phase 2: replace file->f_op with special dummy operations */ |
@@ -549,7 +556,6 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, | |||
549 | const char *nid) | 556 | const char *nid) |
550 | { | 557 | { |
551 | int len, loops; | 558 | int len, loops; |
552 | bool with_suffix; | ||
553 | bool is_default = false; | 559 | bool is_default = false; |
554 | char *id; | 560 | char *id; |
555 | 561 | ||
@@ -565,26 +571,23 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, | |||
565 | is_default = true; | 571 | is_default = true; |
566 | } | 572 | } |
567 | 573 | ||
568 | with_suffix = false; | 574 | len = strlen(id); |
569 | for (loops = 0; loops < SNDRV_CARDS; loops++) { | 575 | for (loops = 0; loops < SNDRV_CARDS; loops++) { |
576 | char *spos; | ||
577 | char sfxstr[5]; /* "_012" */ | ||
578 | int sfxlen; | ||
579 | |||
570 | if (card_id_ok(card, id)) | 580 | if (card_id_ok(card, id)) |
571 | return; /* OK */ | 581 | return; /* OK */ |
572 | 582 | ||
573 | len = strlen(id); | 583 | /* Add _XYZ suffix */ |
574 | if (!with_suffix) { | 584 | sprintf(sfxstr, "_%X", loops + 1); |
575 | /* add the "_X" suffix */ | 585 | sfxlen = strlen(sfxstr); |
576 | char *spos = id + len; | 586 | if (len + sfxlen >= sizeof(card->id)) |
577 | if (len > sizeof(card->id) - 3) | 587 | spos = id + sizeof(card->id) - sfxlen - 1; |
578 | spos = id + sizeof(card->id) - 3; | 588 | else |
579 | strcpy(spos, "_1"); | 589 | spos = id + len; |
580 | with_suffix = true; | 590 | strcpy(spos, sfxstr); |
581 | } else { | ||
582 | /* modify the existing suffix */ | ||
583 | if (id[len - 1] != '9') | ||
584 | id[len - 1]++; | ||
585 | else | ||
586 | id[len - 1] = 'A'; | ||
587 | } | ||
588 | } | 591 | } |
589 | /* fallback to the default id */ | 592 | /* fallback to the default id */ |
590 | if (!is_default) { | 593 | if (!is_default) { |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 41b3dfe68698..82bb029d4414 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -568,7 +568,8 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) | |||
568 | * | 568 | * |
569 | * Sets the given PCM operators to the pcm instance. | 569 | * Sets the given PCM operators to the pcm instance. |
570 | */ | 570 | */ |
571 | void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops) | 571 | void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, |
572 | const struct snd_pcm_ops *ops) | ||
572 | { | 573 | { |
573 | struct snd_pcm_str *stream = &pcm->streams[direction]; | 574 | struct snd_pcm_str *stream = &pcm->streams[direction]; |
574 | struct snd_pcm_substream *substream; | 575 | struct snd_pcm_substream *substream; |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 02f90b4f8b86..5df8dc25ad80 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -310,20 +310,10 @@ static int master_get(struct snd_kcontrol *kcontrol, | |||
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int master_put(struct snd_kcontrol *kcontrol, | 313 | static int sync_slaves(struct link_master *master, int old_val, int new_val) |
314 | struct snd_ctl_elem_value *ucontrol) | ||
315 | { | 314 | { |
316 | struct link_master *master = snd_kcontrol_chip(kcontrol); | ||
317 | struct link_slave *slave; | 315 | struct link_slave *slave; |
318 | struct snd_ctl_elem_value *uval; | 316 | struct snd_ctl_elem_value *uval; |
319 | int err, old_val; | ||
320 | |||
321 | err = master_init(master); | ||
322 | if (err < 0) | ||
323 | return err; | ||
324 | old_val = master->val; | ||
325 | if (ucontrol->value.integer.value[0] == old_val) | ||
326 | return 0; | ||
327 | 317 | ||
328 | uval = kmalloc(sizeof(*uval), GFP_KERNEL); | 318 | uval = kmalloc(sizeof(*uval), GFP_KERNEL); |
329 | if (!uval) | 319 | if (!uval) |
@@ -332,11 +322,33 @@ static int master_put(struct snd_kcontrol *kcontrol, | |||
332 | master->val = old_val; | 322 | master->val = old_val; |
333 | uval->id = slave->slave.id; | 323 | uval->id = slave->slave.id; |
334 | slave_get_val(slave, uval); | 324 | slave_get_val(slave, uval); |
335 | master->val = ucontrol->value.integer.value[0]; | 325 | master->val = new_val; |
336 | slave_put_val(slave, uval); | 326 | slave_put_val(slave, uval); |
337 | } | 327 | } |
338 | kfree(uval); | 328 | kfree(uval); |
339 | if (master->hook && !err) | 329 | return 0; |
330 | } | ||
331 | |||
332 | static int master_put(struct snd_kcontrol *kcontrol, | ||
333 | struct snd_ctl_elem_value *ucontrol) | ||
334 | { | ||
335 | struct link_master *master = snd_kcontrol_chip(kcontrol); | ||
336 | int err, new_val, old_val; | ||
337 | bool first_init; | ||
338 | |||
339 | err = master_init(master); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | first_init = err; | ||
343 | old_val = master->val; | ||
344 | new_val = ucontrol->value.integer.value[0]; | ||
345 | if (new_val == old_val) | ||
346 | return 0; | ||
347 | |||
348 | err = sync_slaves(master, old_val, new_val); | ||
349 | if (err < 0) | ||
350 | return err; | ||
351 | if (master->hook && first_init) | ||
340 | master->hook(master->hook_private_data, master->val); | 352 | master->hook(master->hook_private_data, master->val); |
341 | return 1; | 353 | return 1; |
342 | } | 354 | } |
@@ -442,20 +454,33 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, | |||
442 | EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); | 454 | EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); |
443 | 455 | ||
444 | /** | 456 | /** |
445 | * snd_ctl_sync_vmaster_hook - Sync the vmaster hook | 457 | * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook |
446 | * @kcontrol: vmaster kctl element | 458 | * @kcontrol: vmaster kctl element |
459 | * @hook_only: sync only the hook | ||
447 | * | 460 | * |
448 | * Call the hook function to synchronize with the current value of the given | 461 | * Forcibly call the put callback of each slave and call the hook function |
449 | * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't | 462 | * to synchronize with the current value of the given vmaster element. |
450 | * exist. | 463 | * NOP when NULL is passed to @kcontrol. |
451 | */ | 464 | */ |
452 | void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) | 465 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) |
453 | { | 466 | { |
454 | struct link_master *master; | 467 | struct link_master *master; |
468 | bool first_init = false; | ||
469 | |||
455 | if (!kcontrol) | 470 | if (!kcontrol) |
456 | return; | 471 | return; |
457 | master = snd_kcontrol_chip(kcontrol); | 472 | master = snd_kcontrol_chip(kcontrol); |
458 | if (master->hook) | 473 | if (!hook_only) { |
474 | int err = master_init(master); | ||
475 | if (err < 0) | ||
476 | return; | ||
477 | first_init = err; | ||
478 | err = sync_slaves(master, master->val, master->val); | ||
479 | if (err < 0) | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | if (master->hook && !first_init) | ||
459 | master->hook(master->hook_private_data, master->val); | 484 | master->hook(master->hook_private_data, master->val); |
460 | } | 485 | } |
461 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); | 486 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 6f78de9c6fb6..f7589923effa 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -1183,7 +1183,6 @@ static int loopback_probe(struct platform_device *devptr) | |||
1183 | static int loopback_remove(struct platform_device *devptr) | 1183 | static int loopback_remove(struct platform_device *devptr) |
1184 | { | 1184 | { |
1185 | snd_card_free(platform_get_drvdata(devptr)); | 1185 | snd_card_free(platform_get_drvdata(devptr)); |
1186 | platform_set_drvdata(devptr, NULL); | ||
1187 | return 0; | 1186 | return 0; |
1188 | } | 1187 | } |
1189 | 1188 | ||
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index fd798f753609..11048cc744d0 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -1129,7 +1129,6 @@ static int snd_dummy_probe(struct platform_device *devptr) | |||
1129 | static int snd_dummy_remove(struct platform_device *devptr) | 1129 | static int snd_dummy_remove(struct platform_device *devptr) |
1130 | { | 1130 | { |
1131 | snd_card_free(platform_get_drvdata(devptr)); | 1131 | snd_card_free(platform_get_drvdata(devptr)); |
1132 | platform_set_drvdata(devptr, NULL); | ||
1133 | return 0; | 1132 | return 0; |
1134 | } | 1133 | } |
1135 | 1134 | ||
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 8125a7e95ee4..95ea4a153ea4 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c | |||
@@ -1325,7 +1325,6 @@ static int snd_ml403_ac97cr_probe(struct platform_device *pfdev) | |||
1325 | static int snd_ml403_ac97cr_remove(struct platform_device *pfdev) | 1325 | static int snd_ml403_ac97cr_remove(struct platform_device *pfdev) |
1326 | { | 1326 | { |
1327 | snd_card_free(platform_get_drvdata(pfdev)); | 1327 | snd_card_free(platform_get_drvdata(pfdev)); |
1328 | platform_set_drvdata(pfdev, NULL); | ||
1329 | return 0; | 1328 | return 0; |
1330 | } | 1329 | } |
1331 | 1330 | ||
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index da1a29bfc85d..90a3a7b38a2a 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -129,7 +129,6 @@ static int snd_mpu401_probe(struct platform_device *devptr) | |||
129 | static int snd_mpu401_remove(struct platform_device *devptr) | 129 | static int snd_mpu401_remove(struct platform_device *devptr) |
130 | { | 130 | { |
131 | snd_card_free(platform_get_drvdata(devptr)); | 131 | snd_card_free(platform_get_drvdata(devptr)); |
132 | platform_set_drvdata(devptr, NULL); | ||
133 | return 0; | 132 | return 0; |
134 | } | 133 | } |
135 | 134 | ||
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 9f1815b99a15..e5ec7eb27dec 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -749,7 +749,6 @@ static int snd_mtpav_probe(struct platform_device *dev) | |||
749 | static int snd_mtpav_remove(struct platform_device *devptr) | 749 | static int snd_mtpav_remove(struct platform_device *devptr) |
750 | { | 750 | { |
751 | snd_card_free(platform_get_drvdata(devptr)); | 751 | snd_card_free(platform_get_drvdata(devptr)); |
752 | platform_set_drvdata(devptr, NULL); | ||
753 | return 0; | 752 | return 0; |
754 | } | 753 | } |
755 | 754 | ||
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 7a5fdb9b0afc..1c19cd7ad26e 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -189,7 +189,6 @@ static int pcsp_remove(struct platform_device *dev) | |||
189 | struct snd_pcsp *chip = platform_get_drvdata(dev); | 189 | struct snd_pcsp *chip = platform_get_drvdata(dev); |
190 | alsa_card_pcsp_exit(chip); | 190 | alsa_card_pcsp_exit(chip); |
191 | pcspkr_input_remove(chip->input_dev); | 191 | pcspkr_input_remove(chip->input_dev); |
192 | platform_set_drvdata(dev, NULL); | ||
193 | return 0; | 192 | return 0; |
194 | } | 193 | } |
195 | 194 | ||
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 7425dd8c1f09..e0bf5e77b43a 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -985,7 +985,6 @@ static int snd_serial_probe(struct platform_device *devptr) | |||
985 | static int snd_serial_remove(struct platform_device *devptr) | 985 | static int snd_serial_remove(struct platform_device *devptr) |
986 | { | 986 | { |
987 | snd_card_free(platform_get_drvdata(devptr)); | 987 | snd_card_free(platform_get_drvdata(devptr)); |
988 | platform_set_drvdata(devptr, NULL); | ||
989 | return 0; | 988 | return 0; |
990 | } | 989 | } |
991 | 990 | ||
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index cc4be88d7318..ace3879e8d96 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c | |||
@@ -132,7 +132,6 @@ static int snd_virmidi_probe(struct platform_device *devptr) | |||
132 | static int snd_virmidi_remove(struct platform_device *devptr) | 132 | static int snd_virmidi_remove(struct platform_device *devptr) |
133 | { | 133 | { |
134 | snd_card_free(platform_get_drvdata(devptr)); | 134 | snd_card_free(platform_get_drvdata(devptr)); |
135 | platform_set_drvdata(devptr, NULL); | ||
136 | return 0; | 135 | return 0; |
137 | } | 136 | } |
138 | 137 | ||
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index c39961c11401..83596891cde4 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -205,7 +205,7 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) | |||
205 | 205 | ||
206 | if (size < 1) | 206 | if (size < 1) |
207 | return 0; | 207 | return 0; |
208 | if (snd_BUG_ON(size > SIZE_MAX_STATUS)) | 208 | if (snd_BUG_ON(size >= SIZE_MAX_STATUS)) |
209 | return -EINVAL; | 209 | return -EINVAL; |
210 | 210 | ||
211 | for (i = 1; i <= size; i++) { | 211 | for (i = 1; i <= size; i++) { |
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h index b680c5ef01d6..f6103d68c4b1 100644 --- a/sound/firewire/amdtp.h +++ b/sound/firewire/amdtp.h | |||
@@ -3,7 +3,6 @@ | |||
3 | 3 | ||
4 | #include <linux/interrupt.h> | 4 | #include <linux/interrupt.h> |
5 | #include <linux/mutex.h> | 5 | #include <linux/mutex.h> |
6 | #include <linux/spinlock.h> | ||
7 | #include "packets-buffer.h" | 6 | #include "packets-buffer.h" |
8 | 7 | ||
9 | /** | 8 | /** |
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c index 844a555c3b1e..b252c21b6d13 100644 --- a/sound/firewire/scs1x.c +++ b/sound/firewire/scs1x.c | |||
@@ -405,8 +405,10 @@ static int scs_probe(struct device *unit_dev) | |||
405 | scs->output_idle = true; | 405 | scs->output_idle = true; |
406 | 406 | ||
407 | scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL); | 407 | scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL); |
408 | if (!scs->buffer) | 408 | if (!scs->buffer) { |
409 | err = -ENOMEM; | ||
409 | goto err_card; | 410 | goto err_card; |
411 | } | ||
410 | 412 | ||
411 | scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE; | 413 | scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE; |
412 | scs->hss_handler.address_callback = handle_hss; | 414 | scs->hss_handler.address_callback = handle_hss; |
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index cef813d23641..ed726d1569e8 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -571,7 +571,7 @@ static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, | |||
571 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 571 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
572 | int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); | 572 | int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); |
573 | const char **input_names; | 573 | const char **input_names; |
574 | int num_names, idx; | 574 | unsigned int num_names, idx; |
575 | 575 | ||
576 | num_names = ak4xxx_capture_num_inputs(ak, mixer_ch); | 576 | num_names = ak4xxx_capture_num_inputs(ak, mixer_ch); |
577 | if (!num_names) | 577 | if (!num_names) |
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index c214ecf45400..e3f455bd85cd 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -135,7 +135,6 @@ out: snd_card_free(card); | |||
135 | static int snd_ad1848_remove(struct device *dev, unsigned int n) | 135 | static int snd_ad1848_remove(struct device *dev, unsigned int n) |
136 | { | 136 | { |
137 | snd_card_free(dev_get_drvdata(dev)); | 137 | snd_card_free(dev_get_drvdata(dev)); |
138 | dev_set_drvdata(dev, NULL); | ||
139 | return 0; | 138 | return 0; |
140 | } | 139 | } |
141 | 140 | ||
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index d26545543732..35659218710f 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c | |||
@@ -101,7 +101,6 @@ out: snd_card_free(card); | |||
101 | static int snd_adlib_remove(struct device *dev, unsigned int n) | 101 | static int snd_adlib_remove(struct device *dev, unsigned int n) |
102 | { | 102 | { |
103 | snd_card_free(dev_get_drvdata(dev)); | 103 | snd_card_free(dev_get_drvdata(dev)); |
104 | dev_set_drvdata(dev, NULL); | ||
105 | return 0; | 104 | return 0; |
106 | } | 105 | } |
107 | 106 | ||
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index a7369fe19a6f..f84f073fc1e8 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c | |||
@@ -418,7 +418,6 @@ static int snd_cmi8328_remove(struct device *pdev, unsigned int dev) | |||
418 | snd_cmi8328_cfg_write(cmi->port, CFG2, 0); | 418 | snd_cmi8328_cfg_write(cmi->port, CFG2, 0); |
419 | snd_cmi8328_cfg_write(cmi->port, CFG3, 0); | 419 | snd_cmi8328_cfg_write(cmi->port, CFG3, 0); |
420 | snd_card_free(card); | 420 | snd_card_free(card); |
421 | dev_set_drvdata(pdev, NULL); | ||
422 | return 0; | 421 | return 0; |
423 | } | 422 | } |
424 | 423 | ||
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index c707c52268ab..270b9659ef7f 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c | |||
@@ -651,7 +651,6 @@ static int snd_cmi8330_isa_remove(struct device *devptr, | |||
651 | unsigned int dev) | 651 | unsigned int dev) |
652 | { | 652 | { |
653 | snd_card_free(dev_get_drvdata(devptr)); | 653 | snd_card_free(dev_get_drvdata(devptr)); |
654 | dev_set_drvdata(devptr, NULL); | ||
655 | return 0; | 654 | return 0; |
656 | } | 655 | } |
657 | 656 | ||
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index aa7a5d86e480..ba9a74eff3e0 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -151,7 +151,6 @@ out: snd_card_free(card); | |||
151 | static int snd_cs4231_remove(struct device *dev, unsigned int n) | 151 | static int snd_cs4231_remove(struct device *dev, unsigned int n) |
152 | { | 152 | { |
153 | snd_card_free(dev_get_drvdata(dev)); | 153 | snd_card_free(dev_get_drvdata(dev)); |
154 | dev_set_drvdata(dev, NULL); | ||
155 | return 0; | 154 | return 0; |
156 | } | 155 | } |
157 | 156 | ||
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 252e9fb37db3..69614acb2052 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -504,7 +504,6 @@ static int snd_cs423x_isa_remove(struct device *pdev, | |||
504 | unsigned int dev) | 504 | unsigned int dev) |
505 | { | 505 | { |
506 | snd_card_free(dev_get_drvdata(pdev)); | 506 | snd_card_free(dev_get_drvdata(pdev)); |
507 | dev_set_drvdata(pdev, NULL); | ||
508 | return 0; | 507 | return 0; |
509 | } | 508 | } |
510 | 509 | ||
@@ -600,7 +599,6 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, | |||
600 | static void snd_cs423x_pnp_remove(struct pnp_dev *pdev) | 599 | static void snd_cs423x_pnp_remove(struct pnp_dev *pdev) |
601 | { | 600 | { |
602 | snd_card_free(pnp_get_drvdata(pdev)); | 601 | snd_card_free(pnp_get_drvdata(pdev)); |
603 | pnp_set_drvdata(pdev, NULL); | ||
604 | } | 602 | } |
605 | 603 | ||
606 | #ifdef CONFIG_PM | 604 | #ifdef CONFIG_PM |
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 102874a703d4..cdcfb57f1f0a 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -213,7 +213,6 @@ out: | |||
213 | static int snd_es1688_isa_remove(struct device *dev, unsigned int n) | 213 | static int snd_es1688_isa_remove(struct device *dev, unsigned int n) |
214 | { | 214 | { |
215 | snd_card_free(dev_get_drvdata(dev)); | 215 | snd_card_free(dev_get_drvdata(dev)); |
216 | dev_set_drvdata(dev, NULL); | ||
217 | return 0; | 216 | return 0; |
218 | } | 217 | } |
219 | 218 | ||
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 24380efe31a1..12978b864c3a 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -2235,7 +2235,6 @@ static int snd_es18xx_isa_remove(struct device *devptr, | |||
2235 | unsigned int dev) | 2235 | unsigned int dev) |
2236 | { | 2236 | { |
2237 | snd_card_free(dev_get_drvdata(devptr)); | 2237 | snd_card_free(dev_get_drvdata(devptr)); |
2238 | dev_set_drvdata(devptr, NULL); | ||
2239 | return 0; | 2238 | return 0; |
2240 | } | 2239 | } |
2241 | 2240 | ||
@@ -2305,7 +2304,6 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev, | |||
2305 | static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev) | 2304 | static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev) |
2306 | { | 2305 | { |
2307 | snd_card_free(pnp_get_drvdata(pdev)); | 2306 | snd_card_free(pnp_get_drvdata(pdev)); |
2308 | pnp_set_drvdata(pdev, NULL); | ||
2309 | } | 2307 | } |
2310 | 2308 | ||
2311 | #ifdef CONFIG_PM | 2309 | #ifdef CONFIG_PM |
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index 672184e3221a..81244e7cea5b 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c | |||
@@ -623,7 +623,6 @@ error: | |||
623 | static int snd_galaxy_remove(struct device *dev, unsigned int n) | 623 | static int snd_galaxy_remove(struct device *dev, unsigned int n) |
624 | { | 624 | { |
625 | snd_card_free(dev_get_drvdata(dev)); | 625 | snd_card_free(dev_get_drvdata(dev)); |
626 | dev_set_drvdata(dev, NULL); | ||
627 | return 0; | 626 | return 0; |
628 | } | 627 | } |
629 | 628 | ||
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 16bca4e96c08..1adc1b924f39 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -215,7 +215,6 @@ out: snd_card_free(card); | |||
215 | static int snd_gusclassic_remove(struct device *dev, unsigned int n) | 215 | static int snd_gusclassic_remove(struct device *dev, unsigned int n) |
216 | { | 216 | { |
217 | snd_card_free(dev_get_drvdata(dev)); | 217 | snd_card_free(dev_get_drvdata(dev)); |
218 | dev_set_drvdata(dev, NULL); | ||
219 | return 0; | 218 | return 0; |
220 | } | 219 | } |
221 | 220 | ||
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 0b9c2426b49f..38e1e3260c24 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -344,7 +344,6 @@ out: snd_card_free(card); | |||
344 | static int snd_gusextreme_remove(struct device *dev, unsigned int n) | 344 | static int snd_gusextreme_remove(struct device *dev, unsigned int n) |
345 | { | 345 | { |
346 | snd_card_free(dev_get_drvdata(dev)); | 346 | snd_card_free(dev_get_drvdata(dev)); |
347 | dev_set_drvdata(dev, NULL); | ||
348 | return 0; | 347 | return 0; |
349 | } | 348 | } |
350 | 349 | ||
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index c309a5d0e7e1..652d5d834620 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -357,7 +357,6 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) | |||
357 | static int snd_gusmax_remove(struct device *devptr, unsigned int dev) | 357 | static int snd_gusmax_remove(struct device *devptr, unsigned int dev) |
358 | { | 358 | { |
359 | snd_card_free(dev_get_drvdata(devptr)); | 359 | snd_card_free(dev_get_drvdata(devptr)); |
360 | dev_set_drvdata(devptr, NULL); | ||
361 | return 0; | 360 | return 0; |
362 | } | 361 | } |
363 | 362 | ||
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 78bc5744e89a..9942691cc0ca 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -849,7 +849,6 @@ static int snd_interwave_isa_probe(struct device *pdev, | |||
849 | static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev) | 849 | static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev) |
850 | { | 850 | { |
851 | snd_card_free(dev_get_drvdata(devptr)); | 851 | snd_card_free(dev_get_drvdata(devptr)); |
852 | dev_set_drvdata(devptr, NULL); | ||
853 | return 0; | 852 | return 0; |
854 | } | 853 | } |
855 | 854 | ||
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index ddabb406b14c..81aeb934261a 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c | |||
@@ -1064,7 +1064,6 @@ cfg_error: | |||
1064 | static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev) | 1064 | static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev) |
1065 | { | 1065 | { |
1066 | snd_msnd_unload(dev_get_drvdata(pdev)); | 1066 | snd_msnd_unload(dev_get_drvdata(pdev)); |
1067 | dev_set_drvdata(pdev, NULL); | ||
1068 | return 0; | 1067 | return 0; |
1069 | } | 1068 | } |
1070 | 1069 | ||
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 075777a6cf0b..cc01c419b7e9 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -757,7 +757,6 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, | |||
757 | static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev) | 757 | static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev) |
758 | { | 758 | { |
759 | snd_card_free(pnp_get_drvdata(pdev)); | 759 | snd_card_free(pnp_get_drvdata(pdev)); |
760 | pnp_set_drvdata(pdev, NULL); | ||
761 | } | 760 | } |
762 | 761 | ||
763 | #ifdef CONFIG_PM | 762 | #ifdef CONFIG_PM |
@@ -900,7 +899,6 @@ static int snd_opl3sa2_isa_remove(struct device *devptr, | |||
900 | unsigned int dev) | 899 | unsigned int dev) |
901 | { | 900 | { |
902 | snd_card_free(dev_get_drvdata(devptr)); | 901 | snd_card_free(dev_get_drvdata(devptr)); |
903 | dev_set_drvdata(devptr, NULL); | ||
904 | return 0; | 902 | return 0; |
905 | } | 903 | } |
906 | 904 | ||
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index c3da1df9371d..619753d96ca5 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -1495,7 +1495,6 @@ static int snd_miro_isa_remove(struct device *devptr, | |||
1495 | unsigned int dev) | 1495 | unsigned int dev) |
1496 | { | 1496 | { |
1497 | snd_card_free(dev_get_drvdata(devptr)); | 1497 | snd_card_free(dev_get_drvdata(devptr)); |
1498 | dev_set_drvdata(devptr, NULL); | ||
1499 | return 0; | 1498 | return 0; |
1500 | } | 1499 | } |
1501 | 1500 | ||
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index b41ed8661b23..103b33373fd4 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -1035,7 +1035,6 @@ static int snd_opti9xx_isa_remove(struct device *devptr, | |||
1035 | unsigned int dev) | 1035 | unsigned int dev) |
1036 | { | 1036 | { |
1037 | snd_card_free(dev_get_drvdata(devptr)); | 1037 | snd_card_free(dev_get_drvdata(devptr)); |
1038 | dev_set_drvdata(devptr, NULL); | ||
1039 | return 0; | 1038 | return 0; |
1040 | } | 1039 | } |
1041 | 1040 | ||
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 4961da4e627c..356a6308392f 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c | |||
@@ -345,7 +345,6 @@ static int snd_jazz16_remove(struct device *devptr, unsigned int dev) | |||
345 | { | 345 | { |
346 | struct snd_card *card = dev_get_drvdata(devptr); | 346 | struct snd_card *card = dev_get_drvdata(devptr); |
347 | 347 | ||
348 | dev_set_drvdata(devptr, NULL); | ||
349 | snd_card_free(card); | 348 | snd_card_free(card); |
350 | return 0; | 349 | return 0; |
351 | } | 350 | } |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 50dbec454f98..a4130993955f 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -566,7 +566,6 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev) | |||
566 | static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev) | 566 | static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev) |
567 | { | 567 | { |
568 | snd_card_free(dev_get_drvdata(pdev)); | 568 | snd_card_free(dev_get_drvdata(pdev)); |
569 | dev_set_drvdata(pdev, NULL); | ||
570 | return 0; | 569 | return 0; |
571 | } | 570 | } |
572 | 571 | ||
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 237d964ff8a6..a806ae90a944 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -208,7 +208,6 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) | |||
208 | static int snd_sb8_remove(struct device *pdev, unsigned int dev) | 208 | static int snd_sb8_remove(struct device *pdev, unsigned int dev) |
209 | { | 209 | { |
210 | snd_card_free(dev_get_drvdata(pdev)); | 210 | snd_card_free(dev_get_drvdata(pdev)); |
211 | dev_set_drvdata(pdev, NULL); | ||
212 | return 0; | 211 | return 0; |
213 | } | 212 | } |
214 | 213 | ||
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 5376ebff845e..09d481b3ba7f 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c | |||
@@ -698,7 +698,6 @@ static int snd_sc6000_remove(struct device *devptr, unsigned int dev) | |||
698 | release_region(port[dev], 0x10); | 698 | release_region(port[dev], 0x10); |
699 | release_region(mss_port[dev], 4); | 699 | release_region(mss_port[dev], 4); |
700 | 700 | ||
701 | dev_set_drvdata(devptr, NULL); | ||
702 | snd_card_free(card); | 701 | snd_card_free(card); |
703 | return 0; | 702 | return 0; |
704 | } | 703 | } |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 42a009720b29..57b338973ede 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -1200,7 +1200,6 @@ _release_card: | |||
1200 | static int snd_sscape_remove(struct device *devptr, unsigned int dev) | 1200 | static int snd_sscape_remove(struct device *devptr, unsigned int dev) |
1201 | { | 1201 | { |
1202 | snd_card_free(dev_get_drvdata(devptr)); | 1202 | snd_card_free(dev_get_drvdata(devptr)); |
1203 | dev_set_drvdata(devptr, NULL); | ||
1204 | return 0; | 1203 | return 0; |
1205 | } | 1204 | } |
1206 | 1205 | ||
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index fe5dd982bd23..82dd76939fa0 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
@@ -581,7 +581,6 @@ static int snd_wavefront_isa_remove(struct device *devptr, | |||
581 | unsigned int dev) | 581 | unsigned int dev) |
582 | { | 582 | { |
583 | snd_card_free(dev_get_drvdata(devptr)); | 583 | snd_card_free(dev_get_drvdata(devptr)); |
584 | dev_set_drvdata(devptr, NULL); | ||
585 | return 0; | 584 | return 0; |
586 | } | 585 | } |
587 | 586 | ||
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c index 2a44cc106459..12be1fb512dd 100644 --- a/sound/oss/kahlua.c +++ b/sound/oss/kahlua.c | |||
@@ -178,7 +178,6 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
178 | return 0; | 178 | return 0; |
179 | 179 | ||
180 | err_out_free: | 180 | err_out_free: |
181 | pci_set_drvdata(pdev, NULL); | ||
182 | kfree(hw_config); | 181 | kfree(hw_config); |
183 | return 1; | 182 | return 1; |
184 | } | 183 | } |
@@ -187,7 +186,6 @@ static void remove_one(struct pci_dev *pdev) | |||
187 | { | 186 | { |
188 | struct address_info *hw_config = pci_get_drvdata(pdev); | 187 | struct address_info *hw_config = pci_get_drvdata(pdev); |
189 | sb_dsp_unload(hw_config, 0); | 188 | sb_dsp_unload(hw_config, 0); |
190 | pci_set_drvdata(pdev, NULL); | ||
191 | kfree(hw_config); | 189 | kfree(hw_config); |
192 | } | 190 | } |
193 | 191 | ||
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 0e66ba48d453..67f56a2cee6a 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c | |||
@@ -902,8 +902,6 @@ snd_harmony_free(struct snd_harmony *h) | |||
902 | if (h->iobase) | 902 | if (h->iobase) |
903 | iounmap(h->iobase); | 903 | iounmap(h->iobase); |
904 | 904 | ||
905 | parisc_set_drvdata(h->dev, NULL); | ||
906 | |||
907 | kfree(h); | 905 | kfree(h); |
908 | return 0; | 906 | return 0; |
909 | } | 907 | } |
@@ -1016,7 +1014,6 @@ static int | |||
1016 | snd_harmony_remove(struct parisc_device *padev) | 1014 | snd_harmony_remove(struct parisc_device *padev) |
1017 | { | 1015 | { |
1018 | snd_card_free(parisc_get_drvdata(padev)); | 1016 | snd_card_free(parisc_get_drvdata(padev)); |
1019 | parisc_set_drvdata(padev, NULL); | ||
1020 | return 0; | 1017 | return 0; |
1021 | } | 1018 | } |
1022 | 1019 | ||
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index d37c683cfd7a..445ca481d8d3 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -1296,7 +1296,7 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, | |||
1296 | struct snd_ac97 *ac97) | 1296 | struct snd_ac97 *ac97) |
1297 | { | 1297 | { |
1298 | int err; | 1298 | int err; |
1299 | char name[44]; | 1299 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
1300 | unsigned char lo_max, hi_max; | 1300 | unsigned char lo_max, hi_max; |
1301 | 1301 | ||
1302 | if (! snd_ac97_valid_reg(ac97, reg)) | 1302 | if (! snd_ac97_valid_reg(ac97, reg)) |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index ad8a31173939..d2b9d617aee5 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -1046,7 +1046,6 @@ static void | |||
1046 | snd_ad1889_remove(struct pci_dev *pci) | 1046 | snd_ad1889_remove(struct pci_dev *pci) |
1047 | { | 1047 | { |
1048 | snd_card_free(pci_get_drvdata(pci)); | 1048 | snd_card_free(pci_get_drvdata(pci)); |
1049 | pci_set_drvdata(pci, NULL); | ||
1050 | } | 1049 | } |
1051 | 1050 | ||
1052 | static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = { | 1051 | static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = { |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 53754f5edeb1..3dfa12b670eb 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2298,7 +2298,6 @@ static int snd_ali_probe(struct pci_dev *pci, | |||
2298 | static void snd_ali_remove(struct pci_dev *pci) | 2298 | static void snd_ali_remove(struct pci_dev *pci) |
2299 | { | 2299 | { |
2300 | snd_card_free(pci_get_drvdata(pci)); | 2300 | snd_card_free(pci_get_drvdata(pci)); |
2301 | pci_set_drvdata(pci, NULL); | ||
2302 | } | 2301 | } |
2303 | 2302 | ||
2304 | static struct pci_driver ali5451_driver = { | 2303 | static struct pci_driver ali5451_driver = { |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 864c4310366b..591efb6eef05 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -282,7 +282,6 @@ static void snd_als300_remove(struct pci_dev *pci) | |||
282 | { | 282 | { |
283 | snd_als300_dbgcallenter(); | 283 | snd_als300_dbgcallenter(); |
284 | snd_card_free(pci_get_drvdata(pci)); | 284 | snd_card_free(pci_get_drvdata(pci)); |
285 | pci_set_drvdata(pci, NULL); | ||
286 | snd_als300_dbgcallleave(); | 285 | snd_als300_dbgcallleave(); |
287 | } | 286 | } |
288 | 287 | ||
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 61efda2a4d94..ffc821b0139e 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -984,7 +984,6 @@ out: | |||
984 | static void snd_card_als4000_remove(struct pci_dev *pci) | 984 | static void snd_card_als4000_remove(struct pci_dev *pci) |
985 | { | 985 | { |
986 | snd_card_free(pci_get_drvdata(pci)); | 986 | snd_card_free(pci_get_drvdata(pci)); |
987 | pci_set_drvdata(pci, NULL); | ||
988 | } | 987 | } |
989 | 988 | ||
990 | #ifdef CONFIG_PM_SLEEP | 989 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index fbc17203613c..185d54a5cb1a 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -1278,7 +1278,7 @@ struct hpi_control { | |||
1278 | u16 dst_node_type; | 1278 | u16 dst_node_type; |
1279 | u16 dst_node_index; | 1279 | u16 dst_node_index; |
1280 | u16 band; | 1280 | u16 band; |
1281 | char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ | 1281 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* copied to snd_ctl_elem_id.name[44]; */ |
1282 | }; | 1282 | }; |
1283 | 1283 | ||
1284 | static const char * const asihpi_tuner_band_names[] = { | 1284 | static const char * const asihpi_tuner_band_names[] = { |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index ef5019fe5193..7f0272032fbb 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -445,7 +445,6 @@ void asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
445 | if (pa->p_buffer) | 445 | if (pa->p_buffer) |
446 | vfree(pa->p_buffer); | 446 | vfree(pa->p_buffer); |
447 | 447 | ||
448 | pci_set_drvdata(pci_dev, NULL); | ||
449 | if (1) | 448 | if (1) |
450 | dev_info(&pci_dev->dev, | 449 | dev_info(&pci_dev->dev, |
451 | "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n", | 450 | "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n", |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 6e78c6789858..fe4c61bdb8ba 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1714,7 +1714,6 @@ static int snd_atiixp_probe(struct pci_dev *pci, | |||
1714 | static void snd_atiixp_remove(struct pci_dev *pci) | 1714 | static void snd_atiixp_remove(struct pci_dev *pci) |
1715 | { | 1715 | { |
1716 | snd_card_free(pci_get_drvdata(pci)); | 1716 | snd_card_free(pci_get_drvdata(pci)); |
1717 | pci_set_drvdata(pci, NULL); | ||
1718 | } | 1717 | } |
1719 | 1718 | ||
1720 | static struct pci_driver atiixp_driver = { | 1719 | static struct pci_driver atiixp_driver = { |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index d0bec7ba3b0d..cf29b9a1d65d 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1334,7 +1334,6 @@ static int snd_atiixp_probe(struct pci_dev *pci, | |||
1334 | static void snd_atiixp_remove(struct pci_dev *pci) | 1334 | static void snd_atiixp_remove(struct pci_dev *pci) |
1335 | { | 1335 | { |
1336 | snd_card_free(pci_get_drvdata(pci)); | 1336 | snd_card_free(pci_get_drvdata(pci)); |
1337 | pci_set_drvdata(pci, NULL); | ||
1338 | } | 1337 | } |
1339 | 1338 | ||
1340 | static struct pci_driver atiixp_modem_driver = { | 1339 | static struct pci_driver atiixp_modem_driver = { |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index b157e1fadd8f..7059dd69e5e6 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -371,7 +371,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
371 | static void snd_vortex_remove(struct pci_dev *pci) | 371 | static void snd_vortex_remove(struct pci_dev *pci) |
372 | { | 372 | { |
373 | snd_card_free(pci_get_drvdata(pci)); | 373 | snd_card_free(pci_get_drvdata(pci)); |
374 | pci_set_drvdata(pci, NULL); | ||
375 | } | 374 | } |
376 | 375 | ||
377 | // pci_driver definition | 376 | // pci_driver definition |
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 08e9a4702cbc..2925220d3fcf 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c | |||
@@ -392,7 +392,6 @@ static int snd_aw2_probe(struct pci_dev *pci, | |||
392 | static void snd_aw2_remove(struct pci_dev *pci) | 392 | static void snd_aw2_remove(struct pci_dev *pci) |
393 | { | 393 | { |
394 | snd_card_free(pci_get_drvdata(pci)); | 394 | snd_card_free(pci_get_drvdata(pci)); |
395 | pci_set_drvdata(pci, NULL); | ||
396 | } | 395 | } |
397 | 396 | ||
398 | /* open callback */ | 397 | /* open callback */ |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 1204a0fa3368..c8e121611593 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2725,7 +2725,6 @@ snd_azf3328_remove(struct pci_dev *pci) | |||
2725 | { | 2725 | { |
2726 | snd_azf3328_dbgcallenter(); | 2726 | snd_azf3328_dbgcallenter(); |
2727 | snd_card_free(pci_get_drvdata(pci)); | 2727 | snd_card_free(pci_get_drvdata(pci)); |
2728 | pci_set_drvdata(pci, NULL); | ||
2729 | snd_azf3328_dbgcallleave(); | 2728 | snd_azf3328_dbgcallleave(); |
2730 | } | 2729 | } |
2731 | 2730 | ||
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 9febe5509748..18802039497a 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -953,7 +953,6 @@ _error: | |||
953 | static void snd_bt87x_remove(struct pci_dev *pci) | 953 | static void snd_bt87x_remove(struct pci_dev *pci) |
954 | { | 954 | { |
955 | snd_card_free(pci_get_drvdata(pci)); | 955 | snd_card_free(pci_get_drvdata(pci)); |
956 | pci_set_drvdata(pci, NULL); | ||
957 | } | 956 | } |
958 | 957 | ||
959 | /* default entries for all Bt87x cards - it's not exported */ | 958 | /* default entries for all Bt87x cards - it's not exported */ |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 1610a5705970..f4db5587e86e 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1896,7 +1896,6 @@ static int snd_ca0106_probe(struct pci_dev *pci, | |||
1896 | static void snd_ca0106_remove(struct pci_dev *pci) | 1896 | static void snd_ca0106_remove(struct pci_dev *pci) |
1897 | { | 1897 | { |
1898 | snd_card_free(pci_get_drvdata(pci)); | 1898 | snd_card_free(pci_get_drvdata(pci)); |
1899 | pci_set_drvdata(pci, NULL); | ||
1900 | } | 1899 | } |
1901 | 1900 | ||
1902 | #ifdef CONFIG_PM_SLEEP | 1901 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index c617435db6e6..2755ec5bcc25 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -3317,7 +3317,6 @@ static int snd_cmipci_probe(struct pci_dev *pci, | |||
3317 | static void snd_cmipci_remove(struct pci_dev *pci) | 3317 | static void snd_cmipci_remove(struct pci_dev *pci) |
3318 | { | 3318 | { |
3319 | snd_card_free(pci_get_drvdata(pci)); | 3319 | snd_card_free(pci_get_drvdata(pci)); |
3320 | pci_set_drvdata(pci, NULL); | ||
3321 | } | 3320 | } |
3322 | 3321 | ||
3323 | 3322 | ||
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 6a8695069941..1dc793e742d7 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1312,7 +1312,7 @@ static int snd_cs4281_free(struct cs4281 *chip) | |||
1312 | /* Sound System Power Management - Turn Everything OFF */ | 1312 | /* Sound System Power Management - Turn Everything OFF */ |
1313 | snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); | 1313 | snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); |
1314 | /* PCI interface - D3 state */ | 1314 | /* PCI interface - D3 state */ |
1315 | pci_set_power_state(chip->pci, 3); | 1315 | pci_set_power_state(chip->pci, PCI_D3hot); |
1316 | 1316 | ||
1317 | if (chip->irq >= 0) | 1317 | if (chip->irq >= 0) |
1318 | free_irq(chip->irq, chip); | 1318 | free_irq(chip->irq, chip); |
@@ -1971,7 +1971,6 @@ static int snd_cs4281_probe(struct pci_dev *pci, | |||
1971 | static void snd_cs4281_remove(struct pci_dev *pci) | 1971 | static void snd_cs4281_remove(struct pci_dev *pci) |
1972 | { | 1972 | { |
1973 | snd_card_free(pci_get_drvdata(pci)); | 1973 | snd_card_free(pci_get_drvdata(pci)); |
1974 | pci_set_drvdata(pci, NULL); | ||
1975 | } | 1974 | } |
1976 | 1975 | ||
1977 | /* | 1976 | /* |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 6b0d8b50a305..b03498325d66 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -158,7 +158,6 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, | |||
158 | static void snd_card_cs46xx_remove(struct pci_dev *pci) | 158 | static void snd_card_cs46xx_remove(struct pci_dev *pci) |
159 | { | 159 | { |
160 | snd_card_free(pci_get_drvdata(pci)); | 160 | snd_card_free(pci_get_drvdata(pci)); |
161 | pci_set_drvdata(pci, NULL); | ||
162 | } | 161 | } |
163 | 162 | ||
164 | static struct pci_driver cs46xx_driver = { | 163 | static struct pci_driver cs46xx_driver = { |
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index dace827b45d1..c6b82c85e044 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c | |||
@@ -91,7 +91,6 @@ static int snd_cs5530_dev_free(struct snd_device *device) | |||
91 | static void snd_cs5530_remove(struct pci_dev *pci) | 91 | static void snd_cs5530_remove(struct pci_dev *pci) |
92 | { | 92 | { |
93 | snd_card_free(pci_get_drvdata(pci)); | 93 | snd_card_free(pci_get_drvdata(pci)); |
94 | pci_set_drvdata(pci, NULL); | ||
95 | } | 94 | } |
96 | 95 | ||
97 | static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg) | 96 | static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg) |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 7e4b13e2d12a..902bebd3b3fb 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -391,7 +391,6 @@ static void snd_cs5535audio_remove(struct pci_dev *pci) | |||
391 | { | 391 | { |
392 | olpc_quirks_cleanup(); | 392 | olpc_quirks_cleanup(); |
393 | snd_card_free(pci_get_drvdata(pci)); | 393 | snd_card_free(pci_get_drvdata(pci)); |
394 | pci_set_drvdata(pci, NULL); | ||
395 | } | 394 | } |
396 | 395 | ||
397 | static struct pci_driver cs5535audio_driver = { | 396 | static struct pci_driver cs5535audio_driver = { |
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index d01ffcb2b2f5..d464ad2fc7b7 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
@@ -122,7 +122,6 @@ error: | |||
122 | static void ct_card_remove(struct pci_dev *pci) | 122 | static void ct_card_remove(struct pci_dev *pci) |
123 | { | 123 | { |
124 | snd_card_free(pci_get_drvdata(pci)); | 124 | snd_card_free(pci_get_drvdata(pci)); |
125 | pci_set_drvdata(pci, NULL); | ||
126 | } | 125 | } |
127 | 126 | ||
128 | #ifdef CONFIG_PM_SLEEP | 127 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 760cbff53210..05cfe551ce42 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -2323,7 +2323,6 @@ static void snd_echo_remove(struct pci_dev *pci) | |||
2323 | chip = pci_get_drvdata(pci); | 2323 | chip = pci_get_drvdata(pci); |
2324 | if (chip) | 2324 | if (chip) |
2325 | snd_card_free(chip->card); | 2325 | snd_card_free(chip->card); |
2326 | pci_set_drvdata(pci, NULL); | ||
2327 | } | 2326 | } |
2328 | 2327 | ||
2329 | 2328 | ||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 8c5010f7889c..9e1bd0c39a8c 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -202,7 +202,6 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, | |||
202 | static void snd_card_emu10k1_remove(struct pci_dev *pci) | 202 | static void snd_card_emu10k1_remove(struct pci_dev *pci) |
203 | { | 203 | { |
204 | snd_card_free(pci_get_drvdata(pci)); | 204 | snd_card_free(pci_get_drvdata(pci)); |
205 | pci_set_drvdata(pci, NULL); | ||
206 | } | 205 | } |
207 | 206 | ||
208 | 207 | ||
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index cdff11d48ebd..56ad9d6f200d 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1623,7 +1623,6 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, | |||
1623 | static void snd_emu10k1x_remove(struct pci_dev *pci) | 1623 | static void snd_emu10k1x_remove(struct pci_dev *pci) |
1624 | { | 1624 | { |
1625 | snd_card_free(pci_get_drvdata(pci)); | 1625 | snd_card_free(pci_get_drvdata(pci)); |
1626 | pci_set_drvdata(pci, NULL); | ||
1627 | } | 1626 | } |
1628 | 1627 | ||
1629 | // PCI IDs | 1628 | // PCI IDs |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index db2dc835171d..ca8929b9a5d6 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -1939,7 +1939,7 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq) | |||
1939 | #endif | 1939 | #endif |
1940 | if (ensoniq->irq >= 0) | 1940 | if (ensoniq->irq >= 0) |
1941 | synchronize_irq(ensoniq->irq); | 1941 | synchronize_irq(ensoniq->irq); |
1942 | pci_set_power_state(ensoniq->pci, 3); | 1942 | pci_set_power_state(ensoniq->pci, PCI_D3hot); |
1943 | __hw_end: | 1943 | __hw_end: |
1944 | #ifdef CHIP1370 | 1944 | #ifdef CHIP1370 |
1945 | if (ensoniq->dma_bug.area) | 1945 | if (ensoniq->dma_bug.area) |
@@ -2497,7 +2497,6 @@ static int snd_audiopci_probe(struct pci_dev *pci, | |||
2497 | static void snd_audiopci_remove(struct pci_dev *pci) | 2497 | static void snd_audiopci_remove(struct pci_dev *pci) |
2498 | { | 2498 | { |
2499 | snd_card_free(pci_get_drvdata(pci)); | 2499 | snd_card_free(pci_get_drvdata(pci)); |
2500 | pci_set_drvdata(pci, NULL); | ||
2501 | } | 2500 | } |
2502 | 2501 | ||
2503 | static struct pci_driver ens137x_driver = { | 2502 | static struct pci_driver ens137x_driver = { |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 8423403954ab..9213fb38921c 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1881,7 +1881,6 @@ static int snd_es1938_probe(struct pci_dev *pci, | |||
1881 | static void snd_es1938_remove(struct pci_dev *pci) | 1881 | static void snd_es1938_remove(struct pci_dev *pci) |
1882 | { | 1882 | { |
1883 | snd_card_free(pci_get_drvdata(pci)); | 1883 | snd_card_free(pci_get_drvdata(pci)); |
1884 | pci_set_drvdata(pci, NULL); | ||
1885 | } | 1884 | } |
1886 | 1885 | ||
1887 | static struct pci_driver es1938_driver = { | 1886 | static struct pci_driver es1938_driver = { |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index a1f32b5ae0d1..5e2ec9687731 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -564,6 +564,7 @@ struct es1968 { | |||
564 | #ifdef CONFIG_SND_ES1968_RADIO | 564 | #ifdef CONFIG_SND_ES1968_RADIO |
565 | struct v4l2_device v4l2_dev; | 565 | struct v4l2_device v4l2_dev; |
566 | struct snd_tea575x tea; | 566 | struct snd_tea575x tea; |
567 | unsigned int tea575x_tuner; | ||
567 | #endif | 568 | #endif |
568 | }; | 569 | }; |
569 | 570 | ||
@@ -2557,37 +2558,47 @@ static int snd_es1968_input_register(struct es1968 *chip) | |||
2557 | bits 1=unmask write to given bit */ | 2558 | bits 1=unmask write to given bit */ |
2558 | #define IO_DIR 8 /* direction register offset from GPIO_DATA | 2559 | #define IO_DIR 8 /* direction register offset from GPIO_DATA |
2559 | bits 0/1=read/write direction */ | 2560 | bits 0/1=read/write direction */ |
2560 | /* mask bits for GPIO lines */ | 2561 | |
2561 | #define STR_DATA 0x0040 /* GPIO6 */ | 2562 | /* GPIO to TEA575x maps */ |
2562 | #define STR_CLK 0x0080 /* GPIO7 */ | 2563 | struct snd_es1968_tea575x_gpio { |
2563 | #define STR_WREN 0x0100 /* GPIO8 */ | 2564 | u8 data, clk, wren, most; |
2564 | #define STR_MOST 0x0200 /* GPIO9 */ | 2565 | char *name; |
2566 | }; | ||
2567 | |||
2568 | static struct snd_es1968_tea575x_gpio snd_es1968_tea575x_gpios[] = { | ||
2569 | { .data = 6, .clk = 7, .wren = 8, .most = 9, .name = "SF64-PCE2" }, | ||
2570 | { .data = 7, .clk = 8, .wren = 6, .most = 10, .name = "M56VAP" }, | ||
2571 | }; | ||
2572 | |||
2573 | #define get_tea575x_gpio(chip) \ | ||
2574 | (&snd_es1968_tea575x_gpios[(chip)->tea575x_tuner]) | ||
2575 | |||
2565 | 2576 | ||
2566 | static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) | 2577 | static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) |
2567 | { | 2578 | { |
2568 | struct es1968 *chip = tea->private_data; | 2579 | struct es1968 *chip = tea->private_data; |
2569 | unsigned long io = chip->io_port + GPIO_DATA; | 2580 | struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip); |
2570 | u16 val = 0; | 2581 | u16 val = 0; |
2571 | 2582 | ||
2572 | val |= (pins & TEA575X_DATA) ? STR_DATA : 0; | 2583 | val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0; |
2573 | val |= (pins & TEA575X_CLK) ? STR_CLK : 0; | 2584 | val |= (pins & TEA575X_CLK) ? (1 << gpio.clk) : 0; |
2574 | val |= (pins & TEA575X_WREN) ? STR_WREN : 0; | 2585 | val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0; |
2575 | 2586 | ||
2576 | outw(val, io); | 2587 | outw(val, chip->io_port + GPIO_DATA); |
2577 | } | 2588 | } |
2578 | 2589 | ||
2579 | static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea) | 2590 | static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea) |
2580 | { | 2591 | { |
2581 | struct es1968 *chip = tea->private_data; | 2592 | struct es1968 *chip = tea->private_data; |
2582 | unsigned long io = chip->io_port + GPIO_DATA; | 2593 | struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip); |
2583 | u16 val = inw(io); | 2594 | u16 val = inw(chip->io_port + GPIO_DATA); |
2584 | u8 ret; | 2595 | u8 ret = 0; |
2585 | 2596 | ||
2586 | ret = 0; | 2597 | if (val & (1 << gpio.data)) |
2587 | if (val & STR_DATA) | ||
2588 | ret |= TEA575X_DATA; | 2598 | ret |= TEA575X_DATA; |
2589 | if (val & STR_MOST) | 2599 | if (val & (1 << gpio.most)) |
2590 | ret |= TEA575X_MOST; | 2600 | ret |= TEA575X_MOST; |
2601 | |||
2591 | return ret; | 2602 | return ret; |
2592 | } | 2603 | } |
2593 | 2604 | ||
@@ -2596,13 +2607,18 @@ static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool outpu | |||
2596 | struct es1968 *chip = tea->private_data; | 2607 | struct es1968 *chip = tea->private_data; |
2597 | unsigned long io = chip->io_port + GPIO_DATA; | 2608 | unsigned long io = chip->io_port + GPIO_DATA; |
2598 | u16 odir = inw(io + IO_DIR); | 2609 | u16 odir = inw(io + IO_DIR); |
2610 | struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip); | ||
2599 | 2611 | ||
2600 | if (output) { | 2612 | if (output) { |
2601 | outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); | 2613 | outw(~((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren)), |
2602 | outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR); | 2614 | io + IO_MASK); |
2615 | outw(odir | (1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren), | ||
2616 | io + IO_DIR); | ||
2603 | } else { | 2617 | } else { |
2604 | outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK); | 2618 | outw(~((1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) | (1 << gpio.most)), |
2605 | outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR); | 2619 | io + IO_MASK); |
2620 | outw((odir & ~((1 << gpio.data) | (1 << gpio.most))) | ||
2621 | | (1 << gpio.clk) | (1 << gpio.wren), io + IO_DIR); | ||
2606 | } | 2622 | } |
2607 | } | 2623 | } |
2608 | 2624 | ||
@@ -2772,6 +2788,9 @@ static int snd_es1968_create(struct snd_card *card, | |||
2772 | snd_card_set_dev(card, &pci->dev); | 2788 | snd_card_set_dev(card, &pci->dev); |
2773 | 2789 | ||
2774 | #ifdef CONFIG_SND_ES1968_RADIO | 2790 | #ifdef CONFIG_SND_ES1968_RADIO |
2791 | /* don't play with GPIOs on laptops */ | ||
2792 | if (chip->pci->subsystem_vendor != 0x125d) | ||
2793 | goto no_radio; | ||
2775 | err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); | 2794 | err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); |
2776 | if (err < 0) { | 2795 | if (err < 0) { |
2777 | snd_es1968_free(chip); | 2796 | snd_es1968_free(chip); |
@@ -2781,10 +2800,18 @@ static int snd_es1968_create(struct snd_card *card, | |||
2781 | chip->tea.private_data = chip; | 2800 | chip->tea.private_data = chip; |
2782 | chip->tea.radio_nr = radio_nr; | 2801 | chip->tea.radio_nr = radio_nr; |
2783 | chip->tea.ops = &snd_es1968_tea_ops; | 2802 | chip->tea.ops = &snd_es1968_tea_ops; |
2784 | strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); | ||
2785 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); | 2803 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); |
2786 | if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) | 2804 | for (i = 0; i < ARRAY_SIZE(snd_es1968_tea575x_gpios); i++) { |
2787 | printk(KERN_INFO "es1968: detected TEA575x radio\n"); | 2805 | chip->tea575x_tuner = i; |
2806 | if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) { | ||
2807 | snd_printk(KERN_INFO "es1968: detected TEA575x radio type %s\n", | ||
2808 | get_tea575x_gpio(chip)->name); | ||
2809 | strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, | ||
2810 | sizeof(chip->tea.card)); | ||
2811 | break; | ||
2812 | } | ||
2813 | } | ||
2814 | no_radio: | ||
2788 | #endif | 2815 | #endif |
2789 | 2816 | ||
2790 | *chip_ret = chip; | 2817 | *chip_ret = chip; |
@@ -2909,7 +2936,6 @@ static int snd_es1968_probe(struct pci_dev *pci, | |||
2909 | static void snd_es1968_remove(struct pci_dev *pci) | 2936 | static void snd_es1968_remove(struct pci_dev *pci) |
2910 | { | 2937 | { |
2911 | snd_card_free(pci_get_drvdata(pci)); | 2938 | snd_card_free(pci_get_drvdata(pci)); |
2912 | pci_set_drvdata(pci, NULL); | ||
2913 | } | 2939 | } |
2914 | 2940 | ||
2915 | static struct pci_driver es1968_driver = { | 2941 | static struct pci_driver es1968_driver = { |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 4f07fda5adf2..706c5b67b708 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1370,7 +1370,6 @@ static int snd_card_fm801_probe(struct pci_dev *pci, | |||
1370 | static void snd_card_fm801_remove(struct pci_dev *pci) | 1370 | static void snd_card_fm801_remove(struct pci_dev *pci) |
1371 | { | 1371 | { |
1372 | snd_card_free(pci_get_drvdata(pci)); | 1372 | snd_card_free(pci_get_drvdata(pci)); |
1373 | pci_set_drvdata(pci, NULL); | ||
1374 | } | 1373 | } |
1375 | 1374 | ||
1376 | #ifdef CONFIG_PM_SLEEP | 1375 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 80a7d44bcf81..0c5371abecd2 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -140,7 +140,6 @@ config SND_HDA_CODEC_VIA | |||
140 | 140 | ||
141 | config SND_HDA_CODEC_HDMI | 141 | config SND_HDA_CODEC_HDMI |
142 | bool "Build HDMI/DisplayPort HD-audio codec support" | 142 | bool "Build HDMI/DisplayPort HD-audio codec support" |
143 | select SND_DYNAMIC_MINORS | ||
144 | default y | 143 | default y |
145 | help | 144 | help |
146 | Say Y here to include HDMI and DisplayPort HD-audio codec | 145 | Say Y here to include HDMI and DisplayPort HD-audio codec |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 55108b5fb291..35090b3acbac 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -185,20 +185,19 @@ EXPORT_SYMBOL_HDA(snd_hda_get_jack_type); | |||
185 | * Compose a 32bit command word to be sent to the HD-audio controller | 185 | * Compose a 32bit command word to be sent to the HD-audio controller |
186 | */ | 186 | */ |
187 | static inline unsigned int | 187 | static inline unsigned int |
188 | make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | 188 | make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int flags, |
189 | unsigned int verb, unsigned int parm) | 189 | unsigned int verb, unsigned int parm) |
190 | { | 190 | { |
191 | u32 val; | 191 | u32 val; |
192 | 192 | ||
193 | if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) || | 193 | if ((codec->addr & ~0xf) || (nid & ~0x7f) || |
194 | (verb & ~0xfff) || (parm & ~0xffff)) { | 194 | (verb & ~0xfff) || (parm & ~0xffff)) { |
195 | printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n", | 195 | printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x\n", |
196 | codec->addr, direct, nid, verb, parm); | 196 | codec->addr, nid, verb, parm); |
197 | return ~0; | 197 | return ~0; |
198 | } | 198 | } |
199 | 199 | ||
200 | val = (u32)codec->addr << 28; | 200 | val = (u32)codec->addr << 28; |
201 | val |= (u32)direct << 27; | ||
202 | val |= (u32)nid << 20; | 201 | val |= (u32)nid << 20; |
203 | val |= verb << 8; | 202 | val |= verb << 8; |
204 | val |= parm; | 203 | val |= parm; |
@@ -209,7 +208,7 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
209 | * Send and receive a verb | 208 | * Send and receive a verb |
210 | */ | 209 | */ |
211 | static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | 210 | static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, |
212 | unsigned int *res) | 211 | int flags, unsigned int *res) |
213 | { | 212 | { |
214 | struct hda_bus *bus = codec->bus; | 213 | struct hda_bus *bus = codec->bus; |
215 | int err; | 214 | int err; |
@@ -222,6 +221,8 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | |||
222 | again: | 221 | again: |
223 | snd_hda_power_up(codec); | 222 | snd_hda_power_up(codec); |
224 | mutex_lock(&bus->cmd_mutex); | 223 | mutex_lock(&bus->cmd_mutex); |
224 | if (flags & HDA_RW_NO_RESPONSE_FALLBACK) | ||
225 | bus->no_response_fallback = 1; | ||
225 | for (;;) { | 226 | for (;;) { |
226 | trace_hda_send_cmd(codec, cmd); | 227 | trace_hda_send_cmd(codec, cmd); |
227 | err = bus->ops.command(bus, cmd); | 228 | err = bus->ops.command(bus, cmd); |
@@ -234,6 +235,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | |||
234 | *res = bus->ops.get_response(bus, codec->addr); | 235 | *res = bus->ops.get_response(bus, codec->addr); |
235 | trace_hda_get_response(codec, *res); | 236 | trace_hda_get_response(codec, *res); |
236 | } | 237 | } |
238 | bus->no_response_fallback = 0; | ||
237 | mutex_unlock(&bus->cmd_mutex); | 239 | mutex_unlock(&bus->cmd_mutex); |
238 | snd_hda_power_down(codec); | 240 | snd_hda_power_down(codec); |
239 | if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { | 241 | if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { |
@@ -255,7 +257,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | |||
255 | * snd_hda_codec_read - send a command and get the response | 257 | * snd_hda_codec_read - send a command and get the response |
256 | * @codec: the HDA codec | 258 | * @codec: the HDA codec |
257 | * @nid: NID to send the command | 259 | * @nid: NID to send the command |
258 | * @direct: direct flag | 260 | * @flags: optional bit flags |
259 | * @verb: the verb to send | 261 | * @verb: the verb to send |
260 | * @parm: the parameter for the verb | 262 | * @parm: the parameter for the verb |
261 | * | 263 | * |
@@ -264,12 +266,12 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | |||
264 | * Returns the obtained response value, or -1 for an error. | 266 | * Returns the obtained response value, or -1 for an error. |
265 | */ | 267 | */ |
266 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | 268 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, |
267 | int direct, | 269 | int flags, |
268 | unsigned int verb, unsigned int parm) | 270 | unsigned int verb, unsigned int parm) |
269 | { | 271 | { |
270 | unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm); | 272 | unsigned cmd = make_codec_cmd(codec, nid, flags, verb, parm); |
271 | unsigned int res; | 273 | unsigned int res; |
272 | if (codec_exec_verb(codec, cmd, &res)) | 274 | if (codec_exec_verb(codec, cmd, flags, &res)) |
273 | return -1; | 275 | return -1; |
274 | return res; | 276 | return res; |
275 | } | 277 | } |
@@ -279,7 +281,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read); | |||
279 | * snd_hda_codec_write - send a single command without waiting for response | 281 | * snd_hda_codec_write - send a single command without waiting for response |
280 | * @codec: the HDA codec | 282 | * @codec: the HDA codec |
281 | * @nid: NID to send the command | 283 | * @nid: NID to send the command |
282 | * @direct: direct flag | 284 | * @flags: optional bit flags |
283 | * @verb: the verb to send | 285 | * @verb: the verb to send |
284 | * @parm: the parameter for the verb | 286 | * @parm: the parameter for the verb |
285 | * | 287 | * |
@@ -287,12 +289,12 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read); | |||
287 | * | 289 | * |
288 | * Returns 0 if successful, or a negative error code. | 290 | * Returns 0 if successful, or a negative error code. |
289 | */ | 291 | */ |
290 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 292 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, |
291 | unsigned int verb, unsigned int parm) | 293 | unsigned int verb, unsigned int parm) |
292 | { | 294 | { |
293 | unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); | 295 | unsigned int cmd = make_codec_cmd(codec, nid, flags, verb, parm); |
294 | unsigned int res; | 296 | unsigned int res; |
295 | return codec_exec_verb(codec, cmd, | 297 | return codec_exec_verb(codec, cmd, flags, |
296 | codec->bus->sync_write ? &res : NULL); | 298 | codec->bus->sync_write ? &res : NULL); |
297 | } | 299 | } |
298 | EXPORT_SYMBOL_HDA(snd_hda_codec_write); | 300 | EXPORT_SYMBOL_HDA(snd_hda_codec_write); |
@@ -3582,7 +3584,7 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); | |||
3582 | * snd_hda_codec_write_cache - send a single command with caching | 3584 | * snd_hda_codec_write_cache - send a single command with caching |
3583 | * @codec: the HDA codec | 3585 | * @codec: the HDA codec |
3584 | * @nid: NID to send the command | 3586 | * @nid: NID to send the command |
3585 | * @direct: direct flag | 3587 | * @flags: optional bit flags |
3586 | * @verb: the verb to send | 3588 | * @verb: the verb to send |
3587 | * @parm: the parameter for the verb | 3589 | * @parm: the parameter for the verb |
3588 | * | 3590 | * |
@@ -3591,7 +3593,7 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); | |||
3591 | * Returns 0 if successful, or a negative error code. | 3593 | * Returns 0 if successful, or a negative error code. |
3592 | */ | 3594 | */ |
3593 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 3595 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
3594 | int direct, unsigned int verb, unsigned int parm) | 3596 | int flags, unsigned int verb, unsigned int parm) |
3595 | { | 3597 | { |
3596 | int err; | 3598 | int err; |
3597 | struct hda_cache_head *c; | 3599 | struct hda_cache_head *c; |
@@ -3600,7 +3602,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
3600 | 3602 | ||
3601 | cache_only = codec->cached_write; | 3603 | cache_only = codec->cached_write; |
3602 | if (!cache_only) { | 3604 | if (!cache_only) { |
3603 | err = snd_hda_codec_write(codec, nid, direct, verb, parm); | 3605 | err = snd_hda_codec_write(codec, nid, flags, verb, parm); |
3604 | if (err < 0) | 3606 | if (err < 0) |
3605 | return err; | 3607 | return err; |
3606 | } | 3608 | } |
@@ -3624,7 +3626,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | |||
3624 | * snd_hda_codec_update_cache - check cache and write the cmd only when needed | 3626 | * snd_hda_codec_update_cache - check cache and write the cmd only when needed |
3625 | * @codec: the HDA codec | 3627 | * @codec: the HDA codec |
3626 | * @nid: NID to send the command | 3628 | * @nid: NID to send the command |
3627 | * @direct: direct flag | 3629 | * @flags: optional bit flags |
3628 | * @verb: the verb to send | 3630 | * @verb: the verb to send |
3629 | * @parm: the parameter for the verb | 3631 | * @parm: the parameter for the verb |
3630 | * | 3632 | * |
@@ -3635,7 +3637,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | |||
3635 | * Returns 0 if successful, or a negative error code. | 3637 | * Returns 0 if successful, or a negative error code. |
3636 | */ | 3638 | */ |
3637 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | 3639 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, |
3638 | int direct, unsigned int verb, unsigned int parm) | 3640 | int flags, unsigned int verb, unsigned int parm) |
3639 | { | 3641 | { |
3640 | struct hda_cache_head *c; | 3642 | struct hda_cache_head *c; |
3641 | u32 key; | 3643 | u32 key; |
@@ -3651,7 +3653,7 @@ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | |||
3651 | return 0; | 3653 | return 0; |
3652 | } | 3654 | } |
3653 | mutex_unlock(&codec->bus->cmd_mutex); | 3655 | mutex_unlock(&codec->bus->cmd_mutex); |
3654 | return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); | 3656 | return snd_hda_codec_write_cache(codec, nid, flags, verb, parm); |
3655 | } | 3657 | } |
3656 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); | 3658 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); |
3657 | 3659 | ||
@@ -3806,11 +3808,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, | |||
3806 | hda_nid_t fg = codec->afg ? codec->afg : codec->mfg; | 3808 | hda_nid_t fg = codec->afg ? codec->afg : codec->mfg; |
3807 | int count; | 3809 | int count; |
3808 | unsigned int state; | 3810 | unsigned int state; |
3811 | int flags = 0; | ||
3809 | 3812 | ||
3810 | /* this delay seems necessary to avoid click noise at power-down */ | 3813 | /* this delay seems necessary to avoid click noise at power-down */ |
3811 | if (power_state == AC_PWRST_D3) { | 3814 | if (power_state == AC_PWRST_D3) { |
3812 | /* transition time less than 10ms for power down */ | 3815 | /* transition time less than 10ms for power down */ |
3813 | msleep(codec->epss ? 10 : 100); | 3816 | msleep(codec->epss ? 10 : 100); |
3817 | flags = HDA_RW_NO_RESPONSE_FALLBACK; | ||
3814 | } | 3818 | } |
3815 | 3819 | ||
3816 | /* repeat power states setting at most 10 times*/ | 3820 | /* repeat power states setting at most 10 times*/ |
@@ -3819,7 +3823,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, | |||
3819 | codec->patch_ops.set_power_state(codec, fg, | 3823 | codec->patch_ops.set_power_state(codec, fg, |
3820 | power_state); | 3824 | power_state); |
3821 | else { | 3825 | else { |
3822 | snd_hda_codec_read(codec, fg, 0, | 3826 | snd_hda_codec_read(codec, fg, flags, |
3823 | AC_VERB_SET_POWER_STATE, | 3827 | AC_VERB_SET_POWER_STATE, |
3824 | power_state); | 3828 | power_state); |
3825 | snd_hda_codec_set_power_to_all(codec, fg, power_state); | 3829 | snd_hda_codec_set_power_to_all(codec, fg, power_state); |
@@ -4461,12 +4465,13 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { | |||
4461 | 4465 | ||
4462 | /* | 4466 | /* |
4463 | * get the empty PCM device number to assign | 4467 | * get the empty PCM device number to assign |
4464 | * | ||
4465 | * note the max device number is limited by HDA_MAX_PCMS, currently 10 | ||
4466 | */ | 4468 | */ |
4467 | static int get_empty_pcm_device(struct hda_bus *bus, int type) | 4469 | static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type) |
4468 | { | 4470 | { |
4469 | /* audio device indices; not linear to keep compatibility */ | 4471 | /* audio device indices; not linear to keep compatibility */ |
4472 | /* assigned to static slots up to dev#10; if more needed, assign | ||
4473 | * the later slot dynamically (when CONFIG_SND_DYNAMIC_MINORS=y) | ||
4474 | */ | ||
4470 | static int audio_idx[HDA_PCM_NTYPES][5] = { | 4475 | static int audio_idx[HDA_PCM_NTYPES][5] = { |
4471 | [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 }, | 4476 | [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 }, |
4472 | [HDA_PCM_TYPE_SPDIF] = { 1, -1 }, | 4477 | [HDA_PCM_TYPE_SPDIF] = { 1, -1 }, |
@@ -4480,18 +4485,28 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
4480 | return -EINVAL; | 4485 | return -EINVAL; |
4481 | } | 4486 | } |
4482 | 4487 | ||
4483 | for (i = 0; audio_idx[type][i] >= 0 ; i++) | 4488 | for (i = 0; audio_idx[type][i] >= 0; i++) { |
4489 | #ifndef CONFIG_SND_DYNAMIC_MINORS | ||
4490 | if (audio_idx[type][i] >= 8) | ||
4491 | break; | ||
4492 | #endif | ||
4484 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) | 4493 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) |
4485 | return audio_idx[type][i]; | 4494 | return audio_idx[type][i]; |
4495 | } | ||
4486 | 4496 | ||
4497 | #ifdef CONFIG_SND_DYNAMIC_MINORS | ||
4487 | /* non-fixed slots starting from 10 */ | 4498 | /* non-fixed slots starting from 10 */ |
4488 | for (i = 10; i < 32; i++) { | 4499 | for (i = 10; i < 32; i++) { |
4489 | if (!test_and_set_bit(i, bus->pcm_dev_bits)) | 4500 | if (!test_and_set_bit(i, bus->pcm_dev_bits)) |
4490 | return i; | 4501 | return i; |
4491 | } | 4502 | } |
4503 | #endif | ||
4492 | 4504 | ||
4493 | snd_printk(KERN_WARNING "Too many %s devices\n", | 4505 | snd_printk(KERN_WARNING "Too many %s devices\n", |
4494 | snd_hda_pcm_type_name[type]); | 4506 | snd_hda_pcm_type_name[type]); |
4507 | #ifndef CONFIG_SND_DYNAMIC_MINORS | ||
4508 | snd_printk(KERN_WARNING "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n"); | ||
4509 | #endif | ||
4495 | return -EAGAIN; | 4510 | return -EAGAIN; |
4496 | } | 4511 | } |
4497 | 4512 | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c93f9021f452..701c2e069b10 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -679,6 +679,7 @@ struct hda_bus { | |||
679 | unsigned int response_reset:1; /* controller was reset */ | 679 | unsigned int response_reset:1; /* controller was reset */ |
680 | unsigned int in_reset:1; /* during reset operation */ | 680 | unsigned int in_reset:1; /* during reset operation */ |
681 | unsigned int power_keep_link_on:1; /* don't power off HDA link */ | 681 | unsigned int power_keep_link_on:1; /* don't power off HDA link */ |
682 | unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ | ||
682 | 683 | ||
683 | int primary_dig_out_type; /* primary digital out PCM type */ | 684 | int primary_dig_out_type; /* primary digital out PCM type */ |
684 | }; | 685 | }; |
@@ -930,6 +931,8 @@ enum { | |||
930 | HDA_INPUT, HDA_OUTPUT | 931 | HDA_INPUT, HDA_OUTPUT |
931 | }; | 932 | }; |
932 | 933 | ||
934 | /* snd_hda_codec_read/write optional flags */ | ||
935 | #define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0) | ||
933 | 936 | ||
934 | /* | 937 | /* |
935 | * constructors | 938 | * constructors |
@@ -945,9 +948,9 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec); | |||
945 | * low level functions | 948 | * low level functions |
946 | */ | 949 | */ |
947 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | 950 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, |
948 | int direct, | 951 | int flags, |
949 | unsigned int verb, unsigned int parm); | 952 | unsigned int verb, unsigned int parm); |
950 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 953 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, |
951 | unsigned int verb, unsigned int parm); | 954 | unsigned int verb, unsigned int parm); |
952 | #define snd_hda_param_read(codec, nid, param) \ | 955 | #define snd_hda_param_read(codec, nid, param) \ |
953 | snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) | 956 | snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) |
@@ -986,11 +989,11 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); | |||
986 | 989 | ||
987 | /* cached write */ | 990 | /* cached write */ |
988 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 991 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
989 | int direct, unsigned int verb, unsigned int parm); | 992 | int flags, unsigned int verb, unsigned int parm); |
990 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 993 | void snd_hda_sequence_write_cache(struct hda_codec *codec, |
991 | const struct hda_verb *seq); | 994 | const struct hda_verb *seq); |
992 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | 995 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, |
993 | int direct, unsigned int verb, unsigned int parm); | 996 | int flags, unsigned int verb, unsigned int parm); |
994 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | 997 | void snd_hda_codec_resume_cache(struct hda_codec *codec); |
995 | /* both for cmd & amp caches */ | 998 | /* both for cmd & amp caches */ |
996 | void snd_hda_codec_flush_cache(struct hda_codec *codec); | 999 | void snd_hda_codec_flush_cache(struct hda_codec *codec); |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 4b1524a861f3..8e77cbbad871 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -133,6 +133,9 @@ static void parse_user_hints(struct hda_codec *codec) | |||
133 | val = snd_hda_get_bool_hint(codec, "line_in_auto_switch"); | 133 | val = snd_hda_get_bool_hint(codec, "line_in_auto_switch"); |
134 | if (val >= 0) | 134 | if (val >= 0) |
135 | spec->line_in_auto_switch = !!val; | 135 | spec->line_in_auto_switch = !!val; |
136 | val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp"); | ||
137 | if (val >= 0) | ||
138 | spec->auto_mute_via_amp = !!val; | ||
136 | val = snd_hda_get_bool_hint(codec, "need_dac_fix"); | 139 | val = snd_hda_get_bool_hint(codec, "need_dac_fix"); |
137 | if (val >= 0) | 140 | if (val >= 0) |
138 | spec->need_dac_fix = !!val; | 141 | spec->need_dac_fix = !!val; |
@@ -808,6 +811,9 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx) | |||
808 | * Helper functions for creating mixer ctl elements | 811 | * Helper functions for creating mixer ctl elements |
809 | */ | 812 | */ |
810 | 813 | ||
814 | static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, | ||
815 | struct snd_ctl_elem_value *ucontrol); | ||
816 | |||
811 | enum { | 817 | enum { |
812 | HDA_CTL_WIDGET_VOL, | 818 | HDA_CTL_WIDGET_VOL, |
813 | HDA_CTL_WIDGET_MUTE, | 819 | HDA_CTL_WIDGET_MUTE, |
@@ -815,7 +821,15 @@ enum { | |||
815 | }; | 821 | }; |
816 | static const struct snd_kcontrol_new control_templates[] = { | 822 | static const struct snd_kcontrol_new control_templates[] = { |
817 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 823 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
818 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 824 | /* only the put callback is replaced for handling the special mute */ |
825 | { | ||
826 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
827 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
828 | .info = snd_hda_mixer_amp_switch_info, | ||
829 | .get = snd_hda_mixer_amp_switch_get, | ||
830 | .put = hda_gen_mixer_mute_put, /* replaced */ | ||
831 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), | ||
832 | }, | ||
819 | HDA_BIND_MUTE(NULL, 0, 0, 0), | 833 | HDA_BIND_MUTE(NULL, 0, 0, 0), |
820 | }; | 834 | }; |
821 | 835 | ||
@@ -840,7 +854,7 @@ static int add_control_with_pfx(struct hda_gen_spec *spec, int type, | |||
840 | const char *pfx, const char *dir, | 854 | const char *pfx, const char *dir, |
841 | const char *sfx, int cidx, unsigned long val) | 855 | const char *sfx, int cidx, unsigned long val) |
842 | { | 856 | { |
843 | char name[32]; | 857 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
844 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); | 858 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); |
845 | if (!add_control(spec, type, name, cidx, val)) | 859 | if (!add_control(spec, type, name, cidx, val)) |
846 | return -ENOMEM; | 860 | return -ENOMEM; |
@@ -922,6 +936,23 @@ static int add_stereo_sw(struct hda_codec *codec, const char *pfx, | |||
922 | return add_sw_ctl(codec, pfx, cidx, chs, path); | 936 | return add_sw_ctl(codec, pfx, cidx, chs, path); |
923 | } | 937 | } |
924 | 938 | ||
939 | /* playback mute control with the software mute bit check */ | ||
940 | static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, | ||
941 | struct snd_ctl_elem_value *ucontrol) | ||
942 | { | ||
943 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
944 | struct hda_gen_spec *spec = codec->spec; | ||
945 | |||
946 | if (spec->auto_mute_via_amp) { | ||
947 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
948 | bool enabled = !((spec->mute_bits >> nid) & 1); | ||
949 | ucontrol->value.integer.value[0] &= enabled; | ||
950 | ucontrol->value.integer.value[1] &= enabled; | ||
951 | } | ||
952 | |||
953 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
954 | } | ||
955 | |||
925 | /* any ctl assigned to the path with the given index? */ | 956 | /* any ctl assigned to the path with the given index? */ |
926 | static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type) | 957 | static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type) |
927 | { | 958 | { |
@@ -1900,7 +1931,7 @@ static int create_extra_outs(struct hda_codec *codec, int num_pins, | |||
1900 | 1931 | ||
1901 | for (i = 0; i < num_pins; i++) { | 1932 | for (i = 0; i < num_pins; i++) { |
1902 | const char *name; | 1933 | const char *name; |
1903 | char tmp[44]; | 1934 | char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
1904 | int err, idx = 0; | 1935 | int err, idx = 0; |
1905 | 1936 | ||
1906 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) | 1937 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) |
@@ -2453,7 +2484,7 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins, | |||
2453 | } | 2484 | } |
2454 | if (get_out_jack_num_items(codec, pin) > 1) { | 2485 | if (get_out_jack_num_items(codec, pin) > 1) { |
2455 | struct snd_kcontrol_new *knew; | 2486 | struct snd_kcontrol_new *knew; |
2456 | char name[44]; | 2487 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
2457 | get_jack_mode_name(codec, pin, name, sizeof(name)); | 2488 | get_jack_mode_name(codec, pin, name, sizeof(name)); |
2458 | knew = snd_hda_gen_add_kctl(spec, name, | 2489 | knew = snd_hda_gen_add_kctl(spec, name, |
2459 | &out_jack_mode_enum); | 2490 | &out_jack_mode_enum); |
@@ -2585,7 +2616,7 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) | |||
2585 | { | 2616 | { |
2586 | struct hda_gen_spec *spec = codec->spec; | 2617 | struct hda_gen_spec *spec = codec->spec; |
2587 | struct snd_kcontrol_new *knew; | 2618 | struct snd_kcontrol_new *knew; |
2588 | char name[44]; | 2619 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
2589 | unsigned int defcfg; | 2620 | unsigned int defcfg; |
2590 | 2621 | ||
2591 | if (pin == spec->hp_mic_pin) | 2622 | if (pin == spec->hp_mic_pin) |
@@ -3285,7 +3316,7 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label, | |||
3285 | bool inv_dmic) | 3316 | bool inv_dmic) |
3286 | { | 3317 | { |
3287 | struct hda_gen_spec *spec = codec->spec; | 3318 | struct hda_gen_spec *spec = codec->spec; |
3288 | char tmpname[44]; | 3319 | char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
3289 | int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL; | 3320 | int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL; |
3290 | const char *sfx = is_switch ? "Switch" : "Volume"; | 3321 | const char *sfx = is_switch ? "Switch" : "Volume"; |
3291 | unsigned int chs = inv_dmic ? 1 : 3; | 3322 | unsigned int chs = inv_dmic ? 1 : 3; |
@@ -3547,7 +3578,7 @@ static int parse_mic_boost(struct hda_codec *codec) | |||
3547 | struct nid_path *path; | 3578 | struct nid_path *path; |
3548 | unsigned int val; | 3579 | unsigned int val; |
3549 | int idx; | 3580 | int idx; |
3550 | char boost_label[44]; | 3581 | char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
3551 | 3582 | ||
3552 | idx = imux->items[i].index; | 3583 | idx = imux->items[i].index; |
3553 | if (idx >= imux->num_items) | 3584 | if (idx >= imux->num_items) |
@@ -3719,6 +3750,16 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, | |||
3719 | unsigned int val, oldval; | 3750 | unsigned int val, oldval; |
3720 | if (!nid) | 3751 | if (!nid) |
3721 | break; | 3752 | break; |
3753 | |||
3754 | if (spec->auto_mute_via_amp) { | ||
3755 | if (mute) | ||
3756 | spec->mute_bits |= (1ULL << nid); | ||
3757 | else | ||
3758 | spec->mute_bits &= ~(1ULL << nid); | ||
3759 | set_pin_eapd(codec, nid, !mute); | ||
3760 | continue; | ||
3761 | } | ||
3762 | |||
3722 | oldval = snd_hda_codec_get_pin_target(codec, nid); | 3763 | oldval = snd_hda_codec_get_pin_target(codec, nid); |
3723 | if (oldval & PIN_IN) | 3764 | if (oldval & PIN_IN) |
3724 | continue; /* no mute for inputs */ | 3765 | continue; /* no mute for inputs */ |
@@ -3786,6 +3827,10 @@ static void call_update_outputs(struct hda_codec *codec) | |||
3786 | spec->automute_hook(codec); | 3827 | spec->automute_hook(codec); |
3787 | else | 3828 | else |
3788 | snd_hda_gen_update_outputs(codec); | 3829 | snd_hda_gen_update_outputs(codec); |
3830 | |||
3831 | /* sync the whole vmaster slaves to reflect the new auto-mute status */ | ||
3832 | if (spec->auto_mute_via_amp && !codec->bus->shutdown) | ||
3833 | snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false); | ||
3789 | } | 3834 | } |
3790 | 3835 | ||
3791 | /* standard HP-automute helper */ | 3836 | /* standard HP-automute helper */ |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 76200314ee95..e199a852388b 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -209,6 +209,7 @@ struct hda_gen_spec { | |||
209 | unsigned int master_mute:1; /* master mute over all */ | 209 | unsigned int master_mute:1; /* master mute over all */ |
210 | unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ | 210 | unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ |
211 | unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ | 211 | unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ |
212 | unsigned int auto_mute_via_amp:1; /* auto-mute via amp instead of pinctl */ | ||
212 | 213 | ||
213 | /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */ | 214 | /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */ |
214 | unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */ | 215 | unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */ |
@@ -237,6 +238,9 @@ struct hda_gen_spec { | |||
237 | unsigned int have_aamix_ctl:1; | 238 | unsigned int have_aamix_ctl:1; |
238 | unsigned int hp_mic_jack_modes:1; | 239 | unsigned int hp_mic_jack_modes:1; |
239 | 240 | ||
241 | /* additional mute flags (only effective with auto_mute_via_amp=1) */ | ||
242 | u64 mute_bits; | ||
243 | |||
240 | /* badness tables for output path evaluations */ | 244 | /* badness tables for output path evaluations */ |
241 | const struct badness_table *main_out_badness; | 245 | const struct badness_table *main_out_badness; |
242 | const struct badness_table *extra_out_badness; | 246 | const struct badness_table *extra_out_badness; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index de18722c4873..f39de9055097 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -942,6 +942,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
942 | } | 942 | } |
943 | } | 943 | } |
944 | 944 | ||
945 | if (!bus->no_response_fallback) | ||
946 | return -1; | ||
947 | |||
945 | if (!chip->polling_mode && chip->poll_count < 2) { | 948 | if (!chip->polling_mode && chip->poll_count < 2) { |
946 | snd_printdd(SFX "%s: azx_get_response timeout, " | 949 | snd_printdd(SFX "%s: azx_get_response timeout, " |
947 | "polling the codec once: last cmd=0x%08x\n", | 950 | "polling the codec once: last cmd=0x%08x\n", |
@@ -1117,37 +1120,52 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, | |||
1117 | struct snd_dma_buffer *dmab); | 1120 | struct snd_dma_buffer *dmab); |
1118 | #endif | 1121 | #endif |
1119 | 1122 | ||
1120 | /* reset codec link */ | 1123 | /* enter link reset */ |
1121 | static int azx_reset(struct azx *chip, int full_reset) | 1124 | static void azx_enter_link_reset(struct azx *chip) |
1122 | { | 1125 | { |
1123 | unsigned long timeout; | 1126 | unsigned long timeout; |
1124 | 1127 | ||
1125 | if (!full_reset) | ||
1126 | goto __skip; | ||
1127 | |||
1128 | /* clear STATESTS */ | ||
1129 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | ||
1130 | |||
1131 | /* reset controller */ | 1128 | /* reset controller */ |
1132 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 1129 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); |
1133 | 1130 | ||
1134 | timeout = jiffies + msecs_to_jiffies(100); | 1131 | timeout = jiffies + msecs_to_jiffies(100); |
1135 | while (azx_readb(chip, GCTL) && | 1132 | while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && |
1136 | time_before(jiffies, timeout)) | 1133 | time_before(jiffies, timeout)) |
1137 | usleep_range(500, 1000); | 1134 | usleep_range(500, 1000); |
1135 | } | ||
1138 | 1136 | ||
1139 | /* delay for >= 100us for codec PLL to settle per spec | 1137 | /* exit link reset */ |
1140 | * Rev 0.9 section 5.5.1 | 1138 | static void azx_exit_link_reset(struct azx *chip) |
1141 | */ | 1139 | { |
1142 | usleep_range(500, 1000); | 1140 | unsigned long timeout; |
1143 | 1141 | ||
1144 | /* Bring controller out of reset */ | ||
1145 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 1142 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); |
1146 | 1143 | ||
1147 | timeout = jiffies + msecs_to_jiffies(100); | 1144 | timeout = jiffies + msecs_to_jiffies(100); |
1148 | while (!azx_readb(chip, GCTL) && | 1145 | while (!azx_readb(chip, GCTL) && |
1149 | time_before(jiffies, timeout)) | 1146 | time_before(jiffies, timeout)) |
1150 | usleep_range(500, 1000); | 1147 | usleep_range(500, 1000); |
1148 | } | ||
1149 | |||
1150 | /* reset codec link */ | ||
1151 | static int azx_reset(struct azx *chip, int full_reset) | ||
1152 | { | ||
1153 | if (!full_reset) | ||
1154 | goto __skip; | ||
1155 | |||
1156 | /* clear STATESTS */ | ||
1157 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | ||
1158 | |||
1159 | /* reset controller */ | ||
1160 | azx_enter_link_reset(chip); | ||
1161 | |||
1162 | /* delay for >= 100us for codec PLL to settle per spec | ||
1163 | * Rev 0.9 section 5.5.1 | ||
1164 | */ | ||
1165 | usleep_range(500, 1000); | ||
1166 | |||
1167 | /* Bring controller out of reset */ | ||
1168 | azx_exit_link_reset(chip); | ||
1151 | 1169 | ||
1152 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | 1170 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ |
1153 | usleep_range(1000, 1200); | 1171 | usleep_range(1000, 1200); |
@@ -2891,6 +2909,7 @@ static int azx_suspend(struct device *dev) | |||
2891 | if (chip->initialized) | 2909 | if (chip->initialized) |
2892 | snd_hda_suspend(chip->bus); | 2910 | snd_hda_suspend(chip->bus); |
2893 | azx_stop_chip(chip); | 2911 | azx_stop_chip(chip); |
2912 | azx_enter_link_reset(chip); | ||
2894 | if (chip->irq >= 0) { | 2913 | if (chip->irq >= 0) { |
2895 | free_irq(chip->irq, chip); | 2914 | free_irq(chip->irq, chip); |
2896 | chip->irq = -1; | 2915 | chip->irq = -1; |
@@ -2943,6 +2962,7 @@ static int azx_runtime_suspend(struct device *dev) | |||
2943 | struct azx *chip = card->private_data; | 2962 | struct azx *chip = card->private_data; |
2944 | 2963 | ||
2945 | azx_stop_chip(chip); | 2964 | azx_stop_chip(chip); |
2965 | azx_enter_link_reset(chip); | ||
2946 | azx_clear_irq_pending(chip); | 2966 | azx_clear_irq_pending(chip); |
2947 | return 0; | 2967 | return 0; |
2948 | } | 2968 | } |
@@ -3764,7 +3784,6 @@ static int azx_probe(struct pci_dev *pci, | |||
3764 | 3784 | ||
3765 | out_free: | 3785 | out_free: |
3766 | snd_card_free(card); | 3786 | snd_card_free(card); |
3767 | pci_set_drvdata(pci, NULL); | ||
3768 | return err; | 3787 | return err; |
3769 | } | 3788 | } |
3770 | 3789 | ||
@@ -3834,7 +3853,6 @@ static void azx_remove(struct pci_dev *pci) | |||
3834 | 3853 | ||
3835 | if (card) | 3854 | if (card) |
3836 | snd_card_free(card); | 3855 | snd_card_free(card); |
3837 | pci_set_drvdata(pci, NULL); | ||
3838 | } | 3856 | } |
3839 | 3857 | ||
3840 | /* PCI IDs */ | 3858 | /* PCI IDs */ |
@@ -3878,6 +3896,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3878 | /* Oaktrail */ | 3896 | /* Oaktrail */ |
3879 | { PCI_DEVICE(0x8086, 0x080a), | 3897 | { PCI_DEVICE(0x8086, 0x080a), |
3880 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 3898 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
3899 | /* BayTrail */ | ||
3900 | { PCI_DEVICE(0x8086, 0x0f04), | ||
3901 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | ||
3881 | /* ICH */ | 3902 | /* ICH */ |
3882 | { PCI_DEVICE(0x8086, 0x2668), | 3903 | { PCI_DEVICE(0x8086, 0x2668), |
3883 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | | 3904 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9e0a95288f46..3fd2973183e2 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -398,7 +398,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
398 | const char *base_name) | 398 | const char *base_name) |
399 | { | 399 | { |
400 | unsigned int def_conf, conn; | 400 | unsigned int def_conf, conn; |
401 | char name[44]; | 401 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
402 | int idx, err; | 402 | int idx, err; |
403 | bool phantom_jack; | 403 | bool phantom_jack; |
404 | 404 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index e0bf7534fa1f..2e7493ef8ee0 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -562,6 +562,14 @@ static inline unsigned int get_wcaps_channels(u32 wcaps) | |||
562 | return chans; | 562 | return chans; |
563 | } | 563 | } |
564 | 564 | ||
565 | static inline void snd_hda_override_wcaps(struct hda_codec *codec, | ||
566 | hda_nid_t nid, u32 val) | ||
567 | { | ||
568 | if (nid >= codec->start_nid && | ||
569 | nid < codec->start_nid + codec->num_nodes) | ||
570 | codec->wcaps[nid - codec->start_nid] = val; | ||
571 | } | ||
572 | |||
565 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | 573 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); |
566 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 574 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
567 | unsigned int caps); | 575 | unsigned int caps); |
@@ -667,7 +675,7 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid, | |||
667 | if (state & AC_PWRST_ERROR) | 675 | if (state & AC_PWRST_ERROR) |
668 | return true; | 676 | return true; |
669 | state = (state >> 4) & 0x0f; | 677 | state = (state >> 4) & 0x0f; |
670 | return (state != target_state); | 678 | return (state == target_state); |
671 | } | 679 | } |
672 | 680 | ||
673 | unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec, | 681 | unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec, |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 0fee8fae590a..9760f001916d 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -504,6 +504,8 @@ static void print_conn_list(struct snd_info_buffer *buffer, | |||
504 | int conn_len) | 504 | int conn_len) |
505 | { | 505 | { |
506 | int c, curr = -1; | 506 | int c, curr = -1; |
507 | const hda_nid_t *list; | ||
508 | int cache_len; | ||
507 | 509 | ||
508 | if (conn_len > 1 && | 510 | if (conn_len > 1 && |
509 | wid_type != AC_WID_AUD_MIX && | 511 | wid_type != AC_WID_AUD_MIX && |
@@ -521,6 +523,19 @@ static void print_conn_list(struct snd_info_buffer *buffer, | |||
521 | } | 523 | } |
522 | snd_iprintf(buffer, "\n"); | 524 | snd_iprintf(buffer, "\n"); |
523 | } | 525 | } |
526 | |||
527 | /* Get Cache connections info */ | ||
528 | cache_len = snd_hda_get_conn_list(codec, nid, &list); | ||
529 | if (cache_len != conn_len | ||
530 | || memcmp(list, conn, conn_len)) { | ||
531 | snd_iprintf(buffer, " In-driver Connection: %d\n", cache_len); | ||
532 | if (cache_len > 0) { | ||
533 | snd_iprintf(buffer, " "); | ||
534 | for (c = 0; c < cache_len; c++) | ||
535 | snd_iprintf(buffer, " 0x%02x", list[c]); | ||
536 | snd_iprintf(buffer, "\n"); | ||
537 | } | ||
538 | } | ||
524 | } | 539 | } |
525 | 540 | ||
526 | static void print_gpio(struct snd_info_buffer *buffer, | 541 | static void print_gpio(struct snd_info_buffer *buffer, |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 90ff7a3f72df..6e9876f27d95 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -139,7 +139,7 @@ enum { | |||
139 | #define DSP_SPEAKER_OUT_LATENCY 7 | 139 | #define DSP_SPEAKER_OUT_LATENCY 7 |
140 | 140 | ||
141 | struct ct_effect { | 141 | struct ct_effect { |
142 | char name[44]; | 142 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
143 | hda_nid_t nid; | 143 | hda_nid_t nid; |
144 | int mid; /*effect module ID*/ | 144 | int mid; /*effect module ID*/ |
145 | int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/ | 145 | int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/ |
@@ -270,7 +270,7 @@ enum { | |||
270 | }; | 270 | }; |
271 | 271 | ||
272 | struct ct_tuning_ctl { | 272 | struct ct_tuning_ctl { |
273 | char name[44]; | 273 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
274 | hda_nid_t parent_nid; | 274 | hda_nid_t parent_nid; |
275 | hda_nid_t nid; | 275 | hda_nid_t nid; |
276 | int mid; /*effect module ID*/ | 276 | int mid; /*effect module ID*/ |
@@ -3103,7 +3103,7 @@ static int add_tuning_control(struct hda_codec *codec, | |||
3103 | hda_nid_t pnid, hda_nid_t nid, | 3103 | hda_nid_t pnid, hda_nid_t nid, |
3104 | const char *name, int dir) | 3104 | const char *name, int dir) |
3105 | { | 3105 | { |
3106 | char namestr[44]; | 3106 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
3107 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | 3107 | int type = dir ? HDA_INPUT : HDA_OUTPUT; |
3108 | struct snd_kcontrol_new knew = | 3108 | struct snd_kcontrol_new knew = |
3109 | HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type); | 3109 | HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type); |
@@ -3935,7 +3935,7 @@ static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
3935 | static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, | 3935 | static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, |
3936 | const char *pfx, int dir) | 3936 | const char *pfx, int dir) |
3937 | { | 3937 | { |
3938 | char namestr[44]; | 3938 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
3939 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | 3939 | int type = dir ? HDA_INPUT : HDA_OUTPUT; |
3940 | struct snd_kcontrol_new knew = | 3940 | struct snd_kcontrol_new knew = |
3941 | CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type); | 3941 | CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type); |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index b314d3e6d7fa..de00ce166470 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -2947,7 +2947,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
2947 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | 2947 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), |
2948 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | 2948 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), |
2949 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), | 2949 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), |
2950 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), | ||
2951 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | 2950 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), |
2952 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | 2951 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), |
2953 | {} | 2952 | {} |
@@ -3318,6 +3317,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
3318 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), | 3317 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), |
3319 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), | 3318 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), |
3320 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), | 3319 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), |
3320 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), | ||
3321 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), | 3321 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), |
3322 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), | 3322 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), |
3323 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), | 3323 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index e12f7a030c58..540bdef2f904 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1018,13 +1018,18 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1018 | hdmi_non_intrinsic_event(codec, res); | 1018 | hdmi_non_intrinsic_event(codec, res); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid) | 1021 | static void haswell_verify_pin_D0(struct hda_codec *codec, |
1022 | hda_nid_t cvt_nid, hda_nid_t nid) | ||
1022 | { | 1023 | { |
1023 | int pwr, lamp, ramp; | 1024 | int pwr, lamp, ramp; |
1024 | 1025 | ||
1025 | pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); | 1026 | /* For Haswell, the converter 1/2 may keep in D3 state after bootup, |
1026 | pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; | 1027 | * thus pins could only choose converter 0 for use. Make sure the |
1027 | if (pwr != AC_PWRST_D0) { | 1028 | * converters are in correct power state */ |
1029 | if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0)) | ||
1030 | snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
1031 | |||
1032 | if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) { | ||
1028 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, | 1033 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, |
1029 | AC_PWRST_D0); | 1034 | AC_PWRST_D0); |
1030 | msleep(40); | 1035 | msleep(40); |
@@ -1068,7 +1073,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | |||
1068 | int new_pinctl = 0; | 1073 | int new_pinctl = 0; |
1069 | 1074 | ||
1070 | if (codec->vendor_id == 0x80862807) | 1075 | if (codec->vendor_id == 0x80862807) |
1071 | haswell_verify_pin_D0(codec, pin_nid); | 1076 | haswell_verify_pin_D0(codec, cvt_nid, pin_nid); |
1072 | 1077 | ||
1073 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { | 1078 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { |
1074 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1079 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
@@ -1101,26 +1106,15 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | |||
1101 | return 0; | 1106 | return 0; |
1102 | } | 1107 | } |
1103 | 1108 | ||
1104 | /* | 1109 | static int hdmi_choose_cvt(struct hda_codec *codec, |
1105 | * HDA PCM callbacks | 1110 | int pin_idx, int *cvt_id, int *mux_id) |
1106 | */ | ||
1107 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | ||
1108 | struct hda_codec *codec, | ||
1109 | struct snd_pcm_substream *substream) | ||
1110 | { | 1111 | { |
1111 | struct hdmi_spec *spec = codec->spec; | 1112 | struct hdmi_spec *spec = codec->spec; |
1112 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1113 | int pin_idx, cvt_idx, mux_idx = 0; | ||
1114 | struct hdmi_spec_per_pin *per_pin; | 1113 | struct hdmi_spec_per_pin *per_pin; |
1115 | struct hdmi_eld *eld; | ||
1116 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 1114 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
1115 | int cvt_idx, mux_idx = 0; | ||
1117 | 1116 | ||
1118 | /* Validate hinfo */ | ||
1119 | pin_idx = hinfo_to_pin_index(spec, hinfo); | ||
1120 | if (snd_BUG_ON(pin_idx < 0)) | ||
1121 | return -EINVAL; | ||
1122 | per_pin = get_pin(spec, pin_idx); | 1117 | per_pin = get_pin(spec, pin_idx); |
1123 | eld = &per_pin->sink_eld; | ||
1124 | 1118 | ||
1125 | /* Dynamically assign converter to stream */ | 1119 | /* Dynamically assign converter to stream */ |
1126 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 1120 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
@@ -1138,17 +1132,89 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1138 | continue; | 1132 | continue; |
1139 | break; | 1133 | break; |
1140 | } | 1134 | } |
1135 | |||
1141 | /* No free converters */ | 1136 | /* No free converters */ |
1142 | if (cvt_idx == spec->num_cvts) | 1137 | if (cvt_idx == spec->num_cvts) |
1143 | return -ENODEV; | 1138 | return -ENODEV; |
1144 | 1139 | ||
1140 | if (cvt_id) | ||
1141 | *cvt_id = cvt_idx; | ||
1142 | if (mux_id) | ||
1143 | *mux_id = mux_idx; | ||
1144 | |||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1148 | static void haswell_config_cvts(struct hda_codec *codec, | ||
1149 | int pin_id, int mux_id) | ||
1150 | { | ||
1151 | struct hdmi_spec *spec = codec->spec; | ||
1152 | struct hdmi_spec_per_pin *per_pin; | ||
1153 | int pin_idx, mux_idx; | ||
1154 | int curr; | ||
1155 | int err; | ||
1156 | |||
1157 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
1158 | per_pin = get_pin(spec, pin_idx); | ||
1159 | |||
1160 | if (pin_idx == pin_id) | ||
1161 | continue; | ||
1162 | |||
1163 | curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0, | ||
1164 | AC_VERB_GET_CONNECT_SEL, 0); | ||
1165 | |||
1166 | /* Choose another unused converter */ | ||
1167 | if (curr == mux_id) { | ||
1168 | err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx); | ||
1169 | if (err < 0) | ||
1170 | return; | ||
1171 | snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx); | ||
1172 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, | ||
1173 | AC_VERB_SET_CONNECT_SEL, | ||
1174 | mux_idx); | ||
1175 | } | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * HDA PCM callbacks | ||
1181 | */ | ||
1182 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | ||
1183 | struct hda_codec *codec, | ||
1184 | struct snd_pcm_substream *substream) | ||
1185 | { | ||
1186 | struct hdmi_spec *spec = codec->spec; | ||
1187 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1188 | int pin_idx, cvt_idx, mux_idx = 0; | ||
1189 | struct hdmi_spec_per_pin *per_pin; | ||
1190 | struct hdmi_eld *eld; | ||
1191 | struct hdmi_spec_per_cvt *per_cvt = NULL; | ||
1192 | int err; | ||
1193 | |||
1194 | /* Validate hinfo */ | ||
1195 | pin_idx = hinfo_to_pin_index(spec, hinfo); | ||
1196 | if (snd_BUG_ON(pin_idx < 0)) | ||
1197 | return -EINVAL; | ||
1198 | per_pin = get_pin(spec, pin_idx); | ||
1199 | eld = &per_pin->sink_eld; | ||
1200 | |||
1201 | err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); | ||
1202 | if (err < 0) | ||
1203 | return err; | ||
1204 | |||
1205 | per_cvt = get_cvt(spec, cvt_idx); | ||
1145 | /* Claim converter */ | 1206 | /* Claim converter */ |
1146 | per_cvt->assigned = 1; | 1207 | per_cvt->assigned = 1; |
1147 | hinfo->nid = per_cvt->cvt_nid; | 1208 | hinfo->nid = per_cvt->cvt_nid; |
1148 | 1209 | ||
1149 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | 1210 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, |
1150 | AC_VERB_SET_CONNECT_SEL, | 1211 | AC_VERB_SET_CONNECT_SEL, |
1151 | mux_idx); | 1212 | mux_idx); |
1213 | |||
1214 | /* configure unused pins to choose other converters */ | ||
1215 | if (codec->vendor_id == 0x80862807) | ||
1216 | haswell_config_cvts(codec, pin_idx, mux_idx); | ||
1217 | |||
1152 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); | 1218 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
1153 | 1219 | ||
1154 | /* Initially set the converter's capabilities */ | 1220 | /* Initially set the converter's capabilities */ |
@@ -1798,12 +1864,33 @@ static void generic_hdmi_free(struct hda_codec *codec) | |||
1798 | kfree(spec); | 1864 | kfree(spec); |
1799 | } | 1865 | } |
1800 | 1866 | ||
1867 | #ifdef CONFIG_PM | ||
1868 | static int generic_hdmi_resume(struct hda_codec *codec) | ||
1869 | { | ||
1870 | struct hdmi_spec *spec = codec->spec; | ||
1871 | int pin_idx; | ||
1872 | |||
1873 | generic_hdmi_init(codec); | ||
1874 | snd_hda_codec_resume_amp(codec); | ||
1875 | snd_hda_codec_resume_cache(codec); | ||
1876 | |||
1877 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
1878 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | ||
1879 | hdmi_present_sense(per_pin, 1); | ||
1880 | } | ||
1881 | return 0; | ||
1882 | } | ||
1883 | #endif | ||
1884 | |||
1801 | static const struct hda_codec_ops generic_hdmi_patch_ops = { | 1885 | static const struct hda_codec_ops generic_hdmi_patch_ops = { |
1802 | .init = generic_hdmi_init, | 1886 | .init = generic_hdmi_init, |
1803 | .free = generic_hdmi_free, | 1887 | .free = generic_hdmi_free, |
1804 | .build_pcms = generic_hdmi_build_pcms, | 1888 | .build_pcms = generic_hdmi_build_pcms, |
1805 | .build_controls = generic_hdmi_build_controls, | 1889 | .build_controls = generic_hdmi_build_controls, |
1806 | .unsol_event = hdmi_unsol_event, | 1890 | .unsol_event = hdmi_unsol_event, |
1891 | #ifdef CONFIG_PM | ||
1892 | .resume = generic_hdmi_resume, | ||
1893 | #endif | ||
1807 | }; | 1894 | }; |
1808 | 1895 | ||
1809 | 1896 | ||
@@ -1821,7 +1908,6 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | |||
1821 | 1908 | ||
1822 | /* override pins connection list */ | 1909 | /* override pins connection list */ |
1823 | snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid); | 1910 | snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid); |
1824 | nconns = max(spec->num_cvts, 4); | ||
1825 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); | 1911 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); |
1826 | } | 1912 | } |
1827 | 1913 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 403010c9e82e..7d6a9f5d2b06 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -115,6 +115,7 @@ struct alc_spec { | |||
115 | 115 | ||
116 | int init_amp; | 116 | int init_amp; |
117 | int codec_variant; /* flag for other variants */ | 117 | int codec_variant; /* flag for other variants */ |
118 | bool has_alc5505_dsp; | ||
118 | 119 | ||
119 | /* for PLL fix */ | 120 | /* for PLL fix */ |
120 | hda_nid_t pll_nid; | 121 | hda_nid_t pll_nid; |
@@ -2580,7 +2581,96 @@ static void alc269_shutup(struct hda_codec *codec) | |||
2580 | } | 2581 | } |
2581 | } | 2582 | } |
2582 | 2583 | ||
2584 | static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, | ||
2585 | unsigned int val) | ||
2586 | { | ||
2587 | snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1); | ||
2588 | snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */ | ||
2589 | snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */ | ||
2590 | } | ||
2591 | |||
2592 | static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg) | ||
2593 | { | ||
2594 | unsigned int val; | ||
2595 | |||
2596 | snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1); | ||
2597 | val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0) | ||
2598 | & 0xffff; | ||
2599 | val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0) | ||
2600 | << 16; | ||
2601 | return val; | ||
2602 | } | ||
2603 | |||
2604 | static void alc5505_dsp_halt(struct hda_codec *codec) | ||
2605 | { | ||
2606 | unsigned int val; | ||
2607 | |||
2608 | alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */ | ||
2609 | alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */ | ||
2610 | alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */ | ||
2611 | alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */ | ||
2612 | alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */ | ||
2613 | alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */ | ||
2614 | alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */ | ||
2615 | val = alc5505_coef_get(codec, 0x6220); | ||
2616 | alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */ | ||
2617 | } | ||
2618 | |||
2619 | static void alc5505_dsp_back_from_halt(struct hda_codec *codec) | ||
2620 | { | ||
2621 | alc5505_coef_set(codec, 0x61b8, 0x04133302); | ||
2622 | alc5505_coef_set(codec, 0x61b0, 0x00005b16); | ||
2623 | alc5505_coef_set(codec, 0x61b4, 0x040a2b02); | ||
2624 | alc5505_coef_set(codec, 0x6230, 0xf80d4011); | ||
2625 | alc5505_coef_set(codec, 0x6220, 0x2002010f); | ||
2626 | alc5505_coef_set(codec, 0x880c, 0x00000004); | ||
2627 | } | ||
2628 | |||
2629 | static void alc5505_dsp_init(struct hda_codec *codec) | ||
2630 | { | ||
2631 | unsigned int val; | ||
2632 | |||
2633 | alc5505_dsp_halt(codec); | ||
2634 | alc5505_dsp_back_from_halt(codec); | ||
2635 | alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */ | ||
2636 | alc5505_coef_set(codec, 0x61b0, 0x5b16); | ||
2637 | alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */ | ||
2638 | alc5505_coef_set(codec, 0x61b4, 0x04132b02); | ||
2639 | alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/ | ||
2640 | alc5505_coef_set(codec, 0x61b8, 0x041f3302); | ||
2641 | snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */ | ||
2642 | alc5505_coef_set(codec, 0x61b8, 0x041b3302); | ||
2643 | alc5505_coef_set(codec, 0x61b8, 0x04173302); | ||
2644 | alc5505_coef_set(codec, 0x61b8, 0x04163302); | ||
2645 | alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */ | ||
2646 | alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */ | ||
2647 | alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */ | ||
2648 | |||
2649 | val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */ | ||
2650 | if (val <= 3) | ||
2651 | alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */ | ||
2652 | else | ||
2653 | alc5505_coef_set(codec, 0x6220, 0x6002018f); | ||
2654 | |||
2655 | alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/ | ||
2656 | alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */ | ||
2657 | alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */ | ||
2658 | alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */ | ||
2659 | alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */ | ||
2660 | alc5505_coef_set(codec, 0x880c, 0x00000003); | ||
2661 | alc5505_coef_set(codec, 0x880c, 0x00000010); | ||
2662 | } | ||
2663 | |||
2583 | #ifdef CONFIG_PM | 2664 | #ifdef CONFIG_PM |
2665 | static int alc269_suspend(struct hda_codec *codec) | ||
2666 | { | ||
2667 | struct alc_spec *spec = codec->spec; | ||
2668 | |||
2669 | if (spec->has_alc5505_dsp) | ||
2670 | alc5505_dsp_halt(codec); | ||
2671 | return alc_suspend(codec); | ||
2672 | } | ||
2673 | |||
2584 | static int alc269_resume(struct hda_codec *codec) | 2674 | static int alc269_resume(struct hda_codec *codec) |
2585 | { | 2675 | { |
2586 | struct alc_spec *spec = codec->spec; | 2676 | struct alc_spec *spec = codec->spec; |
@@ -2603,7 +2693,10 @@ static int alc269_resume(struct hda_codec *codec) | |||
2603 | 2693 | ||
2604 | snd_hda_codec_resume_amp(codec); | 2694 | snd_hda_codec_resume_amp(codec); |
2605 | snd_hda_codec_resume_cache(codec); | 2695 | snd_hda_codec_resume_cache(codec); |
2696 | alc_inv_dmic_sync(codec, true); | ||
2606 | hda_call_check_power_status(codec, 0x01); | 2697 | hda_call_check_power_status(codec, 0x01); |
2698 | if (spec->has_alc5505_dsp) | ||
2699 | alc5505_dsp_back_from_halt(codec); | ||
2607 | return 0; | 2700 | return 0; |
2608 | } | 2701 | } |
2609 | #endif /* CONFIG_PM */ | 2702 | #endif /* CONFIG_PM */ |
@@ -3225,6 +3318,7 @@ enum { | |||
3225 | ALC271_FIXUP_HP_GATE_MIC_JACK, | 3318 | ALC271_FIXUP_HP_GATE_MIC_JACK, |
3226 | ALC269_FIXUP_ACER_AC700, | 3319 | ALC269_FIXUP_ACER_AC700, |
3227 | ALC269_FIXUP_LIMIT_INT_MIC_BOOST, | 3320 | ALC269_FIXUP_LIMIT_INT_MIC_BOOST, |
3321 | ALC269VB_FIXUP_ORDISSIMO_EVE2, | ||
3228 | }; | 3322 | }; |
3229 | 3323 | ||
3230 | static const struct hda_fixup alc269_fixups[] = { | 3324 | static const struct hda_fixup alc269_fixups[] = { |
@@ -3467,6 +3561,15 @@ static const struct hda_fixup alc269_fixups[] = { | |||
3467 | .type = HDA_FIXUP_FUNC, | 3561 | .type = HDA_FIXUP_FUNC, |
3468 | .v.func = alc269_fixup_limit_int_mic_boost, | 3562 | .v.func = alc269_fixup_limit_int_mic_boost, |
3469 | }, | 3563 | }, |
3564 | [ALC269VB_FIXUP_ORDISSIMO_EVE2] = { | ||
3565 | .type = HDA_FIXUP_PINS, | ||
3566 | .v.pins = (const struct hda_pintbl[]) { | ||
3567 | { 0x12, 0x99a3092f }, /* int-mic */ | ||
3568 | { 0x18, 0x03a11d20 }, /* mic */ | ||
3569 | { 0x19, 0x411111f0 }, /* Unused bogus pin */ | ||
3570 | { } | ||
3571 | }, | ||
3572 | }, | ||
3470 | }; | 3573 | }; |
3471 | 3574 | ||
3472 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 3575 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -3495,9 +3598,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
3495 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3598 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3496 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3599 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3497 | SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3600 | SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3601 | SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3602 | SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3498 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3603 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3499 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3604 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3500 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 3605 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
3606 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3501 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | 3607 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
3502 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), | 3608 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), |
3503 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 3609 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -3539,6 +3645,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
3539 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), | 3645 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), |
3540 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 3646 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
3541 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 3647 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
3648 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ | ||
3542 | 3649 | ||
3543 | #if 0 | 3650 | #if 0 |
3544 | /* Below is a quirk table taken from the old code. | 3651 | /* Below is a quirk table taken from the old code. |
@@ -3718,6 +3825,11 @@ static int patch_alc269(struct hda_codec *codec) | |||
3718 | break; | 3825 | break; |
3719 | } | 3826 | } |
3720 | 3827 | ||
3828 | if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) { | ||
3829 | spec->has_alc5505_dsp = true; | ||
3830 | spec->init_hook = alc5505_dsp_init; | ||
3831 | } | ||
3832 | |||
3721 | /* automatic parse from the BIOS config */ | 3833 | /* automatic parse from the BIOS config */ |
3722 | err = alc269_parse_auto_config(codec); | 3834 | err = alc269_parse_auto_config(codec); |
3723 | if (err < 0) | 3835 | if (err < 0) |
@@ -3728,6 +3840,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
3728 | 3840 | ||
3729 | codec->patch_ops = alc_patch_ops; | 3841 | codec->patch_ops = alc_patch_ops; |
3730 | #ifdef CONFIG_PM | 3842 | #ifdef CONFIG_PM |
3843 | codec->patch_ops.suspend = alc269_suspend; | ||
3731 | codec->patch_ops.resume = alc269_resume; | 3844 | codec->patch_ops.resume = alc269_resume; |
3732 | #endif | 3845 | #endif |
3733 | spec->shutup = alc269_shutup; | 3846 | spec->shutup = alc269_shutup; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 1d9d6427e0bf..e2f83591161b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2233,6 +2233,10 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2233 | "HP Folio", STAC_92HD83XXX_HP_MIC_LED), | 2233 | "HP Folio", STAC_92HD83XXX_HP_MIC_LED), |
2234 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900, | 2234 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900, |
2235 | "HP", STAC_92HD83XXX_HP_MIC_LED), | 2235 | "HP", STAC_92HD83XXX_HP_MIC_LED), |
2236 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2000, | ||
2237 | "HP", STAC_92HD83XXX_HP_MIC_LED), | ||
2238 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2100, | ||
2239 | "HP", STAC_92HD83XXX_HP_MIC_LED), | ||
2236 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, | 2240 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, |
2237 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2241 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2238 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, | 2242 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, |
@@ -3707,14 +3711,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, | |||
3707 | #endif | 3711 | #endif |
3708 | 3712 | ||
3709 | #ifdef CONFIG_PM | 3713 | #ifdef CONFIG_PM |
3710 | static int stac_resume(struct hda_codec *codec) | ||
3711 | { | ||
3712 | codec->patch_ops.init(codec); | ||
3713 | snd_hda_codec_resume_amp(codec); | ||
3714 | snd_hda_codec_resume_cache(codec); | ||
3715 | return 0; | ||
3716 | } | ||
3717 | |||
3718 | static int stac_suspend(struct hda_codec *codec) | 3714 | static int stac_suspend(struct hda_codec *codec) |
3719 | { | 3715 | { |
3720 | stac_shutup(codec); | 3716 | stac_shutup(codec); |
@@ -3743,7 +3739,6 @@ static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
3743 | } | 3739 | } |
3744 | #else | 3740 | #else |
3745 | #define stac_suspend NULL | 3741 | #define stac_suspend NULL |
3746 | #define stac_resume NULL | ||
3747 | #define stac_set_power_state NULL | 3742 | #define stac_set_power_state NULL |
3748 | #endif /* CONFIG_PM */ | 3743 | #endif /* CONFIG_PM */ |
3749 | 3744 | ||
@@ -3755,7 +3750,6 @@ static const struct hda_codec_ops stac_patch_ops = { | |||
3755 | .unsol_event = snd_hda_jack_unsol_event, | 3750 | .unsol_event = snd_hda_jack_unsol_event, |
3756 | #ifdef CONFIG_PM | 3751 | #ifdef CONFIG_PM |
3757 | .suspend = stac_suspend, | 3752 | .suspend = stac_suspend, |
3758 | .resume = stac_resume, | ||
3759 | #endif | 3753 | #endif |
3760 | .reboot_notify = stac_shutup, | 3754 | .reboot_notify = stac_shutup, |
3761 | }; | 3755 | }; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index e5245544eb52..e2481baddc70 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -480,14 +480,9 @@ static int via_suspend(struct hda_codec *codec) | |||
480 | struct via_spec *spec = codec->spec; | 480 | struct via_spec *spec = codec->spec; |
481 | vt1708_stop_hp_work(codec); | 481 | vt1708_stop_hp_work(codec); |
482 | 482 | ||
483 | if (spec->codec_type == VT1802) { | 483 | /* Fix pop noise on headphones */ |
484 | /* Fix pop noise on headphones */ | 484 | if (spec->codec_type == VT1802) |
485 | int i; | 485 | snd_hda_shutup_pins(codec); |
486 | for (i = 0; i < spec->gen.autocfg.hp_outs; i++) | ||
487 | snd_hda_codec_write(codec, spec->gen.autocfg.hp_pins[i], | ||
488 | 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
489 | 0x00); | ||
490 | } | ||
491 | 486 | ||
492 | return 0; | 487 | return 0; |
493 | } | 488 | } |
@@ -746,6 +741,8 @@ static int patch_vt1708(struct hda_codec *codec) | |||
746 | /* don't support the input jack switching due to lack of unsol event */ | 741 | /* don't support the input jack switching due to lack of unsol event */ |
747 | /* (it may work with polling, though, but it needs testing) */ | 742 | /* (it may work with polling, though, but it needs testing) */ |
748 | spec->gen.suppress_auto_mic = 1; | 743 | spec->gen.suppress_auto_mic = 1; |
744 | /* Some machines show the broken speaker mute */ | ||
745 | spec->gen.auto_mute_via_amp = 1; | ||
749 | 746 | ||
750 | /* Add HP and CD pin config connect bit re-config action */ | 747 | /* Add HP and CD pin config connect bit re-config action */ |
751 | vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID); | 748 | vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID); |
@@ -910,6 +907,8 @@ static const struct hda_verb vt1708S_init_verbs[] = { | |||
910 | static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin, | 907 | static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin, |
911 | int offset, int num_steps, int step_size) | 908 | int offset, int num_steps, int step_size) |
912 | { | 909 | { |
910 | snd_hda_override_wcaps(codec, pin, | ||
911 | get_wcaps(codec, pin) | AC_WCAP_IN_AMP); | ||
913 | snd_hda_override_amp_caps(codec, pin, HDA_INPUT, | 912 | snd_hda_override_amp_caps(codec, pin, HDA_INPUT, |
914 | (offset << AC_AMPCAP_OFFSET_SHIFT) | | 913 | (offset << AC_AMPCAP_OFFSET_SHIFT) | |
915 | (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) | | 914 | (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) | |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 806407a3973e..28ec872e54c0 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2807,7 +2807,6 @@ static void snd_ice1712_remove(struct pci_dev *pci) | |||
2807 | if (ice->card_info && ice->card_info->chip_exit) | 2807 | if (ice->card_info && ice->card_info->chip_exit) |
2808 | ice->card_info->chip_exit(ice); | 2808 | ice->card_info->chip_exit(ice); |
2809 | snd_card_free(card); | 2809 | snd_card_free(card); |
2810 | pci_set_drvdata(pci, NULL); | ||
2811 | } | 2810 | } |
2812 | 2811 | ||
2813 | static struct pci_driver ice1712_driver = { | 2812 | static struct pci_driver ice1712_driver = { |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index ce70e7f113e0..500471778291 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2800,7 +2800,6 @@ static void snd_vt1724_remove(struct pci_dev *pci) | |||
2800 | if (ice->card_info && ice->card_info->chip_exit) | 2800 | if (ice->card_info && ice->card_info->chip_exit) |
2801 | ice->card_info->chip_exit(ice); | 2801 | ice->card_info->chip_exit(ice); |
2802 | snd_card_free(card); | 2802 | snd_card_free(card); |
2803 | pci_set_drvdata(pci, NULL); | ||
2804 | } | 2803 | } |
2805 | 2804 | ||
2806 | #ifdef CONFIG_PM_SLEEP | 2805 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b8fe40531b9c..59c8aaebb91e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -3364,7 +3364,6 @@ static int snd_intel8x0_probe(struct pci_dev *pci, | |||
3364 | static void snd_intel8x0_remove(struct pci_dev *pci) | 3364 | static void snd_intel8x0_remove(struct pci_dev *pci) |
3365 | { | 3365 | { |
3366 | snd_card_free(pci_get_drvdata(pci)); | 3366 | snd_card_free(pci_get_drvdata(pci)); |
3367 | pci_set_drvdata(pci, NULL); | ||
3368 | } | 3367 | } |
3369 | 3368 | ||
3370 | static struct pci_driver intel8x0_driver = { | 3369 | static struct pci_driver intel8x0_driver = { |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index fea09e8ea608..3573c1193665 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1328,7 +1328,6 @@ static int snd_intel8x0m_probe(struct pci_dev *pci, | |||
1328 | static void snd_intel8x0m_remove(struct pci_dev *pci) | 1328 | static void snd_intel8x0m_remove(struct pci_dev *pci) |
1329 | { | 1329 | { |
1330 | snd_card_free(pci_get_drvdata(pci)); | 1330 | snd_card_free(pci_get_drvdata(pci)); |
1331 | pci_set_drvdata(pci, NULL); | ||
1332 | } | 1331 | } |
1333 | 1332 | ||
1334 | static struct pci_driver intel8x0m_driver = { | 1333 | static struct pci_driver intel8x0m_driver = { |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 43b4228d9afe..9cf9829555d4 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2473,7 +2473,6 @@ snd_korg1212_probe(struct pci_dev *pci, | |||
2473 | static void snd_korg1212_remove(struct pci_dev *pci) | 2473 | static void snd_korg1212_remove(struct pci_dev *pci) |
2474 | { | 2474 | { |
2475 | snd_card_free(pci_get_drvdata(pci)); | 2475 | snd_card_free(pci_get_drvdata(pci)); |
2476 | pci_set_drvdata(pci, NULL); | ||
2477 | } | 2476 | } |
2478 | 2477 | ||
2479 | static struct pci_driver korg1212_driver = { | 2478 | static struct pci_driver korg1212_driver = { |
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 322b638e8ec4..7307d97186cb 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c | |||
@@ -759,7 +759,6 @@ out_free: | |||
759 | static void lola_remove(struct pci_dev *pci) | 759 | static void lola_remove(struct pci_dev *pci) |
760 | { | 760 | { |
761 | snd_card_free(pci_get_drvdata(pci)); | 761 | snd_card_free(pci_get_drvdata(pci)); |
762 | pci_set_drvdata(pci, NULL); | ||
763 | } | 762 | } |
764 | 763 | ||
765 | /* PCI IDs */ | 764 | /* PCI IDs */ |
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 298bc9b72991..3230e57f246c 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c | |||
@@ -1139,7 +1139,6 @@ out_free: | |||
1139 | static void snd_lx6464es_remove(struct pci_dev *pci) | 1139 | static void snd_lx6464es_remove(struct pci_dev *pci) |
1140 | { | 1140 | { |
1141 | snd_card_free(pci_get_drvdata(pci)); | 1141 | snd_card_free(pci_get_drvdata(pci)); |
1142 | pci_set_drvdata(pci, NULL); | ||
1143 | } | 1142 | } |
1144 | 1143 | ||
1145 | 1144 | ||
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index c76ac1411210..d5417360f51f 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2775,7 +2775,6 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2775 | static void snd_m3_remove(struct pci_dev *pci) | 2775 | static void snd_m3_remove(struct pci_dev *pci) |
2776 | { | 2776 | { |
2777 | snd_card_free(pci_get_drvdata(pci)); | 2777 | snd_card_free(pci_get_drvdata(pci)); |
2778 | pci_set_drvdata(pci, NULL); | ||
2779 | } | 2778 | } |
2780 | 2779 | ||
2781 | static struct pci_driver m3_driver = { | 2780 | static struct pci_driver m3_driver = { |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 934dec98e2ce..1e0f6ee193f0 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1377,7 +1377,6 @@ static int snd_mixart_probe(struct pci_dev *pci, | |||
1377 | static void snd_mixart_remove(struct pci_dev *pci) | 1377 | static void snd_mixart_remove(struct pci_dev *pci) |
1378 | { | 1378 | { |
1379 | snd_mixart_free(pci_get_drvdata(pci)); | 1379 | snd_mixart_free(pci_get_drvdata(pci)); |
1380 | pci_set_drvdata(pci, NULL); | ||
1381 | } | 1380 | } |
1382 | 1381 | ||
1383 | static struct pci_driver mixart_driver = { | 1382 | static struct pci_driver mixart_driver = { |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 6febedb05936..fe79fff4c6dc 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1746,7 +1746,6 @@ static int snd_nm256_probe(struct pci_dev *pci, | |||
1746 | static void snd_nm256_remove(struct pci_dev *pci) | 1746 | static void snd_nm256_remove(struct pci_dev *pci) |
1747 | { | 1747 | { |
1748 | snd_card_free(pci_get_drvdata(pci)); | 1748 | snd_card_free(pci_get_drvdata(pci)); |
1749 | pci_set_drvdata(pci, NULL); | ||
1750 | } | 1749 | } |
1751 | 1750 | ||
1752 | 1751 | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 9562dc63ba60..b0cb48adddc7 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -722,7 +722,6 @@ EXPORT_SYMBOL(oxygen_pci_probe); | |||
722 | void oxygen_pci_remove(struct pci_dev *pci) | 722 | void oxygen_pci_remove(struct pci_dev *pci) |
723 | { | 723 | { |
724 | snd_card_free(pci_get_drvdata(pci)); | 724 | snd_card_free(pci_get_drvdata(pci)); |
725 | pci_set_drvdata(pci, NULL); | ||
726 | } | 725 | } |
727 | EXPORT_SYMBOL(oxygen_pci_remove); | 726 | EXPORT_SYMBOL(oxygen_pci_remove); |
728 | 727 | ||
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index b97384ad946d..d379b284955b 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1691,7 +1691,6 @@ static int pcxhr_probe(struct pci_dev *pci, | |||
1691 | static void pcxhr_remove(struct pci_dev *pci) | 1691 | static void pcxhr_remove(struct pci_dev *pci) |
1692 | { | 1692 | { |
1693 | pcxhr_free(pci_get_drvdata(pci)); | 1693 | pcxhr_free(pci_get_drvdata(pci)); |
1694 | pci_set_drvdata(pci, NULL); | ||
1695 | } | 1694 | } |
1696 | 1695 | ||
1697 | static struct pci_driver pcxhr_driver = { | 1696 | static struct pci_driver pcxhr_driver = { |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 63c1c8041554..56cc891e395e 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -2066,7 +2066,6 @@ static void snd_riptide_joystick_remove(struct pci_dev *pci) | |||
2066 | if (gameport) { | 2066 | if (gameport) { |
2067 | release_region(gameport->io, 8); | 2067 | release_region(gameport->io, 8); |
2068 | gameport_unregister_port(gameport); | 2068 | gameport_unregister_port(gameport); |
2069 | pci_set_drvdata(pci, NULL); | ||
2070 | } | 2069 | } |
2071 | } | 2070 | } |
2072 | #endif | 2071 | #endif |
@@ -2179,7 +2178,6 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2179 | static void snd_card_riptide_remove(struct pci_dev *pci) | 2178 | static void snd_card_riptide_remove(struct pci_dev *pci) |
2180 | { | 2179 | { |
2181 | snd_card_free(pci_get_drvdata(pci)); | 2180 | snd_card_free(pci_get_drvdata(pci)); |
2182 | pci_set_drvdata(pci, NULL); | ||
2183 | } | 2181 | } |
2184 | 2182 | ||
2185 | static struct pci_driver driver = { | 2183 | static struct pci_driver driver = { |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 0ecd4100713e..cc26346ae66b 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -1981,7 +1981,6 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
1981 | static void snd_rme32_remove(struct pci_dev *pci) | 1981 | static void snd_rme32_remove(struct pci_dev *pci) |
1982 | { | 1982 | { |
1983 | snd_card_free(pci_get_drvdata(pci)); | 1983 | snd_card_free(pci_get_drvdata(pci)); |
1984 | pci_set_drvdata(pci, NULL); | ||
1985 | } | 1984 | } |
1986 | 1985 | ||
1987 | static struct pci_driver rme32_driver = { | 1986 | static struct pci_driver rme32_driver = { |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 5fb88ac82aa9..2a8ad9d1a2ae 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -2390,7 +2390,6 @@ snd_rme96_probe(struct pci_dev *pci, | |||
2390 | static void snd_rme96_remove(struct pci_dev *pci) | 2390 | static void snd_rme96_remove(struct pci_dev *pci) |
2391 | { | 2391 | { |
2392 | snd_card_free(pci_get_drvdata(pci)); | 2392 | snd_card_free(pci_get_drvdata(pci)); |
2393 | pci_set_drvdata(pci, NULL); | ||
2394 | } | 2393 | } |
2395 | 2394 | ||
2396 | static struct pci_driver rme96_driver = { | 2395 | static struct pci_driver rme96_driver = { |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 94084cdb130c..4f255dfee450 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -5412,7 +5412,6 @@ static int snd_hdsp_probe(struct pci_dev *pci, | |||
5412 | static void snd_hdsp_remove(struct pci_dev *pci) | 5412 | static void snd_hdsp_remove(struct pci_dev *pci) |
5413 | { | 5413 | { |
5414 | snd_card_free(pci_get_drvdata(pci)); | 5414 | snd_card_free(pci_get_drvdata(pci)); |
5415 | pci_set_drvdata(pci, NULL); | ||
5416 | } | 5415 | } |
5417 | 5416 | ||
5418 | static struct pci_driver hdsp_driver = { | 5417 | static struct pci_driver hdsp_driver = { |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 9ea05e956474..bd501931ee23 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -400,8 +400,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
400 | 400 | ||
401 | #define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */ | 401 | #define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */ |
402 | #define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */ | 402 | #define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */ |
403 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ | 403 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */ |
404 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ | 404 | #define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */ |
405 | 405 | ||
406 | #define HDSPM_SyncRef0 0x10000 /* Sync Reference */ | 406 | #define HDSPM_SyncRef0 0x10000 /* Sync Reference */ |
407 | #define HDSPM_SyncRef1 0x20000 | 407 | #define HDSPM_SyncRef1 0x20000 |
@@ -412,13 +412,17 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
412 | 412 | ||
413 | #define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync) | 413 | #define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync) |
414 | 414 | ||
415 | #define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2) | 415 | #define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\ |
416 | HDSPM_wc_freq3) | ||
416 | #define HDSPM_wcFreq32 (HDSPM_wc_freq0) | 417 | #define HDSPM_wcFreq32 (HDSPM_wc_freq0) |
417 | #define HDSPM_wcFreq44_1 (HDSPM_wc_freq1) | 418 | #define HDSPM_wcFreq44_1 (HDSPM_wc_freq1) |
418 | #define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1) | 419 | #define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1) |
419 | #define HDSPM_wcFreq64 (HDSPM_wc_freq2) | 420 | #define HDSPM_wcFreq64 (HDSPM_wc_freq2) |
420 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) | 421 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) |
421 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | 422 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) |
423 | #define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2) | ||
424 | #define HDSPM_wcFreq176_4 (HDSPM_wc_freq3) | ||
425 | #define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3) | ||
422 | 426 | ||
423 | #define HDSPM_status1_F_0 0x0400000 | 427 | #define HDSPM_status1_F_0 0x0400000 |
424 | #define HDSPM_status1_F_1 0x0800000 | 428 | #define HDSPM_status1_F_1 0x0800000 |
@@ -1087,6 +1091,26 @@ static int hdspm_round_frequency(int rate) | |||
1087 | return 48000; | 1091 | return 48000; |
1088 | } | 1092 | } |
1089 | 1093 | ||
1094 | /* QS and DS rates normally can not be detected | ||
1095 | * automatically by the card. Only exception is MADI | ||
1096 | * in 96k frame mode. | ||
1097 | * | ||
1098 | * So if we read SS values (32 .. 48k), check for | ||
1099 | * user-provided DS/QS bits in the control register | ||
1100 | * and multiply the base frequency accordingly. | ||
1101 | */ | ||
1102 | static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate) | ||
1103 | { | ||
1104 | if (rate <= 48000) { | ||
1105 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
1106 | return rate * 4; | ||
1107 | else if (hdspm->control_register & | ||
1108 | HDSPM_DoubleSpeed) | ||
1109 | return rate * 2; | ||
1110 | }; | ||
1111 | return rate; | ||
1112 | } | ||
1113 | |||
1090 | static int hdspm_tco_sync_check(struct hdspm *hdspm); | 1114 | static int hdspm_tco_sync_check(struct hdspm *hdspm); |
1091 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm); | 1115 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm); |
1092 | 1116 | ||
@@ -1181,6 +1205,15 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1181 | case HDSPM_wcFreq96: | 1205 | case HDSPM_wcFreq96: |
1182 | rate = 96000; | 1206 | rate = 96000; |
1183 | break; | 1207 | break; |
1208 | case HDSPM_wcFreq128: | ||
1209 | rate = 128000; | ||
1210 | break; | ||
1211 | case HDSPM_wcFreq176_4: | ||
1212 | rate = 176400; | ||
1213 | break; | ||
1214 | case HDSPM_wcFreq192: | ||
1215 | rate = 192000; | ||
1216 | break; | ||
1184 | default: | 1217 | default: |
1185 | rate = 0; | 1218 | rate = 0; |
1186 | break; | 1219 | break; |
@@ -1192,7 +1225,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1192 | */ | 1225 | */ |
1193 | if (rate != 0 && | 1226 | if (rate != 0 && |
1194 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 1227 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
1195 | return rate; | 1228 | return hdspm_rate_multiplier(hdspm, rate); |
1196 | 1229 | ||
1197 | /* maybe a madi input (which is taken if sel sync is madi) */ | 1230 | /* maybe a madi input (which is taken if sel sync is madi) */ |
1198 | if (status & HDSPM_madiLock) { | 1231 | if (status & HDSPM_madiLock) { |
@@ -1255,21 +1288,8 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1255 | } | 1288 | } |
1256 | } | 1289 | } |
1257 | 1290 | ||
1258 | /* QS and DS rates normally can not be detected | 1291 | rate = hdspm_rate_multiplier(hdspm, rate); |
1259 | * automatically by the card. Only exception is MADI | 1292 | |
1260 | * in 96k frame mode. | ||
1261 | * | ||
1262 | * So if we read SS values (32 .. 48k), check for | ||
1263 | * user-provided DS/QS bits in the control register | ||
1264 | * and multiply the base frequency accordingly. | ||
1265 | */ | ||
1266 | if (rate <= 48000) { | ||
1267 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
1268 | rate *= 4; | ||
1269 | else if (hdspm->control_register & | ||
1270 | HDSPM_DoubleSpeed) | ||
1271 | rate *= 2; | ||
1272 | } | ||
1273 | break; | 1293 | break; |
1274 | } | 1294 | } |
1275 | 1295 | ||
@@ -6737,7 +6757,6 @@ static int snd_hdspm_probe(struct pci_dev *pci, | |||
6737 | static void snd_hdspm_remove(struct pci_dev *pci) | 6757 | static void snd_hdspm_remove(struct pci_dev *pci) |
6738 | { | 6758 | { |
6739 | snd_card_free(pci_get_drvdata(pci)); | 6759 | snd_card_free(pci_get_drvdata(pci)); |
6740 | pci_set_drvdata(pci, NULL); | ||
6741 | } | 6760 | } |
6742 | 6761 | ||
6743 | static struct pci_driver hdspm_driver = { | 6762 | static struct pci_driver hdspm_driver = { |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 773a67fff4cd..b96d9e1adf6d 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -2628,7 +2628,6 @@ static int snd_rme9652_probe(struct pci_dev *pci, | |||
2628 | static void snd_rme9652_remove(struct pci_dev *pci) | 2628 | static void snd_rme9652_remove(struct pci_dev *pci) |
2629 | { | 2629 | { |
2630 | snd_card_free(pci_get_drvdata(pci)); | 2630 | snd_card_free(pci_get_drvdata(pci)); |
2631 | pci_set_drvdata(pci, NULL); | ||
2632 | } | 2631 | } |
2633 | 2632 | ||
2634 | static struct pci_driver rme9652_driver = { | 2633 | static struct pci_driver rme9652_driver = { |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 748e82d4d257..e413b4e2c819 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1482,7 +1482,6 @@ error_out: | |||
1482 | static void snd_sis7019_remove(struct pci_dev *pci) | 1482 | static void snd_sis7019_remove(struct pci_dev *pci) |
1483 | { | 1483 | { |
1484 | snd_card_free(pci_get_drvdata(pci)); | 1484 | snd_card_free(pci_get_drvdata(pci)); |
1485 | pci_set_drvdata(pci, NULL); | ||
1486 | } | 1485 | } |
1487 | 1486 | ||
1488 | static struct pci_driver sis7019_driver = { | 1487 | static struct pci_driver sis7019_driver = { |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index a2e7686e7ae3..2a46bf98af30 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1528,7 +1528,6 @@ static int snd_sonic_probe(struct pci_dev *pci, | |||
1528 | static void snd_sonic_remove(struct pci_dev *pci) | 1528 | static void snd_sonic_remove(struct pci_dev *pci) |
1529 | { | 1529 | { |
1530 | snd_card_free(pci_get_drvdata(pci)); | 1530 | snd_card_free(pci_get_drvdata(pci)); |
1531 | pci_set_drvdata(pci, NULL); | ||
1532 | } | 1531 | } |
1533 | 1532 | ||
1534 | static struct pci_driver sonicvibes_driver = { | 1533 | static struct pci_driver sonicvibes_driver = { |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 1aefd6204a63..b3b588bc94c3 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -169,7 +169,6 @@ static int snd_trident_probe(struct pci_dev *pci, | |||
169 | static void snd_trident_remove(struct pci_dev *pci) | 169 | static void snd_trident_remove(struct pci_dev *pci) |
170 | { | 170 | { |
171 | snd_card_free(pci_get_drvdata(pci)); | 171 | snd_card_free(pci_get_drvdata(pci)); |
172 | pci_set_drvdata(pci, NULL); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | static struct pci_driver trident_driver = { | 174 | static struct pci_driver trident_driver = { |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index d756a3562706..3c511d0caf9e 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2646,7 +2646,6 @@ static int snd_via82xx_probe(struct pci_dev *pci, | |||
2646 | static void snd_via82xx_remove(struct pci_dev *pci) | 2646 | static void snd_via82xx_remove(struct pci_dev *pci) |
2647 | { | 2647 | { |
2648 | snd_card_free(pci_get_drvdata(pci)); | 2648 | snd_card_free(pci_get_drvdata(pci)); |
2649 | pci_set_drvdata(pci, NULL); | ||
2650 | } | 2649 | } |
2651 | 2650 | ||
2652 | static struct pci_driver via82xx_driver = { | 2651 | static struct pci_driver via82xx_driver = { |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 4f5fd80b7e56..ca190283cbd7 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -1227,7 +1227,6 @@ static int snd_via82xx_probe(struct pci_dev *pci, | |||
1227 | static void snd_via82xx_remove(struct pci_dev *pci) | 1227 | static void snd_via82xx_remove(struct pci_dev *pci) |
1228 | { | 1228 | { |
1229 | snd_card_free(pci_get_drvdata(pci)); | 1229 | snd_card_free(pci_get_drvdata(pci)); |
1230 | pci_set_drvdata(pci, NULL); | ||
1231 | } | 1230 | } |
1232 | 1231 | ||
1233 | static struct pci_driver via82xx_modem_driver = { | 1232 | static struct pci_driver via82xx_modem_driver = { |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index e2f1ab37e154..ab8a9b1bfb8e 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -254,7 +254,6 @@ static int snd_vx222_probe(struct pci_dev *pci, | |||
254 | static void snd_vx222_remove(struct pci_dev *pci) | 254 | static void snd_vx222_remove(struct pci_dev *pci) |
255 | { | 255 | { |
256 | snd_card_free(pci_get_drvdata(pci)); | 256 | snd_card_free(pci_get_drvdata(pci)); |
257 | pci_set_drvdata(pci, NULL); | ||
258 | } | 257 | } |
259 | 258 | ||
260 | #ifdef CONFIG_PM_SLEEP | 259 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 01c49655a3c1..e8932b2e4a5d 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -347,7 +347,6 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
347 | static void snd_card_ymfpci_remove(struct pci_dev *pci) | 347 | static void snd_card_ymfpci_remove(struct pci_dev *pci) |
348 | { | 348 | { |
349 | snd_card_free(pci_get_drvdata(pci)); | 349 | snd_card_free(pci_get_drvdata(pci)); |
350 | pci_set_drvdata(pci, NULL); | ||
351 | } | 350 | } |
352 | 351 | ||
353 | static struct pci_driver ymfpci_driver = { | 352 | static struct pci_driver ymfpci_driver = { |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 22056c50fe39..d591c154fc58 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -2258,7 +2258,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) | |||
2258 | /* FIXME: temporarily disabled, otherwise we cannot fire up | 2258 | /* FIXME: temporarily disabled, otherwise we cannot fire up |
2259 | * the chip again unless reboot. ACPI bug? | 2259 | * the chip again unless reboot. ACPI bug? |
2260 | */ | 2260 | */ |
2261 | pci_set_power_state(chip->pci, 3); | 2261 | pci_set_power_state(chip->pci, PCI_D3hot); |
2262 | #endif | 2262 | #endif |
2263 | 2263 | ||
2264 | #ifdef CONFIG_PM_SLEEP | 2264 | #ifdef CONFIG_PM_SLEEP |
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 09fc848d32ec..8abb521b4814 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c | |||
@@ -139,7 +139,6 @@ __error: | |||
139 | static int snd_pmac_remove(struct platform_device *devptr) | 139 | static int snd_pmac_remove(struct platform_device *devptr) |
140 | { | 140 | { |
141 | snd_card_free(platform_get_drvdata(devptr)); | 141 | snd_card_free(platform_get_drvdata(devptr)); |
142 | platform_set_drvdata(devptr, NULL); | ||
143 | return 0; | 142 | return 0; |
144 | } | 143 | } |
145 | 144 | ||
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index e59a73a9bc42..78a369785a9e 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -598,7 +598,6 @@ static int snd_aica_remove(struct platform_device *devptr) | |||
598 | return -ENODEV; | 598 | return -ENODEV; |
599 | snd_card_free(dreamcastcard->card); | 599 | snd_card_free(dreamcastcard->card); |
600 | kfree(dreamcastcard); | 600 | kfree(dreamcastcard); |
601 | platform_set_drvdata(devptr, NULL); | ||
602 | return 0; | 601 | return 0; |
603 | } | 602 | } |
604 | 603 | ||
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index e68c4fc91a03..7c9422c4fc0f 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c | |||
@@ -290,8 +290,6 @@ static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) | |||
290 | static int snd_sh_dac_remove(struct platform_device *devptr) | 290 | static int snd_sh_dac_remove(struct platform_device *devptr) |
291 | { | 291 | { |
292 | snd_card_free(platform_get_drvdata(devptr)); | 292 | snd_card_free(platform_get_drvdata(devptr)); |
293 | platform_set_drvdata(devptr, NULL); | ||
294 | |||
295 | return 0; | 293 | return 0; |
296 | } | 294 | } |
297 | 295 | ||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 9e675c76436c..45eeaa9f7fec 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -51,6 +51,7 @@ source "sound/soc/pxa/Kconfig" | |||
51 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
52 | source "sound/soc/s6000/Kconfig" | 52 | source "sound/soc/s6000/Kconfig" |
53 | source "sound/soc/sh/Kconfig" | 53 | source "sound/soc/sh/Kconfig" |
54 | source "sound/soc/spear/Kconfig" | ||
54 | source "sound/soc/tegra/Kconfig" | 55 | source "sound/soc/tegra/Kconfig" |
55 | source "sound/soc/txx9/Kconfig" | 56 | source "sound/soc/txx9/Kconfig" |
56 | source "sound/soc/ux500/Kconfig" | 57 | source "sound/soc/ux500/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 197b6ae54c8d..bc0261476d7a 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -29,6 +29,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ | |||
29 | obj-$(CONFIG_SND_SOC) += samsung/ | 29 | obj-$(CONFIG_SND_SOC) += samsung/ |
30 | obj-$(CONFIG_SND_SOC) += s6000/ | 30 | obj-$(CONFIG_SND_SOC) += s6000/ |
31 | obj-$(CONFIG_SND_SOC) += sh/ | 31 | obj-$(CONFIG_SND_SOC) += sh/ |
32 | obj-$(CONFIG_SND_SOC) += spear/ | ||
32 | obj-$(CONFIG_SND_SOC) += tegra/ | 33 | obj-$(CONFIG_SND_SOC) += tegra/ |
33 | obj-$(CONFIG_SND_SOC) += txx9/ | 34 | obj-$(CONFIG_SND_SOC) += txx9/ |
34 | obj-$(CONFIG_SND_SOC) += ux500/ | 35 | obj-$(CONFIG_SND_SOC) += ux500/ |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 2d6fbd0125b9..802717eccbd0 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -38,8 +38,6 @@ | |||
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
40 | 40 | ||
41 | #include <linux/pinctrl/consumer.h> | ||
42 | |||
43 | #include <linux/atmel-ssc.h> | 41 | #include <linux/atmel-ssc.h> |
44 | 42 | ||
45 | #include <sound/core.h> | 43 | #include <sound/core.h> |
@@ -203,15 +201,8 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) | |||
203 | struct device_node *codec_np, *cpu_np; | 201 | struct device_node *codec_np, *cpu_np; |
204 | struct clk *pllb; | 202 | struct clk *pllb; |
205 | struct snd_soc_card *card = &snd_soc_at91sam9g20ek; | 203 | struct snd_soc_card *card = &snd_soc_at91sam9g20ek; |
206 | struct pinctrl *pinctrl; | ||
207 | int ret; | 204 | int ret; |
208 | 205 | ||
209 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
210 | if (IS_ERR(pinctrl)) { | ||
211 | dev_err(&pdev->dev, "Failed to request pinctrl for mck\n"); | ||
212 | return PTR_ERR(pinctrl); | ||
213 | } | ||
214 | |||
215 | if (!np) { | 206 | if (!np) { |
216 | if (!(machine_is_at91sam9g20ek() || | 207 | if (!(machine_is_at91sam9g20ek() || |
217 | machine_is_at91sam9g20ek_2mmc())) | 208 | machine_is_at91sam9g20ek_2mmc())) |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 16b88f5c26e2..54f74f8cbb75 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -56,6 +56,23 @@ config SND_SOC_BFIN_EVAL_ADAV80X | |||
56 | Note: This driver assumes that the ADAV80X digital record and playback | 56 | Note: This driver assumes that the ADAV80X digital record and playback |
57 | interfaces are connected to the first SPORT port on the BF5XX board. | 57 | interfaces are connected to the first SPORT port on the BF5XX board. |
58 | 58 | ||
59 | config SND_BF5XX_SOC_AD1836 | ||
60 | tristate "SoC AD1836 Audio support for BF5xx" | ||
61 | depends on SND_BF5XX_I2S | ||
62 | select SND_BF5XX_SOC_I2S | ||
63 | select SND_SOC_AD1836 | ||
64 | help | ||
65 | Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. | ||
66 | |||
67 | config SND_BF5XX_SOC_AD193X | ||
68 | tristate "SoC AD193X Audio support for Blackfin" | ||
69 | depends on SND_BF5XX_I2S | ||
70 | select SND_BF5XX_SOC_I2S | ||
71 | select SND_SOC_AD193X | ||
72 | help | ||
73 | Say Y if you want to add support for AD193X codec on Blackfin. | ||
74 | This driver supports AD1936, AD1937, AD1938 and AD1939. | ||
75 | |||
59 | config SND_BF5XX_SOC_AD73311 | 76 | config SND_BF5XX_SOC_AD73311 |
60 | tristate "SoC AD73311 Audio support for Blackfin" | 77 | tristate "SoC AD73311 Audio support for Blackfin" |
61 | depends on SND_BF5XX_I2S | 78 | depends on SND_BF5XX_I2S |
@@ -72,33 +89,6 @@ config SND_BFIN_AD73311_SE | |||
72 | Enter the GPIO used to control AD73311's SE pin. Acceptable | 89 | Enter the GPIO used to control AD73311's SE pin. Acceptable |
73 | values are 0 to 7 | 90 | values are 0 to 7 |
74 | 91 | ||
75 | config SND_BF5XX_TDM | ||
76 | tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" | ||
77 | depends on (BLACKFIN && SND_SOC) | ||
78 | select SND_BF5XX_SOC_SPORT | ||
79 | help | ||
80 | Say Y or M if you want to add support for codecs attached to | ||
81 | the Blackfin SPORT (synchronous serial ports) interface in TDM | ||
82 | mode. | ||
83 | You will also need to select the audio interfaces to support below. | ||
84 | |||
85 | config SND_BF5XX_SOC_AD1836 | ||
86 | tristate "SoC AD1836 Audio support for BF5xx" | ||
87 | depends on SND_BF5XX_TDM | ||
88 | select SND_BF5XX_SOC_TDM | ||
89 | select SND_SOC_AD1836 | ||
90 | help | ||
91 | Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. | ||
92 | |||
93 | config SND_BF5XX_SOC_AD193X | ||
94 | tristate "SoC AD193X Audio support for Blackfin" | ||
95 | depends on SND_BF5XX_TDM | ||
96 | select SND_BF5XX_SOC_TDM | ||
97 | select SND_SOC_AD193X | ||
98 | help | ||
99 | Say Y if you want to add support for AD193X codec on Blackfin. | ||
100 | This driver supports AD1936, AD1937, AD1938 and AD1939. | ||
101 | |||
102 | config SND_BF5XX_AC97 | 92 | config SND_BF5XX_AC97 |
103 | tristate "SoC AC97 Audio for the ADI BF5xx chip" | 93 | tristate "SoC AC97 Audio for the ADI BF5xx chip" |
104 | depends on BLACKFIN | 94 | depends on BLACKFIN |
@@ -174,9 +164,6 @@ config SND_BF5XX_SOC_I2S | |||
174 | config SND_BF6XX_SOC_I2S | 164 | config SND_BF6XX_SOC_I2S |
175 | tristate | 165 | tristate |
176 | 166 | ||
177 | config SND_BF5XX_SOC_TDM | ||
178 | tristate | ||
179 | |||
180 | config SND_BF5XX_SOC_AC97 | 167 | config SND_BF5XX_SOC_AC97 |
181 | tristate | 168 | tristate |
182 | 169 | ||
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 6fea1f4cbee2..ad0a6e99bc5d 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile | |||
@@ -1,23 +1,19 @@ | |||
1 | # Blackfin Platform Support | 1 | # Blackfin Platform Support |
2 | snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o | 2 | snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o |
3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o | 3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o |
4 | snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o | ||
5 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o | 4 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o |
6 | snd-soc-bf6xx-sport-objs := bf6xx-sport.o | 5 | snd-soc-bf6xx-sport-objs := bf6xx-sport.o |
7 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o | 6 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o |
8 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o | 7 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o |
9 | snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o | 8 | snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o |
10 | snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o | ||
11 | 9 | ||
12 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o | 10 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o |
13 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o | 11 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o |
14 | obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o | ||
15 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o | 12 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o |
16 | obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o | 13 | obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o |
17 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o | 14 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o |
18 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o | 15 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o |
19 | obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o | 16 | obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o |
20 | obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o | ||
21 | 17 | ||
22 | # Blackfin Machine Support | 18 | # Blackfin Machine Support |
23 | snd-ad1836-objs := bf5xx-ad1836.o | 19 | snd-ad1836-objs := bf5xx-ad1836.o |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 7e2f36004a5a..53f84085bf1f 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -39,7 +39,6 @@ | |||
39 | 39 | ||
40 | #include <asm/dma.h> | 40 | #include <asm/dma.h> |
41 | 41 | ||
42 | #include "bf5xx-ac97-pcm.h" | ||
43 | #include "bf5xx-ac97.h" | 42 | #include "bf5xx-ac97.h" |
44 | #include "bf5xx-sport.h" | 43 | #include "bf5xx-sport.h" |
45 | 44 | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h deleted file mode 100644 index d324d5826a9b..000000000000 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/bf5xx-ac97-pcm.h -- ALSA PCM interface for the Blackfin | ||
3 | * | ||
4 | * Copyright 2007 Analog Device Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _BF5XX_AC97_PCM_H | ||
12 | #define _BF5XX_AC97_PCM_H | ||
13 | |||
14 | struct bf5xx_pcm_dma_params { | ||
15 | char *name; /* stream identifier */ | ||
16 | }; | ||
17 | |||
18 | struct bf5xx_gpio { | ||
19 | u32 sys; | ||
20 | u32 rx; | ||
21 | u32 tx; | ||
22 | u32 clk; | ||
23 | u32 frm; | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index c5af677ba49c..efb1daecd0dd 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -230,9 +230,9 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
230 | return 0; | 230 | return 0; |
231 | 231 | ||
232 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | 232 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) |
233 | ret = sport_set_multichannel(sport, 16, 0x3FF, 1); | 233 | ret = sport_set_multichannel(sport, 16, 0x3FF, 0x3FF, 1); |
234 | #else | 234 | #else |
235 | ret = sport_set_multichannel(sport, 16, 0x1F, 1); | 235 | ret = sport_set_multichannel(sport, 16, 0x1F, 0x1F, 1); |
236 | #endif | 236 | #endif |
237 | if (ret) { | 237 | if (ret) { |
238 | pr_err("SPORT is busy!\n"); | 238 | pr_err("SPORT is busy!\n"); |
@@ -311,9 +311,9 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
311 | 311 | ||
312 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 312 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
313 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | 313 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) |
314 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); | 314 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 0x3FF, 1); |
315 | #else | 315 | #else |
316 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); | 316 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 0x1F, 1); |
317 | #endif | 317 | #endif |
318 | if (ret) { | 318 | if (ret) { |
319 | pr_err("SPORT is busy!\n"); | 319 | pr_err("SPORT is busy!\n"); |
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d23f4b0ea54f..8fcfc4ec3a51 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -30,15 +30,10 @@ | |||
30 | 30 | ||
31 | #include "../codecs/ad1836.h" | 31 | #include "../codecs/ad1836.h" |
32 | 32 | ||
33 | #include "bf5xx-tdm-pcm.h" | ||
34 | #include "bf5xx-tdm.h" | ||
35 | |||
36 | static struct snd_soc_card bf5xx_ad1836; | 33 | static struct snd_soc_card bf5xx_ad1836; |
37 | 34 | ||
38 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | 35 | static int bf5xx_ad1836_init(struct snd_soc_pcm_runtime *rtd) |
39 | struct snd_pcm_hw_params *params) | ||
40 | { | 36 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 37 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
43 | unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; | 38 | unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; |
44 | int ret = 0; | 39 | int ret = 0; |
@@ -49,13 +44,13 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | |||
49 | if (ret < 0) | 44 | if (ret < 0) |
50 | return ret; | 45 | return ret; |
51 | 46 | ||
47 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32); | ||
48 | if (ret < 0) | ||
49 | return ret; | ||
50 | |||
52 | return 0; | 51 | return 0; |
53 | } | 52 | } |
54 | 53 | ||
55 | static struct snd_soc_ops bf5xx_ad1836_ops = { | ||
56 | .hw_params = bf5xx_ad1836_hw_params, | ||
57 | }; | ||
58 | |||
59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ | 54 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ |
60 | SND_SOC_DAIFMT_CBM_CFM) | 55 | SND_SOC_DAIFMT_CBM_CFM) |
61 | 56 | ||
@@ -63,9 +58,9 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai = { | |||
63 | .name = "ad1836", | 58 | .name = "ad1836", |
64 | .stream_name = "AD1836", | 59 | .stream_name = "AD1836", |
65 | .codec_dai_name = "ad1836-hifi", | 60 | .codec_dai_name = "ad1836-hifi", |
66 | .platform_name = "bfin-tdm-pcm-audio", | 61 | .platform_name = "bfin-i2s-pcm-audio", |
67 | .ops = &bf5xx_ad1836_ops, | ||
68 | .dai_fmt = BF5XX_AD1836_DAIFMT, | 62 | .dai_fmt = BF5XX_AD1836_DAIFMT, |
63 | .init = bf5xx_ad1836_init, | ||
69 | }; | 64 | }; |
70 | 65 | ||
71 | static struct snd_soc_card bf5xx_ad1836 = { | 66 | static struct snd_soc_card bf5xx_ad1836 = { |
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index 0e55e9f2a514..603ad1f2b9b9 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c | |||
@@ -39,30 +39,16 @@ | |||
39 | 39 | ||
40 | #include "../codecs/ad193x.h" | 40 | #include "../codecs/ad193x.h" |
41 | 41 | ||
42 | #include "bf5xx-tdm-pcm.h" | ||
43 | #include "bf5xx-tdm.h" | ||
44 | |||
45 | static struct snd_soc_card bf5xx_ad193x; | 42 | static struct snd_soc_card bf5xx_ad193x; |
46 | 43 | ||
47 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | 44 | static int bf5xx_ad193x_link_init(struct snd_soc_pcm_runtime *rtd) |
48 | struct snd_pcm_hw_params *params) | ||
49 | { | 45 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 46 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | unsigned int clk = 0; | 48 | int ret; |
54 | unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
55 | int ret = 0; | ||
56 | |||
57 | switch (params_rate(params)) { | ||
58 | case 48000: | ||
59 | clk = 24576000; | ||
60 | break; | ||
61 | } | ||
62 | 49 | ||
63 | /* set the codec system clock for DAC and ADC */ | 50 | /* set the codec system clock for DAC and ADC */ |
64 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, | 51 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); |
65 | SND_SOC_CLOCK_IN); | ||
66 | if (ret < 0) | 52 | if (ret < 0) |
67 | return ret; | 53 | return ret; |
68 | 54 | ||
@@ -71,9 +57,7 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
71 | if (ret < 0) | 57 | if (ret < 0) |
72 | return ret; | 58 | return ret; |
73 | 59 | ||
74 | /* set cpu DAI channel mapping */ | 60 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32); |
75 | ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map), | ||
76 | channel_map, ARRAY_SIZE(channel_map), channel_map); | ||
77 | if (ret < 0) | 61 | if (ret < 0) |
78 | return ret; | 62 | return ret; |
79 | 63 | ||
@@ -83,30 +67,26 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
83 | #define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ | 67 | #define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ |
84 | SND_SOC_DAIFMT_CBM_CFM) | 68 | SND_SOC_DAIFMT_CBM_CFM) |
85 | 69 | ||
86 | static struct snd_soc_ops bf5xx_ad193x_ops = { | ||
87 | .hw_params = bf5xx_ad193x_hw_params, | ||
88 | }; | ||
89 | |||
90 | static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { | 70 | static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { |
91 | { | 71 | { |
92 | .name = "ad193x", | 72 | .name = "ad193x", |
93 | .stream_name = "AD193X", | 73 | .stream_name = "AD193X", |
94 | .cpu_dai_name = "bfin-tdm.0", | 74 | .cpu_dai_name = "bfin-i2s.0", |
95 | .codec_dai_name ="ad193x-hifi", | 75 | .codec_dai_name ="ad193x-hifi", |
96 | .platform_name = "bfin-tdm-pcm-audio", | 76 | .platform_name = "bfin-i2s-pcm-audio", |
97 | .codec_name = "spi0.5", | 77 | .codec_name = "spi0.5", |
98 | .ops = &bf5xx_ad193x_ops, | ||
99 | .dai_fmt = BF5XX_AD193X_DAIFMT, | 78 | .dai_fmt = BF5XX_AD193X_DAIFMT, |
79 | .init = bf5xx_ad193x_link_init, | ||
100 | }, | 80 | }, |
101 | { | 81 | { |
102 | .name = "ad193x", | 82 | .name = "ad193x", |
103 | .stream_name = "AD193X", | 83 | .stream_name = "AD193X", |
104 | .cpu_dai_name = "bfin-tdm.1", | 84 | .cpu_dai_name = "bfin-i2s.1", |
105 | .codec_dai_name ="ad193x-hifi", | 85 | .codec_dai_name ="ad193x-hifi", |
106 | .platform_name = "bfin-tdm-pcm-audio", | 86 | .platform_name = "bfin-i2s-pcm-audio", |
107 | .codec_name = "spi0.5", | 87 | .codec_name = "spi0.5", |
108 | .ops = &bf5xx_ad193x_ops, | ||
109 | .dai_fmt = BF5XX_AD193X_DAIFMT, | 88 | .dai_fmt = BF5XX_AD193X_DAIFMT, |
89 | .init = bf5xx_ad193x_link_init, | ||
110 | }, | 90 | }, |
111 | }; | 91 | }; |
112 | 92 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index b30f88bbd703..3450e8f9080d 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -48,7 +48,6 @@ | |||
48 | 48 | ||
49 | #include "../codecs/ad1980.h" | 49 | #include "../codecs/ad1980.h" |
50 | 50 | ||
51 | #include "bf5xx-ac97-pcm.h" | ||
52 | #include "bf5xx-ac97.h" | 51 | #include "bf5xx-ac97.h" |
53 | 52 | ||
54 | static struct snd_soc_card bf5xx_board; | 53 | static struct snd_soc_card bf5xx_board; |
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 61cc91d4a028..786bbdd96e7c 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -45,7 +45,6 @@ | |||
45 | 45 | ||
46 | #include "../codecs/ad73311.h" | 46 | #include "../codecs/ad73311.h" |
47 | #include "bf5xx-sport.h" | 47 | #include "bf5xx-sport.h" |
48 | #include "bf5xx-i2s-pcm.h" | ||
49 | 48 | ||
50 | #if CONFIG_SND_BF5XX_SPORT_NUM == 0 | 49 | #if CONFIG_SND_BF5XX_SPORT_NUM == 0 |
51 | #define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 | 50 | #define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 262c1de364d8..9cb4a80df98e 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -39,8 +39,8 @@ | |||
39 | 39 | ||
40 | #include <asm/dma.h> | 40 | #include <asm/dma.h> |
41 | 41 | ||
42 | #include "bf5xx-i2s-pcm.h" | ||
43 | #include "bf5xx-sport.h" | 42 | #include "bf5xx-sport.h" |
43 | #include "bf5xx-i2s-pcm.h" | ||
44 | 44 | ||
45 | static void bf5xx_dma_irq(void *data) | 45 | static void bf5xx_dma_irq(void *data) |
46 | { | 46 | { |
@@ -50,7 +50,6 @@ static void bf5xx_dma_irq(void *data) | |||
50 | 50 | ||
51 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | 51 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { |
52 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 52 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
53 | SNDRV_PCM_INFO_MMAP | | ||
54 | SNDRV_PCM_INFO_MMAP_VALID | | 53 | SNDRV_PCM_INFO_MMAP_VALID | |
55 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | 54 | SNDRV_PCM_INFO_BLOCK_TRANSFER, |
56 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 55 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
@@ -67,10 +66,16 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | |||
67 | static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | 66 | static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, |
68 | struct snd_pcm_hw_params *params) | 67 | struct snd_pcm_hw_params *params) |
69 | { | 68 | { |
70 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max; | 69 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
71 | snd_pcm_lib_malloc_pages(substream, size); | 70 | unsigned int buffer_size = params_buffer_bytes(params); |
71 | struct bf5xx_i2s_pcm_data *dma_data; | ||
72 | 72 | ||
73 | return 0; | 73 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
74 | |||
75 | if (dma_data->tdm_mode) | ||
76 | buffer_size = buffer_size / params_channels(params) * 8; | ||
77 | |||
78 | return snd_pcm_lib_malloc_pages(substream, buffer_size); | ||
74 | } | 79 | } |
75 | 80 | ||
76 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | 81 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) |
@@ -82,9 +87,16 @@ static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
82 | 87 | ||
83 | static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | 88 | static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) |
84 | { | 89 | { |
90 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
85 | struct snd_pcm_runtime *runtime = substream->runtime; | 91 | struct snd_pcm_runtime *runtime = substream->runtime; |
86 | struct sport_device *sport = runtime->private_data; | 92 | struct sport_device *sport = runtime->private_data; |
87 | int period_bytes = frames_to_bytes(runtime, runtime->period_size); | 93 | int period_bytes = frames_to_bytes(runtime, runtime->period_size); |
94 | struct bf5xx_i2s_pcm_data *dma_data; | ||
95 | |||
96 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
97 | |||
98 | if (dma_data->tdm_mode) | ||
99 | period_bytes = period_bytes / runtime->channels * 8; | ||
88 | 100 | ||
89 | pr_debug("%s enter\n", __func__); | 101 | pr_debug("%s enter\n", __func__); |
90 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 102 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -131,10 +143,15 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
131 | 143 | ||
132 | static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | 144 | static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) |
133 | { | 145 | { |
146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
134 | struct snd_pcm_runtime *runtime = substream->runtime; | 147 | struct snd_pcm_runtime *runtime = substream->runtime; |
135 | struct sport_device *sport = runtime->private_data; | 148 | struct sport_device *sport = runtime->private_data; |
136 | unsigned int diff; | 149 | unsigned int diff; |
137 | snd_pcm_uframes_t frames; | 150 | snd_pcm_uframes_t frames; |
151 | struct bf5xx_i2s_pcm_data *dma_data; | ||
152 | |||
153 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
154 | |||
138 | pr_debug("%s enter\n", __func__); | 155 | pr_debug("%s enter\n", __func__); |
139 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 156 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
140 | diff = sport_curr_offset_tx(sport); | 157 | diff = sport_curr_offset_tx(sport); |
@@ -151,6 +168,8 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
151 | diff = 0; | 168 | diff = 0; |
152 | 169 | ||
153 | frames = bytes_to_frames(substream->runtime, diff); | 170 | frames = bytes_to_frames(substream->runtime, diff); |
171 | if (dma_data->tdm_mode) | ||
172 | frames = frames * runtime->channels / 8; | ||
154 | 173 | ||
155 | return frames; | 174 | return frames; |
156 | } | 175 | } |
@@ -162,11 +181,18 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
162 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | 181 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); |
163 | struct snd_pcm_runtime *runtime = substream->runtime; | 182 | struct snd_pcm_runtime *runtime = substream->runtime; |
164 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 183 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
184 | struct bf5xx_i2s_pcm_data *dma_data; | ||
165 | int ret; | 185 | int ret; |
166 | 186 | ||
187 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
188 | |||
167 | pr_debug("%s enter\n", __func__); | 189 | pr_debug("%s enter\n", __func__); |
168 | 190 | ||
169 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 191 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
192 | if (dma_data->tdm_mode) | ||
193 | runtime->hw.buffer_bytes_max /= 4; | ||
194 | else | ||
195 | runtime->hw.info |= SNDRV_PCM_INFO_MMAP; | ||
170 | 196 | ||
171 | ret = snd_pcm_hw_constraint_integer(runtime, | 197 | ret = snd_pcm_hw_constraint_integer(runtime, |
172 | SNDRV_PCM_HW_PARAM_PERIODS); | 198 | SNDRV_PCM_HW_PARAM_PERIODS); |
@@ -202,6 +228,88 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
202 | return 0 ; | 228 | return 0 ; |
203 | } | 229 | } |
204 | 230 | ||
231 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | ||
232 | snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) | ||
233 | { | ||
234 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
235 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
236 | unsigned int sample_size = runtime->sample_bits / 8; | ||
237 | struct bf5xx_i2s_pcm_data *dma_data; | ||
238 | unsigned int i; | ||
239 | void *src, *dst; | ||
240 | |||
241 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
242 | |||
243 | if (dma_data->tdm_mode) { | ||
244 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
245 | src = buf; | ||
246 | dst = runtime->dma_area; | ||
247 | dst += pos * sample_size * 8; | ||
248 | |||
249 | while (count--) { | ||
250 | for (i = 0; i < runtime->channels; i++) { | ||
251 | memcpy(dst + dma_data->map[i] * | ||
252 | sample_size, src, sample_size); | ||
253 | src += sample_size; | ||
254 | } | ||
255 | dst += 8 * sample_size; | ||
256 | } | ||
257 | } else { | ||
258 | src = runtime->dma_area; | ||
259 | src += pos * sample_size * 8; | ||
260 | dst = buf; | ||
261 | |||
262 | while (count--) { | ||
263 | for (i = 0; i < runtime->channels; i++) { | ||
264 | memcpy(dst, src + dma_data->map[i] * | ||
265 | sample_size, sample_size); | ||
266 | dst += sample_size; | ||
267 | } | ||
268 | src += 8 * sample_size; | ||
269 | } | ||
270 | } | ||
271 | } else { | ||
272 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
273 | src = buf; | ||
274 | dst = runtime->dma_area; | ||
275 | dst += frames_to_bytes(runtime, pos); | ||
276 | } else { | ||
277 | src = runtime->dma_area; | ||
278 | src += frames_to_bytes(runtime, pos); | ||
279 | dst = buf; | ||
280 | } | ||
281 | |||
282 | memcpy(dst, src, frames_to_bytes(runtime, count)); | ||
283 | } | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | ||
289 | int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) | ||
290 | { | ||
291 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
292 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
293 | unsigned int sample_size = runtime->sample_bits / 8; | ||
294 | void *buf = runtime->dma_area; | ||
295 | struct bf5xx_i2s_pcm_data *dma_data; | ||
296 | unsigned int offset, size; | ||
297 | |||
298 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
299 | |||
300 | if (dma_data->tdm_mode) { | ||
301 | offset = pos * 8 * sample_size; | ||
302 | size = count * 8 * sample_size; | ||
303 | } else { | ||
304 | offset = frames_to_bytes(runtime, pos); | ||
305 | size = frames_to_bytes(runtime, count); | ||
306 | } | ||
307 | |||
308 | snd_pcm_format_set_silence(runtime->format, buf + offset, size); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
205 | static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { | 313 | static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { |
206 | .open = bf5xx_pcm_open, | 314 | .open = bf5xx_pcm_open, |
207 | .ioctl = snd_pcm_lib_ioctl, | 315 | .ioctl = snd_pcm_lib_ioctl, |
@@ -211,57 +319,16 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { | |||
211 | .trigger = bf5xx_pcm_trigger, | 319 | .trigger = bf5xx_pcm_trigger, |
212 | .pointer = bf5xx_pcm_pointer, | 320 | .pointer = bf5xx_pcm_pointer, |
213 | .mmap = bf5xx_pcm_mmap, | 321 | .mmap = bf5xx_pcm_mmap, |
322 | .copy = bf5xx_pcm_copy, | ||
323 | .silence = bf5xx_pcm_silence, | ||
214 | }; | 324 | }; |
215 | 325 | ||
216 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
217 | { | ||
218 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
219 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
220 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max; | ||
221 | |||
222 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
223 | buf->dev.dev = pcm->card->dev; | ||
224 | buf->private_data = NULL; | ||
225 | buf->area = dma_alloc_coherent(pcm->card->dev, size, | ||
226 | &buf->addr, GFP_KERNEL); | ||
227 | if (!buf->area) { | ||
228 | pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | buf->bytes = size; | ||
232 | |||
233 | pr_debug("%s, area:%p, size:0x%08lx\n", __func__, | ||
234 | buf->area, buf->bytes); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
240 | { | ||
241 | struct snd_pcm_substream *substream; | ||
242 | struct snd_dma_buffer *buf; | ||
243 | int stream; | ||
244 | |||
245 | for (stream = 0; stream < 2; stream++) { | ||
246 | substream = pcm->streams[stream].substream; | ||
247 | if (!substream) | ||
248 | continue; | ||
249 | |||
250 | buf = &substream->dma_buffer; | ||
251 | if (!buf->area) | ||
252 | continue; | ||
253 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | ||
254 | buf->area = NULL; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 326 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
259 | 327 | ||
260 | static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) | 328 | static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) |
261 | { | 329 | { |
262 | struct snd_card *card = rtd->card->snd_card; | 330 | struct snd_card *card = rtd->card->snd_card; |
263 | struct snd_pcm *pcm = rtd->pcm; | 331 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max; |
264 | int ret = 0; | ||
265 | 332 | ||
266 | pr_debug("%s enter\n", __func__); | 333 | pr_debug("%s enter\n", __func__); |
267 | if (!card->dev->dma_mask) | 334 | if (!card->dev->dma_mask) |
@@ -269,27 +336,13 @@ static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) | |||
269 | if (!card->dev->coherent_dma_mask) | 336 | if (!card->dev->coherent_dma_mask) |
270 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 337 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
271 | 338 | ||
272 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | 339 | return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, |
273 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 340 | SNDRV_DMA_TYPE_DEV, card->dev, size, size); |
274 | SNDRV_PCM_STREAM_PLAYBACK); | ||
275 | if (ret) | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
280 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | ||
281 | SNDRV_PCM_STREAM_CAPTURE); | ||
282 | if (ret) | ||
283 | goto out; | ||
284 | } | ||
285 | out: | ||
286 | return ret; | ||
287 | } | 341 | } |
288 | 342 | ||
289 | static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { | 343 | static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { |
290 | .ops = &bf5xx_pcm_i2s_ops, | 344 | .ops = &bf5xx_pcm_i2s_ops, |
291 | .pcm_new = bf5xx_pcm_i2s_new, | 345 | .pcm_new = bf5xx_pcm_i2s_new, |
292 | .pcm_free = bf5xx_pcm_free_dma_buffers, | ||
293 | }; | 346 | }; |
294 | 347 | ||
295 | static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) | 348 | static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h index 0c2c5a68d4ff..1f0435249f88 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.h +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h | |||
@@ -1,26 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | * linux/sound/arm/bf5xx-i2s-pcm.h -- ALSA PCM interface for the Blackfin | ||
3 | * | ||
4 | * Copyright 2007 Analog Device Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 2 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 3 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 4 | * published by the Free Software Foundation. |
9 | */ | 5 | */ |
10 | 6 | ||
11 | #ifndef _BF5XX_I2S_PCM_H | 7 | #ifndef _BF5XX_TDM_PCM_H |
12 | #define _BF5XX_I2S_PCM_H | 8 | #define _BF5XX_TDM_PCM_H |
13 | 9 | ||
14 | struct bf5xx_pcm_dma_params { | 10 | #define BFIN_TDM_DAI_MAX_SLOTS 8 |
15 | char *name; /* stream identifier */ | ||
16 | }; | ||
17 | 11 | ||
18 | struct bf5xx_gpio { | 12 | struct bf5xx_i2s_pcm_data { |
19 | u32 sys; | 13 | unsigned int map[BFIN_TDM_DAI_MAX_SLOTS]; |
20 | u32 rx; | 14 | bool tdm_mode; |
21 | u32 tx; | ||
22 | u32 clk; | ||
23 | u32 frm; | ||
24 | }; | 15 | }; |
25 | 16 | ||
26 | #endif | 17 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index dd0c2a4f83a3..9a174fc47d39 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
43 | 43 | ||
44 | #include "bf5xx-sport.h" | 44 | #include "bf5xx-sport.h" |
45 | #include "bf5xx-i2s-pcm.h" | ||
45 | 46 | ||
46 | struct bf5xx_i2s_port { | 47 | struct bf5xx_i2s_port { |
47 | u16 tcr1; | 48 | u16 tcr1; |
@@ -49,6 +50,13 @@ struct bf5xx_i2s_port { | |||
49 | u16 tcr2; | 50 | u16 tcr2; |
50 | u16 rcr2; | 51 | u16 rcr2; |
51 | int configured; | 52 | int configured; |
53 | |||
54 | unsigned int slots; | ||
55 | unsigned int tx_mask; | ||
56 | unsigned int rx_mask; | ||
57 | |||
58 | struct bf5xx_i2s_pcm_data tx_dma_data; | ||
59 | struct bf5xx_i2s_pcm_data rx_dma_data; | ||
52 | }; | 60 | }; |
53 | 61 | ||
54 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 62 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
@@ -74,7 +82,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
74 | ret = -EINVAL; | 82 | ret = -EINVAL; |
75 | break; | 83 | break; |
76 | default: | 84 | default: |
77 | printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); | 85 | dev_err(cpu_dai->dev, "%s: Unknown DAI format type\n", |
86 | __func__); | ||
78 | ret = -EINVAL; | 87 | ret = -EINVAL; |
79 | break; | 88 | break; |
80 | } | 89 | } |
@@ -88,7 +97,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
88 | ret = -EINVAL; | 97 | ret = -EINVAL; |
89 | break; | 98 | break; |
90 | default: | 99 | default: |
91 | printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); | 100 | dev_err(cpu_dai->dev, "%s: Unknown DAI master type\n", |
101 | __func__); | ||
92 | ret = -EINVAL; | 102 | ret = -EINVAL; |
93 | break; | 103 | break; |
94 | } | 104 | } |
@@ -141,14 +151,14 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
141 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, | 151 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
142 | bf5xx_i2s->rcr2, 0, 0); | 152 | bf5xx_i2s->rcr2, 0, 0); |
143 | if (ret) { | 153 | if (ret) { |
144 | pr_err("SPORT is busy!\n"); | 154 | dev_err(dai->dev, "SPORT is busy!\n"); |
145 | return -EBUSY; | 155 | return -EBUSY; |
146 | } | 156 | } |
147 | 157 | ||
148 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, | 158 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
149 | bf5xx_i2s->tcr2, 0, 0); | 159 | bf5xx_i2s->tcr2, 0, 0); |
150 | if (ret) { | 160 | if (ret) { |
151 | pr_err("SPORT is busy!\n"); | 161 | dev_err(dai->dev, "SPORT is busy!\n"); |
152 | return -EBUSY; | 162 | return -EBUSY; |
153 | } | 163 | } |
154 | } | 164 | } |
@@ -162,18 +172,76 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
162 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | 172 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); |
163 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | 173 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; |
164 | 174 | ||
165 | pr_debug("%s enter\n", __func__); | 175 | dev_dbg(dai->dev, "%s enter\n", __func__); |
166 | /* No active stream, SPORT is allowed to be configured again. */ | 176 | /* No active stream, SPORT is allowed to be configured again. */ |
167 | if (!dai->active) | 177 | if (!dai->active) |
168 | bf5xx_i2s->configured = 0; | 178 | bf5xx_i2s->configured = 0; |
169 | } | 179 | } |
170 | 180 | ||
181 | static int bf5xx_i2s_set_channel_map(struct snd_soc_dai *dai, | ||
182 | unsigned int tx_num, unsigned int *tx_slot, | ||
183 | unsigned int rx_num, unsigned int *rx_slot) | ||
184 | { | ||
185 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
186 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
187 | unsigned int tx_mapped = 0, rx_mapped = 0; | ||
188 | unsigned int slot; | ||
189 | int i; | ||
190 | |||
191 | if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) || | ||
192 | (rx_num > BFIN_TDM_DAI_MAX_SLOTS)) | ||
193 | return -EINVAL; | ||
194 | |||
195 | for (i = 0; i < tx_num; i++) { | ||
196 | slot = tx_slot[i]; | ||
197 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | ||
198 | (!(tx_mapped & (1 << slot)))) { | ||
199 | bf5xx_i2s->tx_dma_data.map[i] = slot; | ||
200 | tx_mapped |= 1 << slot; | ||
201 | } else | ||
202 | return -EINVAL; | ||
203 | } | ||
204 | for (i = 0; i < rx_num; i++) { | ||
205 | slot = rx_slot[i]; | ||
206 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | ||
207 | (!(rx_mapped & (1 << slot)))) { | ||
208 | bf5xx_i2s->rx_dma_data.map[i] = slot; | ||
209 | rx_mapped |= 1 << slot; | ||
210 | } else | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int bf5xx_i2s_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
218 | unsigned int rx_mask, int slots, int width) | ||
219 | { | ||
220 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
221 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
222 | |||
223 | if (slots % 8 != 0 || slots > 8) | ||
224 | return -EINVAL; | ||
225 | |||
226 | if (width != 32) | ||
227 | return -EINVAL; | ||
228 | |||
229 | bf5xx_i2s->slots = slots; | ||
230 | bf5xx_i2s->tx_mask = tx_mask; | ||
231 | bf5xx_i2s->rx_mask = rx_mask; | ||
232 | |||
233 | bf5xx_i2s->tx_dma_data.tdm_mode = slots != 0; | ||
234 | bf5xx_i2s->rx_dma_data.tdm_mode = slots != 0; | ||
235 | |||
236 | return sport_set_multichannel(sport_handle, slots, tx_mask, rx_mask, 0); | ||
237 | } | ||
238 | |||
171 | #ifdef CONFIG_PM | 239 | #ifdef CONFIG_PM |
172 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | 240 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) |
173 | { | 241 | { |
174 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | 242 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); |
175 | 243 | ||
176 | pr_debug("%s : sport %d\n", __func__, dai->id); | 244 | dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id); |
177 | 245 | ||
178 | if (dai->capture_active) | 246 | if (dai->capture_active) |
179 | sport_rx_stop(sport_handle); | 247 | sport_rx_stop(sport_handle); |
@@ -188,23 +256,24 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | |||
188 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | 256 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; |
189 | int ret; | 257 | int ret; |
190 | 258 | ||
191 | pr_debug("%s : sport %d\n", __func__, dai->id); | 259 | dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id); |
192 | 260 | ||
193 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, | 261 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
194 | bf5xx_i2s->rcr2, 0, 0); | 262 | bf5xx_i2s->rcr2, 0, 0); |
195 | if (ret) { | 263 | if (ret) { |
196 | pr_err("SPORT is busy!\n"); | 264 | dev_err(dai->dev, "SPORT is busy!\n"); |
197 | return -EBUSY; | 265 | return -EBUSY; |
198 | } | 266 | } |
199 | 267 | ||
200 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, | 268 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
201 | bf5xx_i2s->tcr2, 0, 0); | 269 | bf5xx_i2s->tcr2, 0, 0); |
202 | if (ret) { | 270 | if (ret) { |
203 | pr_err("SPORT is busy!\n"); | 271 | dev_err(dai->dev, "SPORT is busy!\n"); |
204 | return -EBUSY; | 272 | return -EBUSY; |
205 | } | 273 | } |
206 | 274 | ||
207 | return 0; | 275 | return sport_set_multichannel(sport_handle, bf5xx_i2s->slots, |
276 | bf5xx_i2s->tx_mask, bf5xx_i2s->rx_mask, 0); | ||
208 | } | 277 | } |
209 | 278 | ||
210 | #else | 279 | #else |
@@ -212,6 +281,23 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | |||
212 | #define bf5xx_i2s_resume NULL | 281 | #define bf5xx_i2s_resume NULL |
213 | #endif | 282 | #endif |
214 | 283 | ||
284 | static int bf5xx_i2s_dai_probe(struct snd_soc_dai *dai) | ||
285 | { | ||
286 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
287 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
288 | unsigned int i; | ||
289 | |||
290 | for (i = 0; i < BFIN_TDM_DAI_MAX_SLOTS; i++) { | ||
291 | bf5xx_i2s->tx_dma_data.map[i] = i; | ||
292 | bf5xx_i2s->rx_dma_data.map[i] = i; | ||
293 | } | ||
294 | |||
295 | dai->playback_dma_data = &bf5xx_i2s->tx_dma_data; | ||
296 | dai->capture_dma_data = &bf5xx_i2s->rx_dma_data; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
215 | #define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 301 | #define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
216 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | 302 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ |
217 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | 303 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ |
@@ -224,22 +310,25 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | |||
224 | SNDRV_PCM_FMTBIT_S32_LE) | 310 | SNDRV_PCM_FMTBIT_S32_LE) |
225 | 311 | ||
226 | static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | 312 | static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { |
227 | .shutdown = bf5xx_i2s_shutdown, | 313 | .shutdown = bf5xx_i2s_shutdown, |
228 | .hw_params = bf5xx_i2s_hw_params, | 314 | .hw_params = bf5xx_i2s_hw_params, |
229 | .set_fmt = bf5xx_i2s_set_dai_fmt, | 315 | .set_fmt = bf5xx_i2s_set_dai_fmt, |
316 | .set_tdm_slot = bf5xx_i2s_set_tdm_slot, | ||
317 | .set_channel_map = bf5xx_i2s_set_channel_map, | ||
230 | }; | 318 | }; |
231 | 319 | ||
232 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { | 320 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { |
321 | .probe = bf5xx_i2s_dai_probe, | ||
233 | .suspend = bf5xx_i2s_suspend, | 322 | .suspend = bf5xx_i2s_suspend, |
234 | .resume = bf5xx_i2s_resume, | 323 | .resume = bf5xx_i2s_resume, |
235 | .playback = { | 324 | .playback = { |
236 | .channels_min = 1, | 325 | .channels_min = 2, |
237 | .channels_max = 2, | 326 | .channels_max = 8, |
238 | .rates = BF5XX_I2S_RATES, | 327 | .rates = BF5XX_I2S_RATES, |
239 | .formats = BF5XX_I2S_FORMATS,}, | 328 | .formats = BF5XX_I2S_FORMATS,}, |
240 | .capture = { | 329 | .capture = { |
241 | .channels_min = 1, | 330 | .channels_min = 2, |
242 | .channels_max = 2, | 331 | .channels_max = 8, |
243 | .rates = BF5XX_I2S_RATES, | 332 | .rates = BF5XX_I2S_RATES, |
244 | .formats = BF5XX_I2S_FORMATS,}, | 333 | .formats = BF5XX_I2S_FORMATS,}, |
245 | .ops = &bf5xx_i2s_dai_ops, | 334 | .ops = &bf5xx_i2s_dai_ops, |
@@ -255,7 +344,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev) | |||
255 | int ret; | 344 | int ret; |
256 | 345 | ||
257 | /* configure SPORT for I2S */ | 346 | /* configure SPORT for I2S */ |
258 | sport_handle = sport_init(pdev, 4, 2 * sizeof(u32), | 347 | sport_handle = sport_init(pdev, 4, 8 * sizeof(u32), |
259 | sizeof(struct bf5xx_i2s_port)); | 348 | sizeof(struct bf5xx_i2s_port)); |
260 | if (!sport_handle) | 349 | if (!sport_handle) |
261 | return -ENODEV; | 350 | return -ENODEV; |
@@ -264,7 +353,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev) | |||
264 | ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component, | 353 | ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component, |
265 | &bf5xx_i2s_dai, 1); | 354 | &bf5xx_i2s_dai, 1); |
266 | if (ret) { | 355 | if (ret) { |
267 | pr_err("Failed to register DAI: %d\n", ret); | 356 | dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); |
268 | sport_done(sport_handle); | 357 | sport_done(sport_handle); |
269 | return ret; | 358 | return ret; |
270 | } | 359 | } |
@@ -276,7 +365,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev) | |||
276 | { | 365 | { |
277 | struct sport_device *sport_handle = platform_get_drvdata(pdev); | 366 | struct sport_device *sport_handle = platform_get_drvdata(pdev); |
278 | 367 | ||
279 | pr_debug("%s enter\n", __func__); | 368 | dev_dbg(&pdev->dev, "%s enter\n", __func__); |
280 | 369 | ||
281 | snd_soc_unregister_component(&pdev->dev); | 370 | snd_soc_unregister_component(&pdev->dev); |
282 | sport_done(sport_handle); | 371 | sport_done(sport_handle); |
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 2fd9f2a06968..695351241db8 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c | |||
@@ -46,10 +46,10 @@ | |||
46 | /* note: multichannel is in units of 8 channels, | 46 | /* note: multichannel is in units of 8 channels, |
47 | * tdm_count is # channels NOT / 8 ! */ | 47 | * tdm_count is # channels NOT / 8 ! */ |
48 | int sport_set_multichannel(struct sport_device *sport, | 48 | int sport_set_multichannel(struct sport_device *sport, |
49 | int tdm_count, u32 mask, int packed) | 49 | int tdm_count, u32 tx_mask, u32 rx_mask, int packed) |
50 | { | 50 | { |
51 | pr_debug("%s tdm_count=%d mask:0x%08x packed=%d\n", __func__, | 51 | pr_debug("%s tdm_count=%d tx_mask:0x%08x rx_mask:0x%08x packed=%d\n", |
52 | tdm_count, mask, packed); | 52 | __func__, tdm_count, tx_mask, rx_mask, packed); |
53 | 53 | ||
54 | if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) | 54 | if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) |
55 | return -EBUSY; | 55 | return -EBUSY; |
@@ -65,8 +65,8 @@ int sport_set_multichannel(struct sport_device *sport, | |||
65 | sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \ | 65 | sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \ |
66 | (packed ? (MCDTXPE|MCDRXPE) : 0); | 66 | (packed ? (MCDTXPE|MCDRXPE) : 0); |
67 | 67 | ||
68 | sport->regs->mtcs0 = mask; | 68 | sport->regs->mtcs0 = tx_mask; |
69 | sport->regs->mrcs0 = mask; | 69 | sport->regs->mrcs0 = rx_mask; |
70 | sport->regs->mtcs1 = 0; | 70 | sport->regs->mtcs1 = 0; |
71 | sport->regs->mrcs1 = 0; | 71 | sport->regs->mrcs1 = 0; |
72 | sport->regs->mtcs2 = 0; | 72 | sport->regs->mtcs2 = 0; |
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index 5ab60bd613ea..9fc2192feb3b 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -128,7 +128,7 @@ void sport_done(struct sport_device *sport); | |||
128 | /* note: multichannel is in units of 8 channels, tdm_count is number of channels | 128 | /* note: multichannel is in units of 8 channels, tdm_count is number of channels |
129 | * NOT / 8 ! all channels are enabled by default */ | 129 | * NOT / 8 ! all channels are enabled by default */ |
130 | int sport_set_multichannel(struct sport_device *sport, int tdm_count, | 130 | int sport_set_multichannel(struct sport_device *sport, int tdm_count, |
131 | u32 mask, int packed); | 131 | u32 tx_mask, u32 rx_mask, int packed); |
132 | 132 | ||
133 | int sport_config_rx(struct sport_device *sport, | 133 | int sport_config_rx(struct sport_device *sport, |
134 | unsigned int rcr1, unsigned int rcr2, | 134 | unsigned int rcr1, unsigned int rcr2, |
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index 7dbeef1099b4..9c19ccc936e2 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/gpio.h> | 40 | #include <linux/gpio.h> |
41 | #include "../codecs/ssm2602.h" | 41 | #include "../codecs/ssm2602.h" |
42 | #include "bf5xx-sport.h" | 42 | #include "bf5xx-sport.h" |
43 | #include "bf5xx-i2s-pcm.h" | ||
44 | 43 | ||
45 | static struct snd_soc_card bf5xx_ssm2602; | 44 | static struct snd_soc_card bf5xx_ssm2602; |
46 | 45 | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c deleted file mode 100644 index 0e6b888bb4cc..000000000000 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ /dev/null | |||
@@ -1,345 +0,0 @@ | |||
1 | /* | ||
2 | * File: sound/soc/blackfin/bf5xx-tdm-pcm.c | ||
3 | * Author: Barry Song <Barry.Song@analog.com> | ||
4 | * | ||
5 | * Created: Tue June 06 2009 | ||
6 | * Description: DMA driver for tdm codec | ||
7 | * | ||
8 | * Modified: | ||
9 | * Copyright 2009 Analog Devices Inc. | ||
10 | * | ||
11 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, see the file COPYING, or write | ||
25 | * to the Free Software Foundation, Inc., | ||
26 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/gfp.h> | ||
34 | |||
35 | #include <sound/core.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/pcm_params.h> | ||
38 | #include <sound/soc.h> | ||
39 | |||
40 | #include <asm/dma.h> | ||
41 | |||
42 | #include "bf5xx-tdm-pcm.h" | ||
43 | #include "bf5xx-tdm.h" | ||
44 | #include "bf5xx-sport.h" | ||
45 | |||
46 | #define PCM_BUFFER_MAX 0x8000 | ||
47 | #define FRAGMENT_SIZE_MIN (4*1024) | ||
48 | #define FRAGMENTS_MIN 2 | ||
49 | #define FRAGMENTS_MAX 32 | ||
50 | |||
51 | static void bf5xx_dma_irq(void *data) | ||
52 | { | ||
53 | struct snd_pcm_substream *pcm = data; | ||
54 | snd_pcm_period_elapsed(pcm); | ||
55 | } | ||
56 | |||
57 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | ||
58 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
59 | SNDRV_PCM_INFO_RESUME), | ||
60 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
61 | .rates = SNDRV_PCM_RATE_48000, | ||
62 | .channels_min = 2, | ||
63 | .channels_max = 8, | ||
64 | .buffer_bytes_max = PCM_BUFFER_MAX, | ||
65 | .period_bytes_min = FRAGMENT_SIZE_MIN, | ||
66 | .period_bytes_max = PCM_BUFFER_MAX/2, | ||
67 | .periods_min = FRAGMENTS_MIN, | ||
68 | .periods_max = FRAGMENTS_MAX, | ||
69 | }; | ||
70 | |||
71 | static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | ||
72 | struct snd_pcm_hw_params *params) | ||
73 | { | ||
74 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max; | ||
75 | snd_pcm_lib_malloc_pages(substream, size * 4); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | ||
81 | { | ||
82 | snd_pcm_lib_free_pages(substream); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | ||
88 | { | ||
89 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
90 | struct sport_device *sport = runtime->private_data; | ||
91 | int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size); | ||
92 | |||
93 | fragsize_bytes /= runtime->channels; | ||
94 | /* inflate the fragsize to match the dma width of SPORT */ | ||
95 | fragsize_bytes *= 8; | ||
96 | |||
97 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
98 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); | ||
99 | sport_config_tx_dma(sport, runtime->dma_area, | ||
100 | runtime->periods, fragsize_bytes); | ||
101 | } else { | ||
102 | sport_set_rx_callback(sport, bf5xx_dma_irq, substream); | ||
103 | sport_config_rx_dma(sport, runtime->dma_area, | ||
104 | runtime->periods, fragsize_bytes); | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
111 | { | ||
112 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
113 | struct sport_device *sport = runtime->private_data; | ||
114 | int ret = 0; | ||
115 | |||
116 | switch (cmd) { | ||
117 | case SNDRV_PCM_TRIGGER_START: | ||
118 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
119 | sport_tx_start(sport); | ||
120 | else | ||
121 | sport_rx_start(sport); | ||
122 | break; | ||
123 | case SNDRV_PCM_TRIGGER_STOP: | ||
124 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
125 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
126 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
127 | sport_tx_stop(sport); | ||
128 | else | ||
129 | sport_rx_stop(sport); | ||
130 | break; | ||
131 | default: | ||
132 | ret = -EINVAL; | ||
133 | } | ||
134 | |||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | ||
139 | { | ||
140 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
141 | struct sport_device *sport = runtime->private_data; | ||
142 | unsigned int diff; | ||
143 | snd_pcm_uframes_t frames; | ||
144 | |||
145 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
146 | diff = sport_curr_offset_tx(sport); | ||
147 | frames = diff / (8*4); /* 32 bytes per frame */ | ||
148 | } else { | ||
149 | diff = sport_curr_offset_rx(sport); | ||
150 | frames = diff / (8*4); | ||
151 | } | ||
152 | return frames; | ||
153 | } | ||
154 | |||
155 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | ||
156 | { | ||
157 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
158 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
159 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
160 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
161 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
162 | |||
163 | int ret = 0; | ||
164 | |||
165 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | ||
166 | |||
167 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
168 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
169 | if (ret < 0) | ||
170 | goto out; | ||
171 | |||
172 | if (sport_handle != NULL) { | ||
173 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
174 | sport_handle->tx_buf = buf->area; | ||
175 | else | ||
176 | sport_handle->rx_buf = buf->area; | ||
177 | |||
178 | runtime->private_data = sport_handle; | ||
179 | } else { | ||
180 | pr_err("sport_handle is NULL\n"); | ||
181 | ret = -ENODEV; | ||
182 | } | ||
183 | out: | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | ||
188 | snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) | ||
189 | { | ||
190 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
191 | struct sport_device *sport = runtime->private_data; | ||
192 | struct bf5xx_tdm_port *tdm_port = sport->private_data; | ||
193 | unsigned int *src; | ||
194 | unsigned int *dst; | ||
195 | int i; | ||
196 | |||
197 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
198 | src = buf; | ||
199 | dst = (unsigned int *)substream->runtime->dma_area; | ||
200 | |||
201 | dst += pos * 8; | ||
202 | while (count--) { | ||
203 | for (i = 0; i < substream->runtime->channels; i++) | ||
204 | *(dst + tdm_port->tx_map[i]) = *src++; | ||
205 | dst += 8; | ||
206 | } | ||
207 | } else { | ||
208 | src = (unsigned int *)substream->runtime->dma_area; | ||
209 | dst = buf; | ||
210 | |||
211 | src += pos * 8; | ||
212 | while (count--) { | ||
213 | for (i = 0; i < substream->runtime->channels; i++) | ||
214 | *dst++ = *(src + tdm_port->rx_map[i]); | ||
215 | src += 8; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | ||
223 | int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) | ||
224 | { | ||
225 | unsigned char *buf = substream->runtime->dma_area; | ||
226 | buf += pos * 8 * 4; | ||
227 | memset(buf, '\0', count * 8 * 4); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | |||
233 | struct snd_pcm_ops bf5xx_pcm_tdm_ops = { | ||
234 | .open = bf5xx_pcm_open, | ||
235 | .ioctl = snd_pcm_lib_ioctl, | ||
236 | .hw_params = bf5xx_pcm_hw_params, | ||
237 | .hw_free = bf5xx_pcm_hw_free, | ||
238 | .prepare = bf5xx_pcm_prepare, | ||
239 | .trigger = bf5xx_pcm_trigger, | ||
240 | .pointer = bf5xx_pcm_pointer, | ||
241 | .copy = bf5xx_pcm_copy, | ||
242 | .silence = bf5xx_pcm_silence, | ||
243 | }; | ||
244 | |||
245 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
246 | { | ||
247 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
248 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
249 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max; | ||
250 | |||
251 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
252 | buf->dev.dev = pcm->card->dev; | ||
253 | buf->private_data = NULL; | ||
254 | buf->area = dma_alloc_coherent(pcm->card->dev, size * 4, | ||
255 | &buf->addr, GFP_KERNEL); | ||
256 | if (!buf->area) { | ||
257 | pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n"); | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | buf->bytes = size; | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
266 | { | ||
267 | struct snd_pcm_substream *substream; | ||
268 | struct snd_dma_buffer *buf; | ||
269 | int stream; | ||
270 | |||
271 | for (stream = 0; stream < 2; stream++) { | ||
272 | substream = pcm->streams[stream].substream; | ||
273 | if (!substream) | ||
274 | continue; | ||
275 | |||
276 | buf = &substream->dma_buffer; | ||
277 | if (!buf->area) | ||
278 | continue; | ||
279 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | ||
280 | buf->area = NULL; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | ||
285 | |||
286 | static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd) | ||
287 | { | ||
288 | struct snd_card *card = rtd->card->snd_card; | ||
289 | struct snd_pcm *pcm = rtd->pcm; | ||
290 | int ret = 0; | ||
291 | |||
292 | if (!card->dev->dma_mask) | ||
293 | card->dev->dma_mask = &bf5xx_pcm_dmamask; | ||
294 | if (!card->dev->coherent_dma_mask) | ||
295 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
296 | |||
297 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
298 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | ||
299 | SNDRV_PCM_STREAM_PLAYBACK); | ||
300 | if (ret) | ||
301 | goto out; | ||
302 | } | ||
303 | |||
304 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
305 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | ||
306 | SNDRV_PCM_STREAM_CAPTURE); | ||
307 | if (ret) | ||
308 | goto out; | ||
309 | } | ||
310 | out: | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = { | ||
315 | .ops = &bf5xx_pcm_tdm_ops, | ||
316 | .pcm_new = bf5xx_pcm_tdm_new, | ||
317 | .pcm_free = bf5xx_pcm_free_dma_buffers, | ||
318 | }; | ||
319 | |||
320 | static int bf5xx_soc_platform_probe(struct platform_device *pdev) | ||
321 | { | ||
322 | return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform); | ||
323 | } | ||
324 | |||
325 | static int bf5xx_soc_platform_remove(struct platform_device *pdev) | ||
326 | { | ||
327 | snd_soc_unregister_platform(&pdev->dev); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct platform_driver bfin_tdm_driver = { | ||
332 | .driver = { | ||
333 | .name = "bfin-tdm-pcm-audio", | ||
334 | .owner = THIS_MODULE, | ||
335 | }, | ||
336 | |||
337 | .probe = bf5xx_soc_platform_probe, | ||
338 | .remove = bf5xx_soc_platform_remove, | ||
339 | }; | ||
340 | |||
341 | module_platform_driver(bfin_tdm_driver); | ||
342 | |||
343 | MODULE_AUTHOR("Barry Song"); | ||
344 | MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); | ||
345 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h deleted file mode 100644 index 7f8cc01c4477..000000000000 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin | ||
3 | * | ||
4 | * Copyright 2009 Analog Device Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _BF5XX_TDM_PCM_H | ||
12 | #define _BF5XX_TDM_PCM_H | ||
13 | |||
14 | struct bf5xx_pcm_dma_params { | ||
15 | char *name; /* stream identifier */ | ||
16 | }; | ||
17 | |||
18 | #endif | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c deleted file mode 100644 index 69e9a3e935bd..000000000000 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ /dev/null | |||
@@ -1,328 +0,0 @@ | |||
1 | /* | ||
2 | * File: sound/soc/blackfin/bf5xx-tdm.c | ||
3 | * Author: Barry Song <Barry.Song@analog.com> | ||
4 | * | ||
5 | * Created: Thurs June 04 2009 | ||
6 | * Description: Blackfin I2S(TDM) CPU DAI driver | ||
7 | * Even though TDM mode can be as part of I2S DAI, but there | ||
8 | * are so much difference in configuration and data flow, | ||
9 | * it's very ugly to integrate I2S and TDM into a module | ||
10 | * | ||
11 | * Modified: | ||
12 | * Copyright 2009 Analog Devices Inc. | ||
13 | * | ||
14 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, see the file COPYING, or write | ||
28 | * to the Free Software Foundation, Inc., | ||
29 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
30 | */ | ||
31 | |||
32 | #include <linux/init.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/device.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/pcm_params.h> | ||
38 | #include <sound/initval.h> | ||
39 | #include <sound/soc.h> | ||
40 | |||
41 | #include <asm/irq.h> | ||
42 | #include <asm/portmux.h> | ||
43 | #include <linux/mutex.h> | ||
44 | #include <linux/gpio.h> | ||
45 | |||
46 | #include "bf5xx-sport.h" | ||
47 | #include "bf5xx-tdm.h" | ||
48 | |||
49 | static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
50 | unsigned int fmt) | ||
51 | { | ||
52 | int ret = 0; | ||
53 | |||
54 | /* interface format:support TDM,slave mode */ | ||
55 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
56 | case SND_SOC_DAIFMT_DSP_A: | ||
57 | break; | ||
58 | default: | ||
59 | printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); | ||
60 | ret = -EINVAL; | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
65 | case SND_SOC_DAIFMT_CBM_CFM: | ||
66 | break; | ||
67 | case SND_SOC_DAIFMT_CBS_CFS: | ||
68 | case SND_SOC_DAIFMT_CBM_CFS: | ||
69 | case SND_SOC_DAIFMT_CBS_CFM: | ||
70 | ret = -EINVAL; | ||
71 | break; | ||
72 | default: | ||
73 | printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); | ||
74 | ret = -EINVAL; | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | ||
82 | struct snd_pcm_hw_params *params, | ||
83 | struct snd_soc_dai *dai) | ||
84 | { | ||
85 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
86 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
87 | int ret = 0; | ||
88 | |||
89 | bf5xx_tdm->tcr2 &= ~0x1f; | ||
90 | bf5xx_tdm->rcr2 &= ~0x1f; | ||
91 | switch (params_format(params)) { | ||
92 | case SNDRV_PCM_FORMAT_S32_LE: | ||
93 | bf5xx_tdm->tcr2 |= 31; | ||
94 | bf5xx_tdm->rcr2 |= 31; | ||
95 | sport_handle->wdsize = 4; | ||
96 | break; | ||
97 | /* at present, we only support 32bit transfer */ | ||
98 | default: | ||
99 | pr_err("not supported PCM format yet\n"); | ||
100 | return -EINVAL; | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | if (!bf5xx_tdm->configured) { | ||
105 | /* | ||
106 | * TX and RX are not independent,they are enabled at the | ||
107 | * same time, even if only one side is running. So, we | ||
108 | * need to configure both of them at the time when the first | ||
109 | * stream is opened. | ||
110 | * | ||
111 | * CPU DAI:slave mode. | ||
112 | */ | ||
113 | ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1, | ||
114 | bf5xx_tdm->rcr2, 0, 0); | ||
115 | if (ret) { | ||
116 | pr_err("SPORT is busy!\n"); | ||
117 | return -EBUSY; | ||
118 | } | ||
119 | |||
120 | ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1, | ||
121 | bf5xx_tdm->tcr2, 0, 0); | ||
122 | if (ret) { | ||
123 | pr_err("SPORT is busy!\n"); | ||
124 | return -EBUSY; | ||
125 | } | ||
126 | |||
127 | bf5xx_tdm->configured = 1; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, | ||
134 | struct snd_soc_dai *dai) | ||
135 | { | ||
136 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
137 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
138 | |||
139 | /* No active stream, SPORT is allowed to be configured again. */ | ||
140 | if (!dai->active) | ||
141 | bf5xx_tdm->configured = 0; | ||
142 | } | ||
143 | |||
144 | static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | ||
145 | unsigned int tx_num, unsigned int *tx_slot, | ||
146 | unsigned int rx_num, unsigned int *rx_slot) | ||
147 | { | ||
148 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
149 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
150 | int i; | ||
151 | unsigned int slot; | ||
152 | unsigned int tx_mapped = 0, rx_mapped = 0; | ||
153 | |||
154 | if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) || | ||
155 | (rx_num > BFIN_TDM_DAI_MAX_SLOTS)) | ||
156 | return -EINVAL; | ||
157 | |||
158 | for (i = 0; i < tx_num; i++) { | ||
159 | slot = tx_slot[i]; | ||
160 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | ||
161 | (!(tx_mapped & (1 << slot)))) { | ||
162 | bf5xx_tdm->tx_map[i] = slot; | ||
163 | tx_mapped |= 1 << slot; | ||
164 | } else | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | for (i = 0; i < rx_num; i++) { | ||
168 | slot = rx_slot[i]; | ||
169 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | ||
170 | (!(rx_mapped & (1 << slot)))) { | ||
171 | bf5xx_tdm->rx_map[i] = slot; | ||
172 | rx_mapped |= 1 << slot; | ||
173 | } else | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | #ifdef CONFIG_PM | ||
181 | static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) | ||
182 | { | ||
183 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | ||
184 | |||
185 | if (dai->playback_active) | ||
186 | sport_tx_stop(sport); | ||
187 | if (dai->capture_active) | ||
188 | sport_rx_stop(sport); | ||
189 | |||
190 | /* isolate sync/clock pins from codec while sports resume */ | ||
191 | peripheral_free_list(sport->pin_req); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | ||
197 | { | ||
198 | int ret; | ||
199 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | ||
200 | |||
201 | ret = sport_set_multichannel(sport, 8, 0xFF, 1); | ||
202 | if (ret) { | ||
203 | pr_err("SPORT is busy!\n"); | ||
204 | ret = -EBUSY; | ||
205 | } | ||
206 | |||
207 | ret = sport_config_rx(sport, 0, 0x1F, 0, 0); | ||
208 | if (ret) { | ||
209 | pr_err("SPORT is busy!\n"); | ||
210 | ret = -EBUSY; | ||
211 | } | ||
212 | |||
213 | ret = sport_config_tx(sport, 0, 0x1F, 0, 0); | ||
214 | if (ret) { | ||
215 | pr_err("SPORT is busy!\n"); | ||
216 | ret = -EBUSY; | ||
217 | } | ||
218 | |||
219 | peripheral_request_list(sport->pin_req, "soc-audio"); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | #else | ||
225 | #define bf5xx_tdm_suspend NULL | ||
226 | #define bf5xx_tdm_resume NULL | ||
227 | #endif | ||
228 | |||
229 | static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { | ||
230 | .hw_params = bf5xx_tdm_hw_params, | ||
231 | .set_fmt = bf5xx_tdm_set_dai_fmt, | ||
232 | .shutdown = bf5xx_tdm_shutdown, | ||
233 | .set_channel_map = bf5xx_tdm_set_channel_map, | ||
234 | }; | ||
235 | |||
236 | static struct snd_soc_dai_driver bf5xx_tdm_dai = { | ||
237 | .suspend = bf5xx_tdm_suspend, | ||
238 | .resume = bf5xx_tdm_resume, | ||
239 | .playback = { | ||
240 | .channels_min = 2, | ||
241 | .channels_max = 8, | ||
242 | .rates = SNDRV_PCM_RATE_48000, | ||
243 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, | ||
244 | .capture = { | ||
245 | .channels_min = 2, | ||
246 | .channels_max = 8, | ||
247 | .rates = SNDRV_PCM_RATE_48000, | ||
248 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, | ||
249 | .ops = &bf5xx_tdm_dai_ops, | ||
250 | }; | ||
251 | |||
252 | static const struct snd_soc_component_driver bf5xx_tdm_component = { | ||
253 | .name = "bf5xx-tdm", | ||
254 | }; | ||
255 | |||
256 | static int bfin_tdm_probe(struct platform_device *pdev) | ||
257 | { | ||
258 | struct sport_device *sport_handle; | ||
259 | int ret; | ||
260 | |||
261 | /* configure SPORT for TDM */ | ||
262 | sport_handle = sport_init(pdev, 4, 8 * sizeof(u32), | ||
263 | sizeof(struct bf5xx_tdm_port)); | ||
264 | if (!sport_handle) | ||
265 | return -ENODEV; | ||
266 | |||
267 | /* SPORT works in TDM mode */ | ||
268 | ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); | ||
269 | if (ret) { | ||
270 | pr_err("SPORT is busy!\n"); | ||
271 | ret = -EBUSY; | ||
272 | goto sport_config_err; | ||
273 | } | ||
274 | |||
275 | ret = sport_config_rx(sport_handle, 0, 0x1F, 0, 0); | ||
276 | if (ret) { | ||
277 | pr_err("SPORT is busy!\n"); | ||
278 | ret = -EBUSY; | ||
279 | goto sport_config_err; | ||
280 | } | ||
281 | |||
282 | ret = sport_config_tx(sport_handle, 0, 0x1F, 0, 0); | ||
283 | if (ret) { | ||
284 | pr_err("SPORT is busy!\n"); | ||
285 | ret = -EBUSY; | ||
286 | goto sport_config_err; | ||
287 | } | ||
288 | |||
289 | ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component, | ||
290 | &bf5xx_tdm_dai, 1); | ||
291 | if (ret) { | ||
292 | pr_err("Failed to register DAI: %d\n", ret); | ||
293 | goto sport_config_err; | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | |||
298 | sport_config_err: | ||
299 | sport_done(sport_handle); | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static int bfin_tdm_remove(struct platform_device *pdev) | ||
304 | { | ||
305 | struct sport_device *sport_handle = platform_get_drvdata(pdev); | ||
306 | |||
307 | snd_soc_unregister_component(&pdev->dev); | ||
308 | sport_done(sport_handle); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static struct platform_driver bfin_tdm_driver = { | ||
314 | .probe = bfin_tdm_probe, | ||
315 | .remove = bfin_tdm_remove, | ||
316 | .driver = { | ||
317 | .name = "bfin-tdm", | ||
318 | .owner = THIS_MODULE, | ||
319 | }, | ||
320 | }; | ||
321 | |||
322 | module_platform_driver(bfin_tdm_driver); | ||
323 | |||
324 | /* Module information */ | ||
325 | MODULE_AUTHOR("Barry Song"); | ||
326 | MODULE_DESCRIPTION("TDM driver for ADI Blackfin"); | ||
327 | MODULE_LICENSE("GPL"); | ||
328 | |||
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h deleted file mode 100644 index e986a3ea3315..000000000000 --- a/sound/soc/blackfin/bf5xx-tdm.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * sound/soc/blackfin/bf5xx-tdm.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _BF5XX_TDM_H | ||
10 | #define _BF5XX_TDM_H | ||
11 | |||
12 | #define BFIN_TDM_DAI_MAX_SLOTS 8 | ||
13 | struct bf5xx_tdm_port { | ||
14 | u16 tcr1; | ||
15 | u16 rcr1; | ||
16 | u16 tcr2; | ||
17 | u16 rcr2; | ||
18 | unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS]; | ||
19 | unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS]; | ||
20 | int configured; | ||
21 | }; | ||
22 | |||
23 | #endif | ||
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 88143db7e753..2c20f01e1f7e 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config SND_EP93XX_SOC | 1 | config SND_EP93XX_SOC |
2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" | 2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" |
3 | depends on ARCH_EP93XX && SND_SOC | 3 | depends on ARCH_EP93XX && SND_SOC |
4 | select SND_SOC_DMAENGINE_PCM | 4 | select SND_SOC_GENERIC_DMAENGINE_PCM |
5 | help | 5 | help |
6 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
7 | the EP93xx I2S or AC97 interfaces. | 7 | the EP93xx I2S or AC97 interfaces. |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 4bc9490e2c84..ac73c607410a 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -313,22 +313,15 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | |||
313 | return 0; | 313 | return 0; |
314 | } | 314 | } |
315 | 315 | ||
316 | static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, | 316 | static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai) |
317 | struct snd_soc_dai *dai) | ||
318 | { | 317 | { |
319 | struct ep93xx_dma_data *dma_data; | 318 | dai->playback_dma_data = &ep93xx_ac97_pcm_out; |
319 | dai->capture_dma_data = &ep93xx_ac97_pcm_in; | ||
320 | 320 | ||
321 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
322 | dma_data = &ep93xx_ac97_pcm_out; | ||
323 | else | ||
324 | dma_data = &ep93xx_ac97_pcm_in; | ||
325 | |||
326 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | ||
327 | return 0; | 321 | return 0; |
328 | } | 322 | } |
329 | 323 | ||
330 | static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { | 324 | static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { |
331 | .startup = ep93xx_ac97_startup, | ||
332 | .trigger = ep93xx_ac97_trigger, | 325 | .trigger = ep93xx_ac97_trigger, |
333 | }; | 326 | }; |
334 | 327 | ||
@@ -336,6 +329,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = { | |||
336 | .name = "ep93xx-ac97", | 329 | .name = "ep93xx-ac97", |
337 | .id = 0, | 330 | .id = 0, |
338 | .ac97_control = 1, | 331 | .ac97_control = 1, |
332 | .probe = ep93xx_ac97_dai_probe, | ||
339 | .playback = { | 333 | .playback = { |
340 | .stream_name = "AC97 Playback", | 334 | .stream_name = "AC97 Playback", |
341 | .channels_min = 2, | 335 | .channels_min = 2, |
@@ -406,7 +400,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
406 | return 0; | 400 | return 0; |
407 | 401 | ||
408 | fail: | 402 | fail: |
409 | platform_set_drvdata(pdev, NULL); | ||
410 | ep93xx_ac97_info = NULL; | 403 | ep93xx_ac97_info = NULL; |
411 | snd_soc_set_ac97_ops(NULL); | 404 | snd_soc_set_ac97_ops(NULL); |
412 | return ret; | 405 | return ret; |
@@ -421,7 +414,6 @@ static int ep93xx_ac97_remove(struct platform_device *pdev) | |||
421 | /* disable the AC97 controller */ | 414 | /* disable the AC97 controller */ |
422 | ep93xx_ac97_write_reg(info, AC97GCR, 0); | 415 | ep93xx_ac97_write_reg(info, AC97GCR, 0); |
423 | 416 | ||
424 | platform_set_drvdata(pdev, NULL); | ||
425 | ep93xx_ac97_info = NULL; | 417 | ep93xx_ac97_info = NULL; |
426 | 418 | ||
427 | snd_soc_set_ac97_ops(NULL); | 419 | snd_soc_set_ac97_ops(NULL); |
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 5c1102e9e159..17ad70bca9fe 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
@@ -60,11 +60,10 @@ struct ep93xx_i2s_info { | |||
60 | struct clk *mclk; | 60 | struct clk *mclk; |
61 | struct clk *sclk; | 61 | struct clk *sclk; |
62 | struct clk *lrclk; | 62 | struct clk *lrclk; |
63 | struct ep93xx_dma_data *dma_data; | ||
64 | void __iomem *regs; | 63 | void __iomem *regs; |
65 | }; | 64 | }; |
66 | 65 | ||
67 | struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { | 66 | static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { |
68 | [SNDRV_PCM_STREAM_PLAYBACK] = { | 67 | [SNDRV_PCM_STREAM_PLAYBACK] = { |
69 | .name = "i2s-pcm-out", | 68 | .name = "i2s-pcm-out", |
70 | .port = EP93XX_DMA_I2S1, | 69 | .port = EP93XX_DMA_I2S1, |
@@ -139,15 +138,11 @@ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) | |||
139 | } | 138 | } |
140 | } | 139 | } |
141 | 140 | ||
142 | static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | 141 | static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) |
143 | struct snd_soc_dai *dai) | ||
144 | { | 142 | { |
145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 143 | dai->playback_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK]; |
146 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); | 144 | dai->capture_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE]; |
147 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
148 | 145 | ||
149 | snd_soc_dai_set_dma_data(cpu_dai, substream, | ||
150 | &info->dma_data[substream->stream]); | ||
151 | return 0; | 146 | return 0; |
152 | } | 147 | } |
153 | 148 | ||
@@ -338,7 +333,6 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai) | |||
338 | #endif | 333 | #endif |
339 | 334 | ||
340 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | 335 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { |
341 | .startup = ep93xx_i2s_startup, | ||
342 | .shutdown = ep93xx_i2s_shutdown, | 336 | .shutdown = ep93xx_i2s_shutdown, |
343 | .hw_params = ep93xx_i2s_hw_params, | 337 | .hw_params = ep93xx_i2s_hw_params, |
344 | .set_sysclk = ep93xx_i2s_set_sysclk, | 338 | .set_sysclk = ep93xx_i2s_set_sysclk, |
@@ -349,6 +343,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | |||
349 | 343 | ||
350 | static struct snd_soc_dai_driver ep93xx_i2s_dai = { | 344 | static struct snd_soc_dai_driver ep93xx_i2s_dai = { |
351 | .symmetric_rates= 1, | 345 | .symmetric_rates= 1, |
346 | .probe = ep93xx_i2s_dai_probe, | ||
352 | .suspend = ep93xx_i2s_suspend, | 347 | .suspend = ep93xx_i2s_suspend, |
353 | .resume = ep93xx_i2s_resume, | 348 | .resume = ep93xx_i2s_resume, |
354 | .playback = { | 349 | .playback = { |
@@ -407,7 +402,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
407 | } | 402 | } |
408 | 403 | ||
409 | dev_set_drvdata(&pdev->dev, info); | 404 | dev_set_drvdata(&pdev->dev, info); |
410 | info->dma_data = ep93xx_i2s_dma_data; | ||
411 | 405 | ||
412 | err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, | 406 | err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, |
413 | &ep93xx_i2s_dai, 1); | 407 | &ep93xx_i2s_dai, 1); |
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 488032690378..0e9f56e0d4b2 100644 --- a/sound/soc/cirrus/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
@@ -14,20 +14,14 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/slab.h> | ||
19 | #include <linux/dmaengine.h> | 18 | #include <linux/dmaengine.h> |
20 | #include <linux/dma-mapping.h> | ||
21 | 19 | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
26 | #include <sound/dmaengine_pcm.h> | 22 | #include <sound/dmaengine_pcm.h> |
27 | 23 | ||
28 | #include <linux/platform_data/dma-ep93xx.h> | 24 | #include <linux/platform_data/dma-ep93xx.h> |
29 | #include <mach/hardware.h> | ||
30 | #include <mach/ep93xx-regs.h> | ||
31 | 25 | ||
32 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | 26 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { |
33 | .info = (SNDRV_PCM_INFO_MMAP | | 27 | .info = (SNDRV_PCM_INFO_MMAP | |
@@ -63,134 +57,24 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) | |||
63 | return false; | 57 | return false; |
64 | } | 58 | } |
65 | 59 | ||
66 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) | 60 | static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = { |
67 | { | 61 | .pcm_hardware = &ep93xx_pcm_hardware, |
68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 62 | .compat_filter_fn = ep93xx_pcm_dma_filter, |
69 | 63 | .prealloc_buffer_size = 131072, | |
70 | snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); | ||
71 | |||
72 | return snd_dmaengine_pcm_open_request_chan(substream, | ||
73 | ep93xx_pcm_dma_filter, | ||
74 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); | ||
75 | } | ||
76 | |||
77 | static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, | ||
78 | struct snd_pcm_hw_params *params) | ||
79 | { | ||
80 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) | ||
86 | { | ||
87 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, | ||
92 | struct vm_area_struct *vma) | ||
93 | { | ||
94 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
95 | |||
96 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
97 | runtime->dma_area, | ||
98 | runtime->dma_addr, | ||
99 | runtime->dma_bytes); | ||
100 | } | ||
101 | |||
102 | static struct snd_pcm_ops ep93xx_pcm_ops = { | ||
103 | .open = ep93xx_pcm_open, | ||
104 | .close = snd_dmaengine_pcm_close_release_chan, | ||
105 | .ioctl = snd_pcm_lib_ioctl, | ||
106 | .hw_params = ep93xx_pcm_hw_params, | ||
107 | .hw_free = ep93xx_pcm_hw_free, | ||
108 | .trigger = snd_dmaengine_pcm_trigger, | ||
109 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
110 | .mmap = ep93xx_pcm_mmap, | ||
111 | }; | ||
112 | |||
113 | static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
114 | { | ||
115 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
116 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
117 | size_t size = ep93xx_pcm_hardware.buffer_bytes_max; | ||
118 | |||
119 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
120 | buf->dev.dev = pcm->card->dev; | ||
121 | buf->private_data = NULL; | ||
122 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
123 | &buf->addr, GFP_KERNEL); | ||
124 | buf->bytes = size; | ||
125 | |||
126 | return (buf->area == NULL) ? -ENOMEM : 0; | ||
127 | } | ||
128 | |||
129 | static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
130 | { | ||
131 | struct snd_pcm_substream *substream; | ||
132 | struct snd_dma_buffer *buf; | ||
133 | int stream; | ||
134 | |||
135 | for (stream = 0; stream < 2; stream++) { | ||
136 | substream = pcm->streams[stream].substream; | ||
137 | if (!substream) | ||
138 | continue; | ||
139 | |||
140 | buf = &substream->dma_buffer; | ||
141 | if (!buf->area) | ||
142 | continue; | ||
143 | |||
144 | dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, | ||
145 | buf->addr); | ||
146 | buf->area = NULL; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); | ||
151 | |||
152 | static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
153 | { | ||
154 | struct snd_card *card = rtd->card->snd_card; | ||
155 | struct snd_pcm *pcm = rtd->pcm; | ||
156 | int ret = 0; | ||
157 | |||
158 | if (!card->dev->dma_mask) | ||
159 | card->dev->dma_mask = &ep93xx_pcm_dmamask; | ||
160 | if (!card->dev->coherent_dma_mask) | ||
161 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
162 | |||
163 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
164 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, | ||
165 | SNDRV_PCM_STREAM_PLAYBACK); | ||
166 | if (ret) | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
171 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, | ||
172 | SNDRV_PCM_STREAM_CAPTURE); | ||
173 | if (ret) | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct snd_soc_platform_driver ep93xx_soc_platform = { | ||
181 | .ops = &ep93xx_pcm_ops, | ||
182 | .pcm_new = &ep93xx_pcm_new, | ||
183 | .pcm_free = &ep93xx_pcm_free_dma_buffers, | ||
184 | }; | 64 | }; |
185 | 65 | ||
186 | static int ep93xx_soc_platform_probe(struct platform_device *pdev) | 66 | static int ep93xx_soc_platform_probe(struct platform_device *pdev) |
187 | { | 67 | { |
188 | return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); | 68 | return snd_dmaengine_pcm_register(&pdev->dev, |
69 | &ep93xx_dmaengine_pcm_config, | ||
70 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | ||
71 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
72 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
189 | } | 73 | } |
190 | 74 | ||
191 | static int ep93xx_soc_platform_remove(struct platform_device *pdev) | 75 | static int ep93xx_soc_platform_remove(struct platform_device *pdev) |
192 | { | 76 | { |
193 | snd_soc_unregister_platform(&pdev->dev); | 77 | snd_dmaengine_pcm_unregister(&pdev->dev); |
194 | return 0; | 78 | return 0; |
195 | } | 79 | } |
196 | 80 | ||
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index e2bd3dd02c0e..8af04343cc1a 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -1442,7 +1442,7 @@ static int pm860x_codec_probe(struct platform_device *pdev) | |||
1442 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 1442 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
1443 | if (!res) { | 1443 | if (!res) { |
1444 | dev_err(&pdev->dev, "Failed to get IRQ resources\n"); | 1444 | dev_err(&pdev->dev, "Failed to get IRQ resources\n"); |
1445 | goto out; | 1445 | return -EINVAL; |
1446 | } | 1446 | } |
1447 | pm860x->irq[i] = res->start + chip->irq_base; | 1447 | pm860x->irq[i] = res->start + chip->irq_base; |
1448 | strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); | 1448 | strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); |
@@ -1452,19 +1452,14 @@ static int pm860x_codec_probe(struct platform_device *pdev) | |||
1452 | pm860x_dai, ARRAY_SIZE(pm860x_dai)); | 1452 | pm860x_dai, ARRAY_SIZE(pm860x_dai)); |
1453 | if (ret) { | 1453 | if (ret) { |
1454 | dev_err(&pdev->dev, "Failed to register codec\n"); | 1454 | dev_err(&pdev->dev, "Failed to register codec\n"); |
1455 | goto out; | 1455 | return -EINVAL; |
1456 | } | 1456 | } |
1457 | return ret; | 1457 | return ret; |
1458 | |||
1459 | out: | ||
1460 | platform_set_drvdata(pdev, NULL); | ||
1461 | return -EINVAL; | ||
1462 | } | 1458 | } |
1463 | 1459 | ||
1464 | static int pm860x_codec_remove(struct platform_device *pdev) | 1460 | static int pm860x_codec_remove(struct platform_device *pdev) |
1465 | { | 1461 | { |
1466 | snd_soc_unregister_codec(&pdev->dev); | 1462 | snd_soc_unregister_codec(&pdev->dev); |
1467 | platform_set_drvdata(pdev, NULL); | ||
1468 | return 0; | 1463 | return 0; |
1469 | } | 1464 | } |
1470 | 1465 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2f45f00e31b0..badb6fbacaa6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -19,7 +19,7 @@ config SND_SOC_ALL_CODECS | |||
19 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 19 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
20 | select SND_SOC_AD73311 | 20 | select SND_SOC_AD73311 |
21 | select SND_SOC_ADAU1373 if I2C | 21 | select SND_SOC_ADAU1373 if I2C |
22 | select SND_SOC_ADAV80X | 22 | select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI |
23 | select SND_SOC_ADS117X | 23 | select SND_SOC_ADS117X |
24 | select SND_SOC_AK4104 if SPI_MASTER | 24 | select SND_SOC_AK4104 if SPI_MASTER |
25 | select SND_SOC_AK4535 if I2C | 25 | select SND_SOC_AK4535 if I2C |
@@ -40,7 +40,7 @@ config SND_SOC_ALL_CODECS | |||
40 | select SND_SOC_DA7213 if I2C | 40 | select SND_SOC_DA7213 if I2C |
41 | select SND_SOC_DA732X if I2C | 41 | select SND_SOC_DA732X if I2C |
42 | select SND_SOC_DA9055 if I2C | 42 | select SND_SOC_DA9055 if I2C |
43 | select SND_SOC_DFBMCS320 | 43 | select SND_SOC_BT_SCO |
44 | select SND_SOC_ISABELLE if I2C | 44 | select SND_SOC_ISABELLE if I2C |
45 | select SND_SOC_JZ4740_CODEC | 45 | select SND_SOC_JZ4740_CODEC |
46 | select SND_SOC_LM4857 if I2C | 46 | select SND_SOC_LM4857 if I2C |
@@ -53,13 +53,15 @@ config SND_SOC_ALL_CODECS | |||
53 | select SND_SOC_MAX9877 if I2C | 53 | select SND_SOC_MAX9877 if I2C |
54 | select SND_SOC_MC13783 if MFD_MC13XXX | 54 | select SND_SOC_MC13783 if MFD_MC13XXX |
55 | select SND_SOC_ML26124 if I2C | 55 | select SND_SOC_ML26124 if I2C |
56 | select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI | 56 | select SND_SOC_HDMI_CODEC |
57 | select SND_SOC_PCM3008 | 57 | select SND_SOC_PCM3008 |
58 | select SND_SOC_RT5631 if I2C | 58 | select SND_SOC_RT5631 if I2C |
59 | select SND_SOC_RT5640 if I2C | ||
59 | select SND_SOC_SGTL5000 if I2C | 60 | select SND_SOC_SGTL5000 if I2C |
60 | select SND_SOC_SI476X if MFD_SI476X_CORE | 61 | select SND_SOC_SI476X if MFD_SI476X_CORE |
61 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 62 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
62 | select SND_SOC_SPDIF | 63 | select SND_SOC_SPDIF |
64 | select SND_SOC_SSM2518 if I2C | ||
63 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 65 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
64 | select SND_SOC_STA32X if I2C | 66 | select SND_SOC_STA32X if I2C |
65 | select SND_SOC_STA529 if I2C | 67 | select SND_SOC_STA529 if I2C |
@@ -263,7 +265,7 @@ config SND_SOC_DA732X | |||
263 | config SND_SOC_DA9055 | 265 | config SND_SOC_DA9055 |
264 | tristate | 266 | tristate |
265 | 267 | ||
266 | config SND_SOC_DFBMCS320 | 268 | config SND_SOC_BT_SCO |
267 | tristate | 269 | tristate |
268 | 270 | ||
269 | config SND_SOC_DMIC | 271 | config SND_SOC_DMIC |
@@ -287,7 +289,7 @@ config SND_SOC_MAX98095 | |||
287 | config SND_SOC_MAX9850 | 289 | config SND_SOC_MAX9850 |
288 | tristate | 290 | tristate |
289 | 291 | ||
290 | config SND_SOC_OMAP_HDMI_CODEC | 292 | config SND_SOC_HDMI_CODEC |
291 | tristate | 293 | tristate |
292 | 294 | ||
293 | config SND_SOC_PCM3008 | 295 | config SND_SOC_PCM3008 |
@@ -296,6 +298,9 @@ config SND_SOC_PCM3008 | |||
296 | config SND_SOC_RT5631 | 298 | config SND_SOC_RT5631 |
297 | tristate | 299 | tristate |
298 | 300 | ||
301 | config SND_SOC_RT5640 | ||
302 | tristate | ||
303 | |||
299 | #Freescale sgtl5000 codec | 304 | #Freescale sgtl5000 codec |
300 | config SND_SOC_SGTL5000 | 305 | config SND_SOC_SGTL5000 |
301 | tristate | 306 | tristate |
@@ -313,6 +318,9 @@ config SND_SOC_SN95031 | |||
313 | config SND_SOC_SPDIF | 318 | config SND_SOC_SPDIF |
314 | tristate | 319 | tristate |
315 | 320 | ||
321 | config SND_SOC_SSM2518 | ||
322 | tristate | ||
323 | |||
316 | config SND_SOC_SSM2602 | 324 | config SND_SOC_SSM2602 |
317 | tristate | 325 | tristate |
318 | 326 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index b9e41c9a1f4c..70fd8066f546 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -27,7 +27,7 @@ snd-soc-da7210-objs := da7210.o | |||
27 | snd-soc-da7213-objs := da7213.o | 27 | snd-soc-da7213-objs := da7213.o |
28 | snd-soc-da732x-objs := da732x.o | 28 | snd-soc-da732x-objs := da732x.o |
29 | snd-soc-da9055-objs := da9055.o | 29 | snd-soc-da9055-objs := da9055.o |
30 | snd-soc-dfbmcs320-objs := dfbmcs320.o | 30 | snd-soc-bt-sco-objs := bt-sco.o |
31 | snd-soc-dmic-objs := dmic.o | 31 | snd-soc-dmic-objs := dmic.o |
32 | snd-soc-isabelle-objs := isabelle.o | 32 | snd-soc-isabelle-objs := isabelle.o |
33 | snd-soc-jz4740-codec-objs := jz4740.o | 33 | snd-soc-jz4740-codec-objs := jz4740.o |
@@ -41,17 +41,19 @@ snd-soc-max98095-objs := max98095.o | |||
41 | snd-soc-max9850-objs := max9850.o | 41 | snd-soc-max9850-objs := max9850.o |
42 | snd-soc-mc13783-objs := mc13783.o | 42 | snd-soc-mc13783-objs := mc13783.o |
43 | snd-soc-ml26124-objs := ml26124.o | 43 | snd-soc-ml26124-objs := ml26124.o |
44 | snd-soc-omap-hdmi-codec-objs := omap-hdmi.o | 44 | snd-soc-hdmi-codec-objs := hdmi.o |
45 | snd-soc-pcm3008-objs := pcm3008.o | 45 | snd-soc-pcm3008-objs := pcm3008.o |
46 | snd-soc-rt5631-objs := rt5631.o | 46 | snd-soc-rt5631-objs := rt5631.o |
47 | snd-soc-rt5640-objs := rt5640.o | ||
47 | snd-soc-sgtl5000-objs := sgtl5000.o | 48 | snd-soc-sgtl5000-objs := sgtl5000.o |
48 | snd-soc-alc5623-objs := alc5623.o | 49 | snd-soc-alc5623-objs := alc5623.o |
49 | snd-soc-alc5632-objs := alc5632.o | 50 | snd-soc-alc5632-objs := alc5632.o |
50 | snd-soc-sigmadsp-objs := sigmadsp.o | 51 | snd-soc-sigmadsp-objs := sigmadsp.o |
51 | snd-soc-si476x-objs := si476x.o | 52 | snd-soc-si476x-objs := si476x.o |
52 | snd-soc-sn95031-objs := sn95031.o | 53 | snd-soc-sn95031-objs := sn95031.o |
53 | snd-soc-spdif-tx-objs := spdif_transciever.o | 54 | snd-soc-spdif-tx-objs := spdif_transmitter.o |
54 | snd-soc-spdif-rx-objs := spdif_receiver.o | 55 | snd-soc-spdif-rx-objs := spdif_receiver.o |
56 | snd-soc-ssm2518-objs := ssm2518.o | ||
55 | snd-soc-ssm2602-objs := ssm2602.o | 57 | snd-soc-ssm2602-objs := ssm2602.o |
56 | snd-soc-sta32x-objs := sta32x.o | 58 | snd-soc-sta32x-objs := sta32x.o |
57 | snd-soc-sta529-objs := sta529.o | 59 | snd-soc-sta529-objs := sta529.o |
@@ -154,7 +156,7 @@ obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | |||
154 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o | 156 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o |
155 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | 157 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o |
156 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | 158 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o |
157 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | 159 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o |
158 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 160 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
159 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 161 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
160 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 162 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
@@ -168,14 +170,16 @@ obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | |||
168 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 170 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
169 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 171 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
170 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 172 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
171 | obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o | 173 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o |
172 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 174 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
173 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 175 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
176 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | ||
174 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 177 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
175 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 178 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
176 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o | 179 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o |
177 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 180 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
178 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 181 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
182 | obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o | ||
179 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 183 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
180 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 184 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
181 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 185 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index a153b168129b..b8ba0adacfce 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -1496,6 +1496,12 @@ static const char * const enum_ad_to_slot_map[] = {"AD_OUT1", | |||
1496 | "AD_OUT7", | 1496 | "AD_OUT7", |
1497 | "AD_OUT8", | 1497 | "AD_OUT8", |
1498 | "zeroes", | 1498 | "zeroes", |
1499 | "zeroes", | ||
1500 | "zeroes", | ||
1501 | "zeroes", | ||
1502 | "tristate", | ||
1503 | "tristate", | ||
1504 | "tristate", | ||
1499 | "tristate"}; | 1505 | "tristate"}; |
1500 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, | 1506 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, |
1501 | AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, | 1507 | AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, |
@@ -2230,7 +2236,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
2230 | int slots, int slot_width) | 2236 | int slots, int slot_width) |
2231 | { | 2237 | { |
2232 | struct snd_soc_codec *codec = dai->codec; | 2238 | struct snd_soc_codec *codec = dai->codec; |
2233 | unsigned int val, mask, slots_active; | 2239 | unsigned int val, mask, slot, slots_active; |
2234 | 2240 | ||
2235 | mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | | 2241 | mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | |
2236 | BIT(AB8500_DIGIFCONF2_IF0WL1); | 2242 | BIT(AB8500_DIGIFCONF2_IF0WL1); |
@@ -2286,27 +2292,34 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
2286 | snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); | 2292 | snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); |
2287 | 2293 | ||
2288 | /* Setup TDM DA according to active tx slots */ | 2294 | /* Setup TDM DA according to active tx slots */ |
2295 | |||
2296 | if (tx_mask & ~0xff) | ||
2297 | return -EINVAL; | ||
2298 | |||
2289 | mask = AB8500_DASLOTCONFX_SLTODAX_MASK; | 2299 | mask = AB8500_DASLOTCONFX_SLTODAX_MASK; |
2300 | tx_mask = tx_mask << AB8500_DA_DATA0_OFFSET; | ||
2290 | slots_active = hweight32(tx_mask); | 2301 | slots_active = hweight32(tx_mask); |
2302 | |||
2291 | dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, | 2303 | dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, |
2292 | slots_active); | 2304 | slots_active); |
2305 | |||
2293 | switch (slots_active) { | 2306 | switch (slots_active) { |
2294 | case 0: | 2307 | case 0: |
2295 | break; | 2308 | break; |
2296 | case 1: | 2309 | case 1: |
2297 | /* Slot 9 -> DA_IN1 & DA_IN3 */ | 2310 | slot = find_first_bit((unsigned long *)&tx_mask, 32); |
2298 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); | 2311 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot); |
2299 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); | 2312 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot); |
2300 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | 2313 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot); |
2301 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | 2314 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot); |
2302 | break; | 2315 | break; |
2303 | case 2: | 2316 | case 2: |
2304 | /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ | 2317 | slot = find_first_bit((unsigned long *)&tx_mask, 32); |
2305 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); | 2318 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot); |
2306 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); | 2319 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot); |
2307 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | 2320 | slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1); |
2308 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | 2321 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot); |
2309 | 2322 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot); | |
2310 | break; | 2323 | break; |
2311 | case 8: | 2324 | case 8: |
2312 | dev_dbg(dai->codec->dev, | 2325 | dev_dbg(dai->codec->dev, |
@@ -2321,25 +2334,36 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
2321 | } | 2334 | } |
2322 | 2335 | ||
2323 | /* Setup TDM AD according to active RX-slots */ | 2336 | /* Setup TDM AD according to active RX-slots */ |
2337 | |||
2338 | if (rx_mask & ~0xff) | ||
2339 | return -EINVAL; | ||
2340 | |||
2341 | rx_mask = rx_mask << AB8500_AD_DATA0_OFFSET; | ||
2324 | slots_active = hweight32(rx_mask); | 2342 | slots_active = hweight32(rx_mask); |
2343 | |||
2325 | dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, | 2344 | dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, |
2326 | slots_active); | 2345 | slots_active); |
2346 | |||
2327 | switch (slots_active) { | 2347 | switch (slots_active) { |
2328 | case 0: | 2348 | case 0: |
2329 | break; | 2349 | break; |
2330 | case 1: | 2350 | case 1: |
2331 | /* AD_OUT3 -> slot 0 & 1 */ | 2351 | slot = find_first_bit((unsigned long *)&rx_mask, 32); |
2332 | snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, | 2352 | snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot), |
2333 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | 2353 | AB8500_MASK_SLOT(slot), |
2334 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); | 2354 | AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot)); |
2335 | break; | 2355 | break; |
2336 | case 2: | 2356 | case 2: |
2337 | /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ | 2357 | slot = find_first_bit((unsigned long *)&rx_mask, 32); |
2338 | snd_soc_update_bits(codec, | 2358 | snd_soc_update_bits(codec, |
2339 | AB8500_ADSLOTSEL1, | 2359 | AB8500_ADSLOTSEL(slot), |
2340 | AB8500_MASK_ALL, | 2360 | AB8500_MASK_SLOT(slot), |
2341 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | 2361 | AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot)); |
2342 | AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD); | 2362 | slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1); |
2363 | snd_soc_update_bits(codec, | ||
2364 | AB8500_ADSLOTSEL(slot), | ||
2365 | AB8500_MASK_SLOT(slot), | ||
2366 | AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT2, slot)); | ||
2343 | break; | 2367 | break; |
2344 | case 8: | 2368 | case 8: |
2345 | dev_dbg(dai->codec->dev, | 2369 | dev_dbg(dai->codec->dev, |
@@ -2356,6 +2380,11 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
2356 | return 0; | 2380 | return 0; |
2357 | } | 2381 | } |
2358 | 2382 | ||
2383 | static const struct snd_soc_dai_ops ab8500_codec_ops = { | ||
2384 | .set_fmt = ab8500_codec_set_dai_fmt, | ||
2385 | .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | ||
2386 | }; | ||
2387 | |||
2359 | static struct snd_soc_dai_driver ab8500_codec_dai[] = { | 2388 | static struct snd_soc_dai_driver ab8500_codec_dai[] = { |
2360 | { | 2389 | { |
2361 | .name = "ab8500-codec-dai.0", | 2390 | .name = "ab8500-codec-dai.0", |
@@ -2367,12 +2396,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = { | |||
2367 | .rates = AB8500_SUPPORTED_RATE, | 2396 | .rates = AB8500_SUPPORTED_RATE, |
2368 | .formats = AB8500_SUPPORTED_FMT, | 2397 | .formats = AB8500_SUPPORTED_FMT, |
2369 | }, | 2398 | }, |
2370 | .ops = (struct snd_soc_dai_ops[]) { | 2399 | .ops = &ab8500_codec_ops, |
2371 | { | ||
2372 | .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | ||
2373 | .set_fmt = ab8500_codec_set_dai_fmt, | ||
2374 | } | ||
2375 | }, | ||
2376 | .symmetric_rates = 1 | 2400 | .symmetric_rates = 1 |
2377 | }, | 2401 | }, |
2378 | { | 2402 | { |
@@ -2385,12 +2409,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = { | |||
2385 | .rates = AB8500_SUPPORTED_RATE, | 2409 | .rates = AB8500_SUPPORTED_RATE, |
2386 | .formats = AB8500_SUPPORTED_FMT, | 2410 | .formats = AB8500_SUPPORTED_FMT, |
2387 | }, | 2411 | }, |
2388 | .ops = (struct snd_soc_dai_ops[]) { | 2412 | .ops = &ab8500_codec_ops, |
2389 | { | ||
2390 | .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | ||
2391 | .set_fmt = ab8500_codec_set_dai_fmt, | ||
2392 | } | ||
2393 | }, | ||
2394 | .symmetric_rates = 1 | 2413 | .symmetric_rates = 1 |
2395 | } | 2414 | } |
2396 | }; | 2415 | }; |
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h index 306d0bc8455f..e2e54425d25e 100644 --- a/sound/soc/codecs/ab8500-codec.h +++ b/sound/soc/codecs/ab8500-codec.h | |||
@@ -24,6 +24,13 @@ | |||
24 | #define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) | 24 | #define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) |
25 | #define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) | 25 | #define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) |
26 | 26 | ||
27 | /* AB8500 interface slot offset definitions */ | ||
28 | |||
29 | #define AB8500_AD_DATA0_OFFSET 0 | ||
30 | #define AB8500_DA_DATA0_OFFSET 8 | ||
31 | #define AB8500_AD_DATA1_OFFSET 16 | ||
32 | #define AB8500_DA_DATA1_OFFSET 24 | ||
33 | |||
27 | /* AB8500 audio bank (0x0d) register definitions */ | 34 | /* AB8500 audio bank (0x0d) register definitions */ |
28 | 35 | ||
29 | #define AB8500_POWERUP 0x00 | 36 | #define AB8500_POWERUP 0x00 |
@@ -73,6 +80,7 @@ | |||
73 | #define AB8500_ADSLOTSEL14 0x2C | 80 | #define AB8500_ADSLOTSEL14 0x2C |
74 | #define AB8500_ADSLOTSEL15 0x2D | 81 | #define AB8500_ADSLOTSEL15 0x2D |
75 | #define AB8500_ADSLOTSEL16 0x2E | 82 | #define AB8500_ADSLOTSEL16 0x2E |
83 | #define AB8500_ADSLOTSEL(slot) (AB8500_ADSLOTSEL1 + (slot >> 1)) | ||
76 | #define AB8500_ADSLOTHIZCTRL1 0x2F | 84 | #define AB8500_ADSLOTHIZCTRL1 0x2F |
77 | #define AB8500_ADSLOTHIZCTRL2 0x30 | 85 | #define AB8500_ADSLOTHIZCTRL2 0x30 |
78 | #define AB8500_ADSLOTHIZCTRL3 0x31 | 86 | #define AB8500_ADSLOTHIZCTRL3 0x31 |
@@ -144,6 +152,7 @@ | |||
144 | #define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) | 152 | #define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) |
145 | 153 | ||
146 | #define AB8500_MASK_ALL 0xFF | 154 | #define AB8500_MASK_ALL 0xFF |
155 | #define AB8500_MASK_SLOT(slot) ((slot & 1) ? 0xF0 : 0x0F) | ||
147 | #define AB8500_MASK_NONE 0x00 | 156 | #define AB8500_MASK_NONE 0x00 |
148 | 157 | ||
149 | /* AB8500_POWERUP */ | 158 | /* AB8500_POWERUP */ |
@@ -347,28 +356,21 @@ | |||
347 | #define AB8500_DIGIFCONF4_IF1WL0 0 | 356 | #define AB8500_DIGIFCONF4_IF1WL0 0 |
348 | 357 | ||
349 | /* AB8500_ADSLOTSELX */ | 358 | /* AB8500_ADSLOTSELX */ |
350 | #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 | 359 | #define AB8500_AD_OUT1 0x0 |
351 | #define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x10 | 360 | #define AB8500_AD_OUT2 0x1 |
352 | #define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x20 | 361 | #define AB8500_AD_OUT3 0x2 |
353 | #define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x30 | 362 | #define AB8500_AD_OUT4 0x3 |
354 | #define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x40 | 363 | #define AB8500_AD_OUT5 0x4 |
355 | #define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x50 | 364 | #define AB8500_AD_OUT6 0x5 |
356 | #define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x60 | 365 | #define AB8500_AD_OUT7 0x6 |
357 | #define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x70 | 366 | #define AB8500_AD_OUT8 0x7 |
358 | #define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x80 | 367 | #define AB8500_ZEROES 0x8 |
359 | #define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0xF0 | 368 | #define AB8500_TRISTATE 0xF |
360 | #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00 | ||
361 | #define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x01 | ||
362 | #define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x02 | ||
363 | #define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x03 | ||
364 | #define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x04 | ||
365 | #define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x05 | ||
366 | #define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x06 | ||
367 | #define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x07 | ||
368 | #define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x08 | ||
369 | #define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0x0F | ||
370 | #define AB8500_ADSLOTSELX_EVEN_SHIFT 0 | 369 | #define AB8500_ADSLOTSELX_EVEN_SHIFT 0 |
371 | #define AB8500_ADSLOTSELX_ODD_SHIFT 4 | 370 | #define AB8500_ADSLOTSELX_ODD_SHIFT 4 |
371 | #define AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(out, slot) \ | ||
372 | ((out) << (((slot) & 1) ? \ | ||
373 | AB8500_ADSLOTSELX_ODD_SHIFT : AB8500_ADSLOTSELX_EVEN_SHIFT)) | ||
372 | 374 | ||
373 | /* AB8500_ADSLOTHIZCTRL1 */ | 375 | /* AB8500_ADSLOTHIZCTRL1 */ |
374 | /* AB8500_ADSLOTHIZCTRL2 */ | 376 | /* AB8500_ADSLOTHIZCTRL2 */ |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 389f23253831..de625813c0e6 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -1198,6 +1198,13 @@ const struct snd_soc_dai_ops arizona_dai_ops = { | |||
1198 | }; | 1198 | }; |
1199 | EXPORT_SYMBOL_GPL(arizona_dai_ops); | 1199 | EXPORT_SYMBOL_GPL(arizona_dai_ops); |
1200 | 1200 | ||
1201 | const struct snd_soc_dai_ops arizona_simple_dai_ops = { | ||
1202 | .startup = arizona_startup, | ||
1203 | .hw_params = arizona_hw_params_rate, | ||
1204 | .set_sysclk = arizona_dai_set_sysclk, | ||
1205 | }; | ||
1206 | EXPORT_SYMBOL_GPL(arizona_simple_dai_ops); | ||
1207 | |||
1201 | int arizona_init_dai(struct arizona_priv *priv, int id) | 1208 | int arizona_init_dai(struct arizona_priv *priv, int id) |
1202 | { | 1209 | { |
1203 | struct arizona_dai_priv *dai_priv = &priv->dai[id]; | 1210 | struct arizona_dai_priv *dai_priv = &priv->dai[id]; |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index af39f1006427..b60b08ccc1d0 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -57,7 +57,7 @@ | |||
57 | #define ARIZONA_CLK_98MHZ 5 | 57 | #define ARIZONA_CLK_98MHZ 5 |
58 | #define ARIZONA_CLK_147MHZ 6 | 58 | #define ARIZONA_CLK_147MHZ 6 |
59 | 59 | ||
60 | #define ARIZONA_MAX_DAI 4 | 60 | #define ARIZONA_MAX_DAI 6 |
61 | #define ARIZONA_MAX_ADSP 4 | 61 | #define ARIZONA_MAX_ADSP 4 |
62 | 62 | ||
63 | struct arizona; | 63 | struct arizona; |
@@ -213,6 +213,7 @@ extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
213 | int source, unsigned int freq, int dir); | 213 | int source, unsigned int freq, int dir); |
214 | 214 | ||
215 | extern const struct snd_soc_dai_ops arizona_dai_ops; | 215 | extern const struct snd_soc_dai_ops arizona_dai_ops; |
216 | extern const struct snd_soc_dai_ops arizona_simple_dai_ops; | ||
216 | 217 | ||
217 | #define ARIZONA_FLL_NAME_LEN 20 | 218 | #define ARIZONA_FLL_NAME_LEN 20 |
218 | 219 | ||
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/bt-sco.c index 4f4f7f41a7d1..a081d9fcb166 100644 --- a/sound/soc/codecs/dfbmcs320.c +++ b/sound/soc/codecs/bt-sco.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for the DFBM-CS320 bluetooth module | 2 | * Driver for generic Bluetooth SCO link |
3 | * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> | 3 | * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
@@ -15,8 +15,8 @@ | |||
15 | 15 | ||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | static struct snd_soc_dai_driver dfbmcs320_dai = { | 18 | static struct snd_soc_dai_driver bt_sco_dai = { |
19 | .name = "dfbmcs320-pcm", | 19 | .name = "bt-sco-pcm", |
20 | .playback = { | 20 | .playback = { |
21 | .channels_min = 1, | 21 | .channels_min = 1, |
22 | .channels_max = 1, | 22 | .channels_max = 1, |
@@ -31,32 +31,41 @@ static struct snd_soc_dai_driver dfbmcs320_dai = { | |||
31 | }, | 31 | }, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320; | 34 | static struct snd_soc_codec_driver soc_codec_dev_bt_sco; |
35 | 35 | ||
36 | static int dfbmcs320_probe(struct platform_device *pdev) | 36 | static int bt_sco_probe(struct platform_device *pdev) |
37 | { | 37 | { |
38 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320, | 38 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_bt_sco, |
39 | &dfbmcs320_dai, 1); | 39 | &bt_sco_dai, 1); |
40 | } | 40 | } |
41 | 41 | ||
42 | static int dfbmcs320_remove(struct platform_device *pdev) | 42 | static int bt_sco_remove(struct platform_device *pdev) |
43 | { | 43 | { |
44 | snd_soc_unregister_codec(&pdev->dev); | 44 | snd_soc_unregister_codec(&pdev->dev); |
45 | 45 | ||
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static struct platform_driver dfmcs320_driver = { | 49 | static struct platform_device_id bt_sco_driver_ids[] = { |
50 | { | ||
51 | .name = "dfbmcs320", | ||
52 | }, | ||
53 | {}, | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); | ||
56 | |||
57 | static struct platform_driver bt_sco_driver = { | ||
50 | .driver = { | 58 | .driver = { |
51 | .name = "dfbmcs320", | 59 | .name = "bt-sco", |
52 | .owner = THIS_MODULE, | 60 | .owner = THIS_MODULE, |
53 | }, | 61 | }, |
54 | .probe = dfbmcs320_probe, | 62 | .probe = bt_sco_probe, |
55 | .remove = dfbmcs320_remove, | 63 | .remove = bt_sco_remove, |
64 | .id_table = bt_sco_driver_ids, | ||
56 | }; | 65 | }; |
57 | 66 | ||
58 | module_platform_driver(dfmcs320_driver); | 67 | module_platform_driver(bt_sco_driver); |
59 | 68 | ||
60 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 69 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
61 | MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver"); | 70 | MODULE_DESCRIPTION("ASoC generic bluethooth sco link driver"); |
62 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/hdmi.c index 529d06444c54..2bcae2b40c92 100644 --- a/sound/soc/codecs/omap-hdmi.c +++ b/sound/soc/codecs/hdmi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA SoC codec driver for HDMI audio on OMAP processors. | 2 | * ALSA SoC codec driver for HDMI audio codecs. |
3 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ | 3 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ |
4 | * Author: Ricardo Neri <ricardo.neri@ti.com> | 4 | * Author: Ricardo Neri <ricardo.neri@ti.com> |
5 | * | 5 | * |
@@ -23,10 +23,10 @@ | |||
23 | 23 | ||
24 | #define DRV_NAME "hdmi-audio-codec" | 24 | #define DRV_NAME "hdmi-audio-codec" |
25 | 25 | ||
26 | static struct snd_soc_codec_driver omap_hdmi_codec; | 26 | static struct snd_soc_codec_driver hdmi_codec; |
27 | 27 | ||
28 | static struct snd_soc_dai_driver omap_hdmi_codec_dai = { | 28 | static struct snd_soc_dai_driver hdmi_codec_dai = { |
29 | .name = "omap-hdmi-hifi", | 29 | .name = "hdmi-hifi", |
30 | .playback = { | 30 | .playback = { |
31 | .channels_min = 2, | 31 | .channels_min = 2, |
32 | .channels_max = 8, | 32 | .channels_max = 8, |
@@ -39,31 +39,31 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = { | |||
39 | }, | 39 | }, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int omap_hdmi_codec_probe(struct platform_device *pdev) | 42 | static int hdmi_codec_probe(struct platform_device *pdev) |
43 | { | 43 | { |
44 | return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec, | 44 | return snd_soc_register_codec(&pdev->dev, &hdmi_codec, |
45 | &omap_hdmi_codec_dai, 1); | 45 | &hdmi_codec_dai, 1); |
46 | } | 46 | } |
47 | 47 | ||
48 | static int omap_hdmi_codec_remove(struct platform_device *pdev) | 48 | static int hdmi_codec_remove(struct platform_device *pdev) |
49 | { | 49 | { |
50 | snd_soc_unregister_codec(&pdev->dev); | 50 | snd_soc_unregister_codec(&pdev->dev); |
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | static struct platform_driver omap_hdmi_codec_driver = { | 54 | static struct platform_driver hdmi_codec_driver = { |
55 | .driver = { | 55 | .driver = { |
56 | .name = DRV_NAME, | 56 | .name = DRV_NAME, |
57 | .owner = THIS_MODULE, | 57 | .owner = THIS_MODULE, |
58 | }, | 58 | }, |
59 | 59 | ||
60 | .probe = omap_hdmi_codec_probe, | 60 | .probe = hdmi_codec_probe, |
61 | .remove = omap_hdmi_codec_remove, | 61 | .remove = hdmi_codec_remove, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | module_platform_driver(omap_hdmi_codec_driver); | 64 | module_platform_driver(hdmi_codec_driver); |
65 | 65 | ||
66 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); | 66 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); |
67 | MODULE_DESCRIPTION("ASoC OMAP HDMI codec driver"); | 67 | MODULE_DESCRIPTION("ASoC generic HDMI codec driver"); |
68 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
69 | MODULE_ALIAS("platform:" DRV_NAME); | 69 | MODULE_ALIAS("platform:" DRV_NAME); |
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 5f607b35b68b..bcebd1a9ce31 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -384,8 +384,6 @@ static int jz4740_codec_remove(struct platform_device *pdev) | |||
384 | { | 384 | { |
385 | snd_soc_unregister_codec(&pdev->dev); | 385 | snd_soc_unregister_codec(&pdev->dev); |
386 | 386 | ||
387 | platform_set_drvdata(pdev, NULL); | ||
388 | |||
389 | return 0; | 387 | return 0; |
390 | } | 388 | } |
391 | 389 | ||
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 8d14a76c7249..ad5313f98f28 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -857,6 +857,14 @@ static const struct soc_enum mic2_mux_enum = | |||
857 | static const struct snd_kcontrol_new max98090_mic2_mux = | 857 | static const struct snd_kcontrol_new max98090_mic2_mux = |
858 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); | 858 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); |
859 | 859 | ||
860 | static const char *dmic_mux_text[] = { "ADC", "DMIC" }; | ||
861 | |||
862 | static const struct soc_enum dmic_mux_enum = | ||
863 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); | ||
864 | |||
865 | static const struct snd_kcontrol_new max98090_dmic_mux = | ||
866 | SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); | ||
867 | |||
860 | static const char *max98090_micpre_text[] = { "Off", "On" }; | 868 | static const char *max98090_micpre_text[] = { "Off", "On" }; |
861 | 869 | ||
862 | static const struct soc_enum max98090_pa1en_enum = | 870 | static const struct soc_enum max98090_pa1en_enum = |
@@ -1144,6 +1152,9 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | |||
1144 | SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM, | 1152 | SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM, |
1145 | 0, 0, &max98090_mic2_mux), | 1153 | 0, 0, &max98090_mic2_mux), |
1146 | 1154 | ||
1155 | SND_SOC_DAPM_VIRT_MUX("DMIC Mux", SND_SOC_NOPM, | ||
1156 | 0, 0, &max98090_dmic_mux), | ||
1157 | |||
1147 | SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL, | 1158 | SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL, |
1148 | M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event, | 1159 | M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event, |
1149 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | 1160 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
@@ -1336,11 +1347,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1336 | {"ADCL", NULL, "SHDN"}, | 1347 | {"ADCL", NULL, "SHDN"}, |
1337 | {"ADCR", NULL, "SHDN"}, | 1348 | {"ADCR", NULL, "SHDN"}, |
1338 | 1349 | ||
1339 | {"LBENL Mux", "Normal", "ADCL"}, | 1350 | {"DMIC Mux", "ADC", "ADCL"}, |
1340 | {"LBENL Mux", "Normal", "DMICL"}, | 1351 | {"DMIC Mux", "ADC", "ADCR"}, |
1352 | {"DMIC Mux", "DMIC", "DMICL"}, | ||
1353 | {"DMIC Mux", "DMIC", "DMICR"}, | ||
1354 | |||
1355 | {"LBENL Mux", "Normal", "DMIC Mux"}, | ||
1341 | {"LBENL Mux", "Loopback", "LTENL Mux"}, | 1356 | {"LBENL Mux", "Loopback", "LTENL Mux"}, |
1342 | {"LBENR Mux", "Normal", "ADCR"}, | 1357 | {"LBENR Mux", "Normal", "DMIC Mux"}, |
1343 | {"LBENR Mux", "Normal", "DMICR"}, | ||
1344 | {"LBENR Mux", "Loopback", "LTENR Mux"}, | 1358 | {"LBENR Mux", "Loopback", "LTENR Mux"}, |
1345 | 1359 | ||
1346 | {"AIFOUTL", NULL, "LBENL Mux"}, | 1360 | {"AIFOUTL", NULL, "LBENL Mux"}, |
@@ -2336,6 +2350,7 @@ static int max98090_i2c_remove(struct i2c_client *client) | |||
2336 | return 0; | 2350 | return 0; |
2337 | } | 2351 | } |
2338 | 2352 | ||
2353 | #ifdef CONFIG_PM_RUNTIME | ||
2339 | static int max98090_runtime_resume(struct device *dev) | 2354 | static int max98090_runtime_resume(struct device *dev) |
2340 | { | 2355 | { |
2341 | struct max98090_priv *max98090 = dev_get_drvdata(dev); | 2356 | struct max98090_priv *max98090 = dev_get_drvdata(dev); |
@@ -2355,6 +2370,7 @@ static int max98090_runtime_suspend(struct device *dev) | |||
2355 | 2370 | ||
2356 | return 0; | 2371 | return 0; |
2357 | } | 2372 | } |
2373 | #endif | ||
2358 | 2374 | ||
2359 | static const struct dev_pm_ops max98090_pm = { | 2375 | static const struct dev_pm_ops max98090_pm = { |
2360 | SET_RUNTIME_PM_OPS(max98090_runtime_suspend, | 2376 | SET_RUNTIME_PM_OPS(max98090_runtime_suspend, |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c new file mode 100644 index 000000000000..ce585e37e38a --- /dev/null +++ b/sound/soc/codecs/rt5640.c | |||
@@ -0,0 +1,2128 @@ | |||
1 | /* | ||
2 | * rt5640.c -- RT5640 ALSA SoC audio codec driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Semiconductor Corp. | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <linux/of_gpio.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/spi/spi.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/initval.h> | ||
30 | #include <sound/tlv.h> | ||
31 | |||
32 | #include "rt5640.h" | ||
33 | |||
34 | #define RT5640_DEVICE_ID 0x6231 | ||
35 | |||
36 | #define RT5640_PR_RANGE_BASE (0xff + 1) | ||
37 | #define RT5640_PR_SPACING 0x100 | ||
38 | |||
39 | #define RT5640_PR_BASE (RT5640_PR_RANGE_BASE + (0 * RT5640_PR_SPACING)) | ||
40 | |||
41 | static const struct regmap_range_cfg rt5640_ranges[] = { | ||
42 | { .name = "PR", .range_min = RT5640_PR_BASE, | ||
43 | .range_max = RT5640_PR_BASE + 0xb4, | ||
44 | .selector_reg = RT5640_PRIV_INDEX, | ||
45 | .selector_mask = 0xff, | ||
46 | .selector_shift = 0x0, | ||
47 | .window_start = RT5640_PRIV_DATA, | ||
48 | .window_len = 0x1, }, | ||
49 | }; | ||
50 | |||
51 | static struct reg_default init_list[] = { | ||
52 | {RT5640_PR_BASE + 0x3d, 0x3600}, | ||
53 | {RT5640_PR_BASE + 0x1c, 0x0D21}, | ||
54 | {RT5640_PR_BASE + 0x1b, 0x0000}, | ||
55 | {RT5640_PR_BASE + 0x12, 0x0aa8}, | ||
56 | {RT5640_PR_BASE + 0x14, 0x0aaa}, | ||
57 | {RT5640_PR_BASE + 0x20, 0x6110}, | ||
58 | {RT5640_PR_BASE + 0x21, 0xe0e0}, | ||
59 | {RT5640_PR_BASE + 0x23, 0x1804}, | ||
60 | }; | ||
61 | #define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list) | ||
62 | |||
63 | static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = { | ||
64 | { 0x00, 0x000e }, | ||
65 | { 0x01, 0xc8c8 }, | ||
66 | { 0x02, 0xc8c8 }, | ||
67 | { 0x03, 0xc8c8 }, | ||
68 | { 0x04, 0x8000 }, | ||
69 | { 0x0d, 0x0000 }, | ||
70 | { 0x0e, 0x0000 }, | ||
71 | { 0x0f, 0x0808 }, | ||
72 | { 0x19, 0xafaf }, | ||
73 | { 0x1a, 0xafaf }, | ||
74 | { 0x1b, 0x0000 }, | ||
75 | { 0x1c, 0x2f2f }, | ||
76 | { 0x1d, 0x2f2f }, | ||
77 | { 0x1e, 0x0000 }, | ||
78 | { 0x27, 0x7060 }, | ||
79 | { 0x28, 0x7070 }, | ||
80 | { 0x29, 0x8080 }, | ||
81 | { 0x2a, 0x5454 }, | ||
82 | { 0x2b, 0x5454 }, | ||
83 | { 0x2c, 0xaa00 }, | ||
84 | { 0x2d, 0x0000 }, | ||
85 | { 0x2e, 0xa000 }, | ||
86 | { 0x2f, 0x0000 }, | ||
87 | { 0x3b, 0x0000 }, | ||
88 | { 0x3c, 0x007f }, | ||
89 | { 0x3d, 0x0000 }, | ||
90 | { 0x3e, 0x007f }, | ||
91 | { 0x45, 0xe000 }, | ||
92 | { 0x46, 0x003e }, | ||
93 | { 0x47, 0x003e }, | ||
94 | { 0x48, 0xf800 }, | ||
95 | { 0x49, 0x3800 }, | ||
96 | { 0x4a, 0x0004 }, | ||
97 | { 0x4c, 0xfc00 }, | ||
98 | { 0x4d, 0x0000 }, | ||
99 | { 0x4f, 0x01ff }, | ||
100 | { 0x50, 0x0000 }, | ||
101 | { 0x51, 0x0000 }, | ||
102 | { 0x52, 0x01ff }, | ||
103 | { 0x53, 0xf000 }, | ||
104 | { 0x61, 0x0000 }, | ||
105 | { 0x62, 0x0000 }, | ||
106 | { 0x63, 0x00c0 }, | ||
107 | { 0x64, 0x0000 }, | ||
108 | { 0x65, 0x0000 }, | ||
109 | { 0x66, 0x0000 }, | ||
110 | { 0x6a, 0x0000 }, | ||
111 | { 0x6c, 0x0000 }, | ||
112 | { 0x70, 0x8000 }, | ||
113 | { 0x71, 0x8000 }, | ||
114 | { 0x72, 0x8000 }, | ||
115 | { 0x73, 0x1114 }, | ||
116 | { 0x74, 0x0c00 }, | ||
117 | { 0x75, 0x1d00 }, | ||
118 | { 0x80, 0x0000 }, | ||
119 | { 0x81, 0x0000 }, | ||
120 | { 0x82, 0x0000 }, | ||
121 | { 0x83, 0x0000 }, | ||
122 | { 0x84, 0x0000 }, | ||
123 | { 0x85, 0x0008 }, | ||
124 | { 0x89, 0x0000 }, | ||
125 | { 0x8a, 0x0000 }, | ||
126 | { 0x8b, 0x0600 }, | ||
127 | { 0x8c, 0x0228 }, | ||
128 | { 0x8d, 0xa000 }, | ||
129 | { 0x8e, 0x0004 }, | ||
130 | { 0x8f, 0x1100 }, | ||
131 | { 0x90, 0x0646 }, | ||
132 | { 0x91, 0x0c00 }, | ||
133 | { 0x92, 0x0000 }, | ||
134 | { 0x93, 0x3000 }, | ||
135 | { 0xb0, 0x2080 }, | ||
136 | { 0xb1, 0x0000 }, | ||
137 | { 0xb4, 0x2206 }, | ||
138 | { 0xb5, 0x1f00 }, | ||
139 | { 0xb6, 0x0000 }, | ||
140 | { 0xb8, 0x034b }, | ||
141 | { 0xb9, 0x0066 }, | ||
142 | { 0xba, 0x000b }, | ||
143 | { 0xbb, 0x0000 }, | ||
144 | { 0xbc, 0x0000 }, | ||
145 | { 0xbd, 0x0000 }, | ||
146 | { 0xbe, 0x0000 }, | ||
147 | { 0xbf, 0x0000 }, | ||
148 | { 0xc0, 0x0400 }, | ||
149 | { 0xc2, 0x0000 }, | ||
150 | { 0xc4, 0x0000 }, | ||
151 | { 0xc5, 0x0000 }, | ||
152 | { 0xc6, 0x2000 }, | ||
153 | { 0xc8, 0x0000 }, | ||
154 | { 0xc9, 0x0000 }, | ||
155 | { 0xca, 0x0000 }, | ||
156 | { 0xcb, 0x0000 }, | ||
157 | { 0xcc, 0x0000 }, | ||
158 | { 0xcf, 0x0013 }, | ||
159 | { 0xd0, 0x0680 }, | ||
160 | { 0xd1, 0x1c17 }, | ||
161 | { 0xd2, 0x8c00 }, | ||
162 | { 0xd3, 0xaa20 }, | ||
163 | { 0xd6, 0x0400 }, | ||
164 | { 0xd9, 0x0809 }, | ||
165 | { 0xfe, 0x10ec }, | ||
166 | { 0xff, 0x6231 }, | ||
167 | }; | ||
168 | |||
169 | static int rt5640_reset(struct snd_soc_codec *codec) | ||
170 | { | ||
171 | return snd_soc_write(codec, RT5640_RESET, 0); | ||
172 | } | ||
173 | |||
174 | static bool rt5640_volatile_register(struct device *dev, unsigned int reg) | ||
175 | { | ||
176 | int i; | ||
177 | |||
178 | for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++) | ||
179 | if ((reg >= rt5640_ranges[i].window_start && | ||
180 | reg <= rt5640_ranges[i].window_start + | ||
181 | rt5640_ranges[i].window_len) || | ||
182 | (reg >= rt5640_ranges[i].range_min && | ||
183 | reg <= rt5640_ranges[i].range_max)) | ||
184 | return true; | ||
185 | |||
186 | switch (reg) { | ||
187 | case RT5640_RESET: | ||
188 | case RT5640_ASRC_5: | ||
189 | case RT5640_EQ_CTRL1: | ||
190 | case RT5640_DRC_AGC_1: | ||
191 | case RT5640_ANC_CTRL1: | ||
192 | case RT5640_IRQ_CTRL2: | ||
193 | case RT5640_INT_IRQ_ST: | ||
194 | case RT5640_DSP_CTRL2: | ||
195 | case RT5640_DSP_CTRL3: | ||
196 | case RT5640_PRIV_INDEX: | ||
197 | case RT5640_PRIV_DATA: | ||
198 | case RT5640_PGM_REG_ARR1: | ||
199 | case RT5640_PGM_REG_ARR3: | ||
200 | case RT5640_VENDOR_ID: | ||
201 | case RT5640_VENDOR_ID1: | ||
202 | case RT5640_VENDOR_ID2: | ||
203 | return true; | ||
204 | default: | ||
205 | return false; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | static bool rt5640_readable_register(struct device *dev, unsigned int reg) | ||
210 | { | ||
211 | int i; | ||
212 | |||
213 | for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++) | ||
214 | if ((reg >= rt5640_ranges[i].window_start && | ||
215 | reg <= rt5640_ranges[i].window_start + | ||
216 | rt5640_ranges[i].window_len) || | ||
217 | (reg >= rt5640_ranges[i].range_min && | ||
218 | reg <= rt5640_ranges[i].range_max)) | ||
219 | return true; | ||
220 | |||
221 | switch (reg) { | ||
222 | case RT5640_RESET: | ||
223 | case RT5640_SPK_VOL: | ||
224 | case RT5640_HP_VOL: | ||
225 | case RT5640_OUTPUT: | ||
226 | case RT5640_MONO_OUT: | ||
227 | case RT5640_IN1_IN2: | ||
228 | case RT5640_IN3_IN4: | ||
229 | case RT5640_INL_INR_VOL: | ||
230 | case RT5640_DAC1_DIG_VOL: | ||
231 | case RT5640_DAC2_DIG_VOL: | ||
232 | case RT5640_DAC2_CTRL: | ||
233 | case RT5640_ADC_DIG_VOL: | ||
234 | case RT5640_ADC_DATA: | ||
235 | case RT5640_ADC_BST_VOL: | ||
236 | case RT5640_STO_ADC_MIXER: | ||
237 | case RT5640_MONO_ADC_MIXER: | ||
238 | case RT5640_AD_DA_MIXER: | ||
239 | case RT5640_STO_DAC_MIXER: | ||
240 | case RT5640_MONO_DAC_MIXER: | ||
241 | case RT5640_DIG_MIXER: | ||
242 | case RT5640_DSP_PATH1: | ||
243 | case RT5640_DSP_PATH2: | ||
244 | case RT5640_DIG_INF_DATA: | ||
245 | case RT5640_REC_L1_MIXER: | ||
246 | case RT5640_REC_L2_MIXER: | ||
247 | case RT5640_REC_R1_MIXER: | ||
248 | case RT5640_REC_R2_MIXER: | ||
249 | case RT5640_HPO_MIXER: | ||
250 | case RT5640_SPK_L_MIXER: | ||
251 | case RT5640_SPK_R_MIXER: | ||
252 | case RT5640_SPO_L_MIXER: | ||
253 | case RT5640_SPO_R_MIXER: | ||
254 | case RT5640_SPO_CLSD_RATIO: | ||
255 | case RT5640_MONO_MIXER: | ||
256 | case RT5640_OUT_L1_MIXER: | ||
257 | case RT5640_OUT_L2_MIXER: | ||
258 | case RT5640_OUT_L3_MIXER: | ||
259 | case RT5640_OUT_R1_MIXER: | ||
260 | case RT5640_OUT_R2_MIXER: | ||
261 | case RT5640_OUT_R3_MIXER: | ||
262 | case RT5640_LOUT_MIXER: | ||
263 | case RT5640_PWR_DIG1: | ||
264 | case RT5640_PWR_DIG2: | ||
265 | case RT5640_PWR_ANLG1: | ||
266 | case RT5640_PWR_ANLG2: | ||
267 | case RT5640_PWR_MIXER: | ||
268 | case RT5640_PWR_VOL: | ||
269 | case RT5640_PRIV_INDEX: | ||
270 | case RT5640_PRIV_DATA: | ||
271 | case RT5640_I2S1_SDP: | ||
272 | case RT5640_I2S2_SDP: | ||
273 | case RT5640_ADDA_CLK1: | ||
274 | case RT5640_ADDA_CLK2: | ||
275 | case RT5640_DMIC: | ||
276 | case RT5640_GLB_CLK: | ||
277 | case RT5640_PLL_CTRL1: | ||
278 | case RT5640_PLL_CTRL2: | ||
279 | case RT5640_ASRC_1: | ||
280 | case RT5640_ASRC_2: | ||
281 | case RT5640_ASRC_3: | ||
282 | case RT5640_ASRC_4: | ||
283 | case RT5640_ASRC_5: | ||
284 | case RT5640_HP_OVCD: | ||
285 | case RT5640_CLS_D_OVCD: | ||
286 | case RT5640_CLS_D_OUT: | ||
287 | case RT5640_DEPOP_M1: | ||
288 | case RT5640_DEPOP_M2: | ||
289 | case RT5640_DEPOP_M3: | ||
290 | case RT5640_CHARGE_PUMP: | ||
291 | case RT5640_PV_DET_SPK_G: | ||
292 | case RT5640_MICBIAS: | ||
293 | case RT5640_EQ_CTRL1: | ||
294 | case RT5640_EQ_CTRL2: | ||
295 | case RT5640_WIND_FILTER: | ||
296 | case RT5640_DRC_AGC_1: | ||
297 | case RT5640_DRC_AGC_2: | ||
298 | case RT5640_DRC_AGC_3: | ||
299 | case RT5640_SVOL_ZC: | ||
300 | case RT5640_ANC_CTRL1: | ||
301 | case RT5640_ANC_CTRL2: | ||
302 | case RT5640_ANC_CTRL3: | ||
303 | case RT5640_JD_CTRL: | ||
304 | case RT5640_ANC_JD: | ||
305 | case RT5640_IRQ_CTRL1: | ||
306 | case RT5640_IRQ_CTRL2: | ||
307 | case RT5640_INT_IRQ_ST: | ||
308 | case RT5640_GPIO_CTRL1: | ||
309 | case RT5640_GPIO_CTRL2: | ||
310 | case RT5640_GPIO_CTRL3: | ||
311 | case RT5640_DSP_CTRL1: | ||
312 | case RT5640_DSP_CTRL2: | ||
313 | case RT5640_DSP_CTRL3: | ||
314 | case RT5640_DSP_CTRL4: | ||
315 | case RT5640_PGM_REG_ARR1: | ||
316 | case RT5640_PGM_REG_ARR2: | ||
317 | case RT5640_PGM_REG_ARR3: | ||
318 | case RT5640_PGM_REG_ARR4: | ||
319 | case RT5640_PGM_REG_ARR5: | ||
320 | case RT5640_SCB_FUNC: | ||
321 | case RT5640_SCB_CTRL: | ||
322 | case RT5640_BASE_BACK: | ||
323 | case RT5640_MP3_PLUS1: | ||
324 | case RT5640_MP3_PLUS2: | ||
325 | case RT5640_3D_HP: | ||
326 | case RT5640_ADJ_HPF: | ||
327 | case RT5640_HP_CALIB_AMP_DET: | ||
328 | case RT5640_HP_CALIB2: | ||
329 | case RT5640_SV_ZCD1: | ||
330 | case RT5640_SV_ZCD2: | ||
331 | case RT5640_DUMMY1: | ||
332 | case RT5640_DUMMY2: | ||
333 | case RT5640_DUMMY3: | ||
334 | case RT5640_VENDOR_ID: | ||
335 | case RT5640_VENDOR_ID1: | ||
336 | case RT5640_VENDOR_ID2: | ||
337 | return true; | ||
338 | default: | ||
339 | return false; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | ||
344 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | ||
345 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | ||
346 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | ||
347 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | ||
348 | |||
349 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | ||
350 | static unsigned int bst_tlv[] = { | ||
351 | TLV_DB_RANGE_HEAD(7), | ||
352 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
353 | 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), | ||
354 | 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), | ||
355 | 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), | ||
356 | 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), | ||
357 | 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), | ||
358 | 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), | ||
359 | }; | ||
360 | |||
361 | /* Interface data select */ | ||
362 | static const char * const rt5640_data_select[] = { | ||
363 | "Normal", "left copy to right", "right copy to left", "Swap"}; | ||
364 | |||
365 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, | ||
366 | RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); | ||
367 | |||
368 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, | ||
369 | RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); | ||
370 | |||
371 | static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, | ||
372 | RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); | ||
373 | |||
374 | static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, | ||
375 | RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); | ||
376 | |||
377 | /* Class D speaker gain ratio */ | ||
378 | static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", | ||
379 | "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; | ||
380 | |||
381 | static const SOC_ENUM_SINGLE_DECL( | ||
382 | rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, | ||
383 | RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); | ||
384 | |||
385 | static const struct snd_kcontrol_new rt5640_snd_controls[] = { | ||
386 | /* Speaker Output Volume */ | ||
387 | SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL, | ||
388 | RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | ||
389 | SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL, | ||
390 | RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1), | ||
391 | SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL, | ||
392 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv), | ||
393 | /* Headphone Output Volume */ | ||
394 | SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL, | ||
395 | RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | ||
396 | SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL, | ||
397 | RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1), | ||
398 | SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL, | ||
399 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv), | ||
400 | /* OUTPUT Control */ | ||
401 | SOC_DOUBLE("OUT Playback Switch", RT5640_OUTPUT, | ||
402 | RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | ||
403 | SOC_DOUBLE("OUT Channel Switch", RT5640_OUTPUT, | ||
404 | RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1), | ||
405 | SOC_DOUBLE_TLV("OUT Playback Volume", RT5640_OUTPUT, | ||
406 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv), | ||
407 | /* MONO Output Control */ | ||
408 | SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT, | ||
409 | RT5640_L_MUTE_SFT, 1, 1), | ||
410 | /* DAC Digital Volume */ | ||
411 | SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL, | ||
412 | RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1), | ||
413 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL, | ||
414 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, | ||
415 | 175, 0, dac_vol_tlv), | ||
416 | SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL, | ||
417 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, | ||
418 | 175, 0, dac_vol_tlv), | ||
419 | /* IN1/IN2 Control */ | ||
420 | SOC_SINGLE_TLV("IN1 Boost", RT5640_IN1_IN2, | ||
421 | RT5640_BST_SFT1, 8, 0, bst_tlv), | ||
422 | SOC_SINGLE_TLV("IN2 Boost", RT5640_IN3_IN4, | ||
423 | RT5640_BST_SFT2, 8, 0, bst_tlv), | ||
424 | /* INL/INR Volume Control */ | ||
425 | SOC_DOUBLE_TLV("IN Capture Volume", RT5640_INL_INR_VOL, | ||
426 | RT5640_INL_VOL_SFT, RT5640_INR_VOL_SFT, | ||
427 | 31, 1, in_vol_tlv), | ||
428 | /* ADC Digital Volume Control */ | ||
429 | SOC_DOUBLE("ADC Capture Switch", RT5640_ADC_DIG_VOL, | ||
430 | RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | ||
431 | SOC_DOUBLE_TLV("ADC Capture Volume", RT5640_ADC_DIG_VOL, | ||
432 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, | ||
433 | 127, 0, adc_vol_tlv), | ||
434 | SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5640_ADC_DATA, | ||
435 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, | ||
436 | 127, 0, adc_vol_tlv), | ||
437 | /* ADC Boost Volume Control */ | ||
438 | SOC_DOUBLE_TLV("ADC Boost Gain", RT5640_ADC_BST_VOL, | ||
439 | RT5640_ADC_L_BST_SFT, RT5640_ADC_R_BST_SFT, | ||
440 | 3, 0, adc_bst_tlv), | ||
441 | /* Class D speaker gain ratio */ | ||
442 | SOC_ENUM("Class D SPK Ratio Control", rt5640_clsd_spk_ratio_enum), | ||
443 | |||
444 | SOC_ENUM("ADC IF1 Data Switch", rt5640_if1_adc_enum), | ||
445 | SOC_ENUM("DAC IF1 Data Switch", rt5640_if1_dac_enum), | ||
446 | SOC_ENUM("ADC IF2 Data Switch", rt5640_if2_adc_enum), | ||
447 | SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum), | ||
448 | }; | ||
449 | |||
450 | /** | ||
451 | * set_dmic_clk - Set parameter of dmic. | ||
452 | * | ||
453 | * @w: DAPM widget. | ||
454 | * @kcontrol: The kcontrol of this widget. | ||
455 | * @event: Event id. | ||
456 | * | ||
457 | * Choose dmic clock between 1MHz and 3MHz. | ||
458 | * It is better for clock to approximate 3MHz. | ||
459 | */ | ||
460 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | ||
461 | struct snd_kcontrol *kcontrol, int event) | ||
462 | { | ||
463 | struct snd_soc_codec *codec = w->codec; | ||
464 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
465 | int div[] = {2, 3, 4, 6, 8, 12}; | ||
466 | int idx = -EINVAL, i; | ||
467 | int rate, red, bound, temp; | ||
468 | |||
469 | rate = rt5640->sysclk; | ||
470 | red = 3000000 * 12; | ||
471 | for (i = 0; i < ARRAY_SIZE(div); i++) { | ||
472 | bound = div[i] * 3000000; | ||
473 | if (rate > bound) | ||
474 | continue; | ||
475 | temp = bound - rate; | ||
476 | if (temp < red) { | ||
477 | red = temp; | ||
478 | idx = i; | ||
479 | } | ||
480 | } | ||
481 | if (idx < 0) | ||
482 | dev_err(codec->dev, "Failed to set DMIC clock\n"); | ||
483 | else | ||
484 | snd_soc_update_bits(codec, RT5640_DMIC, RT5640_DMIC_CLK_MASK, | ||
485 | idx << RT5640_DMIC_CLK_SFT); | ||
486 | return idx; | ||
487 | } | ||
488 | |||
489 | static int check_sysclk1_source(struct snd_soc_dapm_widget *source, | ||
490 | struct snd_soc_dapm_widget *sink) | ||
491 | { | ||
492 | unsigned int val; | ||
493 | |||
494 | val = snd_soc_read(source->codec, RT5640_GLB_CLK); | ||
495 | val &= RT5640_SCLK_SRC_MASK; | ||
496 | if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T) | ||
497 | return 1; | ||
498 | else | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /* Digital Mixer */ | ||
503 | static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = { | ||
504 | SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER, | ||
505 | RT5640_M_ADC_L1_SFT, 1, 1), | ||
506 | SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER, | ||
507 | RT5640_M_ADC_L2_SFT, 1, 1), | ||
508 | }; | ||
509 | |||
510 | static const struct snd_kcontrol_new rt5640_sto_adc_r_mix[] = { | ||
511 | SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER, | ||
512 | RT5640_M_ADC_R1_SFT, 1, 1), | ||
513 | SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER, | ||
514 | RT5640_M_ADC_R2_SFT, 1, 1), | ||
515 | }; | ||
516 | |||
517 | static const struct snd_kcontrol_new rt5640_mono_adc_l_mix[] = { | ||
518 | SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER, | ||
519 | RT5640_M_MONO_ADC_L1_SFT, 1, 1), | ||
520 | SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER, | ||
521 | RT5640_M_MONO_ADC_L2_SFT, 1, 1), | ||
522 | }; | ||
523 | |||
524 | static const struct snd_kcontrol_new rt5640_mono_adc_r_mix[] = { | ||
525 | SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER, | ||
526 | RT5640_M_MONO_ADC_R1_SFT, 1, 1), | ||
527 | SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER, | ||
528 | RT5640_M_MONO_ADC_R2_SFT, 1, 1), | ||
529 | }; | ||
530 | |||
531 | static const struct snd_kcontrol_new rt5640_dac_l_mix[] = { | ||
532 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER, | ||
533 | RT5640_M_ADCMIX_L_SFT, 1, 1), | ||
534 | SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER, | ||
535 | RT5640_M_IF1_DAC_L_SFT, 1, 1), | ||
536 | }; | ||
537 | |||
538 | static const struct snd_kcontrol_new rt5640_dac_r_mix[] = { | ||
539 | SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER, | ||
540 | RT5640_M_ADCMIX_R_SFT, 1, 1), | ||
541 | SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER, | ||
542 | RT5640_M_IF1_DAC_R_SFT, 1, 1), | ||
543 | }; | ||
544 | |||
545 | static const struct snd_kcontrol_new rt5640_sto_dac_l_mix[] = { | ||
546 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_STO_DAC_MIXER, | ||
547 | RT5640_M_DAC_L1_SFT, 1, 1), | ||
548 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_STO_DAC_MIXER, | ||
549 | RT5640_M_DAC_L2_SFT, 1, 1), | ||
550 | SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER, | ||
551 | RT5640_M_ANC_DAC_L_SFT, 1, 1), | ||
552 | }; | ||
553 | |||
554 | static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = { | ||
555 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_STO_DAC_MIXER, | ||
556 | RT5640_M_DAC_R1_SFT, 1, 1), | ||
557 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_STO_DAC_MIXER, | ||
558 | RT5640_M_DAC_R2_SFT, 1, 1), | ||
559 | SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER, | ||
560 | RT5640_M_ANC_DAC_R_SFT, 1, 1), | ||
561 | }; | ||
562 | |||
563 | static const struct snd_kcontrol_new rt5640_mono_dac_l_mix[] = { | ||
564 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_MONO_DAC_MIXER, | ||
565 | RT5640_M_DAC_L1_MONO_L_SFT, 1, 1), | ||
566 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER, | ||
567 | RT5640_M_DAC_L2_MONO_L_SFT, 1, 1), | ||
568 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER, | ||
569 | RT5640_M_DAC_R2_MONO_L_SFT, 1, 1), | ||
570 | }; | ||
571 | |||
572 | static const struct snd_kcontrol_new rt5640_mono_dac_r_mix[] = { | ||
573 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_MONO_DAC_MIXER, | ||
574 | RT5640_M_DAC_R1_MONO_R_SFT, 1, 1), | ||
575 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER, | ||
576 | RT5640_M_DAC_R2_MONO_R_SFT, 1, 1), | ||
577 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER, | ||
578 | RT5640_M_DAC_L2_MONO_R_SFT, 1, 1), | ||
579 | }; | ||
580 | |||
581 | static const struct snd_kcontrol_new rt5640_dig_l_mix[] = { | ||
582 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_DIG_MIXER, | ||
583 | RT5640_M_STO_L_DAC_L_SFT, 1, 1), | ||
584 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_DIG_MIXER, | ||
585 | RT5640_M_DAC_L2_DAC_L_SFT, 1, 1), | ||
586 | }; | ||
587 | |||
588 | static const struct snd_kcontrol_new rt5640_dig_r_mix[] = { | ||
589 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_DIG_MIXER, | ||
590 | RT5640_M_STO_R_DAC_R_SFT, 1, 1), | ||
591 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_DIG_MIXER, | ||
592 | RT5640_M_DAC_R2_DAC_R_SFT, 1, 1), | ||
593 | }; | ||
594 | |||
595 | /* Analog Input Mixer */ | ||
596 | static const struct snd_kcontrol_new rt5640_rec_l_mix[] = { | ||
597 | SOC_DAPM_SINGLE("HPOL Switch", RT5640_REC_L2_MIXER, | ||
598 | RT5640_M_HP_L_RM_L_SFT, 1, 1), | ||
599 | SOC_DAPM_SINGLE("INL Switch", RT5640_REC_L2_MIXER, | ||
600 | RT5640_M_IN_L_RM_L_SFT, 1, 1), | ||
601 | SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_L2_MIXER, | ||
602 | RT5640_M_BST4_RM_L_SFT, 1, 1), | ||
603 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_L2_MIXER, | ||
604 | RT5640_M_BST1_RM_L_SFT, 1, 1), | ||
605 | SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_REC_L2_MIXER, | ||
606 | RT5640_M_OM_L_RM_L_SFT, 1, 1), | ||
607 | }; | ||
608 | |||
609 | static const struct snd_kcontrol_new rt5640_rec_r_mix[] = { | ||
610 | SOC_DAPM_SINGLE("HPOR Switch", RT5640_REC_R2_MIXER, | ||
611 | RT5640_M_HP_R_RM_R_SFT, 1, 1), | ||
612 | SOC_DAPM_SINGLE("INR Switch", RT5640_REC_R2_MIXER, | ||
613 | RT5640_M_IN_R_RM_R_SFT, 1, 1), | ||
614 | SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_R2_MIXER, | ||
615 | RT5640_M_BST4_RM_R_SFT, 1, 1), | ||
616 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_R2_MIXER, | ||
617 | RT5640_M_BST1_RM_R_SFT, 1, 1), | ||
618 | SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_REC_R2_MIXER, | ||
619 | RT5640_M_OM_R_RM_R_SFT, 1, 1), | ||
620 | }; | ||
621 | |||
622 | /* Analog Output Mixer */ | ||
623 | static const struct snd_kcontrol_new rt5640_spk_l_mix[] = { | ||
624 | SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_SPK_L_MIXER, | ||
625 | RT5640_M_RM_L_SM_L_SFT, 1, 1), | ||
626 | SOC_DAPM_SINGLE("INL Switch", RT5640_SPK_L_MIXER, | ||
627 | RT5640_M_IN_L_SM_L_SFT, 1, 1), | ||
628 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPK_L_MIXER, | ||
629 | RT5640_M_DAC_L1_SM_L_SFT, 1, 1), | ||
630 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_SPK_L_MIXER, | ||
631 | RT5640_M_DAC_L2_SM_L_SFT, 1, 1), | ||
632 | SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_SPK_L_MIXER, | ||
633 | RT5640_M_OM_L_SM_L_SFT, 1, 1), | ||
634 | }; | ||
635 | |||
636 | static const struct snd_kcontrol_new rt5640_spk_r_mix[] = { | ||
637 | SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_SPK_R_MIXER, | ||
638 | RT5640_M_RM_R_SM_R_SFT, 1, 1), | ||
639 | SOC_DAPM_SINGLE("INR Switch", RT5640_SPK_R_MIXER, | ||
640 | RT5640_M_IN_R_SM_R_SFT, 1, 1), | ||
641 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPK_R_MIXER, | ||
642 | RT5640_M_DAC_R1_SM_R_SFT, 1, 1), | ||
643 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_SPK_R_MIXER, | ||
644 | RT5640_M_DAC_R2_SM_R_SFT, 1, 1), | ||
645 | SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_SPK_R_MIXER, | ||
646 | RT5640_M_OM_R_SM_R_SFT, 1, 1), | ||
647 | }; | ||
648 | |||
649 | static const struct snd_kcontrol_new rt5640_out_l_mix[] = { | ||
650 | SOC_DAPM_SINGLE("SPK MIXL Switch", RT5640_OUT_L3_MIXER, | ||
651 | RT5640_M_SM_L_OM_L_SFT, 1, 1), | ||
652 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_L3_MIXER, | ||
653 | RT5640_M_BST1_OM_L_SFT, 1, 1), | ||
654 | SOC_DAPM_SINGLE("INL Switch", RT5640_OUT_L3_MIXER, | ||
655 | RT5640_M_IN_L_OM_L_SFT, 1, 1), | ||
656 | SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_OUT_L3_MIXER, | ||
657 | RT5640_M_RM_L_OM_L_SFT, 1, 1), | ||
658 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_L3_MIXER, | ||
659 | RT5640_M_DAC_R2_OM_L_SFT, 1, 1), | ||
660 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_L3_MIXER, | ||
661 | RT5640_M_DAC_L2_OM_L_SFT, 1, 1), | ||
662 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_OUT_L3_MIXER, | ||
663 | RT5640_M_DAC_L1_OM_L_SFT, 1, 1), | ||
664 | }; | ||
665 | |||
666 | static const struct snd_kcontrol_new rt5640_out_r_mix[] = { | ||
667 | SOC_DAPM_SINGLE("SPK MIXR Switch", RT5640_OUT_R3_MIXER, | ||
668 | RT5640_M_SM_L_OM_R_SFT, 1, 1), | ||
669 | SOC_DAPM_SINGLE("BST2 Switch", RT5640_OUT_R3_MIXER, | ||
670 | RT5640_M_BST4_OM_R_SFT, 1, 1), | ||
671 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_R3_MIXER, | ||
672 | RT5640_M_BST1_OM_R_SFT, 1, 1), | ||
673 | SOC_DAPM_SINGLE("INR Switch", RT5640_OUT_R3_MIXER, | ||
674 | RT5640_M_IN_R_OM_R_SFT, 1, 1), | ||
675 | SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_OUT_R3_MIXER, | ||
676 | RT5640_M_RM_R_OM_R_SFT, 1, 1), | ||
677 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_R3_MIXER, | ||
678 | RT5640_M_DAC_L2_OM_R_SFT, 1, 1), | ||
679 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_R3_MIXER, | ||
680 | RT5640_M_DAC_R2_OM_R_SFT, 1, 1), | ||
681 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_OUT_R3_MIXER, | ||
682 | RT5640_M_DAC_R1_OM_R_SFT, 1, 1), | ||
683 | }; | ||
684 | |||
685 | static const struct snd_kcontrol_new rt5640_spo_l_mix[] = { | ||
686 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_L_MIXER, | ||
687 | RT5640_M_DAC_R1_SPM_L_SFT, 1, 1), | ||
688 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPO_L_MIXER, | ||
689 | RT5640_M_DAC_L1_SPM_L_SFT, 1, 1), | ||
690 | SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_L_MIXER, | ||
691 | RT5640_M_SV_R_SPM_L_SFT, 1, 1), | ||
692 | SOC_DAPM_SINGLE("SPKVOL L Switch", RT5640_SPO_L_MIXER, | ||
693 | RT5640_M_SV_L_SPM_L_SFT, 1, 1), | ||
694 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_L_MIXER, | ||
695 | RT5640_M_BST1_SPM_L_SFT, 1, 1), | ||
696 | }; | ||
697 | |||
698 | static const struct snd_kcontrol_new rt5640_spo_r_mix[] = { | ||
699 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_R_MIXER, | ||
700 | RT5640_M_DAC_R1_SPM_R_SFT, 1, 1), | ||
701 | SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_R_MIXER, | ||
702 | RT5640_M_SV_R_SPM_R_SFT, 1, 1), | ||
703 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_R_MIXER, | ||
704 | RT5640_M_BST1_SPM_R_SFT, 1, 1), | ||
705 | }; | ||
706 | |||
707 | static const struct snd_kcontrol_new rt5640_hpo_mix[] = { | ||
708 | SOC_DAPM_SINGLE("HPO MIX DAC2 Switch", RT5640_HPO_MIXER, | ||
709 | RT5640_M_DAC2_HM_SFT, 1, 1), | ||
710 | SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5640_HPO_MIXER, | ||
711 | RT5640_M_DAC1_HM_SFT, 1, 1), | ||
712 | SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5640_HPO_MIXER, | ||
713 | RT5640_M_HPVOL_HM_SFT, 1, 1), | ||
714 | }; | ||
715 | |||
716 | static const struct snd_kcontrol_new rt5640_lout_mix[] = { | ||
717 | SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_LOUT_MIXER, | ||
718 | RT5640_M_DAC_L1_LM_SFT, 1, 1), | ||
719 | SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_LOUT_MIXER, | ||
720 | RT5640_M_DAC_R1_LM_SFT, 1, 1), | ||
721 | SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_LOUT_MIXER, | ||
722 | RT5640_M_OV_L_LM_SFT, 1, 1), | ||
723 | SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_LOUT_MIXER, | ||
724 | RT5640_M_OV_R_LM_SFT, 1, 1), | ||
725 | }; | ||
726 | |||
727 | static const struct snd_kcontrol_new rt5640_mono_mix[] = { | ||
728 | SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_MIXER, | ||
729 | RT5640_M_DAC_R2_MM_SFT, 1, 1), | ||
730 | SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_MIXER, | ||
731 | RT5640_M_DAC_L2_MM_SFT, 1, 1), | ||
732 | SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_MONO_MIXER, | ||
733 | RT5640_M_OV_R_MM_SFT, 1, 1), | ||
734 | SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_MONO_MIXER, | ||
735 | RT5640_M_OV_L_MM_SFT, 1, 1), | ||
736 | SOC_DAPM_SINGLE("BST1 Switch", RT5640_MONO_MIXER, | ||
737 | RT5640_M_BST1_MM_SFT, 1, 1), | ||
738 | }; | ||
739 | |||
740 | /* INL/R source */ | ||
741 | static const char * const rt5640_inl_src[] = { | ||
742 | "IN2P", "MONOP" | ||
743 | }; | ||
744 | |||
745 | static const SOC_ENUM_SINGLE_DECL( | ||
746 | rt5640_inl_enum, RT5640_INL_INR_VOL, | ||
747 | RT5640_INL_SEL_SFT, rt5640_inl_src); | ||
748 | |||
749 | static const struct snd_kcontrol_new rt5640_inl_mux = | ||
750 | SOC_DAPM_ENUM("INL source", rt5640_inl_enum); | ||
751 | |||
752 | static const char * const rt5640_inr_src[] = { | ||
753 | "IN2N", "MONON" | ||
754 | }; | ||
755 | |||
756 | static const SOC_ENUM_SINGLE_DECL( | ||
757 | rt5640_inr_enum, RT5640_INL_INR_VOL, | ||
758 | RT5640_INR_SEL_SFT, rt5640_inr_src); | ||
759 | |||
760 | static const struct snd_kcontrol_new rt5640_inr_mux = | ||
761 | SOC_DAPM_ENUM("INR source", rt5640_inr_enum); | ||
762 | |||
763 | /* Stereo ADC source */ | ||
764 | static const char * const rt5640_stereo_adc1_src[] = { | ||
765 | "DIG MIX", "ADC" | ||
766 | }; | ||
767 | |||
768 | static const SOC_ENUM_SINGLE_DECL( | ||
769 | rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, | ||
770 | RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); | ||
771 | |||
772 | static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = | ||
773 | SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); | ||
774 | |||
775 | static const char * const rt5640_stereo_adc2_src[] = { | ||
776 | "DMIC1", "DMIC2", "DIG MIX" | ||
777 | }; | ||
778 | |||
779 | static const SOC_ENUM_SINGLE_DECL( | ||
780 | rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, | ||
781 | RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); | ||
782 | |||
783 | static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = | ||
784 | SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); | ||
785 | |||
786 | /* Mono ADC source */ | ||
787 | static const char * const rt5640_mono_adc_l1_src[] = { | ||
788 | "Mono DAC MIXL", "ADCL" | ||
789 | }; | ||
790 | |||
791 | static const SOC_ENUM_SINGLE_DECL( | ||
792 | rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, | ||
793 | RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); | ||
794 | |||
795 | static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = | ||
796 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); | ||
797 | |||
798 | static const char * const rt5640_mono_adc_l2_src[] = { | ||
799 | "DMIC L1", "DMIC L2", "Mono DAC MIXL" | ||
800 | }; | ||
801 | |||
802 | static const SOC_ENUM_SINGLE_DECL( | ||
803 | rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, | ||
804 | RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); | ||
805 | |||
806 | static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = | ||
807 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); | ||
808 | |||
809 | static const char * const rt5640_mono_adc_r1_src[] = { | ||
810 | "Mono DAC MIXR", "ADCR" | ||
811 | }; | ||
812 | |||
813 | static const SOC_ENUM_SINGLE_DECL( | ||
814 | rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, | ||
815 | RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); | ||
816 | |||
817 | static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = | ||
818 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); | ||
819 | |||
820 | static const char * const rt5640_mono_adc_r2_src[] = { | ||
821 | "DMIC R1", "DMIC R2", "Mono DAC MIXR" | ||
822 | }; | ||
823 | |||
824 | static const SOC_ENUM_SINGLE_DECL( | ||
825 | rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, | ||
826 | RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); | ||
827 | |||
828 | static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = | ||
829 | SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); | ||
830 | |||
831 | /* DAC2 channel source */ | ||
832 | static const char * const rt5640_dac_l2_src[] = { | ||
833 | "IF2", "Base L/R" | ||
834 | }; | ||
835 | |||
836 | static int rt5640_dac_l2_values[] = { | ||
837 | 0, | ||
838 | 3, | ||
839 | }; | ||
840 | |||
841 | static const SOC_VALUE_ENUM_SINGLE_DECL( | ||
842 | rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, | ||
843 | 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); | ||
844 | |||
845 | static const struct snd_kcontrol_new rt5640_dac_l2_mux = | ||
846 | SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); | ||
847 | |||
848 | static const char * const rt5640_dac_r2_src[] = { | ||
849 | "IF2", | ||
850 | }; | ||
851 | |||
852 | static int rt5640_dac_r2_values[] = { | ||
853 | 0, | ||
854 | }; | ||
855 | |||
856 | static const SOC_VALUE_ENUM_SINGLE_DECL( | ||
857 | rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, | ||
858 | 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); | ||
859 | |||
860 | static const struct snd_kcontrol_new rt5640_dac_r2_mux = | ||
861 | SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); | ||
862 | |||
863 | /* digital interface and iis interface map */ | ||
864 | static const char * const rt5640_dai_iis_map[] = { | ||
865 | "1:1|2:2", "1:2|2:1", "1:1|2:1", "1:2|2:2" | ||
866 | }; | ||
867 | |||
868 | static int rt5640_dai_iis_map_values[] = { | ||
869 | 0, | ||
870 | 5, | ||
871 | 6, | ||
872 | 7, | ||
873 | }; | ||
874 | |||
875 | static const SOC_VALUE_ENUM_SINGLE_DECL( | ||
876 | rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, | ||
877 | 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values); | ||
878 | |||
879 | static const struct snd_kcontrol_new rt5640_dai_mux = | ||
880 | SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); | ||
881 | |||
882 | /* SDI select */ | ||
883 | static const char * const rt5640_sdi_sel[] = { | ||
884 | "IF1", "IF2" | ||
885 | }; | ||
886 | |||
887 | static const SOC_ENUM_SINGLE_DECL( | ||
888 | rt5640_sdi_sel_enum, RT5640_I2S2_SDP, | ||
889 | RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); | ||
890 | |||
891 | static const struct snd_kcontrol_new rt5640_sdi_mux = | ||
892 | SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); | ||
893 | |||
894 | static int spk_event(struct snd_soc_dapm_widget *w, | ||
895 | struct snd_kcontrol *kcontrol, int event) | ||
896 | { | ||
897 | struct snd_soc_codec *codec = w->codec; | ||
898 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
899 | |||
900 | switch (event) { | ||
901 | case SND_SOC_DAPM_POST_PMU: | ||
902 | regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1, | ||
903 | 0x0001, 0x0001); | ||
904 | regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c, | ||
905 | 0xf000, 0xf000); | ||
906 | break; | ||
907 | |||
908 | case SND_SOC_DAPM_PRE_PMD: | ||
909 | regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c, | ||
910 | 0xf000, 0x0000); | ||
911 | regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1, | ||
912 | 0x0001, 0x0000); | ||
913 | break; | ||
914 | |||
915 | default: | ||
916 | return 0; | ||
917 | } | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w, | ||
922 | struct snd_kcontrol *kcontrol, int event) | ||
923 | { | ||
924 | struct snd_soc_codec *codec = w->codec; | ||
925 | |||
926 | switch (event) { | ||
927 | case SND_SOC_DAPM_PRE_PMU: | ||
928 | snd_soc_update_bits(codec, RT5640_GPIO_CTRL1, | ||
929 | RT5640_GP2_PIN_MASK | RT5640_GP3_PIN_MASK, | ||
930 | RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP3_PIN_DMIC1_SDA); | ||
931 | snd_soc_update_bits(codec, RT5640_DMIC, | ||
932 | RT5640_DMIC_1L_LH_MASK | RT5640_DMIC_1R_LH_MASK | | ||
933 | RT5640_DMIC_1_DP_MASK, | ||
934 | RT5640_DMIC_1L_LH_FALLING | RT5640_DMIC_1R_LH_RISING | | ||
935 | RT5640_DMIC_1_DP_IN1P); | ||
936 | break; | ||
937 | |||
938 | default: | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w, | ||
946 | struct snd_kcontrol *kcontrol, int event) | ||
947 | { | ||
948 | struct snd_soc_codec *codec = w->codec; | ||
949 | |||
950 | switch (event) { | ||
951 | case SND_SOC_DAPM_PRE_PMU: | ||
952 | snd_soc_update_bits(codec, RT5640_GPIO_CTRL1, | ||
953 | RT5640_GP2_PIN_MASK | RT5640_GP4_PIN_MASK, | ||
954 | RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP4_PIN_DMIC2_SDA); | ||
955 | snd_soc_update_bits(codec, RT5640_DMIC, | ||
956 | RT5640_DMIC_2L_LH_MASK | RT5640_DMIC_2R_LH_MASK | | ||
957 | RT5640_DMIC_2_DP_MASK, | ||
958 | RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING | | ||
959 | RT5640_DMIC_2_DP_IN1N); | ||
960 | break; | ||
961 | |||
962 | default: | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { | ||
970 | SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2, | ||
971 | RT5640_PWR_PLL_BIT, 0, NULL, 0), | ||
972 | /* Input Side */ | ||
973 | /* micbias */ | ||
974 | SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1, | ||
975 | RT5640_PWR_LDO2_BIT, 0, NULL, 0), | ||
976 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5640_PWR_ANLG2, | ||
977 | RT5640_PWR_MB1_BIT, 0, NULL, 0), | ||
978 | /* Input Lines */ | ||
979 | SND_SOC_DAPM_INPUT("DMIC1"), | ||
980 | SND_SOC_DAPM_INPUT("DMIC2"), | ||
981 | SND_SOC_DAPM_INPUT("IN1P"), | ||
982 | SND_SOC_DAPM_INPUT("IN1N"), | ||
983 | SND_SOC_DAPM_INPUT("IN2P"), | ||
984 | SND_SOC_DAPM_INPUT("IN2N"), | ||
985 | SND_SOC_DAPM_PGA("DMIC L1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
986 | SND_SOC_DAPM_PGA("DMIC R1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
987 | SND_SOC_DAPM_PGA("DMIC L2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
988 | SND_SOC_DAPM_PGA("DMIC R2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
989 | |||
990 | SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, | ||
991 | set_dmic_clk, SND_SOC_DAPM_PRE_PMU), | ||
992 | SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC, | ||
993 | RT5640_DMIC_1_EN_SFT, 0, rt5640_set_dmic1_event, | ||
994 | SND_SOC_DAPM_PRE_PMU), | ||
995 | SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC, | ||
996 | RT5640_DMIC_2_EN_SFT, 0, rt5640_set_dmic2_event, | ||
997 | SND_SOC_DAPM_PRE_PMU), | ||
998 | /* Boost */ | ||
999 | SND_SOC_DAPM_PGA("BST1", RT5640_PWR_ANLG2, | ||
1000 | RT5640_PWR_BST1_BIT, 0, NULL, 0), | ||
1001 | SND_SOC_DAPM_PGA("BST2", RT5640_PWR_ANLG2, | ||
1002 | RT5640_PWR_BST4_BIT, 0, NULL, 0), | ||
1003 | /* Input Volume */ | ||
1004 | SND_SOC_DAPM_PGA("INL VOL", RT5640_PWR_VOL, | ||
1005 | RT5640_PWR_IN_L_BIT, 0, NULL, 0), | ||
1006 | SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL, | ||
1007 | RT5640_PWR_IN_R_BIT, 0, NULL, 0), | ||
1008 | /* IN Mux */ | ||
1009 | SND_SOC_DAPM_MUX("INL Mux", SND_SOC_NOPM, 0, 0, &rt5640_inl_mux), | ||
1010 | SND_SOC_DAPM_MUX("INR Mux", SND_SOC_NOPM, 0, 0, &rt5640_inr_mux), | ||
1011 | /* REC Mixer */ | ||
1012 | SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0, | ||
1013 | rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)), | ||
1014 | SND_SOC_DAPM_MIXER("RECMIXR", RT5640_PWR_MIXER, RT5640_PWR_RM_R_BIT, 0, | ||
1015 | rt5640_rec_r_mix, ARRAY_SIZE(rt5640_rec_r_mix)), | ||
1016 | /* ADCs */ | ||
1017 | SND_SOC_DAPM_ADC("ADC L", NULL, RT5640_PWR_DIG1, | ||
1018 | RT5640_PWR_ADC_L_BIT, 0), | ||
1019 | SND_SOC_DAPM_ADC("ADC R", NULL, RT5640_PWR_DIG1, | ||
1020 | RT5640_PWR_ADC_R_BIT, 0), | ||
1021 | /* ADC Mux */ | ||
1022 | SND_SOC_DAPM_MUX("Stereo ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1023 | &rt5640_sto_adc_2_mux), | ||
1024 | SND_SOC_DAPM_MUX("Stereo ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1025 | &rt5640_sto_adc_2_mux), | ||
1026 | SND_SOC_DAPM_MUX("Stereo ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1027 | &rt5640_sto_adc_1_mux), | ||
1028 | SND_SOC_DAPM_MUX("Stereo ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1029 | &rt5640_sto_adc_1_mux), | ||
1030 | SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1031 | &rt5640_mono_adc_l2_mux), | ||
1032 | SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0, | ||
1033 | &rt5640_mono_adc_l1_mux), | ||
1034 | SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0, | ||
1035 | &rt5640_mono_adc_r1_mux), | ||
1036 | SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1037 | &rt5640_mono_adc_r2_mux), | ||
1038 | /* ADC Mixer */ | ||
1039 | SND_SOC_DAPM_SUPPLY("Stereo Filter", RT5640_PWR_DIG2, | ||
1040 | RT5640_PWR_ADC_SF_BIT, 0, NULL, 0), | ||
1041 | SND_SOC_DAPM_MIXER("Stereo ADC MIXL", SND_SOC_NOPM, 0, 0, | ||
1042 | rt5640_sto_adc_l_mix, ARRAY_SIZE(rt5640_sto_adc_l_mix)), | ||
1043 | SND_SOC_DAPM_MIXER("Stereo ADC MIXR", SND_SOC_NOPM, 0, 0, | ||
1044 | rt5640_sto_adc_r_mix, ARRAY_SIZE(rt5640_sto_adc_r_mix)), | ||
1045 | SND_SOC_DAPM_SUPPLY("Mono Left Filter", RT5640_PWR_DIG2, | ||
1046 | RT5640_PWR_ADC_MF_L_BIT, 0, NULL, 0), | ||
1047 | SND_SOC_DAPM_MIXER("Mono ADC MIXL", SND_SOC_NOPM, 0, 0, | ||
1048 | rt5640_mono_adc_l_mix, ARRAY_SIZE(rt5640_mono_adc_l_mix)), | ||
1049 | SND_SOC_DAPM_SUPPLY("Mono Right Filter", RT5640_PWR_DIG2, | ||
1050 | RT5640_PWR_ADC_MF_R_BIT, 0, NULL, 0), | ||
1051 | SND_SOC_DAPM_MIXER("Mono ADC MIXR", SND_SOC_NOPM, 0, 0, | ||
1052 | rt5640_mono_adc_r_mix, ARRAY_SIZE(rt5640_mono_adc_r_mix)), | ||
1053 | |||
1054 | /* Digital Interface */ | ||
1055 | SND_SOC_DAPM_SUPPLY("I2S1", RT5640_PWR_DIG1, | ||
1056 | RT5640_PWR_I2S1_BIT, 0, NULL, 0), | ||
1057 | SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1058 | SND_SOC_DAPM_PGA("IF1 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1059 | SND_SOC_DAPM_PGA("IF1 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1060 | SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1061 | SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1062 | SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1063 | SND_SOC_DAPM_SUPPLY("I2S2", RT5640_PWR_DIG1, | ||
1064 | RT5640_PWR_I2S2_BIT, 0, NULL, 0), | ||
1065 | SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1066 | SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1067 | SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1068 | SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1069 | SND_SOC_DAPM_PGA("IF2 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1070 | SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1071 | /* Digital Interface Select */ | ||
1072 | SND_SOC_DAPM_MUX("DAI1 RX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1073 | SND_SOC_DAPM_MUX("DAI1 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1074 | SND_SOC_DAPM_MUX("DAI1 IF1 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1075 | SND_SOC_DAPM_MUX("DAI1 IF2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1076 | SND_SOC_DAPM_MUX("SDI1 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_sdi_mux), | ||
1077 | SND_SOC_DAPM_MUX("DAI2 RX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1078 | SND_SOC_DAPM_MUX("DAI2 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1079 | SND_SOC_DAPM_MUX("DAI2 IF1 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1080 | SND_SOC_DAPM_MUX("DAI2 IF2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux), | ||
1081 | SND_SOC_DAPM_MUX("SDI2 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_sdi_mux), | ||
1082 | /* Audio Interface */ | ||
1083 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1084 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
1085 | SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1086 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
1087 | /* Audio DSP */ | ||
1088 | SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1089 | /* ANC */ | ||
1090 | SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1091 | /* Output Side */ | ||
1092 | /* DAC mixer before sound effect */ | ||
1093 | SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1094 | rt5640_dac_l_mix, ARRAY_SIZE(rt5640_dac_l_mix)), | ||
1095 | SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1096 | rt5640_dac_r_mix, ARRAY_SIZE(rt5640_dac_r_mix)), | ||
1097 | /* DAC2 channel Mux */ | ||
1098 | SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, | ||
1099 | &rt5640_dac_l2_mux), | ||
1100 | SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, | ||
1101 | &rt5640_dac_r2_mux), | ||
1102 | /* DAC Mixer */ | ||
1103 | SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1104 | rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)), | ||
1105 | SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1106 | rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)), | ||
1107 | SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0, | ||
1108 | rt5640_mono_dac_l_mix, ARRAY_SIZE(rt5640_mono_dac_l_mix)), | ||
1109 | SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0, | ||
1110 | rt5640_mono_dac_r_mix, ARRAY_SIZE(rt5640_mono_dac_r_mix)), | ||
1111 | SND_SOC_DAPM_MIXER("DIG MIXL", SND_SOC_NOPM, 0, 0, | ||
1112 | rt5640_dig_l_mix, ARRAY_SIZE(rt5640_dig_l_mix)), | ||
1113 | SND_SOC_DAPM_MIXER("DIG MIXR", SND_SOC_NOPM, 0, 0, | ||
1114 | rt5640_dig_r_mix, ARRAY_SIZE(rt5640_dig_r_mix)), | ||
1115 | /* DACs */ | ||
1116 | SND_SOC_DAPM_DAC("DAC L1", NULL, RT5640_PWR_DIG1, | ||
1117 | RT5640_PWR_DAC_L1_BIT, 0), | ||
1118 | SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1, | ||
1119 | RT5640_PWR_DAC_L2_BIT, 0), | ||
1120 | SND_SOC_DAPM_DAC("DAC R1", NULL, RT5640_PWR_DIG1, | ||
1121 | RT5640_PWR_DAC_R1_BIT, 0), | ||
1122 | SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1, | ||
1123 | RT5640_PWR_DAC_R2_BIT, 0), | ||
1124 | /* SPK/OUT Mixer */ | ||
1125 | SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT, | ||
1126 | 0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)), | ||
1127 | SND_SOC_DAPM_MIXER("SPK MIXR", RT5640_PWR_MIXER, RT5640_PWR_SM_R_BIT, | ||
1128 | 0, rt5640_spk_r_mix, ARRAY_SIZE(rt5640_spk_r_mix)), | ||
1129 | SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT, | ||
1130 | 0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)), | ||
1131 | SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT, | ||
1132 | 0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)), | ||
1133 | /* Ouput Volume */ | ||
1134 | SND_SOC_DAPM_PGA("SPKVOL L", RT5640_PWR_VOL, | ||
1135 | RT5640_PWR_SV_L_BIT, 0, NULL, 0), | ||
1136 | SND_SOC_DAPM_PGA("SPKVOL R", RT5640_PWR_VOL, | ||
1137 | RT5640_PWR_SV_R_BIT, 0, NULL, 0), | ||
1138 | SND_SOC_DAPM_PGA("OUTVOL L", RT5640_PWR_VOL, | ||
1139 | RT5640_PWR_OV_L_BIT, 0, NULL, 0), | ||
1140 | SND_SOC_DAPM_PGA("OUTVOL R", RT5640_PWR_VOL, | ||
1141 | RT5640_PWR_OV_R_BIT, 0, NULL, 0), | ||
1142 | SND_SOC_DAPM_PGA("HPOVOL L", RT5640_PWR_VOL, | ||
1143 | RT5640_PWR_HV_L_BIT, 0, NULL, 0), | ||
1144 | SND_SOC_DAPM_PGA("HPOVOL R", RT5640_PWR_VOL, | ||
1145 | RT5640_PWR_HV_R_BIT, 0, NULL, 0), | ||
1146 | /* SPO/HPO/LOUT/Mono Mixer */ | ||
1147 | SND_SOC_DAPM_MIXER("SPOL MIX", SND_SOC_NOPM, 0, | ||
1148 | 0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)), | ||
1149 | SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0, | ||
1150 | 0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)), | ||
1151 | SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0, | ||
1152 | rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)), | ||
1153 | SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0, | ||
1154 | rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)), | ||
1155 | SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0, | ||
1156 | rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)), | ||
1157 | SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0, | ||
1158 | rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)), | ||
1159 | SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1, | ||
1160 | RT5640_PWR_MA_BIT, 0, NULL, 0), | ||
1161 | SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1, | ||
1162 | SND_SOC_NOPM, 0, NULL, 0), | ||
1163 | SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1, | ||
1164 | RT5640_PWR_HP_L_BIT, 0, NULL, 0), | ||
1165 | SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1, | ||
1166 | RT5640_PWR_HP_R_BIT, 0, NULL, 0), | ||
1167 | SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1, | ||
1168 | SND_SOC_NOPM, 0, spk_event, | ||
1169 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
1170 | /* Output Lines */ | ||
1171 | SND_SOC_DAPM_OUTPUT("SPOLP"), | ||
1172 | SND_SOC_DAPM_OUTPUT("SPOLN"), | ||
1173 | SND_SOC_DAPM_OUTPUT("SPORP"), | ||
1174 | SND_SOC_DAPM_OUTPUT("SPORN"), | ||
1175 | SND_SOC_DAPM_OUTPUT("HPOL"), | ||
1176 | SND_SOC_DAPM_OUTPUT("HPOR"), | ||
1177 | SND_SOC_DAPM_OUTPUT("LOUTL"), | ||
1178 | SND_SOC_DAPM_OUTPUT("LOUTR"), | ||
1179 | SND_SOC_DAPM_OUTPUT("MONOP"), | ||
1180 | SND_SOC_DAPM_OUTPUT("MONON"), | ||
1181 | }; | ||
1182 | |||
1183 | static const struct snd_soc_dapm_route rt5640_dapm_routes[] = { | ||
1184 | {"IN1P", NULL, "LDO2"}, | ||
1185 | {"IN2P", NULL, "LDO2"}, | ||
1186 | |||
1187 | {"DMIC L1", NULL, "DMIC1"}, | ||
1188 | {"DMIC R1", NULL, "DMIC1"}, | ||
1189 | {"DMIC L2", NULL, "DMIC2"}, | ||
1190 | {"DMIC R2", NULL, "DMIC2"}, | ||
1191 | |||
1192 | {"BST1", NULL, "IN1P"}, | ||
1193 | {"BST1", NULL, "IN1N"}, | ||
1194 | {"BST2", NULL, "IN2P"}, | ||
1195 | {"BST2", NULL, "IN2N"}, | ||
1196 | |||
1197 | {"INL VOL", NULL, "IN2P"}, | ||
1198 | {"INR VOL", NULL, "IN2N"}, | ||
1199 | |||
1200 | {"RECMIXL", "HPOL Switch", "HPOL"}, | ||
1201 | {"RECMIXL", "INL Switch", "INL VOL"}, | ||
1202 | {"RECMIXL", "BST2 Switch", "BST2"}, | ||
1203 | {"RECMIXL", "BST1 Switch", "BST1"}, | ||
1204 | {"RECMIXL", "OUT MIXL Switch", "OUT MIXL"}, | ||
1205 | |||
1206 | {"RECMIXR", "HPOR Switch", "HPOR"}, | ||
1207 | {"RECMIXR", "INR Switch", "INR VOL"}, | ||
1208 | {"RECMIXR", "BST2 Switch", "BST2"}, | ||
1209 | {"RECMIXR", "BST1 Switch", "BST1"}, | ||
1210 | {"RECMIXR", "OUT MIXR Switch", "OUT MIXR"}, | ||
1211 | |||
1212 | {"ADC L", NULL, "RECMIXL"}, | ||
1213 | {"ADC R", NULL, "RECMIXR"}, | ||
1214 | |||
1215 | {"DMIC L1", NULL, "DMIC CLK"}, | ||
1216 | {"DMIC L1", NULL, "DMIC1 Power"}, | ||
1217 | {"DMIC R1", NULL, "DMIC CLK"}, | ||
1218 | {"DMIC R1", NULL, "DMIC1 Power"}, | ||
1219 | {"DMIC L2", NULL, "DMIC CLK"}, | ||
1220 | {"DMIC L2", NULL, "DMIC2 Power"}, | ||
1221 | {"DMIC R2", NULL, "DMIC CLK"}, | ||
1222 | {"DMIC R2", NULL, "DMIC2 Power"}, | ||
1223 | |||
1224 | {"Stereo ADC L2 Mux", "DMIC1", "DMIC L1"}, | ||
1225 | {"Stereo ADC L2 Mux", "DMIC2", "DMIC L2"}, | ||
1226 | {"Stereo ADC L2 Mux", "DIG MIX", "DIG MIXL"}, | ||
1227 | {"Stereo ADC L1 Mux", "ADC", "ADC L"}, | ||
1228 | {"Stereo ADC L1 Mux", "DIG MIX", "DIG MIXL"}, | ||
1229 | |||
1230 | {"Stereo ADC R1 Mux", "ADC", "ADC R"}, | ||
1231 | {"Stereo ADC R1 Mux", "DIG MIX", "DIG MIXR"}, | ||
1232 | {"Stereo ADC R2 Mux", "DMIC1", "DMIC R1"}, | ||
1233 | {"Stereo ADC R2 Mux", "DMIC2", "DMIC R2"}, | ||
1234 | {"Stereo ADC R2 Mux", "DIG MIX", "DIG MIXR"}, | ||
1235 | |||
1236 | {"Mono ADC L2 Mux", "DMIC L1", "DMIC L1"}, | ||
1237 | {"Mono ADC L2 Mux", "DMIC L2", "DMIC L2"}, | ||
1238 | {"Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL"}, | ||
1239 | {"Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL"}, | ||
1240 | {"Mono ADC L1 Mux", "ADCL", "ADC L"}, | ||
1241 | |||
1242 | {"Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR"}, | ||
1243 | {"Mono ADC R1 Mux", "ADCR", "ADC R"}, | ||
1244 | {"Mono ADC R2 Mux", "DMIC R1", "DMIC R1"}, | ||
1245 | {"Mono ADC R2 Mux", "DMIC R2", "DMIC R2"}, | ||
1246 | {"Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR"}, | ||
1247 | |||
1248 | {"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"}, | ||
1249 | {"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"}, | ||
1250 | {"Stereo ADC MIXL", NULL, "Stereo Filter"}, | ||
1251 | {"Stereo Filter", NULL, "PLL1", check_sysclk1_source}, | ||
1252 | |||
1253 | {"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"}, | ||
1254 | {"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"}, | ||
1255 | {"Stereo ADC MIXR", NULL, "Stereo Filter"}, | ||
1256 | {"Stereo Filter", NULL, "PLL1", check_sysclk1_source}, | ||
1257 | |||
1258 | {"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"}, | ||
1259 | {"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"}, | ||
1260 | {"Mono ADC MIXL", NULL, "Mono Left Filter"}, | ||
1261 | {"Mono Left Filter", NULL, "PLL1", check_sysclk1_source}, | ||
1262 | |||
1263 | {"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"}, | ||
1264 | {"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"}, | ||
1265 | {"Mono ADC MIXR", NULL, "Mono Right Filter"}, | ||
1266 | {"Mono Right Filter", NULL, "PLL1", check_sysclk1_source}, | ||
1267 | |||
1268 | {"IF2 ADC L", NULL, "Mono ADC MIXL"}, | ||
1269 | {"IF2 ADC R", NULL, "Mono ADC MIXR"}, | ||
1270 | {"IF1 ADC L", NULL, "Stereo ADC MIXL"}, | ||
1271 | {"IF1 ADC R", NULL, "Stereo ADC MIXR"}, | ||
1272 | |||
1273 | {"IF1 ADC", NULL, "I2S1"}, | ||
1274 | {"IF1 ADC", NULL, "IF1 ADC L"}, | ||
1275 | {"IF1 ADC", NULL, "IF1 ADC R"}, | ||
1276 | {"IF2 ADC", NULL, "I2S2"}, | ||
1277 | {"IF2 ADC", NULL, "IF2 ADC L"}, | ||
1278 | {"IF2 ADC", NULL, "IF2 ADC R"}, | ||
1279 | |||
1280 | {"DAI1 TX Mux", "1:1|2:2", "IF1 ADC"}, | ||
1281 | {"DAI1 TX Mux", "1:2|2:1", "IF2 ADC"}, | ||
1282 | {"DAI1 IF1 Mux", "1:1|2:1", "IF1 ADC"}, | ||
1283 | {"DAI1 IF2 Mux", "1:1|2:1", "IF2 ADC"}, | ||
1284 | {"SDI1 TX Mux", "IF1", "DAI1 IF1 Mux"}, | ||
1285 | {"SDI1 TX Mux", "IF2", "DAI1 IF2 Mux"}, | ||
1286 | |||
1287 | {"DAI2 TX Mux", "1:2|2:1", "IF1 ADC"}, | ||
1288 | {"DAI2 TX Mux", "1:1|2:2", "IF2 ADC"}, | ||
1289 | {"DAI2 IF1 Mux", "1:2|2:2", "IF1 ADC"}, | ||
1290 | {"DAI2 IF2 Mux", "1:2|2:2", "IF2 ADC"}, | ||
1291 | {"SDI2 TX Mux", "IF1", "DAI2 IF1 Mux"}, | ||
1292 | {"SDI2 TX Mux", "IF2", "DAI2 IF2 Mux"}, | ||
1293 | |||
1294 | {"AIF1TX", NULL, "DAI1 TX Mux"}, | ||
1295 | {"AIF1TX", NULL, "SDI1 TX Mux"}, | ||
1296 | {"AIF2TX", NULL, "DAI2 TX Mux"}, | ||
1297 | {"AIF2TX", NULL, "SDI2 TX Mux"}, | ||
1298 | |||
1299 | {"DAI1 RX Mux", "1:1|2:2", "AIF1RX"}, | ||
1300 | {"DAI1 RX Mux", "1:1|2:1", "AIF1RX"}, | ||
1301 | {"DAI1 RX Mux", "1:2|2:1", "AIF2RX"}, | ||
1302 | {"DAI1 RX Mux", "1:2|2:2", "AIF2RX"}, | ||
1303 | |||
1304 | {"DAI2 RX Mux", "1:2|2:1", "AIF1RX"}, | ||
1305 | {"DAI2 RX Mux", "1:1|2:1", "AIF1RX"}, | ||
1306 | {"DAI2 RX Mux", "1:1|2:2", "AIF2RX"}, | ||
1307 | {"DAI2 RX Mux", "1:2|2:2", "AIF2RX"}, | ||
1308 | |||
1309 | {"IF1 DAC", NULL, "I2S1"}, | ||
1310 | {"IF1 DAC", NULL, "DAI1 RX Mux"}, | ||
1311 | {"IF2 DAC", NULL, "I2S2"}, | ||
1312 | {"IF2 DAC", NULL, "DAI2 RX Mux"}, | ||
1313 | |||
1314 | {"IF1 DAC L", NULL, "IF1 DAC"}, | ||
1315 | {"IF1 DAC R", NULL, "IF1 DAC"}, | ||
1316 | {"IF2 DAC L", NULL, "IF2 DAC"}, | ||
1317 | {"IF2 DAC R", NULL, "IF2 DAC"}, | ||
1318 | |||
1319 | {"DAC MIXL", "Stereo ADC Switch", "Stereo ADC MIXL"}, | ||
1320 | {"DAC MIXL", "INF1 Switch", "IF1 DAC L"}, | ||
1321 | {"DAC MIXR", "Stereo ADC Switch", "Stereo ADC MIXR"}, | ||
1322 | {"DAC MIXR", "INF1 Switch", "IF1 DAC R"}, | ||
1323 | |||
1324 | {"ANC", NULL, "Stereo ADC MIXL"}, | ||
1325 | {"ANC", NULL, "Stereo ADC MIXR"}, | ||
1326 | |||
1327 | {"Audio DSP", NULL, "DAC MIXL"}, | ||
1328 | {"Audio DSP", NULL, "DAC MIXR"}, | ||
1329 | |||
1330 | {"DAC L2 Mux", "IF2", "IF2 DAC L"}, | ||
1331 | {"DAC L2 Mux", "Base L/R", "Audio DSP"}, | ||
1332 | |||
1333 | {"DAC R2 Mux", "IF2", "IF2 DAC R"}, | ||
1334 | |||
1335 | {"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"}, | ||
1336 | {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"}, | ||
1337 | {"Stereo DAC MIXL", "ANC Switch", "ANC"}, | ||
1338 | {"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"}, | ||
1339 | {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"}, | ||
1340 | {"Stereo DAC MIXR", "ANC Switch", "ANC"}, | ||
1341 | |||
1342 | {"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"}, | ||
1343 | {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"}, | ||
1344 | {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"}, | ||
1345 | {"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"}, | ||
1346 | {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"}, | ||
1347 | {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"}, | ||
1348 | |||
1349 | {"DIG MIXL", "DAC L1 Switch", "DAC MIXL"}, | ||
1350 | {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"}, | ||
1351 | {"DIG MIXR", "DAC R1 Switch", "DAC MIXR"}, | ||
1352 | {"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"}, | ||
1353 | |||
1354 | {"DAC L1", NULL, "Stereo DAC MIXL"}, | ||
1355 | {"DAC L1", NULL, "PLL1", check_sysclk1_source}, | ||
1356 | {"DAC R1", NULL, "Stereo DAC MIXR"}, | ||
1357 | {"DAC R1", NULL, "PLL1", check_sysclk1_source}, | ||
1358 | {"DAC L2", NULL, "Mono DAC MIXL"}, | ||
1359 | {"DAC L2", NULL, "PLL1", check_sysclk1_source}, | ||
1360 | {"DAC R2", NULL, "Mono DAC MIXR"}, | ||
1361 | {"DAC R2", NULL, "PLL1", check_sysclk1_source}, | ||
1362 | |||
1363 | {"SPK MIXL", "REC MIXL Switch", "RECMIXL"}, | ||
1364 | {"SPK MIXL", "INL Switch", "INL VOL"}, | ||
1365 | {"SPK MIXL", "DAC L1 Switch", "DAC L1"}, | ||
1366 | {"SPK MIXL", "DAC L2 Switch", "DAC L2"}, | ||
1367 | {"SPK MIXL", "OUT MIXL Switch", "OUT MIXL"}, | ||
1368 | {"SPK MIXR", "REC MIXR Switch", "RECMIXR"}, | ||
1369 | {"SPK MIXR", "INR Switch", "INR VOL"}, | ||
1370 | {"SPK MIXR", "DAC R1 Switch", "DAC R1"}, | ||
1371 | {"SPK MIXR", "DAC R2 Switch", "DAC R2"}, | ||
1372 | {"SPK MIXR", "OUT MIXR Switch", "OUT MIXR"}, | ||
1373 | |||
1374 | {"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"}, | ||
1375 | {"OUT MIXL", "BST1 Switch", "BST1"}, | ||
1376 | {"OUT MIXL", "INL Switch", "INL VOL"}, | ||
1377 | {"OUT MIXL", "REC MIXL Switch", "RECMIXL"}, | ||
1378 | {"OUT MIXL", "DAC R2 Switch", "DAC R2"}, | ||
1379 | {"OUT MIXL", "DAC L2 Switch", "DAC L2"}, | ||
1380 | {"OUT MIXL", "DAC L1 Switch", "DAC L1"}, | ||
1381 | |||
1382 | {"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"}, | ||
1383 | {"OUT MIXR", "BST2 Switch", "BST2"}, | ||
1384 | {"OUT MIXR", "BST1 Switch", "BST1"}, | ||
1385 | {"OUT MIXR", "INR Switch", "INR VOL"}, | ||
1386 | {"OUT MIXR", "REC MIXR Switch", "RECMIXR"}, | ||
1387 | {"OUT MIXR", "DAC L2 Switch", "DAC L2"}, | ||
1388 | {"OUT MIXR", "DAC R2 Switch", "DAC R2"}, | ||
1389 | {"OUT MIXR", "DAC R1 Switch", "DAC R1"}, | ||
1390 | |||
1391 | {"SPKVOL L", NULL, "SPK MIXL"}, | ||
1392 | {"SPKVOL R", NULL, "SPK MIXR"}, | ||
1393 | {"HPOVOL L", NULL, "OUT MIXL"}, | ||
1394 | {"HPOVOL R", NULL, "OUT MIXR"}, | ||
1395 | {"OUTVOL L", NULL, "OUT MIXL"}, | ||
1396 | {"OUTVOL R", NULL, "OUT MIXR"}, | ||
1397 | |||
1398 | {"SPOL MIX", "DAC R1 Switch", "DAC R1"}, | ||
1399 | {"SPOL MIX", "DAC L1 Switch", "DAC L1"}, | ||
1400 | {"SPOL MIX", "SPKVOL R Switch", "SPKVOL R"}, | ||
1401 | {"SPOL MIX", "SPKVOL L Switch", "SPKVOL L"}, | ||
1402 | {"SPOL MIX", "BST1 Switch", "BST1"}, | ||
1403 | {"SPOR MIX", "DAC R1 Switch", "DAC R1"}, | ||
1404 | {"SPOR MIX", "SPKVOL R Switch", "SPKVOL R"}, | ||
1405 | {"SPOR MIX", "BST1 Switch", "BST1"}, | ||
1406 | |||
1407 | {"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"}, | ||
1408 | {"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"}, | ||
1409 | {"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"}, | ||
1410 | {"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"}, | ||
1411 | {"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"}, | ||
1412 | {"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"}, | ||
1413 | |||
1414 | {"LOUT MIX", "DAC L1 Switch", "DAC L1"}, | ||
1415 | {"LOUT MIX", "DAC R1 Switch", "DAC R1"}, | ||
1416 | {"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"}, | ||
1417 | {"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"}, | ||
1418 | |||
1419 | {"Mono MIX", "DAC R2 Switch", "DAC R2"}, | ||
1420 | {"Mono MIX", "DAC L2 Switch", "DAC L2"}, | ||
1421 | {"Mono MIX", "OUTVOL R Switch", "OUTVOL R"}, | ||
1422 | {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"}, | ||
1423 | {"Mono MIX", "BST1 Switch", "BST1"}, | ||
1424 | |||
1425 | {"HP L Amp", NULL, "HPO MIX L"}, | ||
1426 | {"HP R Amp", NULL, "HPO MIX R"}, | ||
1427 | |||
1428 | {"SPOLP", NULL, "SPOL MIX"}, | ||
1429 | {"SPOLN", NULL, "SPOL MIX"}, | ||
1430 | {"SPORP", NULL, "SPOR MIX"}, | ||
1431 | {"SPORN", NULL, "SPOR MIX"}, | ||
1432 | |||
1433 | {"SPOLP", NULL, "Improve SPK Amp Drv"}, | ||
1434 | {"SPOLN", NULL, "Improve SPK Amp Drv"}, | ||
1435 | {"SPORP", NULL, "Improve SPK Amp Drv"}, | ||
1436 | {"SPORN", NULL, "Improve SPK Amp Drv"}, | ||
1437 | |||
1438 | {"HPOL", NULL, "Improve HP Amp Drv"}, | ||
1439 | {"HPOR", NULL, "Improve HP Amp Drv"}, | ||
1440 | |||
1441 | {"HPOL", NULL, "HP L Amp"}, | ||
1442 | {"HPOR", NULL, "HP R Amp"}, | ||
1443 | {"LOUTL", NULL, "LOUT MIX"}, | ||
1444 | {"LOUTR", NULL, "LOUT MIX"}, | ||
1445 | {"MONOP", NULL, "Mono MIX"}, | ||
1446 | {"MONON", NULL, "Mono MIX"}, | ||
1447 | {"MONOP", NULL, "Improve MONO Amp Drv"}, | ||
1448 | }; | ||
1449 | |||
1450 | static int get_sdp_info(struct snd_soc_codec *codec, int dai_id) | ||
1451 | { | ||
1452 | int ret = 0, val; | ||
1453 | |||
1454 | if (codec == NULL) | ||
1455 | return -EINVAL; | ||
1456 | |||
1457 | val = snd_soc_read(codec, RT5640_I2S1_SDP); | ||
1458 | val = (val & RT5640_I2S_IF_MASK) >> RT5640_I2S_IF_SFT; | ||
1459 | switch (dai_id) { | ||
1460 | case RT5640_AIF1: | ||
1461 | switch (val) { | ||
1462 | case RT5640_IF_123: | ||
1463 | case RT5640_IF_132: | ||
1464 | ret |= RT5640_U_IF1; | ||
1465 | break; | ||
1466 | case RT5640_IF_113: | ||
1467 | ret |= RT5640_U_IF1; | ||
1468 | case RT5640_IF_312: | ||
1469 | case RT5640_IF_213: | ||
1470 | ret |= RT5640_U_IF2; | ||
1471 | break; | ||
1472 | } | ||
1473 | break; | ||
1474 | |||
1475 | case RT5640_AIF2: | ||
1476 | switch (val) { | ||
1477 | case RT5640_IF_231: | ||
1478 | case RT5640_IF_213: | ||
1479 | ret |= RT5640_U_IF1; | ||
1480 | break; | ||
1481 | case RT5640_IF_223: | ||
1482 | ret |= RT5640_U_IF1; | ||
1483 | case RT5640_IF_123: | ||
1484 | case RT5640_IF_321: | ||
1485 | ret |= RT5640_U_IF2; | ||
1486 | break; | ||
1487 | } | ||
1488 | break; | ||
1489 | |||
1490 | default: | ||
1491 | ret = -EINVAL; | ||
1492 | break; | ||
1493 | } | ||
1494 | |||
1495 | return ret; | ||
1496 | } | ||
1497 | |||
1498 | static int get_clk_info(int sclk, int rate) | ||
1499 | { | ||
1500 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
1501 | |||
1502 | if (sclk <= 0 || rate <= 0) | ||
1503 | return -EINVAL; | ||
1504 | |||
1505 | rate = rate << 8; | ||
1506 | for (i = 0; i < ARRAY_SIZE(pd); i++) | ||
1507 | if (sclk == rate * pd[i]) | ||
1508 | return i; | ||
1509 | |||
1510 | return -EINVAL; | ||
1511 | } | ||
1512 | |||
1513 | static int rt5640_hw_params(struct snd_pcm_substream *substream, | ||
1514 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
1515 | { | ||
1516 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
1517 | struct snd_soc_codec *codec = rtd->codec; | ||
1518 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1519 | unsigned int val_len = 0, val_clk, mask_clk, dai_sel; | ||
1520 | int pre_div, bclk_ms, frame_size; | ||
1521 | |||
1522 | rt5640->lrck[dai->id] = params_rate(params); | ||
1523 | pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]); | ||
1524 | if (pre_div < 0) { | ||
1525 | dev_err(codec->dev, "Unsupported clock setting\n"); | ||
1526 | return -EINVAL; | ||
1527 | } | ||
1528 | frame_size = snd_soc_params_to_frame_size(params); | ||
1529 | if (frame_size < 0) { | ||
1530 | dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); | ||
1531 | return frame_size; | ||
1532 | } | ||
1533 | if (frame_size > 32) | ||
1534 | bclk_ms = 1; | ||
1535 | else | ||
1536 | bclk_ms = 0; | ||
1537 | rt5640->bclk[dai->id] = rt5640->lrck[dai->id] * (32 << bclk_ms); | ||
1538 | |||
1539 | dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", | ||
1540 | rt5640->bclk[dai->id], rt5640->lrck[dai->id]); | ||
1541 | dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", | ||
1542 | bclk_ms, pre_div, dai->id); | ||
1543 | |||
1544 | switch (params_format(params)) { | ||
1545 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1546 | break; | ||
1547 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1548 | val_len |= RT5640_I2S_DL_20; | ||
1549 | break; | ||
1550 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1551 | val_len |= RT5640_I2S_DL_24; | ||
1552 | break; | ||
1553 | case SNDRV_PCM_FORMAT_S8: | ||
1554 | val_len |= RT5640_I2S_DL_8; | ||
1555 | break; | ||
1556 | default: | ||
1557 | return -EINVAL; | ||
1558 | } | ||
1559 | |||
1560 | dai_sel = get_sdp_info(codec, dai->id); | ||
1561 | if (dai_sel < 0) { | ||
1562 | dev_err(codec->dev, "Failed to get sdp info: %d\n", dai_sel); | ||
1563 | return -EINVAL; | ||
1564 | } | ||
1565 | if (dai_sel & RT5640_U_IF1) { | ||
1566 | mask_clk = RT5640_I2S_BCLK_MS1_MASK | RT5640_I2S_PD1_MASK; | ||
1567 | val_clk = bclk_ms << RT5640_I2S_BCLK_MS1_SFT | | ||
1568 | pre_div << RT5640_I2S_PD1_SFT; | ||
1569 | snd_soc_update_bits(codec, RT5640_I2S1_SDP, | ||
1570 | RT5640_I2S_DL_MASK, val_len); | ||
1571 | snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk); | ||
1572 | } | ||
1573 | if (dai_sel & RT5640_U_IF2) { | ||
1574 | mask_clk = RT5640_I2S_BCLK_MS2_MASK | RT5640_I2S_PD2_MASK; | ||
1575 | val_clk = bclk_ms << RT5640_I2S_BCLK_MS2_SFT | | ||
1576 | pre_div << RT5640_I2S_PD2_SFT; | ||
1577 | snd_soc_update_bits(codec, RT5640_I2S2_SDP, | ||
1578 | RT5640_I2S_DL_MASK, val_len); | ||
1579 | snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk); | ||
1580 | } | ||
1581 | |||
1582 | return 0; | ||
1583 | } | ||
1584 | |||
1585 | static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
1586 | { | ||
1587 | struct snd_soc_codec *codec = dai->codec; | ||
1588 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1589 | unsigned int reg_val = 0, dai_sel; | ||
1590 | |||
1591 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1592 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1593 | rt5640->master[dai->id] = 1; | ||
1594 | break; | ||
1595 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1596 | reg_val |= RT5640_I2S_MS_S; | ||
1597 | rt5640->master[dai->id] = 0; | ||
1598 | break; | ||
1599 | default: | ||
1600 | return -EINVAL; | ||
1601 | } | ||
1602 | |||
1603 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1604 | case SND_SOC_DAIFMT_NB_NF: | ||
1605 | break; | ||
1606 | case SND_SOC_DAIFMT_IB_NF: | ||
1607 | reg_val |= RT5640_I2S_BP_INV; | ||
1608 | break; | ||
1609 | default: | ||
1610 | return -EINVAL; | ||
1611 | } | ||
1612 | |||
1613 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1614 | case SND_SOC_DAIFMT_I2S: | ||
1615 | break; | ||
1616 | case SND_SOC_DAIFMT_LEFT_J: | ||
1617 | reg_val |= RT5640_I2S_DF_LEFT; | ||
1618 | break; | ||
1619 | case SND_SOC_DAIFMT_DSP_A: | ||
1620 | reg_val |= RT5640_I2S_DF_PCM_A; | ||
1621 | break; | ||
1622 | case SND_SOC_DAIFMT_DSP_B: | ||
1623 | reg_val |= RT5640_I2S_DF_PCM_B; | ||
1624 | break; | ||
1625 | default: | ||
1626 | return -EINVAL; | ||
1627 | } | ||
1628 | |||
1629 | dai_sel = get_sdp_info(codec, dai->id); | ||
1630 | if (dai_sel < 0) { | ||
1631 | dev_err(codec->dev, "Failed to get sdp info: %d\n", dai_sel); | ||
1632 | return -EINVAL; | ||
1633 | } | ||
1634 | if (dai_sel & RT5640_U_IF1) { | ||
1635 | snd_soc_update_bits(codec, RT5640_I2S1_SDP, | ||
1636 | RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK | | ||
1637 | RT5640_I2S_DF_MASK, reg_val); | ||
1638 | } | ||
1639 | if (dai_sel & RT5640_U_IF2) { | ||
1640 | snd_soc_update_bits(codec, RT5640_I2S2_SDP, | ||
1641 | RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK | | ||
1642 | RT5640_I2S_DF_MASK, reg_val); | ||
1643 | } | ||
1644 | |||
1645 | return 0; | ||
1646 | } | ||
1647 | |||
1648 | static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai, | ||
1649 | int clk_id, unsigned int freq, int dir) | ||
1650 | { | ||
1651 | struct snd_soc_codec *codec = dai->codec; | ||
1652 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1653 | unsigned int reg_val = 0; | ||
1654 | |||
1655 | if (freq == rt5640->sysclk && clk_id == rt5640->sysclk_src) | ||
1656 | return 0; | ||
1657 | |||
1658 | switch (clk_id) { | ||
1659 | case RT5640_SCLK_S_MCLK: | ||
1660 | reg_val |= RT5640_SCLK_SRC_MCLK; | ||
1661 | break; | ||
1662 | case RT5640_SCLK_S_PLL1: | ||
1663 | reg_val |= RT5640_SCLK_SRC_PLL1; | ||
1664 | break; | ||
1665 | case RT5640_SCLK_S_PLL1_TK: | ||
1666 | reg_val |= RT5640_SCLK_SRC_PLL1T; | ||
1667 | break; | ||
1668 | case RT5640_SCLK_S_RCCLK: | ||
1669 | reg_val |= RT5640_SCLK_SRC_RCCLK; | ||
1670 | break; | ||
1671 | default: | ||
1672 | dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); | ||
1673 | return -EINVAL; | ||
1674 | } | ||
1675 | snd_soc_update_bits(codec, RT5640_GLB_CLK, | ||
1676 | RT5640_SCLK_SRC_MASK, reg_val); | ||
1677 | rt5640->sysclk = freq; | ||
1678 | rt5640->sysclk_src = clk_id; | ||
1679 | |||
1680 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); | ||
1681 | return 0; | ||
1682 | } | ||
1683 | |||
1684 | /** | ||
1685 | * rt5640_pll_calc - Calculate PLL M/N/K code. | ||
1686 | * @freq_in: external clock provided to codec. | ||
1687 | * @freq_out: target clock which codec works on. | ||
1688 | * @pll_code: Pointer to structure with M, N, K and bypass flag. | ||
1689 | * | ||
1690 | * Calculate M/N/K code to configure PLL for codec. And K is assigned to 2 | ||
1691 | * which make calculation more efficiently. | ||
1692 | * | ||
1693 | * Returns 0 for success or negative error code. | ||
1694 | */ | ||
1695 | static int rt5640_pll_calc(const unsigned int freq_in, | ||
1696 | const unsigned int freq_out, struct rt5640_pll_code *pll_code) | ||
1697 | { | ||
1698 | int max_n = RT5640_PLL_N_MAX, max_m = RT5640_PLL_M_MAX; | ||
1699 | int n = 0, m = 0, red, n_t, m_t, in_t, out_t; | ||
1700 | int red_t = abs(freq_out - freq_in); | ||
1701 | bool bypass = false; | ||
1702 | |||
1703 | if (RT5640_PLL_INP_MAX < freq_in || RT5640_PLL_INP_MIN > freq_in) | ||
1704 | return -EINVAL; | ||
1705 | |||
1706 | for (n_t = 0; n_t <= max_n; n_t++) { | ||
1707 | in_t = (freq_in >> 1) + (freq_in >> 2) * n_t; | ||
1708 | if (in_t < 0) | ||
1709 | continue; | ||
1710 | if (in_t == freq_out) { | ||
1711 | bypass = true; | ||
1712 | n = n_t; | ||
1713 | goto code_find; | ||
1714 | } | ||
1715 | for (m_t = 0; m_t <= max_m; m_t++) { | ||
1716 | out_t = in_t / (m_t + 2); | ||
1717 | red = abs(out_t - freq_out); | ||
1718 | if (red < red_t) { | ||
1719 | n = n_t; | ||
1720 | m = m_t; | ||
1721 | if (red == 0) | ||
1722 | goto code_find; | ||
1723 | red_t = red; | ||
1724 | } | ||
1725 | } | ||
1726 | } | ||
1727 | pr_debug("Only get approximation about PLL\n"); | ||
1728 | |||
1729 | code_find: | ||
1730 | pll_code->m_bp = bypass; | ||
1731 | pll_code->m_code = m; | ||
1732 | pll_code->n_code = n; | ||
1733 | pll_code->k_code = 2; | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
1738 | unsigned int freq_in, unsigned int freq_out) | ||
1739 | { | ||
1740 | struct snd_soc_codec *codec = dai->codec; | ||
1741 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1742 | struct rt5640_pll_code *pll_code = &rt5640->pll_code; | ||
1743 | int ret, dai_sel; | ||
1744 | |||
1745 | if (source == rt5640->pll_src && freq_in == rt5640->pll_in && | ||
1746 | freq_out == rt5640->pll_out) | ||
1747 | return 0; | ||
1748 | |||
1749 | if (!freq_in || !freq_out) { | ||
1750 | dev_dbg(codec->dev, "PLL disabled\n"); | ||
1751 | |||
1752 | rt5640->pll_in = 0; | ||
1753 | rt5640->pll_out = 0; | ||
1754 | snd_soc_update_bits(codec, RT5640_GLB_CLK, | ||
1755 | RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_MCLK); | ||
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1759 | switch (source) { | ||
1760 | case RT5640_PLL1_S_MCLK: | ||
1761 | snd_soc_update_bits(codec, RT5640_GLB_CLK, | ||
1762 | RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_MCLK); | ||
1763 | break; | ||
1764 | case RT5640_PLL1_S_BCLK1: | ||
1765 | case RT5640_PLL1_S_BCLK2: | ||
1766 | dai_sel = get_sdp_info(codec, dai->id); | ||
1767 | if (dai_sel < 0) { | ||
1768 | dev_err(codec->dev, | ||
1769 | "Failed to get sdp info: %d\n", dai_sel); | ||
1770 | return -EINVAL; | ||
1771 | } | ||
1772 | if (dai_sel & RT5640_U_IF1) { | ||
1773 | snd_soc_update_bits(codec, RT5640_GLB_CLK, | ||
1774 | RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_BCLK1); | ||
1775 | } | ||
1776 | if (dai_sel & RT5640_U_IF2) { | ||
1777 | snd_soc_update_bits(codec, RT5640_GLB_CLK, | ||
1778 | RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_BCLK2); | ||
1779 | } | ||
1780 | break; | ||
1781 | default: | ||
1782 | dev_err(codec->dev, "Unknown PLL source %d\n", source); | ||
1783 | return -EINVAL; | ||
1784 | } | ||
1785 | |||
1786 | ret = rt5640_pll_calc(freq_in, freq_out, pll_code); | ||
1787 | if (ret < 0) { | ||
1788 | dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); | ||
1789 | return ret; | ||
1790 | } | ||
1791 | |||
1792 | dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp, | ||
1793 | (pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code); | ||
1794 | |||
1795 | snd_soc_write(codec, RT5640_PLL_CTRL1, | ||
1796 | pll_code->n_code << RT5640_PLL_N_SFT | pll_code->k_code); | ||
1797 | snd_soc_write(codec, RT5640_PLL_CTRL2, | ||
1798 | (pll_code->m_bp ? 0 : pll_code->m_code) << RT5640_PLL_M_SFT | | ||
1799 | pll_code->m_bp << RT5640_PLL_M_BP_SFT); | ||
1800 | |||
1801 | rt5640->pll_in = freq_in; | ||
1802 | rt5640->pll_out = freq_out; | ||
1803 | rt5640->pll_src = source; | ||
1804 | |||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | static int rt5640_set_bias_level(struct snd_soc_codec *codec, | ||
1809 | enum snd_soc_bias_level level) | ||
1810 | { | ||
1811 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1812 | switch (level) { | ||
1813 | case SND_SOC_BIAS_STANDBY: | ||
1814 | if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) { | ||
1815 | regcache_cache_only(rt5640->regmap, false); | ||
1816 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, | ||
1817 | RT5640_PWR_VREF1 | RT5640_PWR_MB | | ||
1818 | RT5640_PWR_BG | RT5640_PWR_VREF2, | ||
1819 | RT5640_PWR_VREF1 | RT5640_PWR_MB | | ||
1820 | RT5640_PWR_BG | RT5640_PWR_VREF2); | ||
1821 | mdelay(10); | ||
1822 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, | ||
1823 | RT5640_PWR_FV1 | RT5640_PWR_FV2, | ||
1824 | RT5640_PWR_FV1 | RT5640_PWR_FV2); | ||
1825 | regcache_sync(rt5640->regmap); | ||
1826 | snd_soc_update_bits(codec, RT5640_DUMMY1, | ||
1827 | 0x0301, 0x0301); | ||
1828 | snd_soc_update_bits(codec, RT5640_DEPOP_M1, | ||
1829 | 0x001d, 0x0019); | ||
1830 | snd_soc_update_bits(codec, RT5640_DEPOP_M2, | ||
1831 | 0x2000, 0x2000); | ||
1832 | snd_soc_update_bits(codec, RT5640_MICBIAS, | ||
1833 | 0x0030, 0x0030); | ||
1834 | } | ||
1835 | break; | ||
1836 | |||
1837 | case SND_SOC_BIAS_OFF: | ||
1838 | snd_soc_write(codec, RT5640_DEPOP_M1, 0x0004); | ||
1839 | snd_soc_write(codec, RT5640_DEPOP_M2, 0x1100); | ||
1840 | snd_soc_update_bits(codec, RT5640_DUMMY1, 0x1, 0); | ||
1841 | snd_soc_write(codec, RT5640_PWR_DIG1, 0x0000); | ||
1842 | snd_soc_write(codec, RT5640_PWR_DIG2, 0x0000); | ||
1843 | snd_soc_write(codec, RT5640_PWR_VOL, 0x0000); | ||
1844 | snd_soc_write(codec, RT5640_PWR_MIXER, 0x0000); | ||
1845 | snd_soc_write(codec, RT5640_PWR_ANLG1, 0x0000); | ||
1846 | snd_soc_write(codec, RT5640_PWR_ANLG2, 0x0000); | ||
1847 | break; | ||
1848 | |||
1849 | default: | ||
1850 | break; | ||
1851 | } | ||
1852 | codec->dapm.bias_level = level; | ||
1853 | |||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static int rt5640_probe(struct snd_soc_codec *codec) | ||
1858 | { | ||
1859 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1860 | int ret; | ||
1861 | |||
1862 | rt5640->codec = codec; | ||
1863 | codec->control_data = rt5640->regmap; | ||
1864 | |||
1865 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1866 | if (ret != 0) { | ||
1867 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1868 | return ret; | ||
1869 | } | ||
1870 | |||
1871 | codec->dapm.idle_bias_off = 1; | ||
1872 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1873 | |||
1874 | snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301); | ||
1875 | snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019); | ||
1876 | snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000); | ||
1877 | snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030); | ||
1878 | snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | static int rt5640_remove(struct snd_soc_codec *codec) | ||
1884 | { | ||
1885 | rt5640_reset(codec); | ||
1886 | |||
1887 | return 0; | ||
1888 | } | ||
1889 | |||
1890 | #ifdef CONFIG_PM | ||
1891 | static int rt5640_suspend(struct snd_soc_codec *codec) | ||
1892 | { | ||
1893 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1894 | |||
1895 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1896 | rt5640_reset(codec); | ||
1897 | regcache_cache_only(rt5640->regmap, true); | ||
1898 | regcache_mark_dirty(rt5640->regmap); | ||
1899 | |||
1900 | return 0; | ||
1901 | } | ||
1902 | |||
1903 | static int rt5640_resume(struct snd_soc_codec *codec) | ||
1904 | { | ||
1905 | rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1906 | |||
1907 | return 0; | ||
1908 | } | ||
1909 | #else | ||
1910 | #define rt5640_suspend NULL | ||
1911 | #define rt5640_resume NULL | ||
1912 | #endif | ||
1913 | |||
1914 | #define RT5640_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | ||
1915 | #define RT5640_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1916 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | ||
1917 | |||
1918 | static const struct snd_soc_dai_ops rt5640_aif_dai_ops = { | ||
1919 | .hw_params = rt5640_hw_params, | ||
1920 | .set_fmt = rt5640_set_dai_fmt, | ||
1921 | .set_sysclk = rt5640_set_dai_sysclk, | ||
1922 | .set_pll = rt5640_set_dai_pll, | ||
1923 | }; | ||
1924 | |||
1925 | static struct snd_soc_dai_driver rt5640_dai[] = { | ||
1926 | { | ||
1927 | .name = "rt5640-aif1", | ||
1928 | .id = RT5640_AIF1, | ||
1929 | .playback = { | ||
1930 | .stream_name = "AIF1 Playback", | ||
1931 | .channels_min = 1, | ||
1932 | .channels_max = 2, | ||
1933 | .rates = RT5640_STEREO_RATES, | ||
1934 | .formats = RT5640_FORMATS, | ||
1935 | }, | ||
1936 | .capture = { | ||
1937 | .stream_name = "AIF1 Capture", | ||
1938 | .channels_min = 1, | ||
1939 | .channels_max = 2, | ||
1940 | .rates = RT5640_STEREO_RATES, | ||
1941 | .formats = RT5640_FORMATS, | ||
1942 | }, | ||
1943 | .ops = &rt5640_aif_dai_ops, | ||
1944 | }, | ||
1945 | { | ||
1946 | .name = "rt5640-aif2", | ||
1947 | .id = RT5640_AIF2, | ||
1948 | .playback = { | ||
1949 | .stream_name = "AIF2 Playback", | ||
1950 | .channels_min = 1, | ||
1951 | .channels_max = 2, | ||
1952 | .rates = RT5640_STEREO_RATES, | ||
1953 | .formats = RT5640_FORMATS, | ||
1954 | }, | ||
1955 | .capture = { | ||
1956 | .stream_name = "AIF2 Capture", | ||
1957 | .channels_min = 1, | ||
1958 | .channels_max = 2, | ||
1959 | .rates = RT5640_STEREO_RATES, | ||
1960 | .formats = RT5640_FORMATS, | ||
1961 | }, | ||
1962 | .ops = &rt5640_aif_dai_ops, | ||
1963 | }, | ||
1964 | }; | ||
1965 | |||
1966 | static struct snd_soc_codec_driver soc_codec_dev_rt5640 = { | ||
1967 | .probe = rt5640_probe, | ||
1968 | .remove = rt5640_remove, | ||
1969 | .suspend = rt5640_suspend, | ||
1970 | .resume = rt5640_resume, | ||
1971 | .set_bias_level = rt5640_set_bias_level, | ||
1972 | .controls = rt5640_snd_controls, | ||
1973 | .num_controls = ARRAY_SIZE(rt5640_snd_controls), | ||
1974 | .dapm_widgets = rt5640_dapm_widgets, | ||
1975 | .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets), | ||
1976 | .dapm_routes = rt5640_dapm_routes, | ||
1977 | .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes), | ||
1978 | }; | ||
1979 | |||
1980 | static const struct regmap_config rt5640_regmap = { | ||
1981 | .reg_bits = 8, | ||
1982 | .val_bits = 16, | ||
1983 | |||
1984 | .max_register = RT5640_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5640_ranges) * | ||
1985 | RT5640_PR_SPACING), | ||
1986 | .volatile_reg = rt5640_volatile_register, | ||
1987 | .readable_reg = rt5640_readable_register, | ||
1988 | |||
1989 | .cache_type = REGCACHE_RBTREE, | ||
1990 | .reg_defaults = rt5640_reg, | ||
1991 | .num_reg_defaults = ARRAY_SIZE(rt5640_reg), | ||
1992 | .ranges = rt5640_ranges, | ||
1993 | .num_ranges = ARRAY_SIZE(rt5640_ranges), | ||
1994 | }; | ||
1995 | |||
1996 | static const struct i2c_device_id rt5640_i2c_id[] = { | ||
1997 | { "rt5640", 0 }, | ||
1998 | { } | ||
1999 | }; | ||
2000 | MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); | ||
2001 | |||
2002 | static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np) | ||
2003 | { | ||
2004 | rt5640->pdata.in1_diff = of_property_read_bool(np, | ||
2005 | "realtek,in1-differential"); | ||
2006 | rt5640->pdata.in2_diff = of_property_read_bool(np, | ||
2007 | "realtek,in2-differential"); | ||
2008 | |||
2009 | rt5640->pdata.ldo1_en = of_get_named_gpio(np, | ||
2010 | "realtek,ldo1-en-gpios", 0); | ||
2011 | /* | ||
2012 | * LDO1_EN is optional (it may be statically tied on the board). | ||
2013 | * -ENOENT means that the property doesn't exist, i.e. there is no | ||
2014 | * GPIO, so is not an error. Any other error code means the property | ||
2015 | * exists, but could not be parsed. | ||
2016 | */ | ||
2017 | if (!gpio_is_valid(rt5640->pdata.ldo1_en) && | ||
2018 | (rt5640->pdata.ldo1_en != -ENOENT)) | ||
2019 | return rt5640->pdata.ldo1_en; | ||
2020 | |||
2021 | return 0; | ||
2022 | } | ||
2023 | |||
2024 | static int rt5640_i2c_probe(struct i2c_client *i2c, | ||
2025 | const struct i2c_device_id *id) | ||
2026 | { | ||
2027 | struct rt5640_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
2028 | struct rt5640_priv *rt5640; | ||
2029 | int ret; | ||
2030 | unsigned int val; | ||
2031 | |||
2032 | rt5640 = devm_kzalloc(&i2c->dev, | ||
2033 | sizeof(struct rt5640_priv), | ||
2034 | GFP_KERNEL); | ||
2035 | if (NULL == rt5640) | ||
2036 | return -ENOMEM; | ||
2037 | i2c_set_clientdata(i2c, rt5640); | ||
2038 | |||
2039 | if (pdata) { | ||
2040 | rt5640->pdata = *pdata; | ||
2041 | /* | ||
2042 | * Translate zero'd out (default) pdata value to an invalid | ||
2043 | * GPIO ID. This makes the pdata and DT paths consistent in | ||
2044 | * terms of the value left in this field when no GPIO is | ||
2045 | * specified, but means we can't actually use GPIO 0. | ||
2046 | */ | ||
2047 | if (!rt5640->pdata.ldo1_en) | ||
2048 | rt5640->pdata.ldo1_en = -EINVAL; | ||
2049 | } else if (i2c->dev.of_node) { | ||
2050 | ret = rt5640_parse_dt(rt5640, i2c->dev.of_node); | ||
2051 | if (ret) | ||
2052 | return ret; | ||
2053 | } else | ||
2054 | rt5640->pdata.ldo1_en = -EINVAL; | ||
2055 | |||
2056 | rt5640->regmap = devm_regmap_init_i2c(i2c, &rt5640_regmap); | ||
2057 | if (IS_ERR(rt5640->regmap)) { | ||
2058 | ret = PTR_ERR(rt5640->regmap); | ||
2059 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
2060 | ret); | ||
2061 | return ret; | ||
2062 | } | ||
2063 | |||
2064 | if (gpio_is_valid(rt5640->pdata.ldo1_en)) { | ||
2065 | ret = devm_gpio_request_one(&i2c->dev, rt5640->pdata.ldo1_en, | ||
2066 | GPIOF_OUT_INIT_HIGH, | ||
2067 | "RT5640 LDO1_EN"); | ||
2068 | if (ret < 0) { | ||
2069 | dev_err(&i2c->dev, "Failed to request LDO1_EN %d: %d\n", | ||
2070 | rt5640->pdata.ldo1_en, ret); | ||
2071 | return ret; | ||
2072 | } | ||
2073 | msleep(400); | ||
2074 | } | ||
2075 | |||
2076 | regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); | ||
2077 | if ((val != RT5640_DEVICE_ID)) { | ||
2078 | dev_err(&i2c->dev, | ||
2079 | "Device with ID register %x is not rt5640/39\n", val); | ||
2080 | return -ENODEV; | ||
2081 | } | ||
2082 | |||
2083 | regmap_write(rt5640->regmap, RT5640_RESET, 0); | ||
2084 | |||
2085 | ret = regmap_register_patch(rt5640->regmap, init_list, | ||
2086 | ARRAY_SIZE(init_list)); | ||
2087 | if (ret != 0) | ||
2088 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | ||
2089 | |||
2090 | if (rt5640->pdata.in1_diff) | ||
2091 | regmap_update_bits(rt5640->regmap, RT5640_IN1_IN2, | ||
2092 | RT5640_IN_DF1, RT5640_IN_DF1); | ||
2093 | |||
2094 | if (rt5640->pdata.in2_diff) | ||
2095 | regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4, | ||
2096 | RT5640_IN_DF2, RT5640_IN_DF2); | ||
2097 | |||
2098 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, | ||
2099 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); | ||
2100 | if (ret < 0) | ||
2101 | goto err; | ||
2102 | |||
2103 | return 0; | ||
2104 | err: | ||
2105 | return ret; | ||
2106 | } | ||
2107 | |||
2108 | static int rt5640_i2c_remove(struct i2c_client *i2c) | ||
2109 | { | ||
2110 | snd_soc_unregister_codec(&i2c->dev); | ||
2111 | |||
2112 | return 0; | ||
2113 | } | ||
2114 | |||
2115 | static struct i2c_driver rt5640_i2c_driver = { | ||
2116 | .driver = { | ||
2117 | .name = "rt5640", | ||
2118 | .owner = THIS_MODULE, | ||
2119 | }, | ||
2120 | .probe = rt5640_i2c_probe, | ||
2121 | .remove = rt5640_i2c_remove, | ||
2122 | .id_table = rt5640_i2c_id, | ||
2123 | }; | ||
2124 | module_i2c_driver(rt5640_i2c_driver); | ||
2125 | |||
2126 | MODULE_DESCRIPTION("ASoC RT5640 driver"); | ||
2127 | MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>"); | ||
2128 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h new file mode 100644 index 000000000000..c48286d7118f --- /dev/null +++ b/sound/soc/codecs/rt5640.h | |||
@@ -0,0 +1,2092 @@ | |||
1 | /* | ||
2 | * rt5640.h -- RT5640 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2011 Realtek Microelectronics | ||
5 | * Author: Johnny Hsu <johnnyhsu@realtek.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _RT5640_H | ||
13 | #define _RT5640_H | ||
14 | |||
15 | #include <sound/rt5640.h> | ||
16 | |||
17 | /* Info */ | ||
18 | #define RT5640_RESET 0x00 | ||
19 | #define RT5640_VENDOR_ID 0xfd | ||
20 | #define RT5640_VENDOR_ID1 0xfe | ||
21 | #define RT5640_VENDOR_ID2 0xff | ||
22 | /* I/O - Output */ | ||
23 | #define RT5640_SPK_VOL 0x01 | ||
24 | #define RT5640_HP_VOL 0x02 | ||
25 | #define RT5640_OUTPUT 0x03 | ||
26 | #define RT5640_MONO_OUT 0x04 | ||
27 | /* I/O - Input */ | ||
28 | #define RT5640_IN1_IN2 0x0d | ||
29 | #define RT5640_IN3_IN4 0x0e | ||
30 | #define RT5640_INL_INR_VOL 0x0f | ||
31 | /* I/O - ADC/DAC/DMIC */ | ||
32 | #define RT5640_DAC1_DIG_VOL 0x19 | ||
33 | #define RT5640_DAC2_DIG_VOL 0x1a | ||
34 | #define RT5640_DAC2_CTRL 0x1b | ||
35 | #define RT5640_ADC_DIG_VOL 0x1c | ||
36 | #define RT5640_ADC_DATA 0x1d | ||
37 | #define RT5640_ADC_BST_VOL 0x1e | ||
38 | /* Mixer - D-D */ | ||
39 | #define RT5640_STO_ADC_MIXER 0x27 | ||
40 | #define RT5640_MONO_ADC_MIXER 0x28 | ||
41 | #define RT5640_AD_DA_MIXER 0x29 | ||
42 | #define RT5640_STO_DAC_MIXER 0x2a | ||
43 | #define RT5640_MONO_DAC_MIXER 0x2b | ||
44 | #define RT5640_DIG_MIXER 0x2c | ||
45 | #define RT5640_DSP_PATH1 0x2d | ||
46 | #define RT5640_DSP_PATH2 0x2e | ||
47 | #define RT5640_DIG_INF_DATA 0x2f | ||
48 | /* Mixer - ADC */ | ||
49 | #define RT5640_REC_L1_MIXER 0x3b | ||
50 | #define RT5640_REC_L2_MIXER 0x3c | ||
51 | #define RT5640_REC_R1_MIXER 0x3d | ||
52 | #define RT5640_REC_R2_MIXER 0x3e | ||
53 | /* Mixer - DAC */ | ||
54 | #define RT5640_HPO_MIXER 0x45 | ||
55 | #define RT5640_SPK_L_MIXER 0x46 | ||
56 | #define RT5640_SPK_R_MIXER 0x47 | ||
57 | #define RT5640_SPO_L_MIXER 0x48 | ||
58 | #define RT5640_SPO_R_MIXER 0x49 | ||
59 | #define RT5640_SPO_CLSD_RATIO 0x4a | ||
60 | #define RT5640_MONO_MIXER 0x4c | ||
61 | #define RT5640_OUT_L1_MIXER 0x4d | ||
62 | #define RT5640_OUT_L2_MIXER 0x4e | ||
63 | #define RT5640_OUT_L3_MIXER 0x4f | ||
64 | #define RT5640_OUT_R1_MIXER 0x50 | ||
65 | #define RT5640_OUT_R2_MIXER 0x51 | ||
66 | #define RT5640_OUT_R3_MIXER 0x52 | ||
67 | #define RT5640_LOUT_MIXER 0x53 | ||
68 | /* Power */ | ||
69 | #define RT5640_PWR_DIG1 0x61 | ||
70 | #define RT5640_PWR_DIG2 0x62 | ||
71 | #define RT5640_PWR_ANLG1 0x63 | ||
72 | #define RT5640_PWR_ANLG2 0x64 | ||
73 | #define RT5640_PWR_MIXER 0x65 | ||
74 | #define RT5640_PWR_VOL 0x66 | ||
75 | /* Private Register Control */ | ||
76 | #define RT5640_PRIV_INDEX 0x6a | ||
77 | #define RT5640_PRIV_DATA 0x6c | ||
78 | /* Format - ADC/DAC */ | ||
79 | #define RT5640_I2S1_SDP 0x70 | ||
80 | #define RT5640_I2S2_SDP 0x71 | ||
81 | #define RT5640_ADDA_CLK1 0x73 | ||
82 | #define RT5640_ADDA_CLK2 0x74 | ||
83 | #define RT5640_DMIC 0x75 | ||
84 | /* Function - Analog */ | ||
85 | #define RT5640_GLB_CLK 0x80 | ||
86 | #define RT5640_PLL_CTRL1 0x81 | ||
87 | #define RT5640_PLL_CTRL2 0x82 | ||
88 | #define RT5640_ASRC_1 0x83 | ||
89 | #define RT5640_ASRC_2 0x84 | ||
90 | #define RT5640_ASRC_3 0x85 | ||
91 | #define RT5640_ASRC_4 0x89 | ||
92 | #define RT5640_ASRC_5 0x8a | ||
93 | #define RT5640_HP_OVCD 0x8b | ||
94 | #define RT5640_CLS_D_OVCD 0x8c | ||
95 | #define RT5640_CLS_D_OUT 0x8d | ||
96 | #define RT5640_DEPOP_M1 0x8e | ||
97 | #define RT5640_DEPOP_M2 0x8f | ||
98 | #define RT5640_DEPOP_M3 0x90 | ||
99 | #define RT5640_CHARGE_PUMP 0x91 | ||
100 | #define RT5640_PV_DET_SPK_G 0x92 | ||
101 | #define RT5640_MICBIAS 0x93 | ||
102 | /* Function - Digital */ | ||
103 | #define RT5640_EQ_CTRL1 0xb0 | ||
104 | #define RT5640_EQ_CTRL2 0xb1 | ||
105 | #define RT5640_WIND_FILTER 0xb2 | ||
106 | #define RT5640_DRC_AGC_1 0xb4 | ||
107 | #define RT5640_DRC_AGC_2 0xb5 | ||
108 | #define RT5640_DRC_AGC_3 0xb6 | ||
109 | #define RT5640_SVOL_ZC 0xb7 | ||
110 | #define RT5640_ANC_CTRL1 0xb8 | ||
111 | #define RT5640_ANC_CTRL2 0xb9 | ||
112 | #define RT5640_ANC_CTRL3 0xba | ||
113 | #define RT5640_JD_CTRL 0xbb | ||
114 | #define RT5640_ANC_JD 0xbc | ||
115 | #define RT5640_IRQ_CTRL1 0xbd | ||
116 | #define RT5640_IRQ_CTRL2 0xbe | ||
117 | #define RT5640_INT_IRQ_ST 0xbf | ||
118 | #define RT5640_GPIO_CTRL1 0xc0 | ||
119 | #define RT5640_GPIO_CTRL2 0xc1 | ||
120 | #define RT5640_GPIO_CTRL3 0xc2 | ||
121 | #define RT5640_DSP_CTRL1 0xc4 | ||
122 | #define RT5640_DSP_CTRL2 0xc5 | ||
123 | #define RT5640_DSP_CTRL3 0xc6 | ||
124 | #define RT5640_DSP_CTRL4 0xc7 | ||
125 | #define RT5640_PGM_REG_ARR1 0xc8 | ||
126 | #define RT5640_PGM_REG_ARR2 0xc9 | ||
127 | #define RT5640_PGM_REG_ARR3 0xca | ||
128 | #define RT5640_PGM_REG_ARR4 0xcb | ||
129 | #define RT5640_PGM_REG_ARR5 0xcc | ||
130 | #define RT5640_SCB_FUNC 0xcd | ||
131 | #define RT5640_SCB_CTRL 0xce | ||
132 | #define RT5640_BASE_BACK 0xcf | ||
133 | #define RT5640_MP3_PLUS1 0xd0 | ||
134 | #define RT5640_MP3_PLUS2 0xd1 | ||
135 | #define RT5640_3D_HP 0xd2 | ||
136 | #define RT5640_ADJ_HPF 0xd3 | ||
137 | #define RT5640_HP_CALIB_AMP_DET 0xd6 | ||
138 | #define RT5640_HP_CALIB2 0xd7 | ||
139 | #define RT5640_SV_ZCD1 0xd9 | ||
140 | #define RT5640_SV_ZCD2 0xda | ||
141 | /* Dummy Register */ | ||
142 | #define RT5640_DUMMY1 0xfa | ||
143 | #define RT5640_DUMMY2 0xfb | ||
144 | #define RT5640_DUMMY3 0xfc | ||
145 | |||
146 | |||
147 | /* Index of Codec Private Register definition */ | ||
148 | #define RT5640_3D_SPK 0x63 | ||
149 | #define RT5640_WND_1 0x6c | ||
150 | #define RT5640_WND_2 0x6d | ||
151 | #define RT5640_WND_3 0x6e | ||
152 | #define RT5640_WND_4 0x6f | ||
153 | #define RT5640_WND_5 0x70 | ||
154 | #define RT5640_WND_8 0x73 | ||
155 | #define RT5640_DIP_SPK_INF 0x75 | ||
156 | #define RT5640_EQ_BW_LOP 0xa0 | ||
157 | #define RT5640_EQ_GN_LOP 0xa1 | ||
158 | #define RT5640_EQ_FC_BP1 0xa2 | ||
159 | #define RT5640_EQ_BW_BP1 0xa3 | ||
160 | #define RT5640_EQ_GN_BP1 0xa4 | ||
161 | #define RT5640_EQ_FC_BP2 0xa5 | ||
162 | #define RT5640_EQ_BW_BP2 0xa6 | ||
163 | #define RT5640_EQ_GN_BP2 0xa7 | ||
164 | #define RT5640_EQ_FC_BP3 0xa8 | ||
165 | #define RT5640_EQ_BW_BP3 0xa9 | ||
166 | #define RT5640_EQ_GN_BP3 0xaa | ||
167 | #define RT5640_EQ_FC_BP4 0xab | ||
168 | #define RT5640_EQ_BW_BP4 0xac | ||
169 | #define RT5640_EQ_GN_BP4 0xad | ||
170 | #define RT5640_EQ_FC_HIP1 0xae | ||
171 | #define RT5640_EQ_GN_HIP1 0xaf | ||
172 | #define RT5640_EQ_FC_HIP2 0xb0 | ||
173 | #define RT5640_EQ_BW_HIP2 0xb1 | ||
174 | #define RT5640_EQ_GN_HIP2 0xb2 | ||
175 | #define RT5640_EQ_PRE_VOL 0xb3 | ||
176 | #define RT5640_EQ_PST_VOL 0xb4 | ||
177 | |||
178 | /* global definition */ | ||
179 | #define RT5640_L_MUTE (0x1 << 15) | ||
180 | #define RT5640_L_MUTE_SFT 15 | ||
181 | #define RT5640_VOL_L_MUTE (0x1 << 14) | ||
182 | #define RT5640_VOL_L_SFT 14 | ||
183 | #define RT5640_R_MUTE (0x1 << 7) | ||
184 | #define RT5640_R_MUTE_SFT 7 | ||
185 | #define RT5640_VOL_R_MUTE (0x1 << 6) | ||
186 | #define RT5640_VOL_R_SFT 6 | ||
187 | #define RT5640_L_VOL_MASK (0x3f << 8) | ||
188 | #define RT5640_L_VOL_SFT 8 | ||
189 | #define RT5640_R_VOL_MASK (0x3f) | ||
190 | #define RT5640_R_VOL_SFT 0 | ||
191 | |||
192 | /* IN1 and IN2 Control (0x0d) */ | ||
193 | /* IN3 and IN4 Control (0x0e) */ | ||
194 | #define RT5640_BST_SFT1 12 | ||
195 | #define RT5640_BST_SFT2 8 | ||
196 | #define RT5640_IN_DF1 (0x1 << 7) | ||
197 | #define RT5640_IN_SFT1 7 | ||
198 | #define RT5640_IN_DF2 (0x1 << 6) | ||
199 | #define RT5640_IN_SFT2 6 | ||
200 | |||
201 | /* INL and INR Volume Control (0x0f) */ | ||
202 | #define RT5640_INL_SEL_MASK (0x1 << 15) | ||
203 | #define RT5640_INL_SEL_SFT 15 | ||
204 | #define RT5640_INL_SEL_IN4P (0x0 << 15) | ||
205 | #define RT5640_INL_SEL_MONOP (0x1 << 15) | ||
206 | #define RT5640_INL_VOL_MASK (0x1f << 8) | ||
207 | #define RT5640_INL_VOL_SFT 8 | ||
208 | #define RT5640_INR_SEL_MASK (0x1 << 7) | ||
209 | #define RT5640_INR_SEL_SFT 7 | ||
210 | #define RT5640_INR_SEL_IN4N (0x0 << 7) | ||
211 | #define RT5640_INR_SEL_MONON (0x1 << 7) | ||
212 | #define RT5640_INR_VOL_MASK (0x1f) | ||
213 | #define RT5640_INR_VOL_SFT 0 | ||
214 | |||
215 | /* DAC1 Digital Volume (0x19) */ | ||
216 | #define RT5640_DAC_L1_VOL_MASK (0xff << 8) | ||
217 | #define RT5640_DAC_L1_VOL_SFT 8 | ||
218 | #define RT5640_DAC_R1_VOL_MASK (0xff) | ||
219 | #define RT5640_DAC_R1_VOL_SFT 0 | ||
220 | |||
221 | /* DAC2 Digital Volume (0x1a) */ | ||
222 | #define RT5640_DAC_L2_VOL_MASK (0xff << 8) | ||
223 | #define RT5640_DAC_L2_VOL_SFT 8 | ||
224 | #define RT5640_DAC_R2_VOL_MASK (0xff) | ||
225 | #define RT5640_DAC_R2_VOL_SFT 0 | ||
226 | |||
227 | /* DAC2 Control (0x1b) */ | ||
228 | #define RT5640_M_DAC_L2_VOL (0x1 << 13) | ||
229 | #define RT5640_M_DAC_L2_VOL_SFT 13 | ||
230 | #define RT5640_M_DAC_R2_VOL (0x1 << 12) | ||
231 | #define RT5640_M_DAC_R2_VOL_SFT 12 | ||
232 | |||
233 | /* ADC Digital Volume Control (0x1c) */ | ||
234 | #define RT5640_ADC_L_VOL_MASK (0x7f << 8) | ||
235 | #define RT5640_ADC_L_VOL_SFT 8 | ||
236 | #define RT5640_ADC_R_VOL_MASK (0x7f) | ||
237 | #define RT5640_ADC_R_VOL_SFT 0 | ||
238 | |||
239 | /* Mono ADC Digital Volume Control (0x1d) */ | ||
240 | #define RT5640_MONO_ADC_L_VOL_MASK (0x7f << 8) | ||
241 | #define RT5640_MONO_ADC_L_VOL_SFT 8 | ||
242 | #define RT5640_MONO_ADC_R_VOL_MASK (0x7f) | ||
243 | #define RT5640_MONO_ADC_R_VOL_SFT 0 | ||
244 | |||
245 | /* ADC Boost Volume Control (0x1e) */ | ||
246 | #define RT5640_ADC_L_BST_MASK (0x3 << 14) | ||
247 | #define RT5640_ADC_L_BST_SFT 14 | ||
248 | #define RT5640_ADC_R_BST_MASK (0x3 << 12) | ||
249 | #define RT5640_ADC_R_BST_SFT 12 | ||
250 | #define RT5640_ADC_COMP_MASK (0x3 << 10) | ||
251 | #define RT5640_ADC_COMP_SFT 10 | ||
252 | |||
253 | /* Stereo ADC Mixer Control (0x27) */ | ||
254 | #define RT5640_M_ADC_L1 (0x1 << 14) | ||
255 | #define RT5640_M_ADC_L1_SFT 14 | ||
256 | #define RT5640_M_ADC_L2 (0x1 << 13) | ||
257 | #define RT5640_M_ADC_L2_SFT 13 | ||
258 | #define RT5640_ADC_1_SRC_MASK (0x1 << 12) | ||
259 | #define RT5640_ADC_1_SRC_SFT 12 | ||
260 | #define RT5640_ADC_1_SRC_ADC (0x1 << 12) | ||
261 | #define RT5640_ADC_1_SRC_DACMIX (0x0 << 12) | ||
262 | #define RT5640_ADC_2_SRC_MASK (0x3 << 10) | ||
263 | #define RT5640_ADC_2_SRC_SFT 10 | ||
264 | #define RT5640_ADC_2_SRC_DMIC1 (0x0 << 10) | ||
265 | #define RT5640_ADC_2_SRC_DMIC2 (0x1 << 10) | ||
266 | #define RT5640_ADC_2_SRC_DACMIX (0x2 << 10) | ||
267 | #define RT5640_M_ADC_R1 (0x1 << 6) | ||
268 | #define RT5640_M_ADC_R1_SFT 6 | ||
269 | #define RT5640_M_ADC_R2 (0x1 << 5) | ||
270 | #define RT5640_M_ADC_R2_SFT 5 | ||
271 | |||
272 | /* Mono ADC Mixer Control (0x28) */ | ||
273 | #define RT5640_M_MONO_ADC_L1 (0x1 << 14) | ||
274 | #define RT5640_M_MONO_ADC_L1_SFT 14 | ||
275 | #define RT5640_M_MONO_ADC_L2 (0x1 << 13) | ||
276 | #define RT5640_M_MONO_ADC_L2_SFT 13 | ||
277 | #define RT5640_MONO_ADC_L1_SRC_MASK (0x1 << 12) | ||
278 | #define RT5640_MONO_ADC_L1_SRC_SFT 12 | ||
279 | #define RT5640_MONO_ADC_L1_SRC_DACMIXL (0x0 << 12) | ||
280 | #define RT5640_MONO_ADC_L1_SRC_ADCL (0x1 << 12) | ||
281 | #define RT5640_MONO_ADC_L2_SRC_MASK (0x3 << 10) | ||
282 | #define RT5640_MONO_ADC_L2_SRC_SFT 10 | ||
283 | #define RT5640_MONO_ADC_L2_SRC_DMIC_L1 (0x0 << 10) | ||
284 | #define RT5640_MONO_ADC_L2_SRC_DMIC_L2 (0x1 << 10) | ||
285 | #define RT5640_MONO_ADC_L2_SRC_DACMIXL (0x2 << 10) | ||
286 | #define RT5640_M_MONO_ADC_R1 (0x1 << 6) | ||
287 | #define RT5640_M_MONO_ADC_R1_SFT 6 | ||
288 | #define RT5640_M_MONO_ADC_R2 (0x1 << 5) | ||
289 | #define RT5640_M_MONO_ADC_R2_SFT 5 | ||
290 | #define RT5640_MONO_ADC_R1_SRC_MASK (0x1 << 4) | ||
291 | #define RT5640_MONO_ADC_R1_SRC_SFT 4 | ||
292 | #define RT5640_MONO_ADC_R1_SRC_ADCR (0x1 << 4) | ||
293 | #define RT5640_MONO_ADC_R1_SRC_DACMIXR (0x0 << 4) | ||
294 | #define RT5640_MONO_ADC_R2_SRC_MASK (0x3 << 2) | ||
295 | #define RT5640_MONO_ADC_R2_SRC_SFT 2 | ||
296 | #define RT5640_MONO_ADC_R2_SRC_DMIC_R1 (0x0 << 2) | ||
297 | #define RT5640_MONO_ADC_R2_SRC_DMIC_R2 (0x1 << 2) | ||
298 | #define RT5640_MONO_ADC_R2_SRC_DACMIXR (0x2 << 2) | ||
299 | |||
300 | /* ADC Mixer to DAC Mixer Control (0x29) */ | ||
301 | #define RT5640_M_ADCMIX_L (0x1 << 15) | ||
302 | #define RT5640_M_ADCMIX_L_SFT 15 | ||
303 | #define RT5640_M_IF1_DAC_L (0x1 << 14) | ||
304 | #define RT5640_M_IF1_DAC_L_SFT 14 | ||
305 | #define RT5640_M_ADCMIX_R (0x1 << 7) | ||
306 | #define RT5640_M_ADCMIX_R_SFT 7 | ||
307 | #define RT5640_M_IF1_DAC_R (0x1 << 6) | ||
308 | #define RT5640_M_IF1_DAC_R_SFT 6 | ||
309 | |||
310 | /* Stereo DAC Mixer Control (0x2a) */ | ||
311 | #define RT5640_M_DAC_L1 (0x1 << 14) | ||
312 | #define RT5640_M_DAC_L1_SFT 14 | ||
313 | #define RT5640_DAC_L1_STO_L_VOL_MASK (0x1 << 13) | ||
314 | #define RT5640_DAC_L1_STO_L_VOL_SFT 13 | ||
315 | #define RT5640_M_DAC_L2 (0x1 << 12) | ||
316 | #define RT5640_M_DAC_L2_SFT 12 | ||
317 | #define RT5640_DAC_L2_STO_L_VOL_MASK (0x1 << 11) | ||
318 | #define RT5640_DAC_L2_STO_L_VOL_SFT 11 | ||
319 | #define RT5640_M_ANC_DAC_L (0x1 << 10) | ||
320 | #define RT5640_M_ANC_DAC_L_SFT 10 | ||
321 | #define RT5640_M_DAC_R1 (0x1 << 6) | ||
322 | #define RT5640_M_DAC_R1_SFT 6 | ||
323 | #define RT5640_DAC_R1_STO_R_VOL_MASK (0x1 << 5) | ||
324 | #define RT5640_DAC_R1_STO_R_VOL_SFT 5 | ||
325 | #define RT5640_M_DAC_R2 (0x1 << 4) | ||
326 | #define RT5640_M_DAC_R2_SFT 4 | ||
327 | #define RT5640_DAC_R2_STO_R_VOL_MASK (0x1 << 3) | ||
328 | #define RT5640_DAC_R2_STO_R_VOL_SFT 3 | ||
329 | #define RT5640_M_ANC_DAC_R (0x1 << 2) | ||
330 | #define RT5640_M_ANC_DAC_R_SFT 2 | ||
331 | |||
332 | /* Mono DAC Mixer Control (0x2b) */ | ||
333 | #define RT5640_M_DAC_L1_MONO_L (0x1 << 14) | ||
334 | #define RT5640_M_DAC_L1_MONO_L_SFT 14 | ||
335 | #define RT5640_DAC_L1_MONO_L_VOL_MASK (0x1 << 13) | ||
336 | #define RT5640_DAC_L1_MONO_L_VOL_SFT 13 | ||
337 | #define RT5640_M_DAC_L2_MONO_L (0x1 << 12) | ||
338 | #define RT5640_M_DAC_L2_MONO_L_SFT 12 | ||
339 | #define RT5640_DAC_L2_MONO_L_VOL_MASK (0x1 << 11) | ||
340 | #define RT5640_DAC_L2_MONO_L_VOL_SFT 11 | ||
341 | #define RT5640_M_DAC_R2_MONO_L (0x1 << 10) | ||
342 | #define RT5640_M_DAC_R2_MONO_L_SFT 10 | ||
343 | #define RT5640_DAC_R2_MONO_L_VOL_MASK (0x1 << 9) | ||
344 | #define RT5640_DAC_R2_MONO_L_VOL_SFT 9 | ||
345 | #define RT5640_M_DAC_R1_MONO_R (0x1 << 6) | ||
346 | #define RT5640_M_DAC_R1_MONO_R_SFT 6 | ||
347 | #define RT5640_DAC_R1_MONO_R_VOL_MASK (0x1 << 5) | ||
348 | #define RT5640_DAC_R1_MONO_R_VOL_SFT 5 | ||
349 | #define RT5640_M_DAC_R2_MONO_R (0x1 << 4) | ||
350 | #define RT5640_M_DAC_R2_MONO_R_SFT 4 | ||
351 | #define RT5640_DAC_R2_MONO_R_VOL_MASK (0x1 << 3) | ||
352 | #define RT5640_DAC_R2_MONO_R_VOL_SFT 3 | ||
353 | #define RT5640_M_DAC_L2_MONO_R (0x1 << 2) | ||
354 | #define RT5640_M_DAC_L2_MONO_R_SFT 2 | ||
355 | #define RT5640_DAC_L2_MONO_R_VOL_MASK (0x1 << 1) | ||
356 | #define RT5640_DAC_L2_MONO_R_VOL_SFT 1 | ||
357 | |||
358 | /* Digital Mixer Control (0x2c) */ | ||
359 | #define RT5640_M_STO_L_DAC_L (0x1 << 15) | ||
360 | #define RT5640_M_STO_L_DAC_L_SFT 15 | ||
361 | #define RT5640_STO_L_DAC_L_VOL_MASK (0x1 << 14) | ||
362 | #define RT5640_STO_L_DAC_L_VOL_SFT 14 | ||
363 | #define RT5640_M_DAC_L2_DAC_L (0x1 << 13) | ||
364 | #define RT5640_M_DAC_L2_DAC_L_SFT 13 | ||
365 | #define RT5640_DAC_L2_DAC_L_VOL_MASK (0x1 << 12) | ||
366 | #define RT5640_DAC_L2_DAC_L_VOL_SFT 12 | ||
367 | #define RT5640_M_STO_R_DAC_R (0x1 << 11) | ||
368 | #define RT5640_M_STO_R_DAC_R_SFT 11 | ||
369 | #define RT5640_STO_R_DAC_R_VOL_MASK (0x1 << 10) | ||
370 | #define RT5640_STO_R_DAC_R_VOL_SFT 10 | ||
371 | #define RT5640_M_DAC_R2_DAC_R (0x1 << 9) | ||
372 | #define RT5640_M_DAC_R2_DAC_R_SFT 9 | ||
373 | #define RT5640_DAC_R2_DAC_R_VOL_MASK (0x1 << 8) | ||
374 | #define RT5640_DAC_R2_DAC_R_VOL_SFT 8 | ||
375 | |||
376 | /* DSP Path Control 1 (0x2d) */ | ||
377 | #define RT5640_RXDP_SRC_MASK (0x1 << 15) | ||
378 | #define RT5640_RXDP_SRC_SFT 15 | ||
379 | #define RT5640_RXDP_SRC_NOR (0x0 << 15) | ||
380 | #define RT5640_RXDP_SRC_DIV3 (0x1 << 15) | ||
381 | #define RT5640_TXDP_SRC_MASK (0x1 << 14) | ||
382 | #define RT5640_TXDP_SRC_SFT 14 | ||
383 | #define RT5640_TXDP_SRC_NOR (0x0 << 14) | ||
384 | #define RT5640_TXDP_SRC_DIV3 (0x1 << 14) | ||
385 | |||
386 | /* DSP Path Control 2 (0x2e) */ | ||
387 | #define RT5640_DAC_L2_SEL_MASK (0x3 << 14) | ||
388 | #define RT5640_DAC_L2_SEL_SFT 14 | ||
389 | #define RT5640_DAC_L2_SEL_IF2 (0x0 << 14) | ||
390 | #define RT5640_DAC_L2_SEL_IF3 (0x1 << 14) | ||
391 | #define RT5640_DAC_L2_SEL_TXDC (0x2 << 14) | ||
392 | #define RT5640_DAC_L2_SEL_BASS (0x3 << 14) | ||
393 | #define RT5640_DAC_R2_SEL_MASK (0x3 << 12) | ||
394 | #define RT5640_DAC_R2_SEL_SFT 12 | ||
395 | #define RT5640_DAC_R2_SEL_IF2 (0x0 << 12) | ||
396 | #define RT5640_DAC_R2_SEL_IF3 (0x1 << 12) | ||
397 | #define RT5640_DAC_R2_SEL_TXDC (0x2 << 12) | ||
398 | #define RT5640_IF2_ADC_L_SEL_MASK (0x1 << 11) | ||
399 | #define RT5640_IF2_ADC_L_SEL_SFT 11 | ||
400 | #define RT5640_IF2_ADC_L_SEL_TXDP (0x0 << 11) | ||
401 | #define RT5640_IF2_ADC_L_SEL_PASS (0x1 << 11) | ||
402 | #define RT5640_IF2_ADC_R_SEL_MASK (0x1 << 10) | ||
403 | #define RT5640_IF2_ADC_R_SEL_SFT 10 | ||
404 | #define RT5640_IF2_ADC_R_SEL_TXDP (0x0 << 10) | ||
405 | #define RT5640_IF2_ADC_R_SEL_PASS (0x1 << 10) | ||
406 | #define RT5640_RXDC_SEL_MASK (0x3 << 8) | ||
407 | #define RT5640_RXDC_SEL_SFT 8 | ||
408 | #define RT5640_RXDC_SEL_NOR (0x0 << 8) | ||
409 | #define RT5640_RXDC_SEL_L2R (0x1 << 8) | ||
410 | #define RT5640_RXDC_SEL_R2L (0x2 << 8) | ||
411 | #define RT5640_RXDC_SEL_SWAP (0x3 << 8) | ||
412 | #define RT5640_RXDP_SEL_MASK (0x3 << 6) | ||
413 | #define RT5640_RXDP_SEL_SFT 6 | ||
414 | #define RT5640_RXDP_SEL_NOR (0x0 << 6) | ||
415 | #define RT5640_RXDP_SEL_L2R (0x1 << 6) | ||
416 | #define RT5640_RXDP_SEL_R2L (0x2 << 6) | ||
417 | #define RT5640_RXDP_SEL_SWAP (0x3 << 6) | ||
418 | #define RT5640_TXDC_SEL_MASK (0x3 << 4) | ||
419 | #define RT5640_TXDC_SEL_SFT 4 | ||
420 | #define RT5640_TXDC_SEL_NOR (0x0 << 4) | ||
421 | #define RT5640_TXDC_SEL_L2R (0x1 << 4) | ||
422 | #define RT5640_TXDC_SEL_R2L (0x2 << 4) | ||
423 | #define RT5640_TXDC_SEL_SWAP (0x3 << 4) | ||
424 | #define RT5640_TXDP_SEL_MASK (0x3 << 2) | ||
425 | #define RT5640_TXDP_SEL_SFT 2 | ||
426 | #define RT5640_TXDP_SEL_NOR (0x0 << 2) | ||
427 | #define RT5640_TXDP_SEL_L2R (0x1 << 2) | ||
428 | #define RT5640_TXDP_SEL_R2L (0x2 << 2) | ||
429 | #define RT5640_TRXDP_SEL_SWAP (0x3 << 2) | ||
430 | |||
431 | /* Digital Interface Data Control (0x2f) */ | ||
432 | #define RT5640_IF1_DAC_SEL_MASK (0x3 << 14) | ||
433 | #define RT5640_IF1_DAC_SEL_SFT 14 | ||
434 | #define RT5640_IF1_DAC_SEL_NOR (0x0 << 14) | ||
435 | #define RT5640_IF1_DAC_SEL_L2R (0x1 << 14) | ||
436 | #define RT5640_IF1_DAC_SEL_R2L (0x2 << 14) | ||
437 | #define RT5640_IF1_DAC_SEL_SWAP (0x3 << 14) | ||
438 | #define RT5640_IF1_ADC_SEL_MASK (0x3 << 12) | ||
439 | #define RT5640_IF1_ADC_SEL_SFT 12 | ||
440 | #define RT5640_IF1_ADC_SEL_NOR (0x0 << 12) | ||
441 | #define RT5640_IF1_ADC_SEL_L2R (0x1 << 12) | ||
442 | #define RT5640_IF1_ADC_SEL_R2L (0x2 << 12) | ||
443 | #define RT5640_IF1_ADC_SEL_SWAP (0x3 << 12) | ||
444 | #define RT5640_IF2_DAC_SEL_MASK (0x3 << 10) | ||
445 | #define RT5640_IF2_DAC_SEL_SFT 10 | ||
446 | #define RT5640_IF2_DAC_SEL_NOR (0x0 << 10) | ||
447 | #define RT5640_IF2_DAC_SEL_L2R (0x1 << 10) | ||
448 | #define RT5640_IF2_DAC_SEL_R2L (0x2 << 10) | ||
449 | #define RT5640_IF2_DAC_SEL_SWAP (0x3 << 10) | ||
450 | #define RT5640_IF2_ADC_SEL_MASK (0x3 << 8) | ||
451 | #define RT5640_IF2_ADC_SEL_SFT 8 | ||
452 | #define RT5640_IF2_ADC_SEL_NOR (0x0 << 8) | ||
453 | #define RT5640_IF2_ADC_SEL_L2R (0x1 << 8) | ||
454 | #define RT5640_IF2_ADC_SEL_R2L (0x2 << 8) | ||
455 | #define RT5640_IF2_ADC_SEL_SWAP (0x3 << 8) | ||
456 | #define RT5640_IF3_DAC_SEL_MASK (0x3 << 6) | ||
457 | #define RT5640_IF3_DAC_SEL_SFT 6 | ||
458 | #define RT5640_IF3_DAC_SEL_NOR (0x0 << 6) | ||
459 | #define RT5640_IF3_DAC_SEL_L2R (0x1 << 6) | ||
460 | #define RT5640_IF3_DAC_SEL_R2L (0x2 << 6) | ||
461 | #define RT5640_IF3_DAC_SEL_SWAP (0x3 << 6) | ||
462 | #define RT5640_IF3_ADC_SEL_MASK (0x3 << 4) | ||
463 | #define RT5640_IF3_ADC_SEL_SFT 4 | ||
464 | #define RT5640_IF3_ADC_SEL_NOR (0x0 << 4) | ||
465 | #define RT5640_IF3_ADC_SEL_L2R (0x1 << 4) | ||
466 | #define RT5640_IF3_ADC_SEL_R2L (0x2 << 4) | ||
467 | #define RT5640_IF3_ADC_SEL_SWAP (0x3 << 4) | ||
468 | |||
469 | /* REC Left Mixer Control 1 (0x3b) */ | ||
470 | #define RT5640_G_HP_L_RM_L_MASK (0x7 << 13) | ||
471 | #define RT5640_G_HP_L_RM_L_SFT 13 | ||
472 | #define RT5640_G_IN_L_RM_L_MASK (0x7 << 10) | ||
473 | #define RT5640_G_IN_L_RM_L_SFT 10 | ||
474 | #define RT5640_G_BST4_RM_L_MASK (0x7 << 7) | ||
475 | #define RT5640_G_BST4_RM_L_SFT 7 | ||
476 | #define RT5640_G_BST3_RM_L_MASK (0x7 << 4) | ||
477 | #define RT5640_G_BST3_RM_L_SFT 4 | ||
478 | #define RT5640_G_BST2_RM_L_MASK (0x7 << 1) | ||
479 | #define RT5640_G_BST2_RM_L_SFT 1 | ||
480 | |||
481 | /* REC Left Mixer Control 2 (0x3c) */ | ||
482 | #define RT5640_G_BST1_RM_L_MASK (0x7 << 13) | ||
483 | #define RT5640_G_BST1_RM_L_SFT 13 | ||
484 | #define RT5640_G_OM_L_RM_L_MASK (0x7 << 10) | ||
485 | #define RT5640_G_OM_L_RM_L_SFT 10 | ||
486 | #define RT5640_M_HP_L_RM_L (0x1 << 6) | ||
487 | #define RT5640_M_HP_L_RM_L_SFT 6 | ||
488 | #define RT5640_M_IN_L_RM_L (0x1 << 5) | ||
489 | #define RT5640_M_IN_L_RM_L_SFT 5 | ||
490 | #define RT5640_M_BST4_RM_L (0x1 << 4) | ||
491 | #define RT5640_M_BST4_RM_L_SFT 4 | ||
492 | #define RT5640_M_BST3_RM_L (0x1 << 3) | ||
493 | #define RT5640_M_BST3_RM_L_SFT 3 | ||
494 | #define RT5640_M_BST2_RM_L (0x1 << 2) | ||
495 | #define RT5640_M_BST2_RM_L_SFT 2 | ||
496 | #define RT5640_M_BST1_RM_L (0x1 << 1) | ||
497 | #define RT5640_M_BST1_RM_L_SFT 1 | ||
498 | #define RT5640_M_OM_L_RM_L (0x1) | ||
499 | #define RT5640_M_OM_L_RM_L_SFT 0 | ||
500 | |||
501 | /* REC Right Mixer Control 1 (0x3d) */ | ||
502 | #define RT5640_G_HP_R_RM_R_MASK (0x7 << 13) | ||
503 | #define RT5640_G_HP_R_RM_R_SFT 13 | ||
504 | #define RT5640_G_IN_R_RM_R_MASK (0x7 << 10) | ||
505 | #define RT5640_G_IN_R_RM_R_SFT 10 | ||
506 | #define RT5640_G_BST4_RM_R_MASK (0x7 << 7) | ||
507 | #define RT5640_G_BST4_RM_R_SFT 7 | ||
508 | #define RT5640_G_BST3_RM_R_MASK (0x7 << 4) | ||
509 | #define RT5640_G_BST3_RM_R_SFT 4 | ||
510 | #define RT5640_G_BST2_RM_R_MASK (0x7 << 1) | ||
511 | #define RT5640_G_BST2_RM_R_SFT 1 | ||
512 | |||
513 | /* REC Right Mixer Control 2 (0x3e) */ | ||
514 | #define RT5640_G_BST1_RM_R_MASK (0x7 << 13) | ||
515 | #define RT5640_G_BST1_RM_R_SFT 13 | ||
516 | #define RT5640_G_OM_R_RM_R_MASK (0x7 << 10) | ||
517 | #define RT5640_G_OM_R_RM_R_SFT 10 | ||
518 | #define RT5640_M_HP_R_RM_R (0x1 << 6) | ||
519 | #define RT5640_M_HP_R_RM_R_SFT 6 | ||
520 | #define RT5640_M_IN_R_RM_R (0x1 << 5) | ||
521 | #define RT5640_M_IN_R_RM_R_SFT 5 | ||
522 | #define RT5640_M_BST4_RM_R (0x1 << 4) | ||
523 | #define RT5640_M_BST4_RM_R_SFT 4 | ||
524 | #define RT5640_M_BST3_RM_R (0x1 << 3) | ||
525 | #define RT5640_M_BST3_RM_R_SFT 3 | ||
526 | #define RT5640_M_BST2_RM_R (0x1 << 2) | ||
527 | #define RT5640_M_BST2_RM_R_SFT 2 | ||
528 | #define RT5640_M_BST1_RM_R (0x1 << 1) | ||
529 | #define RT5640_M_BST1_RM_R_SFT 1 | ||
530 | #define RT5640_M_OM_R_RM_R (0x1) | ||
531 | #define RT5640_M_OM_R_RM_R_SFT 0 | ||
532 | |||
533 | /* HPMIX Control (0x45) */ | ||
534 | #define RT5640_M_DAC2_HM (0x1 << 15) | ||
535 | #define RT5640_M_DAC2_HM_SFT 15 | ||
536 | #define RT5640_M_DAC1_HM (0x1 << 14) | ||
537 | #define RT5640_M_DAC1_HM_SFT 14 | ||
538 | #define RT5640_M_HPVOL_HM (0x1 << 13) | ||
539 | #define RT5640_M_HPVOL_HM_SFT 13 | ||
540 | #define RT5640_G_HPOMIX_MASK (0x1 << 12) | ||
541 | #define RT5640_G_HPOMIX_SFT 12 | ||
542 | |||
543 | /* SPK Left Mixer Control (0x46) */ | ||
544 | #define RT5640_G_RM_L_SM_L_MASK (0x3 << 14) | ||
545 | #define RT5640_G_RM_L_SM_L_SFT 14 | ||
546 | #define RT5640_G_IN_L_SM_L_MASK (0x3 << 12) | ||
547 | #define RT5640_G_IN_L_SM_L_SFT 12 | ||
548 | #define RT5640_G_DAC_L1_SM_L_MASK (0x3 << 10) | ||
549 | #define RT5640_G_DAC_L1_SM_L_SFT 10 | ||
550 | #define RT5640_G_DAC_L2_SM_L_MASK (0x3 << 8) | ||
551 | #define RT5640_G_DAC_L2_SM_L_SFT 8 | ||
552 | #define RT5640_G_OM_L_SM_L_MASK (0x3 << 6) | ||
553 | #define RT5640_G_OM_L_SM_L_SFT 6 | ||
554 | #define RT5640_M_RM_L_SM_L (0x1 << 5) | ||
555 | #define RT5640_M_RM_L_SM_L_SFT 5 | ||
556 | #define RT5640_M_IN_L_SM_L (0x1 << 4) | ||
557 | #define RT5640_M_IN_L_SM_L_SFT 4 | ||
558 | #define RT5640_M_DAC_L1_SM_L (0x1 << 3) | ||
559 | #define RT5640_M_DAC_L1_SM_L_SFT 3 | ||
560 | #define RT5640_M_DAC_L2_SM_L (0x1 << 2) | ||
561 | #define RT5640_M_DAC_L2_SM_L_SFT 2 | ||
562 | #define RT5640_M_OM_L_SM_L (0x1 << 1) | ||
563 | #define RT5640_M_OM_L_SM_L_SFT 1 | ||
564 | |||
565 | /* SPK Right Mixer Control (0x47) */ | ||
566 | #define RT5640_G_RM_R_SM_R_MASK (0x3 << 14) | ||
567 | #define RT5640_G_RM_R_SM_R_SFT 14 | ||
568 | #define RT5640_G_IN_R_SM_R_MASK (0x3 << 12) | ||
569 | #define RT5640_G_IN_R_SM_R_SFT 12 | ||
570 | #define RT5640_G_DAC_R1_SM_R_MASK (0x3 << 10) | ||
571 | #define RT5640_G_DAC_R1_SM_R_SFT 10 | ||
572 | #define RT5640_G_DAC_R2_SM_R_MASK (0x3 << 8) | ||
573 | #define RT5640_G_DAC_R2_SM_R_SFT 8 | ||
574 | #define RT5640_G_OM_R_SM_R_MASK (0x3 << 6) | ||
575 | #define RT5640_G_OM_R_SM_R_SFT 6 | ||
576 | #define RT5640_M_RM_R_SM_R (0x1 << 5) | ||
577 | #define RT5640_M_RM_R_SM_R_SFT 5 | ||
578 | #define RT5640_M_IN_R_SM_R (0x1 << 4) | ||
579 | #define RT5640_M_IN_R_SM_R_SFT 4 | ||
580 | #define RT5640_M_DAC_R1_SM_R (0x1 << 3) | ||
581 | #define RT5640_M_DAC_R1_SM_R_SFT 3 | ||
582 | #define RT5640_M_DAC_R2_SM_R (0x1 << 2) | ||
583 | #define RT5640_M_DAC_R2_SM_R_SFT 2 | ||
584 | #define RT5640_M_OM_R_SM_R (0x1 << 1) | ||
585 | #define RT5640_M_OM_R_SM_R_SFT 1 | ||
586 | |||
587 | /* SPOLMIX Control (0x48) */ | ||
588 | #define RT5640_M_DAC_R1_SPM_L (0x1 << 15) | ||
589 | #define RT5640_M_DAC_R1_SPM_L_SFT 15 | ||
590 | #define RT5640_M_DAC_L1_SPM_L (0x1 << 14) | ||
591 | #define RT5640_M_DAC_L1_SPM_L_SFT 14 | ||
592 | #define RT5640_M_SV_R_SPM_L (0x1 << 13) | ||
593 | #define RT5640_M_SV_R_SPM_L_SFT 13 | ||
594 | #define RT5640_M_SV_L_SPM_L (0x1 << 12) | ||
595 | #define RT5640_M_SV_L_SPM_L_SFT 12 | ||
596 | #define RT5640_M_BST1_SPM_L (0x1 << 11) | ||
597 | #define RT5640_M_BST1_SPM_L_SFT 11 | ||
598 | |||
599 | /* SPORMIX Control (0x49) */ | ||
600 | #define RT5640_M_DAC_R1_SPM_R (0x1 << 13) | ||
601 | #define RT5640_M_DAC_R1_SPM_R_SFT 13 | ||
602 | #define RT5640_M_SV_R_SPM_R (0x1 << 12) | ||
603 | #define RT5640_M_SV_R_SPM_R_SFT 12 | ||
604 | #define RT5640_M_BST1_SPM_R (0x1 << 11) | ||
605 | #define RT5640_M_BST1_SPM_R_SFT 11 | ||
606 | |||
607 | /* SPOLMIX / SPORMIX Ratio Control (0x4a) */ | ||
608 | #define RT5640_SPO_CLSD_RATIO_MASK (0x7) | ||
609 | #define RT5640_SPO_CLSD_RATIO_SFT 0 | ||
610 | |||
611 | /* Mono Output Mixer Control (0x4c) */ | ||
612 | #define RT5640_M_DAC_R2_MM (0x1 << 15) | ||
613 | #define RT5640_M_DAC_R2_MM_SFT 15 | ||
614 | #define RT5640_M_DAC_L2_MM (0x1 << 14) | ||
615 | #define RT5640_M_DAC_L2_MM_SFT 14 | ||
616 | #define RT5640_M_OV_R_MM (0x1 << 13) | ||
617 | #define RT5640_M_OV_R_MM_SFT 13 | ||
618 | #define RT5640_M_OV_L_MM (0x1 << 12) | ||
619 | #define RT5640_M_OV_L_MM_SFT 12 | ||
620 | #define RT5640_M_BST1_MM (0x1 << 11) | ||
621 | #define RT5640_M_BST1_MM_SFT 11 | ||
622 | #define RT5640_G_MONOMIX_MASK (0x1 << 10) | ||
623 | #define RT5640_G_MONOMIX_SFT 10 | ||
624 | |||
625 | /* Output Left Mixer Control 1 (0x4d) */ | ||
626 | #define RT5640_G_BST3_OM_L_MASK (0x7 << 13) | ||
627 | #define RT5640_G_BST3_OM_L_SFT 13 | ||
628 | #define RT5640_G_BST2_OM_L_MASK (0x7 << 10) | ||
629 | #define RT5640_G_BST2_OM_L_SFT 10 | ||
630 | #define RT5640_G_BST1_OM_L_MASK (0x7 << 7) | ||
631 | #define RT5640_G_BST1_OM_L_SFT 7 | ||
632 | #define RT5640_G_IN_L_OM_L_MASK (0x7 << 4) | ||
633 | #define RT5640_G_IN_L_OM_L_SFT 4 | ||
634 | #define RT5640_G_RM_L_OM_L_MASK (0x7 << 1) | ||
635 | #define RT5640_G_RM_L_OM_L_SFT 1 | ||
636 | |||
637 | /* Output Left Mixer Control 2 (0x4e) */ | ||
638 | #define RT5640_G_DAC_R2_OM_L_MASK (0x7 << 13) | ||
639 | #define RT5640_G_DAC_R2_OM_L_SFT 13 | ||
640 | #define RT5640_G_DAC_L2_OM_L_MASK (0x7 << 10) | ||
641 | #define RT5640_G_DAC_L2_OM_L_SFT 10 | ||
642 | #define RT5640_G_DAC_L1_OM_L_MASK (0x7 << 7) | ||
643 | #define RT5640_G_DAC_L1_OM_L_SFT 7 | ||
644 | |||
645 | /* Output Left Mixer Control 3 (0x4f) */ | ||
646 | #define RT5640_M_SM_L_OM_L (0x1 << 8) | ||
647 | #define RT5640_M_SM_L_OM_L_SFT 8 | ||
648 | #define RT5640_M_BST3_OM_L (0x1 << 7) | ||
649 | #define RT5640_M_BST3_OM_L_SFT 7 | ||
650 | #define RT5640_M_BST2_OM_L (0x1 << 6) | ||
651 | #define RT5640_M_BST2_OM_L_SFT 6 | ||
652 | #define RT5640_M_BST1_OM_L (0x1 << 5) | ||
653 | #define RT5640_M_BST1_OM_L_SFT 5 | ||
654 | #define RT5640_M_IN_L_OM_L (0x1 << 4) | ||
655 | #define RT5640_M_IN_L_OM_L_SFT 4 | ||
656 | #define RT5640_M_RM_L_OM_L (0x1 << 3) | ||
657 | #define RT5640_M_RM_L_OM_L_SFT 3 | ||
658 | #define RT5640_M_DAC_R2_OM_L (0x1 << 2) | ||
659 | #define RT5640_M_DAC_R2_OM_L_SFT 2 | ||
660 | #define RT5640_M_DAC_L2_OM_L (0x1 << 1) | ||
661 | #define RT5640_M_DAC_L2_OM_L_SFT 1 | ||
662 | #define RT5640_M_DAC_L1_OM_L (0x1) | ||
663 | #define RT5640_M_DAC_L1_OM_L_SFT 0 | ||
664 | |||
665 | /* Output Right Mixer Control 1 (0x50) */ | ||
666 | #define RT5640_G_BST4_OM_R_MASK (0x7 << 13) | ||
667 | #define RT5640_G_BST4_OM_R_SFT 13 | ||
668 | #define RT5640_G_BST2_OM_R_MASK (0x7 << 10) | ||
669 | #define RT5640_G_BST2_OM_R_SFT 10 | ||
670 | #define RT5640_G_BST1_OM_R_MASK (0x7 << 7) | ||
671 | #define RT5640_G_BST1_OM_R_SFT 7 | ||
672 | #define RT5640_G_IN_R_OM_R_MASK (0x7 << 4) | ||
673 | #define RT5640_G_IN_R_OM_R_SFT 4 | ||
674 | #define RT5640_G_RM_R_OM_R_MASK (0x7 << 1) | ||
675 | #define RT5640_G_RM_R_OM_R_SFT 1 | ||
676 | |||
677 | /* Output Right Mixer Control 2 (0x51) */ | ||
678 | #define RT5640_G_DAC_L2_OM_R_MASK (0x7 << 13) | ||
679 | #define RT5640_G_DAC_L2_OM_R_SFT 13 | ||
680 | #define RT5640_G_DAC_R2_OM_R_MASK (0x7 << 10) | ||
681 | #define RT5640_G_DAC_R2_OM_R_SFT 10 | ||
682 | #define RT5640_G_DAC_R1_OM_R_MASK (0x7 << 7) | ||
683 | #define RT5640_G_DAC_R1_OM_R_SFT 7 | ||
684 | |||
685 | /* Output Right Mixer Control 3 (0x52) */ | ||
686 | #define RT5640_M_SM_L_OM_R (0x1 << 8) | ||
687 | #define RT5640_M_SM_L_OM_R_SFT 8 | ||
688 | #define RT5640_M_BST4_OM_R (0x1 << 7) | ||
689 | #define RT5640_M_BST4_OM_R_SFT 7 | ||
690 | #define RT5640_M_BST2_OM_R (0x1 << 6) | ||
691 | #define RT5640_M_BST2_OM_R_SFT 6 | ||
692 | #define RT5640_M_BST1_OM_R (0x1 << 5) | ||
693 | #define RT5640_M_BST1_OM_R_SFT 5 | ||
694 | #define RT5640_M_IN_R_OM_R (0x1 << 4) | ||
695 | #define RT5640_M_IN_R_OM_R_SFT 4 | ||
696 | #define RT5640_M_RM_R_OM_R (0x1 << 3) | ||
697 | #define RT5640_M_RM_R_OM_R_SFT 3 | ||
698 | #define RT5640_M_DAC_L2_OM_R (0x1 << 2) | ||
699 | #define RT5640_M_DAC_L2_OM_R_SFT 2 | ||
700 | #define RT5640_M_DAC_R2_OM_R (0x1 << 1) | ||
701 | #define RT5640_M_DAC_R2_OM_R_SFT 1 | ||
702 | #define RT5640_M_DAC_R1_OM_R (0x1) | ||
703 | #define RT5640_M_DAC_R1_OM_R_SFT 0 | ||
704 | |||
705 | /* LOUT Mixer Control (0x53) */ | ||
706 | #define RT5640_M_DAC_L1_LM (0x1 << 15) | ||
707 | #define RT5640_M_DAC_L1_LM_SFT 15 | ||
708 | #define RT5640_M_DAC_R1_LM (0x1 << 14) | ||
709 | #define RT5640_M_DAC_R1_LM_SFT 14 | ||
710 | #define RT5640_M_OV_L_LM (0x1 << 13) | ||
711 | #define RT5640_M_OV_L_LM_SFT 13 | ||
712 | #define RT5640_M_OV_R_LM (0x1 << 12) | ||
713 | #define RT5640_M_OV_R_LM_SFT 12 | ||
714 | #define RT5640_G_LOUTMIX_MASK (0x1 << 11) | ||
715 | #define RT5640_G_LOUTMIX_SFT 11 | ||
716 | |||
717 | /* Power Management for Digital 1 (0x61) */ | ||
718 | #define RT5640_PWR_I2S1 (0x1 << 15) | ||
719 | #define RT5640_PWR_I2S1_BIT 15 | ||
720 | #define RT5640_PWR_I2S2 (0x1 << 14) | ||
721 | #define RT5640_PWR_I2S2_BIT 14 | ||
722 | #define RT5640_PWR_DAC_L1 (0x1 << 12) | ||
723 | #define RT5640_PWR_DAC_L1_BIT 12 | ||
724 | #define RT5640_PWR_DAC_R1 (0x1 << 11) | ||
725 | #define RT5640_PWR_DAC_R1_BIT 11 | ||
726 | #define RT5640_PWR_DAC_L2 (0x1 << 7) | ||
727 | #define RT5640_PWR_DAC_L2_BIT 7 | ||
728 | #define RT5640_PWR_DAC_R2 (0x1 << 6) | ||
729 | #define RT5640_PWR_DAC_R2_BIT 6 | ||
730 | #define RT5640_PWR_ADC_L (0x1 << 2) | ||
731 | #define RT5640_PWR_ADC_L_BIT 2 | ||
732 | #define RT5640_PWR_ADC_R (0x1 << 1) | ||
733 | #define RT5640_PWR_ADC_R_BIT 1 | ||
734 | #define RT5640_PWR_CLS_D (0x1) | ||
735 | #define RT5640_PWR_CLS_D_BIT 0 | ||
736 | |||
737 | /* Power Management for Digital 2 (0x62) */ | ||
738 | #define RT5640_PWR_ADC_SF (0x1 << 15) | ||
739 | #define RT5640_PWR_ADC_SF_BIT 15 | ||
740 | #define RT5640_PWR_ADC_MF_L (0x1 << 14) | ||
741 | #define RT5640_PWR_ADC_MF_L_BIT 14 | ||
742 | #define RT5640_PWR_ADC_MF_R (0x1 << 13) | ||
743 | #define RT5640_PWR_ADC_MF_R_BIT 13 | ||
744 | #define RT5640_PWR_I2S_DSP (0x1 << 12) | ||
745 | #define RT5640_PWR_I2S_DSP_BIT 12 | ||
746 | |||
747 | /* Power Management for Analog 1 (0x63) */ | ||
748 | #define RT5640_PWR_VREF1 (0x1 << 15) | ||
749 | #define RT5640_PWR_VREF1_BIT 15 | ||
750 | #define RT5640_PWR_FV1 (0x1 << 14) | ||
751 | #define RT5640_PWR_FV1_BIT 14 | ||
752 | #define RT5640_PWR_MB (0x1 << 13) | ||
753 | #define RT5640_PWR_MB_BIT 13 | ||
754 | #define RT5640_PWR_LM (0x1 << 12) | ||
755 | #define RT5640_PWR_LM_BIT 12 | ||
756 | #define RT5640_PWR_BG (0x1 << 11) | ||
757 | #define RT5640_PWR_BG_BIT 11 | ||
758 | #define RT5640_PWR_MM (0x1 << 10) | ||
759 | #define RT5640_PWR_MM_BIT 10 | ||
760 | #define RT5640_PWR_MA (0x1 << 8) | ||
761 | #define RT5640_PWR_MA_BIT 8 | ||
762 | #define RT5640_PWR_HP_L (0x1 << 7) | ||
763 | #define RT5640_PWR_HP_L_BIT 7 | ||
764 | #define RT5640_PWR_HP_R (0x1 << 6) | ||
765 | #define RT5640_PWR_HP_R_BIT 6 | ||
766 | #define RT5640_PWR_HA (0x1 << 5) | ||
767 | #define RT5640_PWR_HA_BIT 5 | ||
768 | #define RT5640_PWR_VREF2 (0x1 << 4) | ||
769 | #define RT5640_PWR_VREF2_BIT 4 | ||
770 | #define RT5640_PWR_FV2 (0x1 << 3) | ||
771 | #define RT5640_PWR_FV2_BIT 3 | ||
772 | #define RT5640_PWR_LDO2 (0x1 << 2) | ||
773 | #define RT5640_PWR_LDO2_BIT 2 | ||
774 | |||
775 | /* Power Management for Analog 2 (0x64) */ | ||
776 | #define RT5640_PWR_BST1 (0x1 << 15) | ||
777 | #define RT5640_PWR_BST1_BIT 15 | ||
778 | #define RT5640_PWR_BST2 (0x1 << 14) | ||
779 | #define RT5640_PWR_BST2_BIT 14 | ||
780 | #define RT5640_PWR_BST3 (0x1 << 13) | ||
781 | #define RT5640_PWR_BST3_BIT 13 | ||
782 | #define RT5640_PWR_BST4 (0x1 << 12) | ||
783 | #define RT5640_PWR_BST4_BIT 12 | ||
784 | #define RT5640_PWR_MB1 (0x1 << 11) | ||
785 | #define RT5640_PWR_MB1_BIT 11 | ||
786 | #define RT5640_PWR_PLL (0x1 << 9) | ||
787 | #define RT5640_PWR_PLL_BIT 9 | ||
788 | |||
789 | /* Power Management for Mixer (0x65) */ | ||
790 | #define RT5640_PWR_OM_L (0x1 << 15) | ||
791 | #define RT5640_PWR_OM_L_BIT 15 | ||
792 | #define RT5640_PWR_OM_R (0x1 << 14) | ||
793 | #define RT5640_PWR_OM_R_BIT 14 | ||
794 | #define RT5640_PWR_SM_L (0x1 << 13) | ||
795 | #define RT5640_PWR_SM_L_BIT 13 | ||
796 | #define RT5640_PWR_SM_R (0x1 << 12) | ||
797 | #define RT5640_PWR_SM_R_BIT 12 | ||
798 | #define RT5640_PWR_RM_L (0x1 << 11) | ||
799 | #define RT5640_PWR_RM_L_BIT 11 | ||
800 | #define RT5640_PWR_RM_R (0x1 << 10) | ||
801 | #define RT5640_PWR_RM_R_BIT 10 | ||
802 | |||
803 | /* Power Management for Volume (0x66) */ | ||
804 | #define RT5640_PWR_SV_L (0x1 << 15) | ||
805 | #define RT5640_PWR_SV_L_BIT 15 | ||
806 | #define RT5640_PWR_SV_R (0x1 << 14) | ||
807 | #define RT5640_PWR_SV_R_BIT 14 | ||
808 | #define RT5640_PWR_OV_L (0x1 << 13) | ||
809 | #define RT5640_PWR_OV_L_BIT 13 | ||
810 | #define RT5640_PWR_OV_R (0x1 << 12) | ||
811 | #define RT5640_PWR_OV_R_BIT 12 | ||
812 | #define RT5640_PWR_HV_L (0x1 << 11) | ||
813 | #define RT5640_PWR_HV_L_BIT 11 | ||
814 | #define RT5640_PWR_HV_R (0x1 << 10) | ||
815 | #define RT5640_PWR_HV_R_BIT 10 | ||
816 | #define RT5640_PWR_IN_L (0x1 << 9) | ||
817 | #define RT5640_PWR_IN_L_BIT 9 | ||
818 | #define RT5640_PWR_IN_R (0x1 << 8) | ||
819 | #define RT5640_PWR_IN_R_BIT 8 | ||
820 | |||
821 | /* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71 0x72) */ | ||
822 | #define RT5640_I2S_MS_MASK (0x1 << 15) | ||
823 | #define RT5640_I2S_MS_SFT 15 | ||
824 | #define RT5640_I2S_MS_M (0x0 << 15) | ||
825 | #define RT5640_I2S_MS_S (0x1 << 15) | ||
826 | #define RT5640_I2S_IF_MASK (0x7 << 12) | ||
827 | #define RT5640_I2S_IF_SFT 12 | ||
828 | #define RT5640_I2S_O_CP_MASK (0x3 << 10) | ||
829 | #define RT5640_I2S_O_CP_SFT 10 | ||
830 | #define RT5640_I2S_O_CP_OFF (0x0 << 10) | ||
831 | #define RT5640_I2S_O_CP_U_LAW (0x1 << 10) | ||
832 | #define RT5640_I2S_O_CP_A_LAW (0x2 << 10) | ||
833 | #define RT5640_I2S_I_CP_MASK (0x3 << 8) | ||
834 | #define RT5640_I2S_I_CP_SFT 8 | ||
835 | #define RT5640_I2S_I_CP_OFF (0x0 << 8) | ||
836 | #define RT5640_I2S_I_CP_U_LAW (0x1 << 8) | ||
837 | #define RT5640_I2S_I_CP_A_LAW (0x2 << 8) | ||
838 | #define RT5640_I2S_BP_MASK (0x1 << 7) | ||
839 | #define RT5640_I2S_BP_SFT 7 | ||
840 | #define RT5640_I2S_BP_NOR (0x0 << 7) | ||
841 | #define RT5640_I2S_BP_INV (0x1 << 7) | ||
842 | #define RT5640_I2S_DL_MASK (0x3 << 2) | ||
843 | #define RT5640_I2S_DL_SFT 2 | ||
844 | #define RT5640_I2S_DL_16 (0x0 << 2) | ||
845 | #define RT5640_I2S_DL_20 (0x1 << 2) | ||
846 | #define RT5640_I2S_DL_24 (0x2 << 2) | ||
847 | #define RT5640_I2S_DL_8 (0x3 << 2) | ||
848 | #define RT5640_I2S_DF_MASK (0x3) | ||
849 | #define RT5640_I2S_DF_SFT 0 | ||
850 | #define RT5640_I2S_DF_I2S (0x0) | ||
851 | #define RT5640_I2S_DF_LEFT (0x1) | ||
852 | #define RT5640_I2S_DF_PCM_A (0x2) | ||
853 | #define RT5640_I2S_DF_PCM_B (0x3) | ||
854 | |||
855 | /* I2S2 Audio Serial Data Port Control (0x71) */ | ||
856 | #define RT5640_I2S2_SDI_MASK (0x1 << 6) | ||
857 | #define RT5640_I2S2_SDI_SFT 6 | ||
858 | #define RT5640_I2S2_SDI_I2S1 (0x0 << 6) | ||
859 | #define RT5640_I2S2_SDI_I2S2 (0x1 << 6) | ||
860 | |||
861 | /* ADC/DAC Clock Control 1 (0x73) */ | ||
862 | #define RT5640_I2S_BCLK_MS1_MASK (0x1 << 15) | ||
863 | #define RT5640_I2S_BCLK_MS1_SFT 15 | ||
864 | #define RT5640_I2S_BCLK_MS1_32 (0x0 << 15) | ||
865 | #define RT5640_I2S_BCLK_MS1_64 (0x1 << 15) | ||
866 | #define RT5640_I2S_PD1_MASK (0x7 << 12) | ||
867 | #define RT5640_I2S_PD1_SFT 12 | ||
868 | #define RT5640_I2S_PD1_1 (0x0 << 12) | ||
869 | #define RT5640_I2S_PD1_2 (0x1 << 12) | ||
870 | #define RT5640_I2S_PD1_3 (0x2 << 12) | ||
871 | #define RT5640_I2S_PD1_4 (0x3 << 12) | ||
872 | #define RT5640_I2S_PD1_6 (0x4 << 12) | ||
873 | #define RT5640_I2S_PD1_8 (0x5 << 12) | ||
874 | #define RT5640_I2S_PD1_12 (0x6 << 12) | ||
875 | #define RT5640_I2S_PD1_16 (0x7 << 12) | ||
876 | #define RT5640_I2S_BCLK_MS2_MASK (0x1 << 11) | ||
877 | #define RT5640_I2S_BCLK_MS2_SFT 11 | ||
878 | #define RT5640_I2S_BCLK_MS2_32 (0x0 << 11) | ||
879 | #define RT5640_I2S_BCLK_MS2_64 (0x1 << 11) | ||
880 | #define RT5640_I2S_PD2_MASK (0x7 << 8) | ||
881 | #define RT5640_I2S_PD2_SFT 8 | ||
882 | #define RT5640_I2S_PD2_1 (0x0 << 8) | ||
883 | #define RT5640_I2S_PD2_2 (0x1 << 8) | ||
884 | #define RT5640_I2S_PD2_3 (0x2 << 8) | ||
885 | #define RT5640_I2S_PD2_4 (0x3 << 8) | ||
886 | #define RT5640_I2S_PD2_6 (0x4 << 8) | ||
887 | #define RT5640_I2S_PD2_8 (0x5 << 8) | ||
888 | #define RT5640_I2S_PD2_12 (0x6 << 8) | ||
889 | #define RT5640_I2S_PD2_16 (0x7 << 8) | ||
890 | #define RT5640_I2S_BCLK_MS3_MASK (0x1 << 7) | ||
891 | #define RT5640_I2S_BCLK_MS3_SFT 7 | ||
892 | #define RT5640_I2S_BCLK_MS3_32 (0x0 << 7) | ||
893 | #define RT5640_I2S_BCLK_MS3_64 (0x1 << 7) | ||
894 | #define RT5640_I2S_PD3_MASK (0x7 << 4) | ||
895 | #define RT5640_I2S_PD3_SFT 4 | ||
896 | #define RT5640_I2S_PD3_1 (0x0 << 4) | ||
897 | #define RT5640_I2S_PD3_2 (0x1 << 4) | ||
898 | #define RT5640_I2S_PD3_3 (0x2 << 4) | ||
899 | #define RT5640_I2S_PD3_4 (0x3 << 4) | ||
900 | #define RT5640_I2S_PD3_6 (0x4 << 4) | ||
901 | #define RT5640_I2S_PD3_8 (0x5 << 4) | ||
902 | #define RT5640_I2S_PD3_12 (0x6 << 4) | ||
903 | #define RT5640_I2S_PD3_16 (0x7 << 4) | ||
904 | #define RT5640_DAC_OSR_MASK (0x3 << 2) | ||
905 | #define RT5640_DAC_OSR_SFT 2 | ||
906 | #define RT5640_DAC_OSR_128 (0x0 << 2) | ||
907 | #define RT5640_DAC_OSR_64 (0x1 << 2) | ||
908 | #define RT5640_DAC_OSR_32 (0x2 << 2) | ||
909 | #define RT5640_DAC_OSR_16 (0x3 << 2) | ||
910 | #define RT5640_ADC_OSR_MASK (0x3) | ||
911 | #define RT5640_ADC_OSR_SFT 0 | ||
912 | #define RT5640_ADC_OSR_128 (0x0) | ||
913 | #define RT5640_ADC_OSR_64 (0x1) | ||
914 | #define RT5640_ADC_OSR_32 (0x2) | ||
915 | #define RT5640_ADC_OSR_16 (0x3) | ||
916 | |||
917 | /* ADC/DAC Clock Control 2 (0x74) */ | ||
918 | #define RT5640_DAC_L_OSR_MASK (0x3 << 14) | ||
919 | #define RT5640_DAC_L_OSR_SFT 14 | ||
920 | #define RT5640_DAC_L_OSR_128 (0x0 << 14) | ||
921 | #define RT5640_DAC_L_OSR_64 (0x1 << 14) | ||
922 | #define RT5640_DAC_L_OSR_32 (0x2 << 14) | ||
923 | #define RT5640_DAC_L_OSR_16 (0x3 << 14) | ||
924 | #define RT5640_ADC_R_OSR_MASK (0x3 << 12) | ||
925 | #define RT5640_ADC_R_OSR_SFT 12 | ||
926 | #define RT5640_ADC_R_OSR_128 (0x0 << 12) | ||
927 | #define RT5640_ADC_R_OSR_64 (0x1 << 12) | ||
928 | #define RT5640_ADC_R_OSR_32 (0x2 << 12) | ||
929 | #define RT5640_ADC_R_OSR_16 (0x3 << 12) | ||
930 | #define RT5640_DAHPF_EN (0x1 << 11) | ||
931 | #define RT5640_DAHPF_EN_SFT 11 | ||
932 | #define RT5640_ADHPF_EN (0x1 << 10) | ||
933 | #define RT5640_ADHPF_EN_SFT 10 | ||
934 | |||
935 | /* Digital Microphone Control (0x75) */ | ||
936 | #define RT5640_DMIC_1_EN_MASK (0x1 << 15) | ||
937 | #define RT5640_DMIC_1_EN_SFT 15 | ||
938 | #define RT5640_DMIC_1_DIS (0x0 << 15) | ||
939 | #define RT5640_DMIC_1_EN (0x1 << 15) | ||
940 | #define RT5640_DMIC_2_EN_MASK (0x1 << 14) | ||
941 | #define RT5640_DMIC_2_EN_SFT 14 | ||
942 | #define RT5640_DMIC_2_DIS (0x0 << 14) | ||
943 | #define RT5640_DMIC_2_EN (0x1 << 14) | ||
944 | #define RT5640_DMIC_1L_LH_MASK (0x1 << 13) | ||
945 | #define RT5640_DMIC_1L_LH_SFT 13 | ||
946 | #define RT5640_DMIC_1L_LH_FALLING (0x0 << 13) | ||
947 | #define RT5640_DMIC_1L_LH_RISING (0x1 << 13) | ||
948 | #define RT5640_DMIC_1R_LH_MASK (0x1 << 12) | ||
949 | #define RT5640_DMIC_1R_LH_SFT 12 | ||
950 | #define RT5640_DMIC_1R_LH_FALLING (0x0 << 12) | ||
951 | #define RT5640_DMIC_1R_LH_RISING (0x1 << 12) | ||
952 | #define RT5640_DMIC_1_DP_MASK (0x1 << 11) | ||
953 | #define RT5640_DMIC_1_DP_SFT 11 | ||
954 | #define RT5640_DMIC_1_DP_GPIO3 (0x0 << 11) | ||
955 | #define RT5640_DMIC_1_DP_IN1P (0x1 << 11) | ||
956 | #define RT5640_DMIC_2_DP_MASK (0x1 << 10) | ||
957 | #define RT5640_DMIC_2_DP_SFT 10 | ||
958 | #define RT5640_DMIC_2_DP_GPIO4 (0x0 << 10) | ||
959 | #define RT5640_DMIC_2_DP_IN1N (0x1 << 10) | ||
960 | #define RT5640_DMIC_2L_LH_MASK (0x1 << 9) | ||
961 | #define RT5640_DMIC_2L_LH_SFT 9 | ||
962 | #define RT5640_DMIC_2L_LH_FALLING (0x0 << 9) | ||
963 | #define RT5640_DMIC_2L_LH_RISING (0x1 << 9) | ||
964 | #define RT5640_DMIC_2R_LH_MASK (0x1 << 8) | ||
965 | #define RT5640_DMIC_2R_LH_SFT 8 | ||
966 | #define RT5640_DMIC_2R_LH_FALLING (0x0 << 8) | ||
967 | #define RT5640_DMIC_2R_LH_RISING (0x1 << 8) | ||
968 | #define RT5640_DMIC_CLK_MASK (0x7 << 5) | ||
969 | #define RT5640_DMIC_CLK_SFT 5 | ||
970 | |||
971 | /* Global Clock Control (0x80) */ | ||
972 | #define RT5640_SCLK_SRC_MASK (0x3 << 14) | ||
973 | #define RT5640_SCLK_SRC_SFT 14 | ||
974 | #define RT5640_SCLK_SRC_MCLK (0x0 << 14) | ||
975 | #define RT5640_SCLK_SRC_PLL1 (0x1 << 14) | ||
976 | #define RT5640_SCLK_SRC_PLL1T (0x2 << 14) | ||
977 | #define RT5640_SCLK_SRC_RCCLK (0x3 << 14) /* 15MHz */ | ||
978 | #define RT5640_PLL1_SRC_MASK (0x3 << 12) | ||
979 | #define RT5640_PLL1_SRC_SFT 12 | ||
980 | #define RT5640_PLL1_SRC_MCLK (0x0 << 12) | ||
981 | #define RT5640_PLL1_SRC_BCLK1 (0x1 << 12) | ||
982 | #define RT5640_PLL1_SRC_BCLK2 (0x2 << 12) | ||
983 | #define RT5640_PLL1_SRC_BCLK3 (0x3 << 12) | ||
984 | #define RT5640_PLL1_PD_MASK (0x1 << 3) | ||
985 | #define RT5640_PLL1_PD_SFT 3 | ||
986 | #define RT5640_PLL1_PD_1 (0x0 << 3) | ||
987 | #define RT5640_PLL1_PD_2 (0x1 << 3) | ||
988 | |||
989 | #define RT5640_PLL_INP_MAX 40000000 | ||
990 | #define RT5640_PLL_INP_MIN 256000 | ||
991 | /* PLL M/N/K Code Control 1 (0x81) */ | ||
992 | #define RT5640_PLL_N_MAX 0x1ff | ||
993 | #define RT5640_PLL_N_MASK (RT5640_PLL_N_MAX << 7) | ||
994 | #define RT5640_PLL_N_SFT 7 | ||
995 | #define RT5640_PLL_K_MAX 0x1f | ||
996 | #define RT5640_PLL_K_MASK (RT5640_PLL_K_MAX) | ||
997 | #define RT5640_PLL_K_SFT 0 | ||
998 | |||
999 | /* PLL M/N/K Code Control 2 (0x82) */ | ||
1000 | #define RT5640_PLL_M_MAX 0xf | ||
1001 | #define RT5640_PLL_M_MASK (RT5640_PLL_M_MAX << 12) | ||
1002 | #define RT5640_PLL_M_SFT 12 | ||
1003 | #define RT5640_PLL_M_BP (0x1 << 11) | ||
1004 | #define RT5640_PLL_M_BP_SFT 11 | ||
1005 | |||
1006 | /* ASRC Control 1 (0x83) */ | ||
1007 | #define RT5640_STO_T_MASK (0x1 << 15) | ||
1008 | #define RT5640_STO_T_SFT 15 | ||
1009 | #define RT5640_STO_T_SCLK (0x0 << 15) | ||
1010 | #define RT5640_STO_T_LRCK1 (0x1 << 15) | ||
1011 | #define RT5640_M1_T_MASK (0x1 << 14) | ||
1012 | #define RT5640_M1_T_SFT 14 | ||
1013 | #define RT5640_M1_T_I2S2 (0x0 << 14) | ||
1014 | #define RT5640_M1_T_I2S2_D3 (0x1 << 14) | ||
1015 | #define RT5640_I2S2_F_MASK (0x1 << 12) | ||
1016 | #define RT5640_I2S2_F_SFT 12 | ||
1017 | #define RT5640_I2S2_F_I2S2_D2 (0x0 << 12) | ||
1018 | #define RT5640_I2S2_F_I2S1_TCLK (0x1 << 12) | ||
1019 | #define RT5640_DMIC_1_M_MASK (0x1 << 9) | ||
1020 | #define RT5640_DMIC_1_M_SFT 9 | ||
1021 | #define RT5640_DMIC_1_M_NOR (0x0 << 9) | ||
1022 | #define RT5640_DMIC_1_M_ASYN (0x1 << 9) | ||
1023 | #define RT5640_DMIC_2_M_MASK (0x1 << 8) | ||
1024 | #define RT5640_DMIC_2_M_SFT 8 | ||
1025 | #define RT5640_DMIC_2_M_NOR (0x0 << 8) | ||
1026 | #define RT5640_DMIC_2_M_ASYN (0x1 << 8) | ||
1027 | |||
1028 | /* ASRC Control 2 (0x84) */ | ||
1029 | #define RT5640_MDA_L_M_MASK (0x1 << 15) | ||
1030 | #define RT5640_MDA_L_M_SFT 15 | ||
1031 | #define RT5640_MDA_L_M_NOR (0x0 << 15) | ||
1032 | #define RT5640_MDA_L_M_ASYN (0x1 << 15) | ||
1033 | #define RT5640_MDA_R_M_MASK (0x1 << 14) | ||
1034 | #define RT5640_MDA_R_M_SFT 14 | ||
1035 | #define RT5640_MDA_R_M_NOR (0x0 << 14) | ||
1036 | #define RT5640_MDA_R_M_ASYN (0x1 << 14) | ||
1037 | #define RT5640_MAD_L_M_MASK (0x1 << 13) | ||
1038 | #define RT5640_MAD_L_M_SFT 13 | ||
1039 | #define RT5640_MAD_L_M_NOR (0x0 << 13) | ||
1040 | #define RT5640_MAD_L_M_ASYN (0x1 << 13) | ||
1041 | #define RT5640_MAD_R_M_MASK (0x1 << 12) | ||
1042 | #define RT5640_MAD_R_M_SFT 12 | ||
1043 | #define RT5640_MAD_R_M_NOR (0x0 << 12) | ||
1044 | #define RT5640_MAD_R_M_ASYN (0x1 << 12) | ||
1045 | #define RT5640_ADC_M_MASK (0x1 << 11) | ||
1046 | #define RT5640_ADC_M_SFT 11 | ||
1047 | #define RT5640_ADC_M_NOR (0x0 << 11) | ||
1048 | #define RT5640_ADC_M_ASYN (0x1 << 11) | ||
1049 | #define RT5640_STO_DAC_M_MASK (0x1 << 5) | ||
1050 | #define RT5640_STO_DAC_M_SFT 5 | ||
1051 | #define RT5640_STO_DAC_M_NOR (0x0 << 5) | ||
1052 | #define RT5640_STO_DAC_M_ASYN (0x1 << 5) | ||
1053 | #define RT5640_I2S1_R_D_MASK (0x1 << 4) | ||
1054 | #define RT5640_I2S1_R_D_SFT 4 | ||
1055 | #define RT5640_I2S1_R_D_DIS (0x0 << 4) | ||
1056 | #define RT5640_I2S1_R_D_EN (0x1 << 4) | ||
1057 | #define RT5640_I2S2_R_D_MASK (0x1 << 3) | ||
1058 | #define RT5640_I2S2_R_D_SFT 3 | ||
1059 | #define RT5640_I2S2_R_D_DIS (0x0 << 3) | ||
1060 | #define RT5640_I2S2_R_D_EN (0x1 << 3) | ||
1061 | #define RT5640_PRE_SCLK_MASK (0x3) | ||
1062 | #define RT5640_PRE_SCLK_SFT 0 | ||
1063 | #define RT5640_PRE_SCLK_512 (0x0) | ||
1064 | #define RT5640_PRE_SCLK_1024 (0x1) | ||
1065 | #define RT5640_PRE_SCLK_2048 (0x2) | ||
1066 | |||
1067 | /* ASRC Control 3 (0x85) */ | ||
1068 | #define RT5640_I2S1_RATE_MASK (0xf << 12) | ||
1069 | #define RT5640_I2S1_RATE_SFT 12 | ||
1070 | #define RT5640_I2S2_RATE_MASK (0xf << 8) | ||
1071 | #define RT5640_I2S2_RATE_SFT 8 | ||
1072 | |||
1073 | /* ASRC Control 4 (0x89) */ | ||
1074 | #define RT5640_I2S1_PD_MASK (0x7 << 12) | ||
1075 | #define RT5640_I2S1_PD_SFT 12 | ||
1076 | #define RT5640_I2S2_PD_MASK (0x7 << 8) | ||
1077 | #define RT5640_I2S2_PD_SFT 8 | ||
1078 | |||
1079 | /* HPOUT Over Current Detection (0x8b) */ | ||
1080 | #define RT5640_HP_OVCD_MASK (0x1 << 10) | ||
1081 | #define RT5640_HP_OVCD_SFT 10 | ||
1082 | #define RT5640_HP_OVCD_DIS (0x0 << 10) | ||
1083 | #define RT5640_HP_OVCD_EN (0x1 << 10) | ||
1084 | #define RT5640_HP_OC_TH_MASK (0x3 << 8) | ||
1085 | #define RT5640_HP_OC_TH_SFT 8 | ||
1086 | #define RT5640_HP_OC_TH_90 (0x0 << 8) | ||
1087 | #define RT5640_HP_OC_TH_105 (0x1 << 8) | ||
1088 | #define RT5640_HP_OC_TH_120 (0x2 << 8) | ||
1089 | #define RT5640_HP_OC_TH_135 (0x3 << 8) | ||
1090 | |||
1091 | /* Class D Over Current Control (0x8c) */ | ||
1092 | #define RT5640_CLSD_OC_MASK (0x1 << 9) | ||
1093 | #define RT5640_CLSD_OC_SFT 9 | ||
1094 | #define RT5640_CLSD_OC_PU (0x0 << 9) | ||
1095 | #define RT5640_CLSD_OC_PD (0x1 << 9) | ||
1096 | #define RT5640_AUTO_PD_MASK (0x1 << 8) | ||
1097 | #define RT5640_AUTO_PD_SFT 8 | ||
1098 | #define RT5640_AUTO_PD_DIS (0x0 << 8) | ||
1099 | #define RT5640_AUTO_PD_EN (0x1 << 8) | ||
1100 | #define RT5640_CLSD_OC_TH_MASK (0x3f) | ||
1101 | #define RT5640_CLSD_OC_TH_SFT 0 | ||
1102 | |||
1103 | /* Class D Output Control (0x8d) */ | ||
1104 | #define RT5640_CLSD_RATIO_MASK (0xf << 12) | ||
1105 | #define RT5640_CLSD_RATIO_SFT 12 | ||
1106 | #define RT5640_CLSD_OM_MASK (0x1 << 11) | ||
1107 | #define RT5640_CLSD_OM_SFT 11 | ||
1108 | #define RT5640_CLSD_OM_MONO (0x0 << 11) | ||
1109 | #define RT5640_CLSD_OM_STO (0x1 << 11) | ||
1110 | #define RT5640_CLSD_SCH_MASK (0x1 << 10) | ||
1111 | #define RT5640_CLSD_SCH_SFT 10 | ||
1112 | #define RT5640_CLSD_SCH_L (0x0 << 10) | ||
1113 | #define RT5640_CLSD_SCH_S (0x1 << 10) | ||
1114 | |||
1115 | /* Depop Mode Control 1 (0x8e) */ | ||
1116 | #define RT5640_SMT_TRIG_MASK (0x1 << 15) | ||
1117 | #define RT5640_SMT_TRIG_SFT 15 | ||
1118 | #define RT5640_SMT_TRIG_DIS (0x0 << 15) | ||
1119 | #define RT5640_SMT_TRIG_EN (0x1 << 15) | ||
1120 | #define RT5640_HP_L_SMT_MASK (0x1 << 9) | ||
1121 | #define RT5640_HP_L_SMT_SFT 9 | ||
1122 | #define RT5640_HP_L_SMT_DIS (0x0 << 9) | ||
1123 | #define RT5640_HP_L_SMT_EN (0x1 << 9) | ||
1124 | #define RT5640_HP_R_SMT_MASK (0x1 << 8) | ||
1125 | #define RT5640_HP_R_SMT_SFT 8 | ||
1126 | #define RT5640_HP_R_SMT_DIS (0x0 << 8) | ||
1127 | #define RT5640_HP_R_SMT_EN (0x1 << 8) | ||
1128 | #define RT5640_HP_CD_PD_MASK (0x1 << 7) | ||
1129 | #define RT5640_HP_CD_PD_SFT 7 | ||
1130 | #define RT5640_HP_CD_PD_DIS (0x0 << 7) | ||
1131 | #define RT5640_HP_CD_PD_EN (0x1 << 7) | ||
1132 | #define RT5640_RSTN_MASK (0x1 << 6) | ||
1133 | #define RT5640_RSTN_SFT 6 | ||
1134 | #define RT5640_RSTN_DIS (0x0 << 6) | ||
1135 | #define RT5640_RSTN_EN (0x1 << 6) | ||
1136 | #define RT5640_RSTP_MASK (0x1 << 5) | ||
1137 | #define RT5640_RSTP_SFT 5 | ||
1138 | #define RT5640_RSTP_DIS (0x0 << 5) | ||
1139 | #define RT5640_RSTP_EN (0x1 << 5) | ||
1140 | #define RT5640_HP_CO_MASK (0x1 << 4) | ||
1141 | #define RT5640_HP_CO_SFT 4 | ||
1142 | #define RT5640_HP_CO_DIS (0x0 << 4) | ||
1143 | #define RT5640_HP_CO_EN (0x1 << 4) | ||
1144 | #define RT5640_HP_CP_MASK (0x1 << 3) | ||
1145 | #define RT5640_HP_CP_SFT 3 | ||
1146 | #define RT5640_HP_CP_PD (0x0 << 3) | ||
1147 | #define RT5640_HP_CP_PU (0x1 << 3) | ||
1148 | #define RT5640_HP_SG_MASK (0x1 << 2) | ||
1149 | #define RT5640_HP_SG_SFT 2 | ||
1150 | #define RT5640_HP_SG_DIS (0x0 << 2) | ||
1151 | #define RT5640_HP_SG_EN (0x1 << 2) | ||
1152 | #define RT5640_HP_DP_MASK (0x1 << 1) | ||
1153 | #define RT5640_HP_DP_SFT 1 | ||
1154 | #define RT5640_HP_DP_PD (0x0 << 1) | ||
1155 | #define RT5640_HP_DP_PU (0x1 << 1) | ||
1156 | #define RT5640_HP_CB_MASK (0x1) | ||
1157 | #define RT5640_HP_CB_SFT 0 | ||
1158 | #define RT5640_HP_CB_PD (0x0) | ||
1159 | #define RT5640_HP_CB_PU (0x1) | ||
1160 | |||
1161 | /* Depop Mode Control 2 (0x8f) */ | ||
1162 | #define RT5640_DEPOP_MASK (0x1 << 13) | ||
1163 | #define RT5640_DEPOP_SFT 13 | ||
1164 | #define RT5640_DEPOP_AUTO (0x0 << 13) | ||
1165 | #define RT5640_DEPOP_MAN (0x1 << 13) | ||
1166 | #define RT5640_RAMP_MASK (0x1 << 12) | ||
1167 | #define RT5640_RAMP_SFT 12 | ||
1168 | #define RT5640_RAMP_DIS (0x0 << 12) | ||
1169 | #define RT5640_RAMP_EN (0x1 << 12) | ||
1170 | #define RT5640_BPS_MASK (0x1 << 11) | ||
1171 | #define RT5640_BPS_SFT 11 | ||
1172 | #define RT5640_BPS_DIS (0x0 << 11) | ||
1173 | #define RT5640_BPS_EN (0x1 << 11) | ||
1174 | #define RT5640_FAST_UPDN_MASK (0x1 << 10) | ||
1175 | #define RT5640_FAST_UPDN_SFT 10 | ||
1176 | #define RT5640_FAST_UPDN_DIS (0x0 << 10) | ||
1177 | #define RT5640_FAST_UPDN_EN (0x1 << 10) | ||
1178 | #define RT5640_MRES_MASK (0x3 << 8) | ||
1179 | #define RT5640_MRES_SFT 8 | ||
1180 | #define RT5640_MRES_15MO (0x0 << 8) | ||
1181 | #define RT5640_MRES_25MO (0x1 << 8) | ||
1182 | #define RT5640_MRES_35MO (0x2 << 8) | ||
1183 | #define RT5640_MRES_45MO (0x3 << 8) | ||
1184 | #define RT5640_VLO_MASK (0x1 << 7) | ||
1185 | #define RT5640_VLO_SFT 7 | ||
1186 | #define RT5640_VLO_3V (0x0 << 7) | ||
1187 | #define RT5640_VLO_32V (0x1 << 7) | ||
1188 | #define RT5640_DIG_DP_MASK (0x1 << 6) | ||
1189 | #define RT5640_DIG_DP_SFT 6 | ||
1190 | #define RT5640_DIG_DP_DIS (0x0 << 6) | ||
1191 | #define RT5640_DIG_DP_EN (0x1 << 6) | ||
1192 | #define RT5640_DP_TH_MASK (0x3 << 4) | ||
1193 | #define RT5640_DP_TH_SFT 4 | ||
1194 | |||
1195 | /* Depop Mode Control 3 (0x90) */ | ||
1196 | #define RT5640_CP_SYS_MASK (0x7 << 12) | ||
1197 | #define RT5640_CP_SYS_SFT 12 | ||
1198 | #define RT5640_CP_FQ1_MASK (0x7 << 8) | ||
1199 | #define RT5640_CP_FQ1_SFT 8 | ||
1200 | #define RT5640_CP_FQ2_MASK (0x7 << 4) | ||
1201 | #define RT5640_CP_FQ2_SFT 4 | ||
1202 | #define RT5640_CP_FQ3_MASK (0x7) | ||
1203 | #define RT5640_CP_FQ3_SFT 0 | ||
1204 | |||
1205 | /* HPOUT charge pump (0x91) */ | ||
1206 | #define RT5640_OSW_L_MASK (0x1 << 11) | ||
1207 | #define RT5640_OSW_L_SFT 11 | ||
1208 | #define RT5640_OSW_L_DIS (0x0 << 11) | ||
1209 | #define RT5640_OSW_L_EN (0x1 << 11) | ||
1210 | #define RT5640_OSW_R_MASK (0x1 << 10) | ||
1211 | #define RT5640_OSW_R_SFT 10 | ||
1212 | #define RT5640_OSW_R_DIS (0x0 << 10) | ||
1213 | #define RT5640_OSW_R_EN (0x1 << 10) | ||
1214 | #define RT5640_PM_HP_MASK (0x3 << 8) | ||
1215 | #define RT5640_PM_HP_SFT 8 | ||
1216 | #define RT5640_PM_HP_LV (0x0 << 8) | ||
1217 | #define RT5640_PM_HP_MV (0x1 << 8) | ||
1218 | #define RT5640_PM_HP_HV (0x2 << 8) | ||
1219 | #define RT5640_IB_HP_MASK (0x3 << 6) | ||
1220 | #define RT5640_IB_HP_SFT 6 | ||
1221 | #define RT5640_IB_HP_125IL (0x0 << 6) | ||
1222 | #define RT5640_IB_HP_25IL (0x1 << 6) | ||
1223 | #define RT5640_IB_HP_5IL (0x2 << 6) | ||
1224 | #define RT5640_IB_HP_1IL (0x3 << 6) | ||
1225 | |||
1226 | /* PV detection and SPK gain control (0x92) */ | ||
1227 | #define RT5640_PVDD_DET_MASK (0x1 << 15) | ||
1228 | #define RT5640_PVDD_DET_SFT 15 | ||
1229 | #define RT5640_PVDD_DET_DIS (0x0 << 15) | ||
1230 | #define RT5640_PVDD_DET_EN (0x1 << 15) | ||
1231 | #define RT5640_SPK_AG_MASK (0x1 << 14) | ||
1232 | #define RT5640_SPK_AG_SFT 14 | ||
1233 | #define RT5640_SPK_AG_DIS (0x0 << 14) | ||
1234 | #define RT5640_SPK_AG_EN (0x1 << 14) | ||
1235 | |||
1236 | /* Micbias Control (0x93) */ | ||
1237 | #define RT5640_MIC1_BS_MASK (0x1 << 15) | ||
1238 | #define RT5640_MIC1_BS_SFT 15 | ||
1239 | #define RT5640_MIC1_BS_9AV (0x0 << 15) | ||
1240 | #define RT5640_MIC1_BS_75AV (0x1 << 15) | ||
1241 | #define RT5640_MIC2_BS_MASK (0x1 << 14) | ||
1242 | #define RT5640_MIC2_BS_SFT 14 | ||
1243 | #define RT5640_MIC2_BS_9AV (0x0 << 14) | ||
1244 | #define RT5640_MIC2_BS_75AV (0x1 << 14) | ||
1245 | #define RT5640_MIC1_CLK_MASK (0x1 << 13) | ||
1246 | #define RT5640_MIC1_CLK_SFT 13 | ||
1247 | #define RT5640_MIC1_CLK_DIS (0x0 << 13) | ||
1248 | #define RT5640_MIC1_CLK_EN (0x1 << 13) | ||
1249 | #define RT5640_MIC2_CLK_MASK (0x1 << 12) | ||
1250 | #define RT5640_MIC2_CLK_SFT 12 | ||
1251 | #define RT5640_MIC2_CLK_DIS (0x0 << 12) | ||
1252 | #define RT5640_MIC2_CLK_EN (0x1 << 12) | ||
1253 | #define RT5640_MIC1_OVCD_MASK (0x1 << 11) | ||
1254 | #define RT5640_MIC1_OVCD_SFT 11 | ||
1255 | #define RT5640_MIC1_OVCD_DIS (0x0 << 11) | ||
1256 | #define RT5640_MIC1_OVCD_EN (0x1 << 11) | ||
1257 | #define RT5640_MIC1_OVTH_MASK (0x3 << 9) | ||
1258 | #define RT5640_MIC1_OVTH_SFT 9 | ||
1259 | #define RT5640_MIC1_OVTH_600UA (0x0 << 9) | ||
1260 | #define RT5640_MIC1_OVTH_1500UA (0x1 << 9) | ||
1261 | #define RT5640_MIC1_OVTH_2000UA (0x2 << 9) | ||
1262 | #define RT5640_MIC2_OVCD_MASK (0x1 << 8) | ||
1263 | #define RT5640_MIC2_OVCD_SFT 8 | ||
1264 | #define RT5640_MIC2_OVCD_DIS (0x0 << 8) | ||
1265 | #define RT5640_MIC2_OVCD_EN (0x1 << 8) | ||
1266 | #define RT5640_MIC2_OVTH_MASK (0x3 << 6) | ||
1267 | #define RT5640_MIC2_OVTH_SFT 6 | ||
1268 | #define RT5640_MIC2_OVTH_600UA (0x0 << 6) | ||
1269 | #define RT5640_MIC2_OVTH_1500UA (0x1 << 6) | ||
1270 | #define RT5640_MIC2_OVTH_2000UA (0x2 << 6) | ||
1271 | #define RT5640_PWR_MB_MASK (0x1 << 5) | ||
1272 | #define RT5640_PWR_MB_SFT 5 | ||
1273 | #define RT5640_PWR_MB_PD (0x0 << 5) | ||
1274 | #define RT5640_PWR_MB_PU (0x1 << 5) | ||
1275 | #define RT5640_PWR_CLK25M_MASK (0x1 << 4) | ||
1276 | #define RT5640_PWR_CLK25M_SFT 4 | ||
1277 | #define RT5640_PWR_CLK25M_PD (0x0 << 4) | ||
1278 | #define RT5640_PWR_CLK25M_PU (0x1 << 4) | ||
1279 | |||
1280 | /* EQ Control 1 (0xb0) */ | ||
1281 | #define RT5640_EQ_SRC_MASK (0x1 << 15) | ||
1282 | #define RT5640_EQ_SRC_SFT 15 | ||
1283 | #define RT5640_EQ_SRC_DAC (0x0 << 15) | ||
1284 | #define RT5640_EQ_SRC_ADC (0x1 << 15) | ||
1285 | #define RT5640_EQ_UPD (0x1 << 14) | ||
1286 | #define RT5640_EQ_UPD_BIT 14 | ||
1287 | #define RT5640_EQ_CD_MASK (0x1 << 13) | ||
1288 | #define RT5640_EQ_CD_SFT 13 | ||
1289 | #define RT5640_EQ_CD_DIS (0x0 << 13) | ||
1290 | #define RT5640_EQ_CD_EN (0x1 << 13) | ||
1291 | #define RT5640_EQ_DITH_MASK (0x3 << 8) | ||
1292 | #define RT5640_EQ_DITH_SFT 8 | ||
1293 | #define RT5640_EQ_DITH_NOR (0x0 << 8) | ||
1294 | #define RT5640_EQ_DITH_LSB (0x1 << 8) | ||
1295 | #define RT5640_EQ_DITH_LSB_1 (0x2 << 8) | ||
1296 | #define RT5640_EQ_DITH_LSB_2 (0x3 << 8) | ||
1297 | |||
1298 | /* EQ Control 2 (0xb1) */ | ||
1299 | #define RT5640_EQ_HPF1_M_MASK (0x1 << 8) | ||
1300 | #define RT5640_EQ_HPF1_M_SFT 8 | ||
1301 | #define RT5640_EQ_HPF1_M_HI (0x0 << 8) | ||
1302 | #define RT5640_EQ_HPF1_M_1ST (0x1 << 8) | ||
1303 | #define RT5640_EQ_LPF1_M_MASK (0x1 << 7) | ||
1304 | #define RT5640_EQ_LPF1_M_SFT 7 | ||
1305 | #define RT5640_EQ_LPF1_M_LO (0x0 << 7) | ||
1306 | #define RT5640_EQ_LPF1_M_1ST (0x1 << 7) | ||
1307 | #define RT5640_EQ_HPF2_MASK (0x1 << 6) | ||
1308 | #define RT5640_EQ_HPF2_SFT 6 | ||
1309 | #define RT5640_EQ_HPF2_DIS (0x0 << 6) | ||
1310 | #define RT5640_EQ_HPF2_EN (0x1 << 6) | ||
1311 | #define RT5640_EQ_HPF1_MASK (0x1 << 5) | ||
1312 | #define RT5640_EQ_HPF1_SFT 5 | ||
1313 | #define RT5640_EQ_HPF1_DIS (0x0 << 5) | ||
1314 | #define RT5640_EQ_HPF1_EN (0x1 << 5) | ||
1315 | #define RT5640_EQ_BPF4_MASK (0x1 << 4) | ||
1316 | #define RT5640_EQ_BPF4_SFT 4 | ||
1317 | #define RT5640_EQ_BPF4_DIS (0x0 << 4) | ||
1318 | #define RT5640_EQ_BPF4_EN (0x1 << 4) | ||
1319 | #define RT5640_EQ_BPF3_MASK (0x1 << 3) | ||
1320 | #define RT5640_EQ_BPF3_SFT 3 | ||
1321 | #define RT5640_EQ_BPF3_DIS (0x0 << 3) | ||
1322 | #define RT5640_EQ_BPF3_EN (0x1 << 3) | ||
1323 | #define RT5640_EQ_BPF2_MASK (0x1 << 2) | ||
1324 | #define RT5640_EQ_BPF2_SFT 2 | ||
1325 | #define RT5640_EQ_BPF2_DIS (0x0 << 2) | ||
1326 | #define RT5640_EQ_BPF2_EN (0x1 << 2) | ||
1327 | #define RT5640_EQ_BPF1_MASK (0x1 << 1) | ||
1328 | #define RT5640_EQ_BPF1_SFT 1 | ||
1329 | #define RT5640_EQ_BPF1_DIS (0x0 << 1) | ||
1330 | #define RT5640_EQ_BPF1_EN (0x1 << 1) | ||
1331 | #define RT5640_EQ_LPF_MASK (0x1) | ||
1332 | #define RT5640_EQ_LPF_SFT 0 | ||
1333 | #define RT5640_EQ_LPF_DIS (0x0) | ||
1334 | #define RT5640_EQ_LPF_EN (0x1) | ||
1335 | |||
1336 | /* Memory Test (0xb2) */ | ||
1337 | #define RT5640_MT_MASK (0x1 << 15) | ||
1338 | #define RT5640_MT_SFT 15 | ||
1339 | #define RT5640_MT_DIS (0x0 << 15) | ||
1340 | #define RT5640_MT_EN (0x1 << 15) | ||
1341 | |||
1342 | /* DRC/AGC Control 1 (0xb4) */ | ||
1343 | #define RT5640_DRC_AGC_P_MASK (0x1 << 15) | ||
1344 | #define RT5640_DRC_AGC_P_SFT 15 | ||
1345 | #define RT5640_DRC_AGC_P_DAC (0x0 << 15) | ||
1346 | #define RT5640_DRC_AGC_P_ADC (0x1 << 15) | ||
1347 | #define RT5640_DRC_AGC_MASK (0x1 << 14) | ||
1348 | #define RT5640_DRC_AGC_SFT 14 | ||
1349 | #define RT5640_DRC_AGC_DIS (0x0 << 14) | ||
1350 | #define RT5640_DRC_AGC_EN (0x1 << 14) | ||
1351 | #define RT5640_DRC_AGC_UPD (0x1 << 13) | ||
1352 | #define RT5640_DRC_AGC_UPD_BIT 13 | ||
1353 | #define RT5640_DRC_AGC_AR_MASK (0x1f << 8) | ||
1354 | #define RT5640_DRC_AGC_AR_SFT 8 | ||
1355 | #define RT5640_DRC_AGC_R_MASK (0x7 << 5) | ||
1356 | #define RT5640_DRC_AGC_R_SFT 5 | ||
1357 | #define RT5640_DRC_AGC_R_48K (0x1 << 5) | ||
1358 | #define RT5640_DRC_AGC_R_96K (0x2 << 5) | ||
1359 | #define RT5640_DRC_AGC_R_192K (0x3 << 5) | ||
1360 | #define RT5640_DRC_AGC_R_441K (0x5 << 5) | ||
1361 | #define RT5640_DRC_AGC_R_882K (0x6 << 5) | ||
1362 | #define RT5640_DRC_AGC_R_1764K (0x7 << 5) | ||
1363 | #define RT5640_DRC_AGC_RC_MASK (0x1f) | ||
1364 | #define RT5640_DRC_AGC_RC_SFT 0 | ||
1365 | |||
1366 | /* DRC/AGC Control 2 (0xb5) */ | ||
1367 | #define RT5640_DRC_AGC_POB_MASK (0x3f << 8) | ||
1368 | #define RT5640_DRC_AGC_POB_SFT 8 | ||
1369 | #define RT5640_DRC_AGC_CP_MASK (0x1 << 7) | ||
1370 | #define RT5640_DRC_AGC_CP_SFT 7 | ||
1371 | #define RT5640_DRC_AGC_CP_DIS (0x0 << 7) | ||
1372 | #define RT5640_DRC_AGC_CP_EN (0x1 << 7) | ||
1373 | #define RT5640_DRC_AGC_CPR_MASK (0x3 << 5) | ||
1374 | #define RT5640_DRC_AGC_CPR_SFT 5 | ||
1375 | #define RT5640_DRC_AGC_CPR_1_1 (0x0 << 5) | ||
1376 | #define RT5640_DRC_AGC_CPR_1_2 (0x1 << 5) | ||
1377 | #define RT5640_DRC_AGC_CPR_1_3 (0x2 << 5) | ||
1378 | #define RT5640_DRC_AGC_CPR_1_4 (0x3 << 5) | ||
1379 | #define RT5640_DRC_AGC_PRB_MASK (0x1f) | ||
1380 | #define RT5640_DRC_AGC_PRB_SFT 0 | ||
1381 | |||
1382 | /* DRC/AGC Control 3 (0xb6) */ | ||
1383 | #define RT5640_DRC_AGC_NGB_MASK (0xf << 12) | ||
1384 | #define RT5640_DRC_AGC_NGB_SFT 12 | ||
1385 | #define RT5640_DRC_AGC_TAR_MASK (0x1f << 7) | ||
1386 | #define RT5640_DRC_AGC_TAR_SFT 7 | ||
1387 | #define RT5640_DRC_AGC_NG_MASK (0x1 << 6) | ||
1388 | #define RT5640_DRC_AGC_NG_SFT 6 | ||
1389 | #define RT5640_DRC_AGC_NG_DIS (0x0 << 6) | ||
1390 | #define RT5640_DRC_AGC_NG_EN (0x1 << 6) | ||
1391 | #define RT5640_DRC_AGC_NGH_MASK (0x1 << 5) | ||
1392 | #define RT5640_DRC_AGC_NGH_SFT 5 | ||
1393 | #define RT5640_DRC_AGC_NGH_DIS (0x0 << 5) | ||
1394 | #define RT5640_DRC_AGC_NGH_EN (0x1 << 5) | ||
1395 | #define RT5640_DRC_AGC_NGT_MASK (0x1f) | ||
1396 | #define RT5640_DRC_AGC_NGT_SFT 0 | ||
1397 | |||
1398 | /* ANC Control 1 (0xb8) */ | ||
1399 | #define RT5640_ANC_M_MASK (0x1 << 15) | ||
1400 | #define RT5640_ANC_M_SFT 15 | ||
1401 | #define RT5640_ANC_M_NOR (0x0 << 15) | ||
1402 | #define RT5640_ANC_M_REV (0x1 << 15) | ||
1403 | #define RT5640_ANC_MASK (0x1 << 14) | ||
1404 | #define RT5640_ANC_SFT 14 | ||
1405 | #define RT5640_ANC_DIS (0x0 << 14) | ||
1406 | #define RT5640_ANC_EN (0x1 << 14) | ||
1407 | #define RT5640_ANC_MD_MASK (0x3 << 12) | ||
1408 | #define RT5640_ANC_MD_SFT 12 | ||
1409 | #define RT5640_ANC_MD_DIS (0x0 << 12) | ||
1410 | #define RT5640_ANC_MD_67MS (0x1 << 12) | ||
1411 | #define RT5640_ANC_MD_267MS (0x2 << 12) | ||
1412 | #define RT5640_ANC_MD_1067MS (0x3 << 12) | ||
1413 | #define RT5640_ANC_SN_MASK (0x1 << 11) | ||
1414 | #define RT5640_ANC_SN_SFT 11 | ||
1415 | #define RT5640_ANC_SN_DIS (0x0 << 11) | ||
1416 | #define RT5640_ANC_SN_EN (0x1 << 11) | ||
1417 | #define RT5640_ANC_CLK_MASK (0x1 << 10) | ||
1418 | #define RT5640_ANC_CLK_SFT 10 | ||
1419 | #define RT5640_ANC_CLK_ANC (0x0 << 10) | ||
1420 | #define RT5640_ANC_CLK_REG (0x1 << 10) | ||
1421 | #define RT5640_ANC_ZCD_MASK (0x3 << 8) | ||
1422 | #define RT5640_ANC_ZCD_SFT 8 | ||
1423 | #define RT5640_ANC_ZCD_DIS (0x0 << 8) | ||
1424 | #define RT5640_ANC_ZCD_T1 (0x1 << 8) | ||
1425 | #define RT5640_ANC_ZCD_T2 (0x2 << 8) | ||
1426 | #define RT5640_ANC_ZCD_WT (0x3 << 8) | ||
1427 | #define RT5640_ANC_CS_MASK (0x1 << 7) | ||
1428 | #define RT5640_ANC_CS_SFT 7 | ||
1429 | #define RT5640_ANC_CS_DIS (0x0 << 7) | ||
1430 | #define RT5640_ANC_CS_EN (0x1 << 7) | ||
1431 | #define RT5640_ANC_SW_MASK (0x1 << 6) | ||
1432 | #define RT5640_ANC_SW_SFT 6 | ||
1433 | #define RT5640_ANC_SW_NOR (0x0 << 6) | ||
1434 | #define RT5640_ANC_SW_AUTO (0x1 << 6) | ||
1435 | #define RT5640_ANC_CO_L_MASK (0x3f) | ||
1436 | #define RT5640_ANC_CO_L_SFT 0 | ||
1437 | |||
1438 | /* ANC Control 2 (0xb6) */ | ||
1439 | #define RT5640_ANC_FG_R_MASK (0xf << 12) | ||
1440 | #define RT5640_ANC_FG_R_SFT 12 | ||
1441 | #define RT5640_ANC_FG_L_MASK (0xf << 8) | ||
1442 | #define RT5640_ANC_FG_L_SFT 8 | ||
1443 | #define RT5640_ANC_CG_R_MASK (0xf << 4) | ||
1444 | #define RT5640_ANC_CG_R_SFT 4 | ||
1445 | #define RT5640_ANC_CG_L_MASK (0xf) | ||
1446 | #define RT5640_ANC_CG_L_SFT 0 | ||
1447 | |||
1448 | /* ANC Control 3 (0xb6) */ | ||
1449 | #define RT5640_ANC_CD_MASK (0x1 << 6) | ||
1450 | #define RT5640_ANC_CD_SFT 6 | ||
1451 | #define RT5640_ANC_CD_BOTH (0x0 << 6) | ||
1452 | #define RT5640_ANC_CD_IND (0x1 << 6) | ||
1453 | #define RT5640_ANC_CO_R_MASK (0x3f) | ||
1454 | #define RT5640_ANC_CO_R_SFT 0 | ||
1455 | |||
1456 | /* Jack Detect Control (0xbb) */ | ||
1457 | #define RT5640_JD_MASK (0x7 << 13) | ||
1458 | #define RT5640_JD_SFT 13 | ||
1459 | #define RT5640_JD_DIS (0x0 << 13) | ||
1460 | #define RT5640_JD_GPIO1 (0x1 << 13) | ||
1461 | #define RT5640_JD_JD1_IN4P (0x2 << 13) | ||
1462 | #define RT5640_JD_JD2_IN4N (0x3 << 13) | ||
1463 | #define RT5640_JD_GPIO2 (0x4 << 13) | ||
1464 | #define RT5640_JD_GPIO3 (0x5 << 13) | ||
1465 | #define RT5640_JD_GPIO4 (0x6 << 13) | ||
1466 | #define RT5640_JD_HP_MASK (0x1 << 11) | ||
1467 | #define RT5640_JD_HP_SFT 11 | ||
1468 | #define RT5640_JD_HP_DIS (0x0 << 11) | ||
1469 | #define RT5640_JD_HP_EN (0x1 << 11) | ||
1470 | #define RT5640_JD_HP_TRG_MASK (0x1 << 10) | ||
1471 | #define RT5640_JD_HP_TRG_SFT 10 | ||
1472 | #define RT5640_JD_HP_TRG_LO (0x0 << 10) | ||
1473 | #define RT5640_JD_HP_TRG_HI (0x1 << 10) | ||
1474 | #define RT5640_JD_SPL_MASK (0x1 << 9) | ||
1475 | #define RT5640_JD_SPL_SFT 9 | ||
1476 | #define RT5640_JD_SPL_DIS (0x0 << 9) | ||
1477 | #define RT5640_JD_SPL_EN (0x1 << 9) | ||
1478 | #define RT5640_JD_SPL_TRG_MASK (0x1 << 8) | ||
1479 | #define RT5640_JD_SPL_TRG_SFT 8 | ||
1480 | #define RT5640_JD_SPL_TRG_LO (0x0 << 8) | ||
1481 | #define RT5640_JD_SPL_TRG_HI (0x1 << 8) | ||
1482 | #define RT5640_JD_SPR_MASK (0x1 << 7) | ||
1483 | #define RT5640_JD_SPR_SFT 7 | ||
1484 | #define RT5640_JD_SPR_DIS (0x0 << 7) | ||
1485 | #define RT5640_JD_SPR_EN (0x1 << 7) | ||
1486 | #define RT5640_JD_SPR_TRG_MASK (0x1 << 6) | ||
1487 | #define RT5640_JD_SPR_TRG_SFT 6 | ||
1488 | #define RT5640_JD_SPR_TRG_LO (0x0 << 6) | ||
1489 | #define RT5640_JD_SPR_TRG_HI (0x1 << 6) | ||
1490 | #define RT5640_JD_MO_MASK (0x1 << 5) | ||
1491 | #define RT5640_JD_MO_SFT 5 | ||
1492 | #define RT5640_JD_MO_DIS (0x0 << 5) | ||
1493 | #define RT5640_JD_MO_EN (0x1 << 5) | ||
1494 | #define RT5640_JD_MO_TRG_MASK (0x1 << 4) | ||
1495 | #define RT5640_JD_MO_TRG_SFT 4 | ||
1496 | #define RT5640_JD_MO_TRG_LO (0x0 << 4) | ||
1497 | #define RT5640_JD_MO_TRG_HI (0x1 << 4) | ||
1498 | #define RT5640_JD_LO_MASK (0x1 << 3) | ||
1499 | #define RT5640_JD_LO_SFT 3 | ||
1500 | #define RT5640_JD_LO_DIS (0x0 << 3) | ||
1501 | #define RT5640_JD_LO_EN (0x1 << 3) | ||
1502 | #define RT5640_JD_LO_TRG_MASK (0x1 << 2) | ||
1503 | #define RT5640_JD_LO_TRG_SFT 2 | ||
1504 | #define RT5640_JD_LO_TRG_LO (0x0 << 2) | ||
1505 | #define RT5640_JD_LO_TRG_HI (0x1 << 2) | ||
1506 | #define RT5640_JD1_IN4P_MASK (0x1 << 1) | ||
1507 | #define RT5640_JD1_IN4P_SFT 1 | ||
1508 | #define RT5640_JD1_IN4P_DIS (0x0 << 1) | ||
1509 | #define RT5640_JD1_IN4P_EN (0x1 << 1) | ||
1510 | #define RT5640_JD2_IN4N_MASK (0x1) | ||
1511 | #define RT5640_JD2_IN4N_SFT 0 | ||
1512 | #define RT5640_JD2_IN4N_DIS (0x0) | ||
1513 | #define RT5640_JD2_IN4N_EN (0x1) | ||
1514 | |||
1515 | /* Jack detect for ANC (0xbc) */ | ||
1516 | #define RT5640_ANC_DET_MASK (0x3 << 4) | ||
1517 | #define RT5640_ANC_DET_SFT 4 | ||
1518 | #define RT5640_ANC_DET_DIS (0x0 << 4) | ||
1519 | #define RT5640_ANC_DET_MB1 (0x1 << 4) | ||
1520 | #define RT5640_ANC_DET_MB2 (0x2 << 4) | ||
1521 | #define RT5640_ANC_DET_JD (0x3 << 4) | ||
1522 | #define RT5640_AD_TRG_MASK (0x1 << 3) | ||
1523 | #define RT5640_AD_TRG_SFT 3 | ||
1524 | #define RT5640_AD_TRG_LO (0x0 << 3) | ||
1525 | #define RT5640_AD_TRG_HI (0x1 << 3) | ||
1526 | #define RT5640_ANCM_DET_MASK (0x3 << 4) | ||
1527 | #define RT5640_ANCM_DET_SFT 4 | ||
1528 | #define RT5640_ANCM_DET_DIS (0x0 << 4) | ||
1529 | #define RT5640_ANCM_DET_MB1 (0x1 << 4) | ||
1530 | #define RT5640_ANCM_DET_MB2 (0x2 << 4) | ||
1531 | #define RT5640_ANCM_DET_JD (0x3 << 4) | ||
1532 | #define RT5640_AMD_TRG_MASK (0x1 << 3) | ||
1533 | #define RT5640_AMD_TRG_SFT 3 | ||
1534 | #define RT5640_AMD_TRG_LO (0x0 << 3) | ||
1535 | #define RT5640_AMD_TRG_HI (0x1 << 3) | ||
1536 | |||
1537 | /* IRQ Control 1 (0xbd) */ | ||
1538 | #define RT5640_IRQ_JD_MASK (0x1 << 15) | ||
1539 | #define RT5640_IRQ_JD_SFT 15 | ||
1540 | #define RT5640_IRQ_JD_BP (0x0 << 15) | ||
1541 | #define RT5640_IRQ_JD_NOR (0x1 << 15) | ||
1542 | #define RT5640_IRQ_OT_MASK (0x1 << 14) | ||
1543 | #define RT5640_IRQ_OT_SFT 14 | ||
1544 | #define RT5640_IRQ_OT_BP (0x0 << 14) | ||
1545 | #define RT5640_IRQ_OT_NOR (0x1 << 14) | ||
1546 | #define RT5640_JD_STKY_MASK (0x1 << 13) | ||
1547 | #define RT5640_JD_STKY_SFT 13 | ||
1548 | #define RT5640_JD_STKY_DIS (0x0 << 13) | ||
1549 | #define RT5640_JD_STKY_EN (0x1 << 13) | ||
1550 | #define RT5640_OT_STKY_MASK (0x1 << 12) | ||
1551 | #define RT5640_OT_STKY_SFT 12 | ||
1552 | #define RT5640_OT_STKY_DIS (0x0 << 12) | ||
1553 | #define RT5640_OT_STKY_EN (0x1 << 12) | ||
1554 | #define RT5640_JD_P_MASK (0x1 << 11) | ||
1555 | #define RT5640_JD_P_SFT 11 | ||
1556 | #define RT5640_JD_P_NOR (0x0 << 11) | ||
1557 | #define RT5640_JD_P_INV (0x1 << 11) | ||
1558 | #define RT5640_OT_P_MASK (0x1 << 10) | ||
1559 | #define RT5640_OT_P_SFT 10 | ||
1560 | #define RT5640_OT_P_NOR (0x0 << 10) | ||
1561 | #define RT5640_OT_P_INV (0x1 << 10) | ||
1562 | |||
1563 | /* IRQ Control 2 (0xbe) */ | ||
1564 | #define RT5640_IRQ_MB1_OC_MASK (0x1 << 15) | ||
1565 | #define RT5640_IRQ_MB1_OC_SFT 15 | ||
1566 | #define RT5640_IRQ_MB1_OC_BP (0x0 << 15) | ||
1567 | #define RT5640_IRQ_MB1_OC_NOR (0x1 << 15) | ||
1568 | #define RT5640_IRQ_MB2_OC_MASK (0x1 << 14) | ||
1569 | #define RT5640_IRQ_MB2_OC_SFT 14 | ||
1570 | #define RT5640_IRQ_MB2_OC_BP (0x0 << 14) | ||
1571 | #define RT5640_IRQ_MB2_OC_NOR (0x1 << 14) | ||
1572 | #define RT5640_MB1_OC_STKY_MASK (0x1 << 11) | ||
1573 | #define RT5640_MB1_OC_STKY_SFT 11 | ||
1574 | #define RT5640_MB1_OC_STKY_DIS (0x0 << 11) | ||
1575 | #define RT5640_MB1_OC_STKY_EN (0x1 << 11) | ||
1576 | #define RT5640_MB2_OC_STKY_MASK (0x1 << 10) | ||
1577 | #define RT5640_MB2_OC_STKY_SFT 10 | ||
1578 | #define RT5640_MB2_OC_STKY_DIS (0x0 << 10) | ||
1579 | #define RT5640_MB2_OC_STKY_EN (0x1 << 10) | ||
1580 | #define RT5640_MB1_OC_P_MASK (0x1 << 7) | ||
1581 | #define RT5640_MB1_OC_P_SFT 7 | ||
1582 | #define RT5640_MB1_OC_P_NOR (0x0 << 7) | ||
1583 | #define RT5640_MB1_OC_P_INV (0x1 << 7) | ||
1584 | #define RT5640_MB2_OC_P_MASK (0x1 << 6) | ||
1585 | #define RT5640_MB2_OC_P_SFT 6 | ||
1586 | #define RT5640_MB2_OC_P_NOR (0x0 << 6) | ||
1587 | #define RT5640_MB2_OC_P_INV (0x1 << 6) | ||
1588 | #define RT5640_MB1_OC_CLR (0x1 << 3) | ||
1589 | #define RT5640_MB1_OC_CLR_SFT 3 | ||
1590 | #define RT5640_MB2_OC_CLR (0x1 << 2) | ||
1591 | #define RT5640_MB2_OC_CLR_SFT 2 | ||
1592 | |||
1593 | /* GPIO Control 1 (0xc0) */ | ||
1594 | #define RT5640_GP1_PIN_MASK (0x1 << 15) | ||
1595 | #define RT5640_GP1_PIN_SFT 15 | ||
1596 | #define RT5640_GP1_PIN_GPIO1 (0x0 << 15) | ||
1597 | #define RT5640_GP1_PIN_IRQ (0x1 << 15) | ||
1598 | #define RT5640_GP2_PIN_MASK (0x1 << 14) | ||
1599 | #define RT5640_GP2_PIN_SFT 14 | ||
1600 | #define RT5640_GP2_PIN_GPIO2 (0x0 << 14) | ||
1601 | #define RT5640_GP2_PIN_DMIC1_SCL (0x1 << 14) | ||
1602 | #define RT5640_GP3_PIN_MASK (0x3 << 12) | ||
1603 | #define RT5640_GP3_PIN_SFT 12 | ||
1604 | #define RT5640_GP3_PIN_GPIO3 (0x0 << 12) | ||
1605 | #define RT5640_GP3_PIN_DMIC1_SDA (0x1 << 12) | ||
1606 | #define RT5640_GP3_PIN_IRQ (0x2 << 12) | ||
1607 | #define RT5640_GP4_PIN_MASK (0x1 << 11) | ||
1608 | #define RT5640_GP4_PIN_SFT 11 | ||
1609 | #define RT5640_GP4_PIN_GPIO4 (0x0 << 11) | ||
1610 | #define RT5640_GP4_PIN_DMIC2_SDA (0x1 << 11) | ||
1611 | #define RT5640_DP_SIG_MASK (0x1 << 10) | ||
1612 | #define RT5640_DP_SIG_SFT 10 | ||
1613 | #define RT5640_DP_SIG_TEST (0x0 << 10) | ||
1614 | #define RT5640_DP_SIG_AP (0x1 << 10) | ||
1615 | #define RT5640_GPIO_M_MASK (0x1 << 9) | ||
1616 | #define RT5640_GPIO_M_SFT 9 | ||
1617 | #define RT5640_GPIO_M_FLT (0x0 << 9) | ||
1618 | #define RT5640_GPIO_M_PH (0x1 << 9) | ||
1619 | |||
1620 | /* GPIO Control 3 (0xc2) */ | ||
1621 | #define RT5640_GP4_PF_MASK (0x1 << 11) | ||
1622 | #define RT5640_GP4_PF_SFT 11 | ||
1623 | #define RT5640_GP4_PF_IN (0x0 << 11) | ||
1624 | #define RT5640_GP4_PF_OUT (0x1 << 11) | ||
1625 | #define RT5640_GP4_OUT_MASK (0x1 << 10) | ||
1626 | #define RT5640_GP4_OUT_SFT 10 | ||
1627 | #define RT5640_GP4_OUT_LO (0x0 << 10) | ||
1628 | #define RT5640_GP4_OUT_HI (0x1 << 10) | ||
1629 | #define RT5640_GP4_P_MASK (0x1 << 9) | ||
1630 | #define RT5640_GP4_P_SFT 9 | ||
1631 | #define RT5640_GP4_P_NOR (0x0 << 9) | ||
1632 | #define RT5640_GP4_P_INV (0x1 << 9) | ||
1633 | #define RT5640_GP3_PF_MASK (0x1 << 8) | ||
1634 | #define RT5640_GP3_PF_SFT 8 | ||
1635 | #define RT5640_GP3_PF_IN (0x0 << 8) | ||
1636 | #define RT5640_GP3_PF_OUT (0x1 << 8) | ||
1637 | #define RT5640_GP3_OUT_MASK (0x1 << 7) | ||
1638 | #define RT5640_GP3_OUT_SFT 7 | ||
1639 | #define RT5640_GP3_OUT_LO (0x0 << 7) | ||
1640 | #define RT5640_GP3_OUT_HI (0x1 << 7) | ||
1641 | #define RT5640_GP3_P_MASK (0x1 << 6) | ||
1642 | #define RT5640_GP3_P_SFT 6 | ||
1643 | #define RT5640_GP3_P_NOR (0x0 << 6) | ||
1644 | #define RT5640_GP3_P_INV (0x1 << 6) | ||
1645 | #define RT5640_GP2_PF_MASK (0x1 << 5) | ||
1646 | #define RT5640_GP2_PF_SFT 5 | ||
1647 | #define RT5640_GP2_PF_IN (0x0 << 5) | ||
1648 | #define RT5640_GP2_PF_OUT (0x1 << 5) | ||
1649 | #define RT5640_GP2_OUT_MASK (0x1 << 4) | ||
1650 | #define RT5640_GP2_OUT_SFT 4 | ||
1651 | #define RT5640_GP2_OUT_LO (0x0 << 4) | ||
1652 | #define RT5640_GP2_OUT_HI (0x1 << 4) | ||
1653 | #define RT5640_GP2_P_MASK (0x1 << 3) | ||
1654 | #define RT5640_GP2_P_SFT 3 | ||
1655 | #define RT5640_GP2_P_NOR (0x0 << 3) | ||
1656 | #define RT5640_GP2_P_INV (0x1 << 3) | ||
1657 | #define RT5640_GP1_PF_MASK (0x1 << 2) | ||
1658 | #define RT5640_GP1_PF_SFT 2 | ||
1659 | #define RT5640_GP1_PF_IN (0x0 << 2) | ||
1660 | #define RT5640_GP1_PF_OUT (0x1 << 2) | ||
1661 | #define RT5640_GP1_OUT_MASK (0x1 << 1) | ||
1662 | #define RT5640_GP1_OUT_SFT 1 | ||
1663 | #define RT5640_GP1_OUT_LO (0x0 << 1) | ||
1664 | #define RT5640_GP1_OUT_HI (0x1 << 1) | ||
1665 | #define RT5640_GP1_P_MASK (0x1) | ||
1666 | #define RT5640_GP1_P_SFT 0 | ||
1667 | #define RT5640_GP1_P_NOR (0x0) | ||
1668 | #define RT5640_GP1_P_INV (0x1) | ||
1669 | |||
1670 | /* FM34-500 Register Control 1 (0xc4) */ | ||
1671 | #define RT5640_DSP_ADD_SFT 0 | ||
1672 | |||
1673 | /* FM34-500 Register Control 2 (0xc5) */ | ||
1674 | #define RT5640_DSP_DAT_SFT 0 | ||
1675 | |||
1676 | /* FM34-500 Register Control 3 (0xc6) */ | ||
1677 | #define RT5640_DSP_BUSY_MASK (0x1 << 15) | ||
1678 | #define RT5640_DSP_BUSY_BIT 15 | ||
1679 | #define RT5640_DSP_DS_MASK (0x1 << 14) | ||
1680 | #define RT5640_DSP_DS_SFT 14 | ||
1681 | #define RT5640_DSP_DS_FM3010 (0x1 << 14) | ||
1682 | #define RT5640_DSP_DS_TEMP (0x1 << 14) | ||
1683 | #define RT5640_DSP_CLK_MASK (0x3 << 12) | ||
1684 | #define RT5640_DSP_CLK_SFT 12 | ||
1685 | #define RT5640_DSP_CLK_384K (0x0 << 12) | ||
1686 | #define RT5640_DSP_CLK_192K (0x1 << 12) | ||
1687 | #define RT5640_DSP_CLK_96K (0x2 << 12) | ||
1688 | #define RT5640_DSP_CLK_64K (0x3 << 12) | ||
1689 | #define RT5640_DSP_PD_PIN_MASK (0x1 << 11) | ||
1690 | #define RT5640_DSP_PD_PIN_SFT 11 | ||
1691 | #define RT5640_DSP_PD_PIN_LO (0x0 << 11) | ||
1692 | #define RT5640_DSP_PD_PIN_HI (0x1 << 11) | ||
1693 | #define RT5640_DSP_RST_PIN_MASK (0x1 << 10) | ||
1694 | #define RT5640_DSP_RST_PIN_SFT 10 | ||
1695 | #define RT5640_DSP_RST_PIN_LO (0x0 << 10) | ||
1696 | #define RT5640_DSP_RST_PIN_HI (0x1 << 10) | ||
1697 | #define RT5640_DSP_R_EN (0x1 << 9) | ||
1698 | #define RT5640_DSP_R_EN_BIT 9 | ||
1699 | #define RT5640_DSP_W_EN (0x1 << 8) | ||
1700 | #define RT5640_DSP_W_EN_BIT 8 | ||
1701 | #define RT5640_DSP_CMD_MASK (0xff) | ||
1702 | #define RT5640_DSP_CMD_SFT 0 | ||
1703 | #define RT5640_DSP_CMD_MW (0x3B) /* Memory Write */ | ||
1704 | #define RT5640_DSP_CMD_MR (0x37) /* Memory Read */ | ||
1705 | #define RT5640_DSP_CMD_RR (0x60) /* Register Read */ | ||
1706 | #define RT5640_DSP_CMD_RW (0x68) /* Register Write */ | ||
1707 | |||
1708 | /* Programmable Register Array Control 1 (0xc8) */ | ||
1709 | #define RT5640_REG_SEQ_MASK (0xf << 12) | ||
1710 | #define RT5640_REG_SEQ_SFT 12 | ||
1711 | #define RT5640_SEQ1_ST_MASK (0x1 << 11) /*RO*/ | ||
1712 | #define RT5640_SEQ1_ST_SFT 11 | ||
1713 | #define RT5640_SEQ1_ST_RUN (0x0 << 11) | ||
1714 | #define RT5640_SEQ1_ST_FIN (0x1 << 11) | ||
1715 | #define RT5640_SEQ2_ST_MASK (0x1 << 10) /*RO*/ | ||
1716 | #define RT5640_SEQ2_ST_SFT 10 | ||
1717 | #define RT5640_SEQ2_ST_RUN (0x0 << 10) | ||
1718 | #define RT5640_SEQ2_ST_FIN (0x1 << 10) | ||
1719 | #define RT5640_REG_LV_MASK (0x1 << 9) | ||
1720 | #define RT5640_REG_LV_SFT 9 | ||
1721 | #define RT5640_REG_LV_MX (0x0 << 9) | ||
1722 | #define RT5640_REG_LV_PR (0x1 << 9) | ||
1723 | #define RT5640_SEQ_2_PT_MASK (0x1 << 8) | ||
1724 | #define RT5640_SEQ_2_PT_BIT 8 | ||
1725 | #define RT5640_REG_IDX_MASK (0xff) | ||
1726 | #define RT5640_REG_IDX_SFT 0 | ||
1727 | |||
1728 | /* Programmable Register Array Control 2 (0xc9) */ | ||
1729 | #define RT5640_REG_DAT_MASK (0xffff) | ||
1730 | #define RT5640_REG_DAT_SFT 0 | ||
1731 | |||
1732 | /* Programmable Register Array Control 3 (0xca) */ | ||
1733 | #define RT5640_SEQ_DLY_MASK (0xff << 8) | ||
1734 | #define RT5640_SEQ_DLY_SFT 8 | ||
1735 | #define RT5640_PROG_MASK (0x1 << 7) | ||
1736 | #define RT5640_PROG_SFT 7 | ||
1737 | #define RT5640_PROG_DIS (0x0 << 7) | ||
1738 | #define RT5640_PROG_EN (0x1 << 7) | ||
1739 | #define RT5640_SEQ1_PT_RUN (0x1 << 6) | ||
1740 | #define RT5640_SEQ1_PT_RUN_BIT 6 | ||
1741 | #define RT5640_SEQ2_PT_RUN (0x1 << 5) | ||
1742 | #define RT5640_SEQ2_PT_RUN_BIT 5 | ||
1743 | |||
1744 | /* Programmable Register Array Control 4 (0xcb) */ | ||
1745 | #define RT5640_SEQ1_START_MASK (0xf << 8) | ||
1746 | #define RT5640_SEQ1_START_SFT 8 | ||
1747 | #define RT5640_SEQ1_END_MASK (0xf) | ||
1748 | #define RT5640_SEQ1_END_SFT 0 | ||
1749 | |||
1750 | /* Programmable Register Array Control 5 (0xcc) */ | ||
1751 | #define RT5640_SEQ2_START_MASK (0xf << 8) | ||
1752 | #define RT5640_SEQ2_START_SFT 8 | ||
1753 | #define RT5640_SEQ2_END_MASK (0xf) | ||
1754 | #define RT5640_SEQ2_END_SFT 0 | ||
1755 | |||
1756 | /* Scramble Function (0xcd) */ | ||
1757 | #define RT5640_SCB_KEY_MASK (0xff) | ||
1758 | #define RT5640_SCB_KEY_SFT 0 | ||
1759 | |||
1760 | /* Scramble Control (0xce) */ | ||
1761 | #define RT5640_SCB_SWAP_MASK (0x1 << 15) | ||
1762 | #define RT5640_SCB_SWAP_SFT 15 | ||
1763 | #define RT5640_SCB_SWAP_DIS (0x0 << 15) | ||
1764 | #define RT5640_SCB_SWAP_EN (0x1 << 15) | ||
1765 | #define RT5640_SCB_MASK (0x1 << 14) | ||
1766 | #define RT5640_SCB_SFT 14 | ||
1767 | #define RT5640_SCB_DIS (0x0 << 14) | ||
1768 | #define RT5640_SCB_EN (0x1 << 14) | ||
1769 | |||
1770 | /* Baseback Control (0xcf) */ | ||
1771 | #define RT5640_BB_MASK (0x1 << 15) | ||
1772 | #define RT5640_BB_SFT 15 | ||
1773 | #define RT5640_BB_DIS (0x0 << 15) | ||
1774 | #define RT5640_BB_EN (0x1 << 15) | ||
1775 | #define RT5640_BB_CT_MASK (0x7 << 12) | ||
1776 | #define RT5640_BB_CT_SFT 12 | ||
1777 | #define RT5640_BB_CT_A (0x0 << 12) | ||
1778 | #define RT5640_BB_CT_B (0x1 << 12) | ||
1779 | #define RT5640_BB_CT_C (0x2 << 12) | ||
1780 | #define RT5640_BB_CT_D (0x3 << 12) | ||
1781 | #define RT5640_M_BB_L_MASK (0x1 << 9) | ||
1782 | #define RT5640_M_BB_L_SFT 9 | ||
1783 | #define RT5640_M_BB_R_MASK (0x1 << 8) | ||
1784 | #define RT5640_M_BB_R_SFT 8 | ||
1785 | #define RT5640_M_BB_HPF_L_MASK (0x1 << 7) | ||
1786 | #define RT5640_M_BB_HPF_L_SFT 7 | ||
1787 | #define RT5640_M_BB_HPF_R_MASK (0x1 << 6) | ||
1788 | #define RT5640_M_BB_HPF_R_SFT 6 | ||
1789 | #define RT5640_G_BB_BST_MASK (0x3f) | ||
1790 | #define RT5640_G_BB_BST_SFT 0 | ||
1791 | |||
1792 | /* MP3 Plus Control 1 (0xd0) */ | ||
1793 | #define RT5640_M_MP3_L_MASK (0x1 << 15) | ||
1794 | #define RT5640_M_MP3_L_SFT 15 | ||
1795 | #define RT5640_M_MP3_R_MASK (0x1 << 14) | ||
1796 | #define RT5640_M_MP3_R_SFT 14 | ||
1797 | #define RT5640_M_MP3_MASK (0x1 << 13) | ||
1798 | #define RT5640_M_MP3_SFT 13 | ||
1799 | #define RT5640_M_MP3_DIS (0x0 << 13) | ||
1800 | #define RT5640_M_MP3_EN (0x1 << 13) | ||
1801 | #define RT5640_EG_MP3_MASK (0x1f << 8) | ||
1802 | #define RT5640_EG_MP3_SFT 8 | ||
1803 | #define RT5640_MP3_HLP_MASK (0x1 << 7) | ||
1804 | #define RT5640_MP3_HLP_SFT 7 | ||
1805 | #define RT5640_MP3_HLP_DIS (0x0 << 7) | ||
1806 | #define RT5640_MP3_HLP_EN (0x1 << 7) | ||
1807 | #define RT5640_M_MP3_ORG_L_MASK (0x1 << 6) | ||
1808 | #define RT5640_M_MP3_ORG_L_SFT 6 | ||
1809 | #define RT5640_M_MP3_ORG_R_MASK (0x1 << 5) | ||
1810 | #define RT5640_M_MP3_ORG_R_SFT 5 | ||
1811 | |||
1812 | /* MP3 Plus Control 2 (0xd1) */ | ||
1813 | #define RT5640_MP3_WT_MASK (0x1 << 13) | ||
1814 | #define RT5640_MP3_WT_SFT 13 | ||
1815 | #define RT5640_MP3_WT_1_4 (0x0 << 13) | ||
1816 | #define RT5640_MP3_WT_1_2 (0x1 << 13) | ||
1817 | #define RT5640_OG_MP3_MASK (0x1f << 8) | ||
1818 | #define RT5640_OG_MP3_SFT 8 | ||
1819 | #define RT5640_HG_MP3_MASK (0x3f) | ||
1820 | #define RT5640_HG_MP3_SFT 0 | ||
1821 | |||
1822 | /* 3D HP Control 1 (0xd2) */ | ||
1823 | #define RT5640_3D_CF_MASK (0x1 << 15) | ||
1824 | #define RT5640_3D_CF_SFT 15 | ||
1825 | #define RT5640_3D_CF_DIS (0x0 << 15) | ||
1826 | #define RT5640_3D_CF_EN (0x1 << 15) | ||
1827 | #define RT5640_3D_HP_MASK (0x1 << 14) | ||
1828 | #define RT5640_3D_HP_SFT 14 | ||
1829 | #define RT5640_3D_HP_DIS (0x0 << 14) | ||
1830 | #define RT5640_3D_HP_EN (0x1 << 14) | ||
1831 | #define RT5640_3D_BT_MASK (0x1 << 13) | ||
1832 | #define RT5640_3D_BT_SFT 13 | ||
1833 | #define RT5640_3D_BT_DIS (0x0 << 13) | ||
1834 | #define RT5640_3D_BT_EN (0x1 << 13) | ||
1835 | #define RT5640_3D_1F_MIX_MASK (0x3 << 11) | ||
1836 | #define RT5640_3D_1F_MIX_SFT 11 | ||
1837 | #define RT5640_3D_HP_M_MASK (0x1 << 10) | ||
1838 | #define RT5640_3D_HP_M_SFT 10 | ||
1839 | #define RT5640_3D_HP_M_SUR (0x0 << 10) | ||
1840 | #define RT5640_3D_HP_M_FRO (0x1 << 10) | ||
1841 | #define RT5640_M_3D_HRTF_MASK (0x1 << 9) | ||
1842 | #define RT5640_M_3D_HRTF_SFT 9 | ||
1843 | #define RT5640_M_3D_D2H_MASK (0x1 << 8) | ||
1844 | #define RT5640_M_3D_D2H_SFT 8 | ||
1845 | #define RT5640_M_3D_D2R_MASK (0x1 << 7) | ||
1846 | #define RT5640_M_3D_D2R_SFT 7 | ||
1847 | #define RT5640_M_3D_REVB_MASK (0x1 << 6) | ||
1848 | #define RT5640_M_3D_REVB_SFT 6 | ||
1849 | |||
1850 | /* Adjustable high pass filter control 1 (0xd3) */ | ||
1851 | #define RT5640_2ND_HPF_MASK (0x1 << 15) | ||
1852 | #define RT5640_2ND_HPF_SFT 15 | ||
1853 | #define RT5640_2ND_HPF_DIS (0x0 << 15) | ||
1854 | #define RT5640_2ND_HPF_EN (0x1 << 15) | ||
1855 | #define RT5640_HPF_CF_L_MASK (0x7 << 12) | ||
1856 | #define RT5640_HPF_CF_L_SFT 12 | ||
1857 | #define RT5640_1ST_HPF_MASK (0x1 << 11) | ||
1858 | #define RT5640_1ST_HPF_SFT 11 | ||
1859 | #define RT5640_1ST_HPF_DIS (0x0 << 11) | ||
1860 | #define RT5640_1ST_HPF_EN (0x1 << 11) | ||
1861 | #define RT5640_HPF_CF_R_MASK (0x7 << 8) | ||
1862 | #define RT5640_HPF_CF_R_SFT 8 | ||
1863 | #define RT5640_ZD_T_MASK (0x3 << 6) | ||
1864 | #define RT5640_ZD_T_SFT 6 | ||
1865 | #define RT5640_ZD_F_MASK (0x3 << 4) | ||
1866 | #define RT5640_ZD_F_SFT 4 | ||
1867 | #define RT5640_ZD_F_IM (0x0 << 4) | ||
1868 | #define RT5640_ZD_F_ZC_IM (0x1 << 4) | ||
1869 | #define RT5640_ZD_F_ZC_IOD (0x2 << 4) | ||
1870 | #define RT5640_ZD_F_UN (0x3 << 4) | ||
1871 | |||
1872 | /* HP calibration control and Amp detection (0xd6) */ | ||
1873 | #define RT5640_SI_DAC_MASK (0x1 << 11) | ||
1874 | #define RT5640_SI_DAC_SFT 11 | ||
1875 | #define RT5640_SI_DAC_AUTO (0x0 << 11) | ||
1876 | #define RT5640_SI_DAC_TEST (0x1 << 11) | ||
1877 | #define RT5640_DC_CAL_M_MASK (0x1 << 10) | ||
1878 | #define RT5640_DC_CAL_M_SFT 10 | ||
1879 | #define RT5640_DC_CAL_M_CAL (0x0 << 10) | ||
1880 | #define RT5640_DC_CAL_M_NOR (0x1 << 10) | ||
1881 | #define RT5640_DC_CAL_MASK (0x1 << 9) | ||
1882 | #define RT5640_DC_CAL_SFT 9 | ||
1883 | #define RT5640_DC_CAL_DIS (0x0 << 9) | ||
1884 | #define RT5640_DC_CAL_EN (0x1 << 9) | ||
1885 | #define RT5640_HPD_RCV_MASK (0x7 << 6) | ||
1886 | #define RT5640_HPD_RCV_SFT 6 | ||
1887 | #define RT5640_HPD_PS_MASK (0x1 << 5) | ||
1888 | #define RT5640_HPD_PS_SFT 5 | ||
1889 | #define RT5640_HPD_PS_DIS (0x0 << 5) | ||
1890 | #define RT5640_HPD_PS_EN (0x1 << 5) | ||
1891 | #define RT5640_CAL_M_MASK (0x1 << 4) | ||
1892 | #define RT5640_CAL_M_SFT 4 | ||
1893 | #define RT5640_CAL_M_DEP (0x0 << 4) | ||
1894 | #define RT5640_CAL_M_CAL (0x1 << 4) | ||
1895 | #define RT5640_CAL_MASK (0x1 << 3) | ||
1896 | #define RT5640_CAL_SFT 3 | ||
1897 | #define RT5640_CAL_DIS (0x0 << 3) | ||
1898 | #define RT5640_CAL_EN (0x1 << 3) | ||
1899 | #define RT5640_CAL_TEST_MASK (0x1 << 2) | ||
1900 | #define RT5640_CAL_TEST_SFT 2 | ||
1901 | #define RT5640_CAL_TEST_DIS (0x0 << 2) | ||
1902 | #define RT5640_CAL_TEST_EN (0x1 << 2) | ||
1903 | #define RT5640_CAL_P_MASK (0x3) | ||
1904 | #define RT5640_CAL_P_SFT 0 | ||
1905 | #define RT5640_CAL_P_NONE (0x0) | ||
1906 | #define RT5640_CAL_P_CAL (0x1) | ||
1907 | #define RT5640_CAL_P_DAC_CAL (0x2) | ||
1908 | |||
1909 | /* Soft volume and zero cross control 1 (0xd9) */ | ||
1910 | #define RT5640_SV_MASK (0x1 << 15) | ||
1911 | #define RT5640_SV_SFT 15 | ||
1912 | #define RT5640_SV_DIS (0x0 << 15) | ||
1913 | #define RT5640_SV_EN (0x1 << 15) | ||
1914 | #define RT5640_SPO_SV_MASK (0x1 << 14) | ||
1915 | #define RT5640_SPO_SV_SFT 14 | ||
1916 | #define RT5640_SPO_SV_DIS (0x0 << 14) | ||
1917 | #define RT5640_SPO_SV_EN (0x1 << 14) | ||
1918 | #define RT5640_OUT_SV_MASK (0x1 << 13) | ||
1919 | #define RT5640_OUT_SV_SFT 13 | ||
1920 | #define RT5640_OUT_SV_DIS (0x0 << 13) | ||
1921 | #define RT5640_OUT_SV_EN (0x1 << 13) | ||
1922 | #define RT5640_HP_SV_MASK (0x1 << 12) | ||
1923 | #define RT5640_HP_SV_SFT 12 | ||
1924 | #define RT5640_HP_SV_DIS (0x0 << 12) | ||
1925 | #define RT5640_HP_SV_EN (0x1 << 12) | ||
1926 | #define RT5640_ZCD_DIG_MASK (0x1 << 11) | ||
1927 | #define RT5640_ZCD_DIG_SFT 11 | ||
1928 | #define RT5640_ZCD_DIG_DIS (0x0 << 11) | ||
1929 | #define RT5640_ZCD_DIG_EN (0x1 << 11) | ||
1930 | #define RT5640_ZCD_MASK (0x1 << 10) | ||
1931 | #define RT5640_ZCD_SFT 10 | ||
1932 | #define RT5640_ZCD_PD (0x0 << 10) | ||
1933 | #define RT5640_ZCD_PU (0x1 << 10) | ||
1934 | #define RT5640_M_ZCD_MASK (0x3f << 4) | ||
1935 | #define RT5640_M_ZCD_SFT 4 | ||
1936 | #define RT5640_M_ZCD_RM_L (0x1 << 9) | ||
1937 | #define RT5640_M_ZCD_RM_R (0x1 << 8) | ||
1938 | #define RT5640_M_ZCD_SM_L (0x1 << 7) | ||
1939 | #define RT5640_M_ZCD_SM_R (0x1 << 6) | ||
1940 | #define RT5640_M_ZCD_OM_L (0x1 << 5) | ||
1941 | #define RT5640_M_ZCD_OM_R (0x1 << 4) | ||
1942 | #define RT5640_SV_DLY_MASK (0xf) | ||
1943 | #define RT5640_SV_DLY_SFT 0 | ||
1944 | |||
1945 | /* Soft volume and zero cross control 2 (0xda) */ | ||
1946 | #define RT5640_ZCD_HP_MASK (0x1 << 15) | ||
1947 | #define RT5640_ZCD_HP_SFT 15 | ||
1948 | #define RT5640_ZCD_HP_DIS (0x0 << 15) | ||
1949 | #define RT5640_ZCD_HP_EN (0x1 << 15) | ||
1950 | |||
1951 | |||
1952 | /* Codec Private Register definition */ | ||
1953 | /* 3D Speaker Control (0x63) */ | ||
1954 | #define RT5640_3D_SPK_MASK (0x1 << 15) | ||
1955 | #define RT5640_3D_SPK_SFT 15 | ||
1956 | #define RT5640_3D_SPK_DIS (0x0 << 15) | ||
1957 | #define RT5640_3D_SPK_EN (0x1 << 15) | ||
1958 | #define RT5640_3D_SPK_M_MASK (0x3 << 13) | ||
1959 | #define RT5640_3D_SPK_M_SFT 13 | ||
1960 | #define RT5640_3D_SPK_CG_MASK (0x1f << 8) | ||
1961 | #define RT5640_3D_SPK_CG_SFT 8 | ||
1962 | #define RT5640_3D_SPK_SG_MASK (0x1f) | ||
1963 | #define RT5640_3D_SPK_SG_SFT 0 | ||
1964 | |||
1965 | /* Wind Noise Detection Control 1 (0x6c) */ | ||
1966 | #define RT5640_WND_MASK (0x1 << 15) | ||
1967 | #define RT5640_WND_SFT 15 | ||
1968 | #define RT5640_WND_DIS (0x0 << 15) | ||
1969 | #define RT5640_WND_EN (0x1 << 15) | ||
1970 | |||
1971 | /* Wind Noise Detection Control 2 (0x6d) */ | ||
1972 | #define RT5640_WND_FC_NW_MASK (0x3f << 10) | ||
1973 | #define RT5640_WND_FC_NW_SFT 10 | ||
1974 | #define RT5640_WND_FC_WK_MASK (0x3f << 4) | ||
1975 | #define RT5640_WND_FC_WK_SFT 4 | ||
1976 | |||
1977 | /* Wind Noise Detection Control 3 (0x6e) */ | ||
1978 | #define RT5640_HPF_FC_MASK (0x3f << 6) | ||
1979 | #define RT5640_HPF_FC_SFT 6 | ||
1980 | #define RT5640_WND_FC_ST_MASK (0x3f) | ||
1981 | #define RT5640_WND_FC_ST_SFT 0 | ||
1982 | |||
1983 | /* Wind Noise Detection Control 4 (0x6f) */ | ||
1984 | #define RT5640_WND_TH_LO_MASK (0x3ff) | ||
1985 | #define RT5640_WND_TH_LO_SFT 0 | ||
1986 | |||
1987 | /* Wind Noise Detection Control 5 (0x70) */ | ||
1988 | #define RT5640_WND_TH_HI_MASK (0x3ff) | ||
1989 | #define RT5640_WND_TH_HI_SFT 0 | ||
1990 | |||
1991 | /* Wind Noise Detection Control 8 (0x73) */ | ||
1992 | #define RT5640_WND_WIND_MASK (0x1 << 13) /* Read-Only */ | ||
1993 | #define RT5640_WND_WIND_SFT 13 | ||
1994 | #define RT5640_WND_STRONG_MASK (0x1 << 12) /* Read-Only */ | ||
1995 | #define RT5640_WND_STRONG_SFT 12 | ||
1996 | enum { | ||
1997 | RT5640_NO_WIND, | ||
1998 | RT5640_BREEZE, | ||
1999 | RT5640_STORM, | ||
2000 | }; | ||
2001 | |||
2002 | /* Dipole Speaker Interface (0x75) */ | ||
2003 | #define RT5640_DP_ATT_MASK (0x3 << 14) | ||
2004 | #define RT5640_DP_ATT_SFT 14 | ||
2005 | #define RT5640_DP_SPK_MASK (0x1 << 10) | ||
2006 | #define RT5640_DP_SPK_SFT 10 | ||
2007 | #define RT5640_DP_SPK_DIS (0x0 << 10) | ||
2008 | #define RT5640_DP_SPK_EN (0x1 << 10) | ||
2009 | |||
2010 | /* EQ Pre Volume Control (0xb3) */ | ||
2011 | #define RT5640_EQ_PRE_VOL_MASK (0xffff) | ||
2012 | #define RT5640_EQ_PRE_VOL_SFT 0 | ||
2013 | |||
2014 | /* EQ Post Volume Control (0xb4) */ | ||
2015 | #define RT5640_EQ_PST_VOL_MASK (0xffff) | ||
2016 | #define RT5640_EQ_PST_VOL_SFT 0 | ||
2017 | |||
2018 | #define RT5640_NO_JACK BIT(0) | ||
2019 | #define RT5640_HEADSET_DET BIT(1) | ||
2020 | #define RT5640_HEADPHO_DET BIT(2) | ||
2021 | |||
2022 | /* System Clock Source */ | ||
2023 | #define RT5640_SCLK_S_MCLK 0 | ||
2024 | #define RT5640_SCLK_S_PLL1 1 | ||
2025 | #define RT5640_SCLK_S_PLL1_TK 2 | ||
2026 | #define RT5640_SCLK_S_RCCLK 3 | ||
2027 | |||
2028 | /* PLL1 Source */ | ||
2029 | #define RT5640_PLL1_S_MCLK 0 | ||
2030 | #define RT5640_PLL1_S_BCLK1 1 | ||
2031 | #define RT5640_PLL1_S_BCLK2 2 | ||
2032 | #define RT5640_PLL1_S_BCLK3 3 | ||
2033 | |||
2034 | |||
2035 | enum { | ||
2036 | RT5640_AIF1, | ||
2037 | RT5640_AIF2, | ||
2038 | RT5640_AIF3, | ||
2039 | RT5640_AIFS, | ||
2040 | }; | ||
2041 | |||
2042 | enum { | ||
2043 | RT5640_U_IF1 = 0x1, | ||
2044 | RT5640_U_IF2 = 0x2, | ||
2045 | RT5640_U_IF3 = 0x4, | ||
2046 | }; | ||
2047 | |||
2048 | enum { | ||
2049 | RT5640_IF_123, | ||
2050 | RT5640_IF_132, | ||
2051 | RT5640_IF_312, | ||
2052 | RT5640_IF_321, | ||
2053 | RT5640_IF_231, | ||
2054 | RT5640_IF_213, | ||
2055 | RT5640_IF_113, | ||
2056 | RT5640_IF_223, | ||
2057 | RT5640_IF_ALL, | ||
2058 | }; | ||
2059 | |||
2060 | enum { | ||
2061 | RT5640_DMIC_DIS, | ||
2062 | RT5640_DMIC1, | ||
2063 | RT5640_DMIC2, | ||
2064 | }; | ||
2065 | |||
2066 | struct rt5640_pll_code { | ||
2067 | bool m_bp; /* Indicates bypass m code or not. */ | ||
2068 | int m_code; | ||
2069 | int n_code; | ||
2070 | int k_code; | ||
2071 | }; | ||
2072 | |||
2073 | struct rt5640_priv { | ||
2074 | struct snd_soc_codec *codec; | ||
2075 | struct rt5640_platform_data pdata; | ||
2076 | struct regmap *regmap; | ||
2077 | |||
2078 | int sysclk; | ||
2079 | int sysclk_src; | ||
2080 | int lrck[RT5640_AIFS]; | ||
2081 | int bclk[RT5640_AIFS]; | ||
2082 | int master[RT5640_AIFS]; | ||
2083 | |||
2084 | struct rt5640_pll_code pll_code; | ||
2085 | int pll_src; | ||
2086 | int pll_in; | ||
2087 | int pll_out; | ||
2088 | |||
2089 | int dmic_en; | ||
2090 | }; | ||
2091 | |||
2092 | #endif | ||
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 92bbfec9b107..d441559dc92c 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
20 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
@@ -34,30 +35,30 @@ | |||
34 | #define SGTL5000_MAX_REG_OFFSET 0x013A | 35 | #define SGTL5000_MAX_REG_OFFSET 0x013A |
35 | 36 | ||
36 | /* default value of sgtl5000 registers */ | 37 | /* default value of sgtl5000 registers */ |
37 | static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = { | 38 | static const struct reg_default sgtl5000_reg_defaults[] = { |
38 | [SGTL5000_CHIP_CLK_CTRL] = 0x0008, | 39 | { SGTL5000_CHIP_CLK_CTRL, 0x0008 }, |
39 | [SGTL5000_CHIP_I2S_CTRL] = 0x0010, | 40 | { SGTL5000_CHIP_I2S_CTRL, 0x0010 }, |
40 | [SGTL5000_CHIP_SSS_CTRL] = 0x0008, | 41 | { SGTL5000_CHIP_SSS_CTRL, 0x0008 }, |
41 | [SGTL5000_CHIP_DAC_VOL] = 0x3c3c, | 42 | { SGTL5000_CHIP_DAC_VOL, 0x3c3c }, |
42 | [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f, | 43 | { SGTL5000_CHIP_PAD_STRENGTH, 0x015f }, |
43 | [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818, | 44 | { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 }, |
44 | [SGTL5000_CHIP_ANA_CTRL] = 0x0111, | 45 | { SGTL5000_CHIP_ANA_CTRL, 0x0111 }, |
45 | [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404, | 46 | { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 }, |
46 | [SGTL5000_CHIP_ANA_POWER] = 0x7060, | 47 | { SGTL5000_CHIP_ANA_POWER, 0x7060 }, |
47 | [SGTL5000_CHIP_PLL_CTRL] = 0x5000, | 48 | { SGTL5000_CHIP_PLL_CTRL, 0x5000 }, |
48 | [SGTL5000_DAP_BASS_ENHANCE] = 0x0040, | 49 | { SGTL5000_DAP_BASS_ENHANCE, 0x0040 }, |
49 | [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f, | 50 | { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f }, |
50 | [SGTL5000_DAP_SURROUND] = 0x0040, | 51 | { SGTL5000_DAP_SURROUND, 0x0040 }, |
51 | [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f, | 52 | { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f }, |
52 | [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f, | 53 | { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f }, |
53 | [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f, | 54 | { SGTL5000_DAP_EQ_BASS_BAND2, 0x002f }, |
54 | [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f, | 55 | { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f }, |
55 | [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f, | 56 | { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, |
56 | [SGTL5000_DAP_MAIN_CHAN] = 0x8000, | 57 | { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, |
57 | [SGTL5000_DAP_AVC_CTRL] = 0x0510, | 58 | { SGTL5000_DAP_AVC_CTRL, 0x0510 }, |
58 | [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473, | 59 | { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, |
59 | [SGTL5000_DAP_AVC_ATTACK] = 0x0028, | 60 | { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, |
60 | [SGTL5000_DAP_AVC_DECAY] = 0x0050, | 61 | { SGTL5000_DAP_AVC_DECAY, 0x0050 }, |
61 | }; | 62 | }; |
62 | 63 | ||
63 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ | 64 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ |
@@ -112,6 +113,8 @@ struct sgtl5000_priv { | |||
112 | int fmt; /* i2s data format */ | 113 | int fmt; /* i2s data format */ |
113 | struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; | 114 | struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; |
114 | struct ldo_regulator *ldo; | 115 | struct ldo_regulator *ldo; |
116 | struct regmap *regmap; | ||
117 | struct clk *mclk; | ||
115 | }; | 118 | }; |
116 | 119 | ||
117 | /* | 120 | /* |
@@ -151,12 +154,12 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, | |||
151 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
152 | { | 155 | { |
153 | switch (event) { | 156 | switch (event) { |
154 | case SND_SOC_DAPM_PRE_PMU: | 157 | case SND_SOC_DAPM_POST_PMU: |
155 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 158 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, |
156 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | 159 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); |
157 | break; | 160 | break; |
158 | 161 | ||
159 | case SND_SOC_DAPM_POST_PMD: | 162 | case SND_SOC_DAPM_PRE_PMD: |
160 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 163 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, |
161 | SGTL5000_VAG_POWERUP, 0); | 164 | SGTL5000_VAG_POWERUP, 0); |
162 | msleep(400); | 165 | msleep(400); |
@@ -217,12 +220,11 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { | |||
217 | 0, SGTL5000_CHIP_DIG_POWER, | 220 | 0, SGTL5000_CHIP_DIG_POWER, |
218 | 1, 0), | 221 | 1, 0), |
219 | 222 | ||
220 | SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0, | ||
221 | power_vag_event, | ||
222 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
223 | |||
224 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), | 223 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), |
225 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), | 224 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), |
225 | |||
226 | SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), | ||
227 | SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), | ||
226 | }; | 228 | }; |
227 | 229 | ||
228 | /* routes for sgtl5000 */ | 230 | /* routes for sgtl5000 */ |
@@ -230,16 +232,13 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { | |||
230 | {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ | 232 | {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ |
231 | {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ | 233 | {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ |
232 | 234 | ||
233 | {"ADC", NULL, "VAG_POWER"}, | ||
234 | {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ | 235 | {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ |
235 | {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ | 236 | {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ |
236 | 237 | ||
237 | {"DAC", NULL, "VAG_POWER"}, | ||
238 | {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ | 238 | {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ |
239 | {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ | 239 | {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ |
240 | {"LO", NULL, "DAC"}, /* dac --> line_out */ | 240 | {"LO", NULL, "DAC"}, /* dac --> line_out */ |
241 | 241 | ||
242 | {"LINE_IN", NULL, "VAG_POWER"}, | ||
243 | {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ | 242 | {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ |
244 | {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ | 243 | {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ |
245 | 244 | ||
@@ -909,10 +908,25 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, | |||
909 | if (ret) | 908 | if (ret) |
910 | return ret; | 909 | return ret; |
911 | udelay(10); | 910 | udelay(10); |
911 | |||
912 | regcache_cache_only(sgtl5000->regmap, false); | ||
913 | |||
914 | ret = regcache_sync(sgtl5000->regmap); | ||
915 | if (ret != 0) { | ||
916 | dev_err(codec->dev, | ||
917 | "Failed to restore cache: %d\n", ret); | ||
918 | |||
919 | regcache_cache_only(sgtl5000->regmap, true); | ||
920 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
921 | sgtl5000->supplies); | ||
922 | |||
923 | return ret; | ||
924 | } | ||
912 | } | 925 | } |
913 | 926 | ||
914 | break; | 927 | break; |
915 | case SND_SOC_BIAS_OFF: | 928 | case SND_SOC_BIAS_OFF: |
929 | regcache_cache_only(sgtl5000->regmap, true); | ||
916 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 930 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
917 | sgtl5000->supplies); | 931 | sgtl5000->supplies); |
918 | break; | 932 | break; |
@@ -958,17 +972,76 @@ static struct snd_soc_dai_driver sgtl5000_dai = { | |||
958 | .symmetric_rates = 1, | 972 | .symmetric_rates = 1, |
959 | }; | 973 | }; |
960 | 974 | ||
961 | static int sgtl5000_volatile_register(struct snd_soc_codec *codec, | 975 | static bool sgtl5000_volatile(struct device *dev, unsigned int reg) |
962 | unsigned int reg) | ||
963 | { | 976 | { |
964 | switch (reg) { | 977 | switch (reg) { |
965 | case SGTL5000_CHIP_ID: | 978 | case SGTL5000_CHIP_ID: |
966 | case SGTL5000_CHIP_ADCDAC_CTRL: | 979 | case SGTL5000_CHIP_ADCDAC_CTRL: |
967 | case SGTL5000_CHIP_ANA_STATUS: | 980 | case SGTL5000_CHIP_ANA_STATUS: |
968 | return 1; | 981 | return true; |
969 | } | 982 | } |
970 | 983 | ||
971 | return 0; | 984 | return false; |
985 | } | ||
986 | |||
987 | static bool sgtl5000_readable(struct device *dev, unsigned int reg) | ||
988 | { | ||
989 | switch (reg) { | ||
990 | case SGTL5000_CHIP_ID: | ||
991 | case SGTL5000_CHIP_DIG_POWER: | ||
992 | case SGTL5000_CHIP_CLK_CTRL: | ||
993 | case SGTL5000_CHIP_I2S_CTRL: | ||
994 | case SGTL5000_CHIP_SSS_CTRL: | ||
995 | case SGTL5000_CHIP_ADCDAC_CTRL: | ||
996 | case SGTL5000_CHIP_DAC_VOL: | ||
997 | case SGTL5000_CHIP_PAD_STRENGTH: | ||
998 | case SGTL5000_CHIP_ANA_ADC_CTRL: | ||
999 | case SGTL5000_CHIP_ANA_HP_CTRL: | ||
1000 | case SGTL5000_CHIP_ANA_CTRL: | ||
1001 | case SGTL5000_CHIP_LINREG_CTRL: | ||
1002 | case SGTL5000_CHIP_REF_CTRL: | ||
1003 | case SGTL5000_CHIP_MIC_CTRL: | ||
1004 | case SGTL5000_CHIP_LINE_OUT_CTRL: | ||
1005 | case SGTL5000_CHIP_LINE_OUT_VOL: | ||
1006 | case SGTL5000_CHIP_ANA_POWER: | ||
1007 | case SGTL5000_CHIP_PLL_CTRL: | ||
1008 | case SGTL5000_CHIP_CLK_TOP_CTRL: | ||
1009 | case SGTL5000_CHIP_ANA_STATUS: | ||
1010 | case SGTL5000_CHIP_SHORT_CTRL: | ||
1011 | case SGTL5000_CHIP_ANA_TEST2: | ||
1012 | case SGTL5000_DAP_CTRL: | ||
1013 | case SGTL5000_DAP_PEQ: | ||
1014 | case SGTL5000_DAP_BASS_ENHANCE: | ||
1015 | case SGTL5000_DAP_BASS_ENHANCE_CTRL: | ||
1016 | case SGTL5000_DAP_AUDIO_EQ: | ||
1017 | case SGTL5000_DAP_SURROUND: | ||
1018 | case SGTL5000_DAP_FLT_COEF_ACCESS: | ||
1019 | case SGTL5000_DAP_COEF_WR_B0_MSB: | ||
1020 | case SGTL5000_DAP_COEF_WR_B0_LSB: | ||
1021 | case SGTL5000_DAP_EQ_BASS_BAND0: | ||
1022 | case SGTL5000_DAP_EQ_BASS_BAND1: | ||
1023 | case SGTL5000_DAP_EQ_BASS_BAND2: | ||
1024 | case SGTL5000_DAP_EQ_BASS_BAND3: | ||
1025 | case SGTL5000_DAP_EQ_BASS_BAND4: | ||
1026 | case SGTL5000_DAP_MAIN_CHAN: | ||
1027 | case SGTL5000_DAP_MIX_CHAN: | ||
1028 | case SGTL5000_DAP_AVC_CTRL: | ||
1029 | case SGTL5000_DAP_AVC_THRESHOLD: | ||
1030 | case SGTL5000_DAP_AVC_ATTACK: | ||
1031 | case SGTL5000_DAP_AVC_DECAY: | ||
1032 | case SGTL5000_DAP_COEF_WR_B1_MSB: | ||
1033 | case SGTL5000_DAP_COEF_WR_B1_LSB: | ||
1034 | case SGTL5000_DAP_COEF_WR_B2_MSB: | ||
1035 | case SGTL5000_DAP_COEF_WR_B2_LSB: | ||
1036 | case SGTL5000_DAP_COEF_WR_A1_MSB: | ||
1037 | case SGTL5000_DAP_COEF_WR_A1_LSB: | ||
1038 | case SGTL5000_DAP_COEF_WR_A2_MSB: | ||
1039 | case SGTL5000_DAP_COEF_WR_A2_LSB: | ||
1040 | return true; | ||
1041 | |||
1042 | default: | ||
1043 | return false; | ||
1044 | } | ||
972 | } | 1045 | } |
973 | 1046 | ||
974 | #ifdef CONFIG_SUSPEND | 1047 | #ifdef CONFIG_SUSPEND |
@@ -1214,7 +1287,7 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec) | |||
1214 | 1287 | ||
1215 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | 1288 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) |
1216 | { | 1289 | { |
1217 | u16 reg; | 1290 | int reg; |
1218 | int ret; | 1291 | int ret; |
1219 | int rev; | 1292 | int rev; |
1220 | int i; | 1293 | int i; |
@@ -1242,23 +1315,17 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1242 | /* wait for all power rails bring up */ | 1315 | /* wait for all power rails bring up */ |
1243 | udelay(10); | 1316 | udelay(10); |
1244 | 1317 | ||
1245 | /* read chip information */ | ||
1246 | reg = snd_soc_read(codec, SGTL5000_CHIP_ID); | ||
1247 | if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != | ||
1248 | SGTL5000_PARTID_PART_ID) { | ||
1249 | dev_err(codec->dev, | ||
1250 | "Device with ID register %x is not a sgtl5000\n", reg); | ||
1251 | ret = -ENODEV; | ||
1252 | goto err_regulator_disable; | ||
1253 | } | ||
1254 | |||
1255 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1256 | dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev); | ||
1257 | |||
1258 | /* | 1318 | /* |
1259 | * workaround for revision 0x11 and later, | 1319 | * workaround for revision 0x11 and later, |
1260 | * roll back to use internal LDO | 1320 | * roll back to use internal LDO |
1261 | */ | 1321 | */ |
1322 | |||
1323 | ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); | ||
1324 | if (ret) | ||
1325 | goto err_regulator_disable; | ||
1326 | |||
1327 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1328 | |||
1262 | if (external_vddd && rev >= 0x11) { | 1329 | if (external_vddd && rev >= 0x11) { |
1263 | /* disable all regulator first */ | 1330 | /* disable all regulator first */ |
1264 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1331 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
@@ -1300,7 +1367,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1300 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1367 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1301 | 1368 | ||
1302 | /* setup i2c data ops */ | 1369 | /* setup i2c data ops */ |
1303 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); | 1370 | codec->control_data = sgtl5000->regmap; |
1371 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
1304 | if (ret < 0) { | 1372 | if (ret < 0) { |
1305 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1373 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1306 | return ret; | 1374 | return ret; |
@@ -1391,11 +1459,6 @@ static struct snd_soc_codec_driver sgtl5000_driver = { | |||
1391 | .suspend = sgtl5000_suspend, | 1459 | .suspend = sgtl5000_suspend, |
1392 | .resume = sgtl5000_resume, | 1460 | .resume = sgtl5000_resume, |
1393 | .set_bias_level = sgtl5000_set_bias_level, | 1461 | .set_bias_level = sgtl5000_set_bias_level, |
1394 | .reg_cache_size = ARRAY_SIZE(sgtl5000_regs), | ||
1395 | .reg_word_size = sizeof(u16), | ||
1396 | .reg_cache_step = 2, | ||
1397 | .reg_cache_default = sgtl5000_regs, | ||
1398 | .volatile_register = sgtl5000_volatile_register, | ||
1399 | .controls = sgtl5000_snd_controls, | 1462 | .controls = sgtl5000_snd_controls, |
1400 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), | 1463 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), |
1401 | .dapm_widgets = sgtl5000_dapm_widgets, | 1464 | .dapm_widgets = sgtl5000_dapm_widgets, |
@@ -1404,28 +1467,114 @@ static struct snd_soc_codec_driver sgtl5000_driver = { | |||
1404 | .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), | 1467 | .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), |
1405 | }; | 1468 | }; |
1406 | 1469 | ||
1470 | static const struct regmap_config sgtl5000_regmap = { | ||
1471 | .reg_bits = 16, | ||
1472 | .val_bits = 16, | ||
1473 | |||
1474 | .max_register = SGTL5000_MAX_REG_OFFSET, | ||
1475 | .volatile_reg = sgtl5000_volatile, | ||
1476 | .readable_reg = sgtl5000_readable, | ||
1477 | |||
1478 | .cache_type = REGCACHE_RBTREE, | ||
1479 | .reg_defaults = sgtl5000_reg_defaults, | ||
1480 | .num_reg_defaults = ARRAY_SIZE(sgtl5000_reg_defaults), | ||
1481 | }; | ||
1482 | |||
1483 | /* | ||
1484 | * Write all the default values from sgtl5000_reg_defaults[] array into the | ||
1485 | * sgtl5000 registers, to make sure we always start with the sane registers | ||
1486 | * values as stated in the datasheet. | ||
1487 | * | ||
1488 | * Since sgtl5000 does not have a reset line, nor a reset command in software, | ||
1489 | * we follow this approach to guarantee we always start from the default values | ||
1490 | * and avoid problems like, not being able to probe after an audio playback | ||
1491 | * followed by a system reset or a 'reboot' command in Linux | ||
1492 | */ | ||
1493 | static int sgtl5000_fill_defaults(struct sgtl5000_priv *sgtl5000) | ||
1494 | { | ||
1495 | int i, ret, val, index; | ||
1496 | |||
1497 | for (i = 0; i < ARRAY_SIZE(sgtl5000_reg_defaults); i++) { | ||
1498 | val = sgtl5000_reg_defaults[i].def; | ||
1499 | index = sgtl5000_reg_defaults[i].reg; | ||
1500 | ret = regmap_write(sgtl5000->regmap, index, val); | ||
1501 | if (ret) | ||
1502 | return ret; | ||
1503 | } | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1407 | static int sgtl5000_i2c_probe(struct i2c_client *client, | 1508 | static int sgtl5000_i2c_probe(struct i2c_client *client, |
1408 | const struct i2c_device_id *id) | 1509 | const struct i2c_device_id *id) |
1409 | { | 1510 | { |
1410 | struct sgtl5000_priv *sgtl5000; | 1511 | struct sgtl5000_priv *sgtl5000; |
1411 | int ret; | 1512 | int ret, reg, rev; |
1412 | 1513 | ||
1413 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), | 1514 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), |
1414 | GFP_KERNEL); | 1515 | GFP_KERNEL); |
1415 | if (!sgtl5000) | 1516 | if (!sgtl5000) |
1416 | return -ENOMEM; | 1517 | return -ENOMEM; |
1417 | 1518 | ||
1519 | sgtl5000->regmap = devm_regmap_init_i2c(client, &sgtl5000_regmap); | ||
1520 | if (IS_ERR(sgtl5000->regmap)) { | ||
1521 | ret = PTR_ERR(sgtl5000->regmap); | ||
1522 | dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | sgtl5000->mclk = devm_clk_get(&client->dev, NULL); | ||
1527 | if (IS_ERR(sgtl5000->mclk)) { | ||
1528 | ret = PTR_ERR(sgtl5000->mclk); | ||
1529 | dev_err(&client->dev, "Failed to get mclock: %d\n", ret); | ||
1530 | return ret; | ||
1531 | } | ||
1532 | |||
1533 | ret = clk_prepare_enable(sgtl5000->mclk); | ||
1534 | if (ret) | ||
1535 | return ret; | ||
1536 | |||
1537 | /* read chip information */ | ||
1538 | ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); | ||
1539 | if (ret) | ||
1540 | goto disable_clk; | ||
1541 | |||
1542 | if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != | ||
1543 | SGTL5000_PARTID_PART_ID) { | ||
1544 | dev_err(&client->dev, | ||
1545 | "Device with ID register %x is not a sgtl5000\n", reg); | ||
1546 | ret = -ENODEV; | ||
1547 | goto disable_clk; | ||
1548 | } | ||
1549 | |||
1550 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1551 | dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev); | ||
1552 | |||
1418 | i2c_set_clientdata(client, sgtl5000); | 1553 | i2c_set_clientdata(client, sgtl5000); |
1419 | 1554 | ||
1555 | /* Ensure sgtl5000 will start with sane register values */ | ||
1556 | ret = sgtl5000_fill_defaults(sgtl5000); | ||
1557 | if (ret) | ||
1558 | goto disable_clk; | ||
1559 | |||
1420 | ret = snd_soc_register_codec(&client->dev, | 1560 | ret = snd_soc_register_codec(&client->dev, |
1421 | &sgtl5000_driver, &sgtl5000_dai, 1); | 1561 | &sgtl5000_driver, &sgtl5000_dai, 1); |
1562 | if (ret) | ||
1563 | goto disable_clk; | ||
1564 | |||
1565 | return 0; | ||
1566 | |||
1567 | disable_clk: | ||
1568 | clk_disable_unprepare(sgtl5000->mclk); | ||
1422 | return ret; | 1569 | return ret; |
1423 | } | 1570 | } |
1424 | 1571 | ||
1425 | static int sgtl5000_i2c_remove(struct i2c_client *client) | 1572 | static int sgtl5000_i2c_remove(struct i2c_client *client) |
1426 | { | 1573 | { |
1427 | snd_soc_unregister_codec(&client->dev); | 1574 | struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); |
1428 | 1575 | ||
1576 | snd_soc_unregister_codec(&client->dev); | ||
1577 | clk_disable_unprepare(sgtl5000->mclk); | ||
1429 | return 0; | 1578 | return 0; |
1430 | } | 1579 | } |
1431 | 1580 | ||
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 8a9f43534b79..4b69229a9818 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #define _SGTL5000_H | 12 | #define _SGTL5000_H |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * Register values. | 15 | * Registers addresses |
16 | */ | 16 | */ |
17 | #define SGTL5000_CHIP_ID 0x0000 | 17 | #define SGTL5000_CHIP_ID 0x0000 |
18 | #define SGTL5000_CHIP_DIG_POWER 0x0002 | 18 | #define SGTL5000_CHIP_DIG_POWER 0x0002 |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index d1ae869d3181..dba26e63844e 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -883,7 +883,7 @@ static int sn95031_codec_remove(struct snd_soc_codec *codec) | |||
883 | return 0; | 883 | return 0; |
884 | } | 884 | } |
885 | 885 | ||
886 | struct snd_soc_codec_driver sn95031_codec = { | 886 | static struct snd_soc_codec_driver sn95031_codec = { |
887 | .probe = sn95031_codec_probe, | 887 | .probe = sn95031_codec_probe, |
888 | .remove = sn95031_codec_remove, | 888 | .remove = sn95031_codec_remove, |
889 | .read = sn95031_read, | 889 | .read = sn95031_read, |
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index dd8d856053fc..e9d7881ed2c8 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
22 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
24 | #include <linux/of.h> | ||
24 | 25 | ||
25 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 | 26 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 |
26 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 27 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
@@ -51,12 +52,21 @@ static int spdif_dir_remove(struct platform_device *pdev) | |||
51 | return 0; | 52 | return 0; |
52 | } | 53 | } |
53 | 54 | ||
55 | #ifdef CONFIG_OF | ||
56 | static const struct of_device_id spdif_dir_dt_ids[] = { | ||
57 | { .compatible = "linux,spdif-dir", }, | ||
58 | { } | ||
59 | }; | ||
60 | MODULE_DEVICE_TABLE(of, spdif_dir_dt_ids); | ||
61 | #endif | ||
62 | |||
54 | static struct platform_driver spdif_dir_driver = { | 63 | static struct platform_driver spdif_dir_driver = { |
55 | .probe = spdif_dir_probe, | 64 | .probe = spdif_dir_probe, |
56 | .remove = spdif_dir_remove, | 65 | .remove = spdif_dir_remove, |
57 | .driver = { | 66 | .driver = { |
58 | .name = "spdif-dir", | 67 | .name = "spdif-dir", |
59 | .owner = THIS_MODULE, | 68 | .owner = THIS_MODULE, |
69 | .of_match_table = of_match_ptr(spdif_dir_dt_ids), | ||
60 | }, | 70 | }, |
61 | }; | 71 | }; |
62 | 72 | ||
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transmitter.c index 112a49d66e39..18280499fd55 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transmitter.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include <linux/of.h> | ||
23 | 24 | ||
24 | #define DRV_NAME "spdif-dit" | 25 | #define DRV_NAME "spdif-dit" |
25 | 26 | ||
@@ -52,12 +53,21 @@ static int spdif_dit_remove(struct platform_device *pdev) | |||
52 | return 0; | 53 | return 0; |
53 | } | 54 | } |
54 | 55 | ||
56 | #ifdef CONFIG_OF | ||
57 | static const struct of_device_id spdif_dit_dt_ids[] = { | ||
58 | { .compatible = "linux,spdif-dit", }, | ||
59 | { } | ||
60 | }; | ||
61 | MODULE_DEVICE_TABLE(of, spdif_dit_dt_ids); | ||
62 | #endif | ||
63 | |||
55 | static struct platform_driver spdif_dit_driver = { | 64 | static struct platform_driver spdif_dit_driver = { |
56 | .probe = spdif_dit_probe, | 65 | .probe = spdif_dit_probe, |
57 | .remove = spdif_dit_remove, | 66 | .remove = spdif_dit_remove, |
58 | .driver = { | 67 | .driver = { |
59 | .name = DRV_NAME, | 68 | .name = DRV_NAME, |
60 | .owner = THIS_MODULE, | 69 | .owner = THIS_MODULE, |
70 | .of_match_table = of_match_ptr(spdif_dit_dt_ids), | ||
61 | }, | 71 | }, |
62 | }; | 72 | }; |
63 | 73 | ||
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c new file mode 100644 index 000000000000..95aed552139a --- /dev/null +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -0,0 +1,856 @@ | |||
1 | /* | ||
2 | * SSM2518 amplifier audio driver | ||
3 | * | ||
4 | * Copyright 2013 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/regmap.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/platform_data/ssm2518.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/tlv.h> | ||
24 | |||
25 | #include "ssm2518.h" | ||
26 | |||
27 | #define SSM2518_REG_POWER1 0x00 | ||
28 | #define SSM2518_REG_CLOCK 0x01 | ||
29 | #define SSM2518_REG_SAI_CTRL1 0x02 | ||
30 | #define SSM2518_REG_SAI_CTRL2 0x03 | ||
31 | #define SSM2518_REG_CHAN_MAP 0x04 | ||
32 | #define SSM2518_REG_LEFT_VOL 0x05 | ||
33 | #define SSM2518_REG_RIGHT_VOL 0x06 | ||
34 | #define SSM2518_REG_MUTE_CTRL 0x07 | ||
35 | #define SSM2518_REG_FAULT_CTRL 0x08 | ||
36 | #define SSM2518_REG_POWER2 0x09 | ||
37 | #define SSM2518_REG_DRC_1 0x0a | ||
38 | #define SSM2518_REG_DRC_2 0x0b | ||
39 | #define SSM2518_REG_DRC_3 0x0c | ||
40 | #define SSM2518_REG_DRC_4 0x0d | ||
41 | #define SSM2518_REG_DRC_5 0x0e | ||
42 | #define SSM2518_REG_DRC_6 0x0f | ||
43 | #define SSM2518_REG_DRC_7 0x10 | ||
44 | #define SSM2518_REG_DRC_8 0x11 | ||
45 | #define SSM2518_REG_DRC_9 0x12 | ||
46 | |||
47 | #define SSM2518_POWER1_RESET BIT(7) | ||
48 | #define SSM2518_POWER1_NO_BCLK BIT(5) | ||
49 | #define SSM2518_POWER1_MCS_MASK (0xf << 1) | ||
50 | #define SSM2518_POWER1_MCS_64FS (0x0 << 1) | ||
51 | #define SSM2518_POWER1_MCS_128FS (0x1 << 1) | ||
52 | #define SSM2518_POWER1_MCS_256FS (0x2 << 1) | ||
53 | #define SSM2518_POWER1_MCS_384FS (0x3 << 1) | ||
54 | #define SSM2518_POWER1_MCS_512FS (0x4 << 1) | ||
55 | #define SSM2518_POWER1_MCS_768FS (0x5 << 1) | ||
56 | #define SSM2518_POWER1_MCS_100FS (0x6 << 1) | ||
57 | #define SSM2518_POWER1_MCS_200FS (0x7 << 1) | ||
58 | #define SSM2518_POWER1_MCS_400FS (0x8 << 1) | ||
59 | #define SSM2518_POWER1_SPWDN BIT(0) | ||
60 | |||
61 | #define SSM2518_CLOCK_ASR BIT(0) | ||
62 | |||
63 | #define SSM2518_SAI_CTRL1_FMT_MASK (0x3 << 5) | ||
64 | #define SSM2518_SAI_CTRL1_FMT_I2S (0x0 << 5) | ||
65 | #define SSM2518_SAI_CTRL1_FMT_LJ (0x1 << 5) | ||
66 | #define SSM2518_SAI_CTRL1_FMT_RJ_24BIT (0x2 << 5) | ||
67 | #define SSM2518_SAI_CTRL1_FMT_RJ_16BIT (0x3 << 5) | ||
68 | |||
69 | #define SSM2518_SAI_CTRL1_SAI_MASK (0x7 << 2) | ||
70 | #define SSM2518_SAI_CTRL1_SAI_I2S (0x0 << 2) | ||
71 | #define SSM2518_SAI_CTRL1_SAI_TDM_2 (0x1 << 2) | ||
72 | #define SSM2518_SAI_CTRL1_SAI_TDM_4 (0x2 << 2) | ||
73 | #define SSM2518_SAI_CTRL1_SAI_TDM_8 (0x3 << 2) | ||
74 | #define SSM2518_SAI_CTRL1_SAI_TDM_16 (0x4 << 2) | ||
75 | #define SSM2518_SAI_CTRL1_SAI_MONO (0x5 << 2) | ||
76 | |||
77 | #define SSM2518_SAI_CTRL1_FS_MASK (0x3) | ||
78 | #define SSM2518_SAI_CTRL1_FS_8000_12000 (0x0) | ||
79 | #define SSM2518_SAI_CTRL1_FS_16000_24000 (0x1) | ||
80 | #define SSM2518_SAI_CTRL1_FS_32000_48000 (0x2) | ||
81 | #define SSM2518_SAI_CTRL1_FS_64000_96000 (0x3) | ||
82 | |||
83 | #define SSM2518_SAI_CTRL2_BCLK_INTERAL BIT(7) | ||
84 | #define SSM2518_SAI_CTRL2_LRCLK_PULSE BIT(6) | ||
85 | #define SSM2518_SAI_CTRL2_LRCLK_INVERT BIT(5) | ||
86 | #define SSM2518_SAI_CTRL2_MSB BIT(4) | ||
87 | #define SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK (0x3 << 2) | ||
88 | #define SSM2518_SAI_CTRL2_SLOT_WIDTH_32 (0x0 << 2) | ||
89 | #define SSM2518_SAI_CTRL2_SLOT_WIDTH_24 (0x1 << 2) | ||
90 | #define SSM2518_SAI_CTRL2_SLOT_WIDTH_16 (0x2 << 2) | ||
91 | #define SSM2518_SAI_CTRL2_BCLK_INVERT BIT(1) | ||
92 | |||
93 | #define SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET 4 | ||
94 | #define SSM2518_CHAN_MAP_RIGHT_SLOT_MASK 0xf0 | ||
95 | #define SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET 0 | ||
96 | #define SSM2518_CHAN_MAP_LEFT_SLOT_MASK 0x0f | ||
97 | |||
98 | #define SSM2518_MUTE_CTRL_ANA_GAIN BIT(5) | ||
99 | #define SSM2518_MUTE_CTRL_MUTE_MASTER BIT(0) | ||
100 | |||
101 | #define SSM2518_POWER2_APWDN BIT(0) | ||
102 | |||
103 | #define SSM2518_DAC_MUTE BIT(6) | ||
104 | #define SSM2518_DAC_FS_MASK 0x07 | ||
105 | #define SSM2518_DAC_FS_8000 0x00 | ||
106 | #define SSM2518_DAC_FS_16000 0x01 | ||
107 | #define SSM2518_DAC_FS_32000 0x02 | ||
108 | #define SSM2518_DAC_FS_64000 0x03 | ||
109 | #define SSM2518_DAC_FS_128000 0x04 | ||
110 | |||
111 | struct ssm2518 { | ||
112 | struct regmap *regmap; | ||
113 | bool right_j; | ||
114 | |||
115 | unsigned int sysclk; | ||
116 | const struct snd_pcm_hw_constraint_list *constraints; | ||
117 | |||
118 | int enable_gpio; | ||
119 | }; | ||
120 | |||
121 | static const struct reg_default ssm2518_reg_defaults[] = { | ||
122 | { 0x00, 0x05 }, | ||
123 | { 0x01, 0x00 }, | ||
124 | { 0x02, 0x02 }, | ||
125 | { 0x03, 0x00 }, | ||
126 | { 0x04, 0x10 }, | ||
127 | { 0x05, 0x40 }, | ||
128 | { 0x06, 0x40 }, | ||
129 | { 0x07, 0x81 }, | ||
130 | { 0x08, 0x0c }, | ||
131 | { 0x09, 0x99 }, | ||
132 | { 0x0a, 0x7c }, | ||
133 | { 0x0b, 0x5b }, | ||
134 | { 0x0c, 0x57 }, | ||
135 | { 0x0d, 0x89 }, | ||
136 | { 0x0e, 0x8c }, | ||
137 | { 0x0f, 0x77 }, | ||
138 | { 0x10, 0x26 }, | ||
139 | { 0x11, 0x1c }, | ||
140 | { 0x12, 0x97 }, | ||
141 | }; | ||
142 | |||
143 | static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400); | ||
144 | static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0); | ||
145 | static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0); | ||
146 | static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0); | ||
147 | static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0); | ||
148 | |||
149 | static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv, | ||
150 | 0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0), | ||
151 | 7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0), | ||
152 | ); | ||
153 | |||
154 | static const char * const ssm2518_drc_peak_detector_attack_time_text[] = { | ||
155 | "0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms", | ||
156 | "6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms", | ||
157 | "768 ms", "1536 ms", | ||
158 | }; | ||
159 | |||
160 | static const char * const ssm2518_drc_peak_detector_release_time_text[] = { | ||
161 | "0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms", | ||
162 | "192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms", | ||
163 | "12288 ms", "24576 ms" | ||
164 | }; | ||
165 | |||
166 | static const char * const ssm2518_drc_hold_time_text[] = { | ||
167 | "0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms", | ||
168 | "21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms", | ||
169 | "682.24 ms", "1364 ms", | ||
170 | }; | ||
171 | |||
172 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, | ||
173 | SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); | ||
174 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, | ||
175 | SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); | ||
176 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, | ||
177 | SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); | ||
178 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, | ||
179 | SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); | ||
180 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, | ||
181 | SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); | ||
182 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, | ||
183 | SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); | ||
184 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, | ||
185 | SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); | ||
186 | |||
187 | static const struct snd_kcontrol_new ssm2518_snd_controls[] = { | ||
188 | SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL, | ||
189 | 4, 1, 0), | ||
190 | SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2518_REG_LEFT_VOL, | ||
191 | SSM2518_REG_RIGHT_VOL, 0, 0xff, 1, ssm2518_vol_tlv), | ||
192 | SOC_DOUBLE("Master Playback Switch", SSM2518_REG_MUTE_CTRL, 2, 1, 1, 1), | ||
193 | |||
194 | SOC_SINGLE("Amp Low Power Mode Switch", SSM2518_REG_POWER2, 4, 1, 0), | ||
195 | SOC_SINGLE("DAC Low Power Mode Switch", SSM2518_REG_POWER2, 3, 1, 0), | ||
196 | |||
197 | SOC_SINGLE("DRC Limiter Switch", SSM2518_REG_DRC_1, 5, 1, 0), | ||
198 | SOC_SINGLE("DRC Compressor Switch", SSM2518_REG_DRC_1, 4, 1, 0), | ||
199 | SOC_SINGLE("DRC Expander Switch", SSM2518_REG_DRC_1, 3, 1, 0), | ||
200 | SOC_SINGLE("DRC Noise Gate Switch", SSM2518_REG_DRC_1, 2, 1, 0), | ||
201 | SOC_DOUBLE("DRC Switch", SSM2518_REG_DRC_1, 0, 1, 1, 0), | ||
202 | |||
203 | SOC_SINGLE_TLV("DRC Limiter Threshold Volume", | ||
204 | SSM2518_REG_DRC_3, 4, 15, 1, ssm2518_limiter_tlv), | ||
205 | SOC_SINGLE_TLV("DRC Compressor Lower Threshold Volume", | ||
206 | SSM2518_REG_DRC_3, 0, 15, 1, ssm2518_compressor_tlv), | ||
207 | SOC_SINGLE_TLV("DRC Expander Upper Threshold Volume", SSM2518_REG_DRC_4, | ||
208 | 4, 15, 1, ssm2518_expander_tlv), | ||
209 | SOC_SINGLE_TLV("DRC Noise Gate Threshold Volume", | ||
210 | SSM2518_REG_DRC_4, 0, 15, 1, ssm2518_noise_gate_tlv), | ||
211 | SOC_SINGLE_TLV("DRC Upper Output Threshold Volume", | ||
212 | SSM2518_REG_DRC_5, 4, 15, 1, ssm2518_limiter_tlv), | ||
213 | SOC_SINGLE_TLV("DRC Lower Output Threshold Volume", | ||
214 | SSM2518_REG_DRC_5, 0, 15, 1, ssm2518_noise_gate_tlv), | ||
215 | SOC_SINGLE_TLV("DRC Post Volume", SSM2518_REG_DRC_8, | ||
216 | 2, 15, 1, ssm2518_post_drc_tlv), | ||
217 | |||
218 | SOC_ENUM("DRC Peak Detector Attack Time", | ||
219 | ssm2518_drc_peak_detector_attack_time_enum), | ||
220 | SOC_ENUM("DRC Peak Detector Release Time", | ||
221 | ssm2518_drc_peak_detector_release_time_enum), | ||
222 | SOC_ENUM("DRC Attack Time", ssm2518_drc_attack_time_enum), | ||
223 | SOC_ENUM("DRC Decay Time", ssm2518_drc_decay_time_enum), | ||
224 | SOC_ENUM("DRC Hold Time", ssm2518_drc_hold_time_enum), | ||
225 | SOC_ENUM("DRC Noise Gate Hold Time", | ||
226 | ssm2518_drc_noise_gate_hold_time_enum), | ||
227 | SOC_ENUM("DRC RMS Averaging Time", ssm2518_drc_rms_averaging_time_enum), | ||
228 | }; | ||
229 | |||
230 | static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = { | ||
231 | SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1), | ||
232 | SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1), | ||
233 | |||
234 | SND_SOC_DAPM_OUTPUT("OUTL"), | ||
235 | SND_SOC_DAPM_OUTPUT("OUTR"), | ||
236 | }; | ||
237 | |||
238 | static const struct snd_soc_dapm_route ssm2518_routes[] = { | ||
239 | { "OUTL", NULL, "DACL" }, | ||
240 | { "OUTR", NULL, "DACR" }, | ||
241 | }; | ||
242 | |||
243 | struct ssm2518_mcs_lut { | ||
244 | unsigned int rate; | ||
245 | const unsigned int *sysclks; | ||
246 | }; | ||
247 | |||
248 | static const unsigned int ssm2518_sysclks_2048000[] = { | ||
249 | 2048000, 4096000, 8192000, 12288000, 16384000, 24576000, | ||
250 | 3200000, 6400000, 12800000, 0 | ||
251 | }; | ||
252 | |||
253 | static const unsigned int ssm2518_sysclks_2822000[] = { | ||
254 | 2822000, 5644800, 11289600, 16934400, 22579200, 33868800, | ||
255 | 4410000, 8820000, 17640000, 0 | ||
256 | }; | ||
257 | |||
258 | static const unsigned int ssm2518_sysclks_3072000[] = { | ||
259 | 3072000, 6144000, 12288000, 16384000, 24576000, 38864000, | ||
260 | 4800000, 9600000, 19200000, 0 | ||
261 | }; | ||
262 | |||
263 | static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = { | ||
264 | { 8000, ssm2518_sysclks_2048000, }, | ||
265 | { 11025, ssm2518_sysclks_2822000, }, | ||
266 | { 12000, ssm2518_sysclks_3072000, }, | ||
267 | { 16000, ssm2518_sysclks_2048000, }, | ||
268 | { 24000, ssm2518_sysclks_3072000, }, | ||
269 | { 22050, ssm2518_sysclks_2822000, }, | ||
270 | { 32000, ssm2518_sysclks_2048000, }, | ||
271 | { 44100, ssm2518_sysclks_2822000, }, | ||
272 | { 48000, ssm2518_sysclks_3072000, }, | ||
273 | { 96000, ssm2518_sysclks_3072000, }, | ||
274 | }; | ||
275 | |||
276 | static const unsigned int ssm2518_rates_2048000[] = { | ||
277 | 8000, 16000, 32000, | ||
278 | }; | ||
279 | |||
280 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = { | ||
281 | .list = ssm2518_rates_2048000, | ||
282 | .count = ARRAY_SIZE(ssm2518_rates_2048000), | ||
283 | }; | ||
284 | |||
285 | static const unsigned int ssm2518_rates_2822000[] = { | ||
286 | 11025, 22050, 44100, | ||
287 | }; | ||
288 | |||
289 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = { | ||
290 | .list = ssm2518_rates_2822000, | ||
291 | .count = ARRAY_SIZE(ssm2518_rates_2822000), | ||
292 | }; | ||
293 | |||
294 | static const unsigned int ssm2518_rates_3072000[] = { | ||
295 | 12000, 24000, 48000, 96000, | ||
296 | }; | ||
297 | |||
298 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = { | ||
299 | .list = ssm2518_rates_3072000, | ||
300 | .count = ARRAY_SIZE(ssm2518_rates_3072000), | ||
301 | }; | ||
302 | |||
303 | static const unsigned int ssm2518_rates_12288000[] = { | ||
304 | 8000, 12000, 16000, 24000, 32000, 48000, 96000, | ||
305 | }; | ||
306 | |||
307 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = { | ||
308 | .list = ssm2518_rates_12288000, | ||
309 | .count = ARRAY_SIZE(ssm2518_rates_12288000), | ||
310 | }; | ||
311 | |||
312 | static unsigned int ssm2518_lookup_mcs(struct ssm2518 *ssm2518, | ||
313 | unsigned int rate) | ||
314 | { | ||
315 | const unsigned int *sysclks = NULL; | ||
316 | int i; | ||
317 | |||
318 | for (i = 0; i < ARRAY_SIZE(ssm2518_mcs_lut); i++) { | ||
319 | if (ssm2518_mcs_lut[i].rate == rate) { | ||
320 | sysclks = ssm2518_mcs_lut[i].sysclks; | ||
321 | break; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | if (!sysclks) | ||
326 | return -EINVAL; | ||
327 | |||
328 | for (i = 0; sysclks[i]; i++) { | ||
329 | if (sysclks[i] == ssm2518->sysclk) | ||
330 | return i; | ||
331 | } | ||
332 | |||
333 | return -EINVAL; | ||
334 | } | ||
335 | |||
336 | static int ssm2518_hw_params(struct snd_pcm_substream *substream, | ||
337 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
338 | { | ||
339 | struct snd_soc_codec *codec = dai->codec; | ||
340 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); | ||
341 | unsigned int rate = params_rate(params); | ||
342 | unsigned int ctrl1, ctrl1_mask; | ||
343 | int mcs; | ||
344 | int ret; | ||
345 | |||
346 | mcs = ssm2518_lookup_mcs(ssm2518, rate); | ||
347 | if (mcs < 0) | ||
348 | return mcs; | ||
349 | |||
350 | ctrl1_mask = SSM2518_SAI_CTRL1_FS_MASK; | ||
351 | |||
352 | if (rate >= 8000 && rate <= 12000) | ||
353 | ctrl1 = SSM2518_SAI_CTRL1_FS_8000_12000; | ||
354 | else if (rate >= 16000 && rate <= 24000) | ||
355 | ctrl1 = SSM2518_SAI_CTRL1_FS_16000_24000; | ||
356 | else if (rate >= 32000 && rate <= 48000) | ||
357 | ctrl1 = SSM2518_SAI_CTRL1_FS_32000_48000; | ||
358 | else if (rate >= 64000 && rate <= 96000) | ||
359 | ctrl1 = SSM2518_SAI_CTRL1_FS_64000_96000; | ||
360 | else | ||
361 | return -EINVAL; | ||
362 | |||
363 | if (ssm2518->right_j) { | ||
364 | switch (params_format(params)) { | ||
365 | case SNDRV_PCM_FORMAT_S16_LE: | ||
366 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT; | ||
367 | break; | ||
368 | case SNDRV_PCM_FORMAT_S24_LE: | ||
369 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT; | ||
370 | break; | ||
371 | default: | ||
372 | return -EINVAL; | ||
373 | } | ||
374 | ctrl1_mask |= SSM2518_SAI_CTRL1_FMT_MASK; | ||
375 | } | ||
376 | |||
377 | /* Disable auto samplerate detection */ | ||
378 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_CLOCK, | ||
379 | SSM2518_CLOCK_ASR, SSM2518_CLOCK_ASR); | ||
380 | if (ret < 0) | ||
381 | return ret; | ||
382 | |||
383 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, | ||
384 | ctrl1_mask, ctrl1); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1, | ||
389 | SSM2518_POWER1_MCS_MASK, mcs << 1); | ||
390 | } | ||
391 | |||
392 | static int ssm2518_mute(struct snd_soc_dai *dai, int mute) | ||
393 | { | ||
394 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec); | ||
395 | unsigned int val; | ||
396 | |||
397 | if (mute) | ||
398 | val = SSM2518_MUTE_CTRL_MUTE_MASTER; | ||
399 | else | ||
400 | val = 0; | ||
401 | |||
402 | return regmap_update_bits(ssm2518->regmap, SSM2518_REG_MUTE_CTRL, | ||
403 | SSM2518_MUTE_CTRL_MUTE_MASTER, val); | ||
404 | } | ||
405 | |||
406 | static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
407 | { | ||
408 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec); | ||
409 | unsigned int ctrl1 = 0, ctrl2 = 0; | ||
410 | bool invert_fclk; | ||
411 | int ret; | ||
412 | |||
413 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
414 | case SND_SOC_DAIFMT_CBS_CFS: | ||
415 | break; | ||
416 | default: | ||
417 | return -EINVAL; | ||
418 | } | ||
419 | |||
420 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
421 | case SND_SOC_DAIFMT_NB_NF: | ||
422 | invert_fclk = false; | ||
423 | break; | ||
424 | case SND_SOC_DAIFMT_IB_NF: | ||
425 | ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT; | ||
426 | invert_fclk = false; | ||
427 | break; | ||
428 | case SND_SOC_DAIFMT_NB_IF: | ||
429 | invert_fclk = true; | ||
430 | break; | ||
431 | case SND_SOC_DAIFMT_IB_IF: | ||
432 | ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT; | ||
433 | invert_fclk = true; | ||
434 | break; | ||
435 | default: | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | |||
439 | ssm2518->right_j = false; | ||
440 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
441 | case SND_SOC_DAIFMT_I2S: | ||
442 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S; | ||
443 | break; | ||
444 | case SND_SOC_DAIFMT_LEFT_J: | ||
445 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ; | ||
446 | invert_fclk = !invert_fclk; | ||
447 | break; | ||
448 | case SND_SOC_DAIFMT_RIGHT_J: | ||
449 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT; | ||
450 | ssm2518->right_j = true; | ||
451 | invert_fclk = !invert_fclk; | ||
452 | break; | ||
453 | case SND_SOC_DAIFMT_DSP_A: | ||
454 | ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE; | ||
455 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S; | ||
456 | invert_fclk = false; | ||
457 | break; | ||
458 | case SND_SOC_DAIFMT_DSP_B: | ||
459 | ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE; | ||
460 | ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ; | ||
461 | invert_fclk = false; | ||
462 | break; | ||
463 | default: | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | |||
467 | if (invert_fclk) | ||
468 | ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_INVERT; | ||
469 | |||
470 | ret = regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, ctrl1); | ||
471 | if (ret) | ||
472 | return ret; | ||
473 | |||
474 | return regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, ctrl2); | ||
475 | } | ||
476 | |||
477 | static int ssm2518_set_power(struct ssm2518 *ssm2518, bool enable) | ||
478 | { | ||
479 | int ret = 0; | ||
480 | |||
481 | if (!enable) { | ||
482 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1, | ||
483 | SSM2518_POWER1_SPWDN, SSM2518_POWER1_SPWDN); | ||
484 | regcache_mark_dirty(ssm2518->regmap); | ||
485 | } | ||
486 | |||
487 | if (gpio_is_valid(ssm2518->enable_gpio)) | ||
488 | gpio_set_value(ssm2518->enable_gpio, enable); | ||
489 | |||
490 | regcache_cache_only(ssm2518->regmap, !enable); | ||
491 | |||
492 | if (enable) { | ||
493 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1, | ||
494 | SSM2518_POWER1_SPWDN | SSM2518_POWER1_RESET, 0x00); | ||
495 | regcache_sync(ssm2518->regmap); | ||
496 | } | ||
497 | |||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | static int ssm2518_set_bias_level(struct snd_soc_codec *codec, | ||
502 | enum snd_soc_bias_level level) | ||
503 | { | ||
504 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); | ||
505 | int ret = 0; | ||
506 | |||
507 | switch (level) { | ||
508 | case SND_SOC_BIAS_ON: | ||
509 | break; | ||
510 | case SND_SOC_BIAS_PREPARE: | ||
511 | break; | ||
512 | case SND_SOC_BIAS_STANDBY: | ||
513 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
514 | ret = ssm2518_set_power(ssm2518, true); | ||
515 | break; | ||
516 | case SND_SOC_BIAS_OFF: | ||
517 | ret = ssm2518_set_power(ssm2518, false); | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | if (ret) | ||
522 | return ret; | ||
523 | |||
524 | codec->dapm.bias_level = level; | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
530 | unsigned int rx_mask, int slots, int width) | ||
531 | { | ||
532 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec); | ||
533 | unsigned int ctrl1, ctrl2; | ||
534 | int left_slot, right_slot; | ||
535 | int ret; | ||
536 | |||
537 | if (slots == 0) | ||
538 | return regmap_update_bits(ssm2518->regmap, | ||
539 | SSM2518_REG_SAI_CTRL1, SSM2518_SAI_CTRL1_SAI_MASK, | ||
540 | SSM2518_SAI_CTRL1_SAI_I2S); | ||
541 | |||
542 | if (tx_mask == 0 || rx_mask != 0) | ||
543 | return -EINVAL; | ||
544 | |||
545 | if (slots == 1) { | ||
546 | if (tx_mask != 1) | ||
547 | return -EINVAL; | ||
548 | left_slot = 0; | ||
549 | right_slot = 0; | ||
550 | } else { | ||
551 | /* We assume the left channel < right channel */ | ||
552 | left_slot = ffs(tx_mask); | ||
553 | tx_mask &= ~(1 << tx_mask); | ||
554 | if (tx_mask == 0) { | ||
555 | right_slot = left_slot; | ||
556 | } else { | ||
557 | right_slot = ffs(tx_mask); | ||
558 | tx_mask &= ~(1 << tx_mask); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) | ||
563 | return -EINVAL; | ||
564 | |||
565 | switch (width) { | ||
566 | case 16: | ||
567 | ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_16; | ||
568 | break; | ||
569 | case 24: | ||
570 | ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_24; | ||
571 | break; | ||
572 | case 32: | ||
573 | ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_32; | ||
574 | break; | ||
575 | default: | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | switch (slots) { | ||
580 | case 1: | ||
581 | ctrl1 = SSM2518_SAI_CTRL1_SAI_MONO; | ||
582 | break; | ||
583 | case 2: | ||
584 | ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_2; | ||
585 | break; | ||
586 | case 4: | ||
587 | ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_4; | ||
588 | break; | ||
589 | case 8: | ||
590 | ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_8; | ||
591 | break; | ||
592 | case 16: | ||
593 | ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_16; | ||
594 | break; | ||
595 | default: | ||
596 | return -EINVAL; | ||
597 | } | ||
598 | |||
599 | ret = regmap_write(ssm2518->regmap, SSM2518_REG_CHAN_MAP, | ||
600 | (left_slot << SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET) | | ||
601 | (right_slot << SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET)); | ||
602 | if (ret) | ||
603 | return ret; | ||
604 | |||
605 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, | ||
606 | SSM2518_SAI_CTRL1_SAI_MASK, ctrl1); | ||
607 | if (ret) | ||
608 | return ret; | ||
609 | |||
610 | return regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, | ||
611 | SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK, ctrl2); | ||
612 | } | ||
613 | |||
614 | static int ssm2518_startup(struct snd_pcm_substream *substream, | ||
615 | struct snd_soc_dai *dai) | ||
616 | { | ||
617 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec); | ||
618 | |||
619 | if (ssm2518->constraints) | ||
620 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
621 | SNDRV_PCM_HW_PARAM_RATE, ssm2518->constraints); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | #define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
627 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32) | ||
628 | |||
629 | static const struct snd_soc_dai_ops ssm2518_dai_ops = { | ||
630 | .startup = ssm2518_startup, | ||
631 | .hw_params = ssm2518_hw_params, | ||
632 | .digital_mute = ssm2518_mute, | ||
633 | .set_fmt = ssm2518_set_dai_fmt, | ||
634 | .set_tdm_slot = ssm2518_set_tdm_slot, | ||
635 | }; | ||
636 | |||
637 | static struct snd_soc_dai_driver ssm2518_dai = { | ||
638 | .name = "ssm2518-hifi", | ||
639 | .playback = { | ||
640 | .stream_name = "Playback", | ||
641 | .channels_min = 2, | ||
642 | .channels_max = 2, | ||
643 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
644 | .formats = SSM2518_FORMATS, | ||
645 | }, | ||
646 | .ops = &ssm2518_dai_ops, | ||
647 | }; | ||
648 | |||
649 | static int ssm2518_probe(struct snd_soc_codec *codec) | ||
650 | { | ||
651 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); | ||
652 | int ret; | ||
653 | |||
654 | codec->control_data = ssm2518->regmap; | ||
655 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
656 | if (ret < 0) { | ||
657 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
662 | } | ||
663 | |||
664 | static int ssm2518_remove(struct snd_soc_codec *codec) | ||
665 | { | ||
666 | ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
671 | int source, unsigned int freq, int dir) | ||
672 | { | ||
673 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); | ||
674 | unsigned int val; | ||
675 | |||
676 | if (clk_id != SSM2518_SYSCLK) | ||
677 | return -EINVAL; | ||
678 | |||
679 | switch (source) { | ||
680 | case SSM2518_SYSCLK_SRC_MCLK: | ||
681 | val = 0; | ||
682 | break; | ||
683 | case SSM2518_SYSCLK_SRC_BCLK: | ||
684 | /* In this case the bitclock is used as the system clock, and | ||
685 | * the bitclock signal needs to be connected to the MCLK pin and | ||
686 | * the BCLK pin is left unconnected */ | ||
687 | val = SSM2518_POWER1_NO_BCLK; | ||
688 | break; | ||
689 | default: | ||
690 | return -EINVAL; | ||
691 | } | ||
692 | |||
693 | switch (freq) { | ||
694 | case 0: | ||
695 | ssm2518->constraints = NULL; | ||
696 | break; | ||
697 | case 2048000: | ||
698 | case 4096000: | ||
699 | case 8192000: | ||
700 | case 3200000: | ||
701 | case 6400000: | ||
702 | case 12800000: | ||
703 | ssm2518->constraints = &ssm2518_constraints_2048000; | ||
704 | break; | ||
705 | case 2822000: | ||
706 | case 5644800: | ||
707 | case 11289600: | ||
708 | case 16934400: | ||
709 | case 22579200: | ||
710 | case 33868800: | ||
711 | case 4410000: | ||
712 | case 8820000: | ||
713 | case 17640000: | ||
714 | ssm2518->constraints = &ssm2518_constraints_2822000; | ||
715 | break; | ||
716 | case 3072000: | ||
717 | case 6144000: | ||
718 | case 38864000: | ||
719 | case 4800000: | ||
720 | case 9600000: | ||
721 | case 19200000: | ||
722 | ssm2518->constraints = &ssm2518_constraints_3072000; | ||
723 | break; | ||
724 | case 12288000: | ||
725 | case 16384000: | ||
726 | case 24576000: | ||
727 | ssm2518->constraints = &ssm2518_constraints_12288000; | ||
728 | break; | ||
729 | default: | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | |||
733 | ssm2518->sysclk = freq; | ||
734 | |||
735 | return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1, | ||
736 | SSM2518_POWER1_NO_BCLK, val); | ||
737 | } | ||
738 | |||
739 | static struct snd_soc_codec_driver ssm2518_codec_driver = { | ||
740 | .probe = ssm2518_probe, | ||
741 | .remove = ssm2518_remove, | ||
742 | .set_bias_level = ssm2518_set_bias_level, | ||
743 | .set_sysclk = ssm2518_set_sysclk, | ||
744 | .idle_bias_off = true, | ||
745 | |||
746 | .controls = ssm2518_snd_controls, | ||
747 | .num_controls = ARRAY_SIZE(ssm2518_snd_controls), | ||
748 | .dapm_widgets = ssm2518_dapm_widgets, | ||
749 | .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets), | ||
750 | .dapm_routes = ssm2518_routes, | ||
751 | .num_dapm_routes = ARRAY_SIZE(ssm2518_routes), | ||
752 | }; | ||
753 | |||
754 | static bool ssm2518_register_volatile(struct device *dev, unsigned int reg) | ||
755 | { | ||
756 | return false; | ||
757 | } | ||
758 | |||
759 | static const struct regmap_config ssm2518_regmap_config = { | ||
760 | .val_bits = 8, | ||
761 | .reg_bits = 8, | ||
762 | |||
763 | .max_register = SSM2518_REG_DRC_9, | ||
764 | .volatile_reg = ssm2518_register_volatile, | ||
765 | |||
766 | .cache_type = REGCACHE_RBTREE, | ||
767 | .reg_defaults = ssm2518_reg_defaults, | ||
768 | .num_reg_defaults = ARRAY_SIZE(ssm2518_reg_defaults), | ||
769 | }; | ||
770 | |||
771 | static int ssm2518_i2c_probe(struct i2c_client *i2c, | ||
772 | const struct i2c_device_id *id) | ||
773 | { | ||
774 | struct ssm2518_platform_data *pdata = i2c->dev.platform_data; | ||
775 | struct ssm2518 *ssm2518; | ||
776 | int ret; | ||
777 | |||
778 | ssm2518 = devm_kzalloc(&i2c->dev, sizeof(*ssm2518), GFP_KERNEL); | ||
779 | if (ssm2518 == NULL) | ||
780 | return -ENOMEM; | ||
781 | |||
782 | if (pdata) { | ||
783 | ssm2518->enable_gpio = pdata->enable_gpio; | ||
784 | } else if (i2c->dev.of_node) { | ||
785 | ssm2518->enable_gpio = of_get_gpio(i2c->dev.of_node, 0); | ||
786 | if (ssm2518->enable_gpio < 0 && ssm2518->enable_gpio != -ENOENT) | ||
787 | return ssm2518->enable_gpio; | ||
788 | } else { | ||
789 | ssm2518->enable_gpio = -1; | ||
790 | } | ||
791 | |||
792 | if (gpio_is_valid(ssm2518->enable_gpio)) { | ||
793 | ret = devm_gpio_request_one(&i2c->dev, ssm2518->enable_gpio, | ||
794 | GPIOF_OUT_INIT_HIGH, "SSM2518 nSD"); | ||
795 | if (ret) | ||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | i2c_set_clientdata(i2c, ssm2518); | ||
800 | |||
801 | ssm2518->regmap = devm_regmap_init_i2c(i2c, &ssm2518_regmap_config); | ||
802 | if (IS_ERR(ssm2518->regmap)) | ||
803 | return PTR_ERR(ssm2518->regmap); | ||
804 | |||
805 | /* | ||
806 | * The reset bit is obviously volatile, but we need to be able to cache | ||
807 | * the other bits in the register, so we can't just mark the whole | ||
808 | * register as volatile. Since this is the only place where we'll ever | ||
809 | * touch the reset bit just bypass the cache for this operation. | ||
810 | */ | ||
811 | regcache_cache_bypass(ssm2518->regmap, true); | ||
812 | ret = regmap_write(ssm2518->regmap, SSM2518_REG_POWER1, | ||
813 | SSM2518_POWER1_RESET); | ||
814 | regcache_cache_bypass(ssm2518->regmap, false); | ||
815 | if (ret) | ||
816 | return ret; | ||
817 | |||
818 | ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER2, | ||
819 | SSM2518_POWER2_APWDN, 0x00); | ||
820 | if (ret) | ||
821 | return ret; | ||
822 | |||
823 | ret = ssm2518_set_power(ssm2518, false); | ||
824 | if (ret) | ||
825 | return ret; | ||
826 | |||
827 | return snd_soc_register_codec(&i2c->dev, &ssm2518_codec_driver, | ||
828 | &ssm2518_dai, 1); | ||
829 | } | ||
830 | |||
831 | static int ssm2518_i2c_remove(struct i2c_client *client) | ||
832 | { | ||
833 | snd_soc_unregister_codec(&client->dev); | ||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | static const struct i2c_device_id ssm2518_i2c_ids[] = { | ||
838 | { "ssm2518", 0 }, | ||
839 | { } | ||
840 | }; | ||
841 | MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids); | ||
842 | |||
843 | static struct i2c_driver ssm2518_driver = { | ||
844 | .driver = { | ||
845 | .name = "ssm2518", | ||
846 | .owner = THIS_MODULE, | ||
847 | }, | ||
848 | .probe = ssm2518_i2c_probe, | ||
849 | .remove = ssm2518_i2c_remove, | ||
850 | .id_table = ssm2518_i2c_ids, | ||
851 | }; | ||
852 | module_i2c_driver(ssm2518_driver); | ||
853 | |||
854 | MODULE_DESCRIPTION("ASoC SSM2518 driver"); | ||
855 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
856 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ssm2518.h b/sound/soc/codecs/ssm2518.h new file mode 100644 index 000000000000..62511d80518e --- /dev/null +++ b/sound/soc/codecs/ssm2518.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * SSM2518 amplifier audio driver | ||
3 | * | ||
4 | * Copyright 2013 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #ifndef __SND_SOC_CODECS_SSM2518_H__ | ||
11 | #define __SND_SOC_CODECS_SSM2518_H__ | ||
12 | |||
13 | #define SSM2518_SYSCLK 0 | ||
14 | |||
15 | enum ssm2518_sysclk_src { | ||
16 | SSM2518_SYSCLK_SRC_MCLK = 0, | ||
17 | SSM2518_SYSCLK_SRC_BCLK = 1, | ||
18 | }; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 370af0cbcc9a..f5e835662cdc 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
17 | #include <linux/interrupt.h> | ||
17 | #include <linux/irqreturn.h> | 18 | #include <linux/irqreturn.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
@@ -972,6 +973,13 @@ static int wm0010_spi_probe(struct spi_device *spi) | |||
972 | } | 973 | } |
973 | wm0010->irq = irq; | 974 | wm0010->irq = irq; |
974 | 975 | ||
976 | ret = irq_set_irq_wake(irq, 1); | ||
977 | if (ret) { | ||
978 | dev_err(wm0010->dev, "Failed to set IRQ %d as wake source: %d\n", | ||
979 | irq, ret); | ||
980 | return ret; | ||
981 | } | ||
982 | |||
975 | if (spi->max_speed_hz) | 983 | if (spi->max_speed_hz) |
976 | wm0010->board_max_spi_speed = spi->max_speed_hz; | 984 | wm0010->board_max_spi_speed = spi->max_speed_hz; |
977 | else | 985 | else |
@@ -995,6 +1003,8 @@ static int wm0010_spi_remove(struct spi_device *spi) | |||
995 | gpio_set_value_cansleep(wm0010->gpio_reset, | 1003 | gpio_set_value_cansleep(wm0010->gpio_reset, |
996 | wm0010->gpio_reset_value); | 1004 | wm0010->gpio_reset_value); |
997 | 1005 | ||
1006 | irq_set_irq_wake(wm0010->irq, 0); | ||
1007 | |||
998 | if (wm0010->irq) | 1008 | if (wm0010->irq) |
999 | free_irq(wm0010->irq, wm0010); | 1009 | free_irq(wm0010->irq, wm0010); |
1000 | 1010 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 100fdadda56a..282fd232cdf7 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -814,7 +814,20 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |||
814 | 814 | ||
815 | SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), | 815 | SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), |
816 | SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), | 816 | SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), |
817 | SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]), | 817 | SOC_VALUE_ENUM("EPOUT OSR", wm5102_hpout_osr[2]), |
818 | |||
819 | SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, | ||
820 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0), | ||
821 | SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, | ||
822 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0), | ||
823 | SOC_SINGLE("EPOUT DRE Switch", ARIZONA_DRE_ENABLE, | ||
824 | ARIZONA_DRE3L_ENA_SHIFT, 1, 0), | ||
825 | |||
826 | SOC_SINGLE("DRE Threshold", ARIZONA_DRE_CONTROL_2, | ||
827 | ARIZONA_DRE_T_LOW_SHIFT, 63, 0), | ||
828 | |||
829 | SOC_SINGLE("DRE Low Level ABS", ARIZONA_DRE_CONTROL_3, | ||
830 | ARIZONA_DRE_LOW_LEVEL_ABS_SHIFT, 15, 0), | ||
818 | 831 | ||
819 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 832 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
820 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 833 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
@@ -852,6 +865,15 @@ ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | |||
852 | 865 | ||
853 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 866 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
854 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 867 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
868 | |||
869 | ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
870 | ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
871 | ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
872 | ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
873 | ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
874 | ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
875 | ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
876 | ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
855 | }; | 877 | }; |
856 | 878 | ||
857 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | 879 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); |
@@ -898,6 +920,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
898 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 920 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
899 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 921 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
900 | 922 | ||
923 | ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
924 | ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
925 | ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
926 | ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
927 | ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
928 | ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
929 | ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
930 | ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
931 | |||
901 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 932 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
902 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 933 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
903 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 934 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
@@ -1117,6 +1148,56 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
1117 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 1148 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, |
1118 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 1149 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
1119 | 1150 | ||
1151 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
1152 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1153 | ARIZONA_SLIMTX1_ENA_SHIFT, 0), | ||
1154 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
1155 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1156 | ARIZONA_SLIMTX2_ENA_SHIFT, 0), | ||
1157 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
1158 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1159 | ARIZONA_SLIMTX3_ENA_SHIFT, 0), | ||
1160 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
1161 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1162 | ARIZONA_SLIMTX4_ENA_SHIFT, 0), | ||
1163 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
1164 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1165 | ARIZONA_SLIMTX5_ENA_SHIFT, 0), | ||
1166 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
1167 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1168 | ARIZONA_SLIMTX6_ENA_SHIFT, 0), | ||
1169 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
1170 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1171 | ARIZONA_SLIMTX7_ENA_SHIFT, 0), | ||
1172 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
1173 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1174 | ARIZONA_SLIMTX8_ENA_SHIFT, 0), | ||
1175 | |||
1176 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | ||
1177 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1178 | ARIZONA_SLIMRX1_ENA_SHIFT, 0), | ||
1179 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, | ||
1180 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1181 | ARIZONA_SLIMRX2_ENA_SHIFT, 0), | ||
1182 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, | ||
1183 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1184 | ARIZONA_SLIMRX3_ENA_SHIFT, 0), | ||
1185 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, | ||
1186 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1187 | ARIZONA_SLIMRX4_ENA_SHIFT, 0), | ||
1188 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, | ||
1189 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1190 | ARIZONA_SLIMRX5_ENA_SHIFT, 0), | ||
1191 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, | ||
1192 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1193 | ARIZONA_SLIMRX6_ENA_SHIFT, 0), | ||
1194 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, | ||
1195 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1196 | ARIZONA_SLIMRX7_ENA_SHIFT, 0), | ||
1197 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, | ||
1198 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1199 | ARIZONA_SLIMRX8_ENA_SHIFT, 0), | ||
1200 | |||
1120 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), | 1201 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), |
1121 | 1202 | ||
1122 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | 1203 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, |
@@ -1189,6 +1270,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
1189 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 1270 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
1190 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 1271 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
1191 | 1272 | ||
1273 | ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
1274 | ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
1275 | ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
1276 | ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
1277 | ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
1278 | ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
1279 | ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
1280 | ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
1281 | |||
1192 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), | 1282 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
1193 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | 1283 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
1194 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 1284 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
@@ -1249,6 +1339,14 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
1249 | { name, "AIF2RX2", "AIF2RX2" }, \ | 1339 | { name, "AIF2RX2", "AIF2RX2" }, \ |
1250 | { name, "AIF3RX1", "AIF3RX1" }, \ | 1340 | { name, "AIF3RX1", "AIF3RX1" }, \ |
1251 | { name, "AIF3RX2", "AIF3RX2" }, \ | 1341 | { name, "AIF3RX2", "AIF3RX2" }, \ |
1342 | { name, "SLIMRX1", "SLIMRX1" }, \ | ||
1343 | { name, "SLIMRX2", "SLIMRX2" }, \ | ||
1344 | { name, "SLIMRX3", "SLIMRX3" }, \ | ||
1345 | { name, "SLIMRX4", "SLIMRX4" }, \ | ||
1346 | { name, "SLIMRX5", "SLIMRX5" }, \ | ||
1347 | { name, "SLIMRX6", "SLIMRX6" }, \ | ||
1348 | { name, "SLIMRX7", "SLIMRX7" }, \ | ||
1349 | { name, "SLIMRX8", "SLIMRX8" }, \ | ||
1252 | { name, "EQ1", "EQ1" }, \ | 1350 | { name, "EQ1", "EQ1" }, \ |
1253 | { name, "EQ2", "EQ2" }, \ | 1351 | { name, "EQ2", "EQ2" }, \ |
1254 | { name, "EQ3", "EQ3" }, \ | 1352 | { name, "EQ3", "EQ3" }, \ |
@@ -1304,10 +1402,21 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
1304 | { "OUT5L", NULL, "SYSCLK" }, | 1402 | { "OUT5L", NULL, "SYSCLK" }, |
1305 | { "OUT5R", NULL, "SYSCLK" }, | 1403 | { "OUT5R", NULL, "SYSCLK" }, |
1306 | 1404 | ||
1405 | { "IN1L", NULL, "SYSCLK" }, | ||
1406 | { "IN1R", NULL, "SYSCLK" }, | ||
1407 | { "IN2L", NULL, "SYSCLK" }, | ||
1408 | { "IN2R", NULL, "SYSCLK" }, | ||
1409 | { "IN3L", NULL, "SYSCLK" }, | ||
1410 | { "IN3R", NULL, "SYSCLK" }, | ||
1411 | |||
1307 | { "MICBIAS1", NULL, "MICVDD" }, | 1412 | { "MICBIAS1", NULL, "MICVDD" }, |
1308 | { "MICBIAS2", NULL, "MICVDD" }, | 1413 | { "MICBIAS2", NULL, "MICVDD" }, |
1309 | { "MICBIAS3", NULL, "MICVDD" }, | 1414 | { "MICBIAS3", NULL, "MICVDD" }, |
1310 | 1415 | ||
1416 | { "Noise Generator", NULL, "SYSCLK" }, | ||
1417 | { "Tone Generator 1", NULL, "SYSCLK" }, | ||
1418 | { "Tone Generator 2", NULL, "SYSCLK" }, | ||
1419 | |||
1311 | { "Noise Generator", NULL, "NOISE" }, | 1420 | { "Noise Generator", NULL, "NOISE" }, |
1312 | { "Tone Generator 1", NULL, "TONE" }, | 1421 | { "Tone Generator 1", NULL, "TONE" }, |
1313 | { "Tone Generator 2", NULL, "TONE" }, | 1422 | { "Tone Generator 2", NULL, "TONE" }, |
@@ -1345,13 +1454,41 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
1345 | { "AIF3RX1", NULL, "AIF3 Playback" }, | 1454 | { "AIF3RX1", NULL, "AIF3 Playback" }, |
1346 | { "AIF3RX2", NULL, "AIF3 Playback" }, | 1455 | { "AIF3RX2", NULL, "AIF3 Playback" }, |
1347 | 1456 | ||
1457 | { "Slim1 Capture", NULL, "SLIMTX1" }, | ||
1458 | { "Slim1 Capture", NULL, "SLIMTX2" }, | ||
1459 | { "Slim1 Capture", NULL, "SLIMTX3" }, | ||
1460 | { "Slim1 Capture", NULL, "SLIMTX4" }, | ||
1461 | |||
1462 | { "SLIMRX1", NULL, "Slim1 Playback" }, | ||
1463 | { "SLIMRX2", NULL, "Slim1 Playback" }, | ||
1464 | { "SLIMRX3", NULL, "Slim1 Playback" }, | ||
1465 | { "SLIMRX4", NULL, "Slim1 Playback" }, | ||
1466 | |||
1467 | { "Slim2 Capture", NULL, "SLIMTX5" }, | ||
1468 | { "Slim2 Capture", NULL, "SLIMTX6" }, | ||
1469 | |||
1470 | { "SLIMRX5", NULL, "Slim2 Playback" }, | ||
1471 | { "SLIMRX6", NULL, "Slim2 Playback" }, | ||
1472 | |||
1473 | { "Slim3 Capture", NULL, "SLIMTX7" }, | ||
1474 | { "Slim3 Capture", NULL, "SLIMTX8" }, | ||
1475 | |||
1476 | { "SLIMRX7", NULL, "Slim3 Playback" }, | ||
1477 | { "SLIMRX8", NULL, "Slim3 Playback" }, | ||
1478 | |||
1348 | { "AIF1 Playback", NULL, "SYSCLK" }, | 1479 | { "AIF1 Playback", NULL, "SYSCLK" }, |
1349 | { "AIF2 Playback", NULL, "SYSCLK" }, | 1480 | { "AIF2 Playback", NULL, "SYSCLK" }, |
1350 | { "AIF3 Playback", NULL, "SYSCLK" }, | 1481 | { "AIF3 Playback", NULL, "SYSCLK" }, |
1482 | { "Slim1 Playback", NULL, "SYSCLK" }, | ||
1483 | { "Slim2 Playback", NULL, "SYSCLK" }, | ||
1484 | { "Slim3 Playback", NULL, "SYSCLK" }, | ||
1351 | 1485 | ||
1352 | { "AIF1 Capture", NULL, "SYSCLK" }, | 1486 | { "AIF1 Capture", NULL, "SYSCLK" }, |
1353 | { "AIF2 Capture", NULL, "SYSCLK" }, | 1487 | { "AIF2 Capture", NULL, "SYSCLK" }, |
1354 | { "AIF3 Capture", NULL, "SYSCLK" }, | 1488 | { "AIF3 Capture", NULL, "SYSCLK" }, |
1489 | { "Slim1 Capture", NULL, "SYSCLK" }, | ||
1490 | { "Slim2 Capture", NULL, "SYSCLK" }, | ||
1491 | { "Slim3 Capture", NULL, "SYSCLK" }, | ||
1355 | 1492 | ||
1356 | { "IN1L PGA", NULL, "IN1L" }, | 1493 | { "IN1L PGA", NULL, "IN1L" }, |
1357 | { "IN1R PGA", NULL, "IN1R" }, | 1494 | { "IN1R PGA", NULL, "IN1R" }, |
@@ -1408,6 +1545,15 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
1408 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | 1545 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), |
1409 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | 1546 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), |
1410 | 1547 | ||
1548 | ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), | ||
1549 | ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), | ||
1550 | ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), | ||
1551 | ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), | ||
1552 | ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), | ||
1553 | ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), | ||
1554 | ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), | ||
1555 | ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), | ||
1556 | |||
1411 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | 1557 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), |
1412 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | 1558 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), |
1413 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | 1559 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), |
@@ -1560,6 +1706,63 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1560 | .ops = &arizona_dai_ops, | 1706 | .ops = &arizona_dai_ops, |
1561 | .symmetric_rates = 1, | 1707 | .symmetric_rates = 1, |
1562 | }, | 1708 | }, |
1709 | { | ||
1710 | .name = "wm5102-slim1", | ||
1711 | .id = 4, | ||
1712 | .playback = { | ||
1713 | .stream_name = "Slim1 Playback", | ||
1714 | .channels_min = 1, | ||
1715 | .channels_max = 4, | ||
1716 | .rates = WM5102_RATES, | ||
1717 | .formats = WM5102_FORMATS, | ||
1718 | }, | ||
1719 | .capture = { | ||
1720 | .stream_name = "Slim1 Capture", | ||
1721 | .channels_min = 1, | ||
1722 | .channels_max = 4, | ||
1723 | .rates = WM5102_RATES, | ||
1724 | .formats = WM5102_FORMATS, | ||
1725 | }, | ||
1726 | .ops = &arizona_simple_dai_ops, | ||
1727 | }, | ||
1728 | { | ||
1729 | .name = "wm5102-slim2", | ||
1730 | .id = 5, | ||
1731 | .playback = { | ||
1732 | .stream_name = "Slim2 Playback", | ||
1733 | .channels_min = 1, | ||
1734 | .channels_max = 2, | ||
1735 | .rates = WM5102_RATES, | ||
1736 | .formats = WM5102_FORMATS, | ||
1737 | }, | ||
1738 | .capture = { | ||
1739 | .stream_name = "Slim2 Capture", | ||
1740 | .channels_min = 1, | ||
1741 | .channels_max = 2, | ||
1742 | .rates = WM5102_RATES, | ||
1743 | .formats = WM5102_FORMATS, | ||
1744 | }, | ||
1745 | .ops = &arizona_simple_dai_ops, | ||
1746 | }, | ||
1747 | { | ||
1748 | .name = "wm5102-slim3", | ||
1749 | .id = 6, | ||
1750 | .playback = { | ||
1751 | .stream_name = "Slim3 Playback", | ||
1752 | .channels_min = 1, | ||
1753 | .channels_max = 2, | ||
1754 | .rates = WM5102_RATES, | ||
1755 | .formats = WM5102_FORMATS, | ||
1756 | }, | ||
1757 | .capture = { | ||
1758 | .stream_name = "Slim3 Capture", | ||
1759 | .channels_min = 1, | ||
1760 | .channels_max = 2, | ||
1761 | .rates = WM5102_RATES, | ||
1762 | .formats = WM5102_FORMATS, | ||
1763 | }, | ||
1764 | .ops = &arizona_simple_dai_ops, | ||
1765 | }, | ||
1563 | }; | 1766 | }; |
1564 | 1767 | ||
1565 | static int wm5102_codec_probe(struct snd_soc_codec *codec) | 1768 | static int wm5102_codec_probe(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 88ad7db52dde..2e7cb4ba161a 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -309,6 +309,15 @@ ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | |||
309 | 309 | ||
310 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 310 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
311 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 311 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
312 | |||
313 | ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
314 | ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
315 | ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
316 | ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
317 | ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
318 | ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
319 | ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
320 | ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
312 | }; | 321 | }; |
313 | 322 | ||
314 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | 323 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); |
@@ -360,6 +369,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
360 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 369 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
361 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 370 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
362 | 371 | ||
372 | ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
373 | ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
374 | ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
375 | ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
376 | ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
377 | ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
378 | ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
379 | ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
380 | |||
363 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 381 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
364 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 382 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
365 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 383 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
@@ -550,6 +568,56 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | |||
550 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | 568 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, |
551 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | 569 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), |
552 | 570 | ||
571 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | ||
572 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
573 | ARIZONA_SLIMRX1_ENA_SHIFT, 0), | ||
574 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, | ||
575 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
576 | ARIZONA_SLIMRX2_ENA_SHIFT, 0), | ||
577 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, | ||
578 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
579 | ARIZONA_SLIMRX3_ENA_SHIFT, 0), | ||
580 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, | ||
581 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
582 | ARIZONA_SLIMRX4_ENA_SHIFT, 0), | ||
583 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, | ||
584 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
585 | ARIZONA_SLIMRX5_ENA_SHIFT, 0), | ||
586 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, | ||
587 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
588 | ARIZONA_SLIMRX6_ENA_SHIFT, 0), | ||
589 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, | ||
590 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
591 | ARIZONA_SLIMRX7_ENA_SHIFT, 0), | ||
592 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, | ||
593 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
594 | ARIZONA_SLIMRX8_ENA_SHIFT, 0), | ||
595 | |||
596 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
597 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
598 | ARIZONA_SLIMTX1_ENA_SHIFT, 0), | ||
599 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
600 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
601 | ARIZONA_SLIMTX2_ENA_SHIFT, 0), | ||
602 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
603 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
604 | ARIZONA_SLIMTX3_ENA_SHIFT, 0), | ||
605 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
606 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
607 | ARIZONA_SLIMTX4_ENA_SHIFT, 0), | ||
608 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
609 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
610 | ARIZONA_SLIMTX5_ENA_SHIFT, 0), | ||
611 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
612 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
613 | ARIZONA_SLIMTX6_ENA_SHIFT, 0), | ||
614 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
615 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
616 | ARIZONA_SLIMTX7_ENA_SHIFT, 0), | ||
617 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
618 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
619 | ARIZONA_SLIMTX8_ENA_SHIFT, 0), | ||
620 | |||
553 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | 621 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, |
554 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), | 622 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), |
555 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | 623 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, |
@@ -640,6 +708,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
640 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 708 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
641 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 709 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
642 | 710 | ||
711 | ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
712 | ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
713 | ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
714 | ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
715 | ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
716 | ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
717 | ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
718 | ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
719 | |||
643 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), | 720 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
644 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | 721 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
645 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 722 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
@@ -690,6 +767,14 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), | |||
690 | { name, "AIF2RX2", "AIF2RX2" }, \ | 767 | { name, "AIF2RX2", "AIF2RX2" }, \ |
691 | { name, "AIF3RX1", "AIF3RX1" }, \ | 768 | { name, "AIF3RX1", "AIF3RX1" }, \ |
692 | { name, "AIF3RX2", "AIF3RX2" }, \ | 769 | { name, "AIF3RX2", "AIF3RX2" }, \ |
770 | { name, "SLIMRX1", "SLIMRX1" }, \ | ||
771 | { name, "SLIMRX2", "SLIMRX2" }, \ | ||
772 | { name, "SLIMRX3", "SLIMRX3" }, \ | ||
773 | { name, "SLIMRX4", "SLIMRX4" }, \ | ||
774 | { name, "SLIMRX5", "SLIMRX5" }, \ | ||
775 | { name, "SLIMRX6", "SLIMRX6" }, \ | ||
776 | { name, "SLIMRX7", "SLIMRX7" }, \ | ||
777 | { name, "SLIMRX8", "SLIMRX8" }, \ | ||
693 | { name, "EQ1", "EQ1" }, \ | 778 | { name, "EQ1", "EQ1" }, \ |
694 | { name, "EQ2", "EQ2" }, \ | 779 | { name, "EQ2", "EQ2" }, \ |
695 | { name, "EQ3", "EQ3" }, \ | 780 | { name, "EQ3", "EQ3" }, \ |
@@ -736,10 +821,23 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
736 | { "OUT6L", NULL, "SYSCLK" }, | 821 | { "OUT6L", NULL, "SYSCLK" }, |
737 | { "OUT6R", NULL, "SYSCLK" }, | 822 | { "OUT6R", NULL, "SYSCLK" }, |
738 | 823 | ||
824 | { "IN1L", NULL, "SYSCLK" }, | ||
825 | { "IN1R", NULL, "SYSCLK" }, | ||
826 | { "IN2L", NULL, "SYSCLK" }, | ||
827 | { "IN2R", NULL, "SYSCLK" }, | ||
828 | { "IN3L", NULL, "SYSCLK" }, | ||
829 | { "IN3R", NULL, "SYSCLK" }, | ||
830 | { "IN4L", NULL, "SYSCLK" }, | ||
831 | { "IN4R", NULL, "SYSCLK" }, | ||
832 | |||
739 | { "MICBIAS1", NULL, "MICVDD" }, | 833 | { "MICBIAS1", NULL, "MICVDD" }, |
740 | { "MICBIAS2", NULL, "MICVDD" }, | 834 | { "MICBIAS2", NULL, "MICVDD" }, |
741 | { "MICBIAS3", NULL, "MICVDD" }, | 835 | { "MICBIAS3", NULL, "MICVDD" }, |
742 | 836 | ||
837 | { "Noise Generator", NULL, "SYSCLK" }, | ||
838 | { "Tone Generator 1", NULL, "SYSCLK" }, | ||
839 | { "Tone Generator 2", NULL, "SYSCLK" }, | ||
840 | |||
743 | { "Noise Generator", NULL, "NOISE" }, | 841 | { "Noise Generator", NULL, "NOISE" }, |
744 | { "Tone Generator 1", NULL, "TONE" }, | 842 | { "Tone Generator 1", NULL, "TONE" }, |
745 | { "Tone Generator 2", NULL, "TONE" }, | 843 | { "Tone Generator 2", NULL, "TONE" }, |
@@ -777,13 +875,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
777 | { "AIF3RX1", NULL, "AIF3 Playback" }, | 875 | { "AIF3RX1", NULL, "AIF3 Playback" }, |
778 | { "AIF3RX2", NULL, "AIF3 Playback" }, | 876 | { "AIF3RX2", NULL, "AIF3 Playback" }, |
779 | 877 | ||
878 | { "Slim1 Capture", NULL, "SLIMTX1" }, | ||
879 | { "Slim1 Capture", NULL, "SLIMTX2" }, | ||
880 | { "Slim1 Capture", NULL, "SLIMTX3" }, | ||
881 | { "Slim1 Capture", NULL, "SLIMTX4" }, | ||
882 | |||
883 | { "SLIMRX1", NULL, "Slim1 Playback" }, | ||
884 | { "SLIMRX2", NULL, "Slim1 Playback" }, | ||
885 | { "SLIMRX3", NULL, "Slim1 Playback" }, | ||
886 | { "SLIMRX4", NULL, "Slim1 Playback" }, | ||
887 | |||
888 | { "Slim2 Capture", NULL, "SLIMTX5" }, | ||
889 | { "Slim2 Capture", NULL, "SLIMTX6" }, | ||
890 | |||
891 | { "SLIMRX5", NULL, "Slim2 Playback" }, | ||
892 | { "SLIMRX6", NULL, "Slim2 Playback" }, | ||
893 | |||
894 | { "Slim3 Capture", NULL, "SLIMTX7" }, | ||
895 | { "Slim3 Capture", NULL, "SLIMTX8" }, | ||
896 | |||
897 | { "SLIMRX7", NULL, "Slim3 Playback" }, | ||
898 | { "SLIMRX8", NULL, "Slim3 Playback" }, | ||
899 | |||
780 | { "AIF1 Playback", NULL, "SYSCLK" }, | 900 | { "AIF1 Playback", NULL, "SYSCLK" }, |
781 | { "AIF2 Playback", NULL, "SYSCLK" }, | 901 | { "AIF2 Playback", NULL, "SYSCLK" }, |
782 | { "AIF3 Playback", NULL, "SYSCLK" }, | 902 | { "AIF3 Playback", NULL, "SYSCLK" }, |
903 | { "Slim1 Playback", NULL, "SYSCLK" }, | ||
904 | { "Slim2 Playback", NULL, "SYSCLK" }, | ||
905 | { "Slim3 Playback", NULL, "SYSCLK" }, | ||
783 | 906 | ||
784 | { "AIF1 Capture", NULL, "SYSCLK" }, | 907 | { "AIF1 Capture", NULL, "SYSCLK" }, |
785 | { "AIF2 Capture", NULL, "SYSCLK" }, | 908 | { "AIF2 Capture", NULL, "SYSCLK" }, |
786 | { "AIF3 Capture", NULL, "SYSCLK" }, | 909 | { "AIF3 Capture", NULL, "SYSCLK" }, |
910 | { "Slim1 Capture", NULL, "SYSCLK" }, | ||
911 | { "Slim2 Capture", NULL, "SYSCLK" }, | ||
912 | { "Slim3 Capture", NULL, "SYSCLK" }, | ||
787 | 913 | ||
788 | { "IN1L PGA", NULL, "IN1L" }, | 914 | { "IN1L PGA", NULL, "IN1L" }, |
789 | { "IN1R PGA", NULL, "IN1R" }, | 915 | { "IN1R PGA", NULL, "IN1R" }, |
@@ -829,6 +955,15 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
829 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | 955 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), |
830 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | 956 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), |
831 | 957 | ||
958 | ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), | ||
959 | ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), | ||
960 | ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), | ||
961 | ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), | ||
962 | ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), | ||
963 | ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), | ||
964 | ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), | ||
965 | ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), | ||
966 | |||
832 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | 967 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), |
833 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | 968 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), |
834 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | 969 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), |
@@ -963,6 +1098,63 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
963 | .ops = &arizona_dai_ops, | 1098 | .ops = &arizona_dai_ops, |
964 | .symmetric_rates = 1, | 1099 | .symmetric_rates = 1, |
965 | }, | 1100 | }, |
1101 | { | ||
1102 | .name = "wm5110-slim1", | ||
1103 | .id = 4, | ||
1104 | .playback = { | ||
1105 | .stream_name = "Slim1 Playback", | ||
1106 | .channels_min = 1, | ||
1107 | .channels_max = 4, | ||
1108 | .rates = WM5110_RATES, | ||
1109 | .formats = WM5110_FORMATS, | ||
1110 | }, | ||
1111 | .capture = { | ||
1112 | .stream_name = "Slim1 Capture", | ||
1113 | .channels_min = 1, | ||
1114 | .channels_max = 4, | ||
1115 | .rates = WM5110_RATES, | ||
1116 | .formats = WM5110_FORMATS, | ||
1117 | }, | ||
1118 | .ops = &arizona_simple_dai_ops, | ||
1119 | }, | ||
1120 | { | ||
1121 | .name = "wm5110-slim2", | ||
1122 | .id = 5, | ||
1123 | .playback = { | ||
1124 | .stream_name = "Slim2 Playback", | ||
1125 | .channels_min = 1, | ||
1126 | .channels_max = 2, | ||
1127 | .rates = WM5110_RATES, | ||
1128 | .formats = WM5110_FORMATS, | ||
1129 | }, | ||
1130 | .capture = { | ||
1131 | .stream_name = "Slim2 Capture", | ||
1132 | .channels_min = 1, | ||
1133 | .channels_max = 2, | ||
1134 | .rates = WM5110_RATES, | ||
1135 | .formats = WM5110_FORMATS, | ||
1136 | }, | ||
1137 | .ops = &arizona_simple_dai_ops, | ||
1138 | }, | ||
1139 | { | ||
1140 | .name = "wm5110-slim3", | ||
1141 | .id = 6, | ||
1142 | .playback = { | ||
1143 | .stream_name = "Slim3 Playback", | ||
1144 | .channels_min = 1, | ||
1145 | .channels_max = 2, | ||
1146 | .rates = WM5110_RATES, | ||
1147 | .formats = WM5110_FORMATS, | ||
1148 | }, | ||
1149 | .capture = { | ||
1150 | .stream_name = "Slim3 Capture", | ||
1151 | .channels_min = 1, | ||
1152 | .channels_max = 2, | ||
1153 | .rates = WM5110_RATES, | ||
1154 | .formats = WM5110_FORMATS, | ||
1155 | }, | ||
1156 | .ops = &arizona_simple_dai_ops, | ||
1157 | }, | ||
966 | }; | 1158 | }; |
967 | 1159 | ||
968 | static int wm5110_codec_probe(struct snd_soc_codec *codec) | 1160 | static int wm5110_codec_probe(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index e9710280e5e1..b1dc7d426438 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -51,6 +51,7 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { | |||
51 | 51 | ||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8962_priv { | 53 | struct wm8962_priv { |
54 | struct wm8962_pdata pdata; | ||
54 | struct regmap *regmap; | 55 | struct regmap *regmap; |
55 | struct snd_soc_codec *codec; | 56 | struct snd_soc_codec *codec; |
56 | 57 | ||
@@ -1600,7 +1601,6 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, | |||
1600 | struct snd_ctl_elem_value *ucontrol) | 1601 | struct snd_ctl_elem_value *ucontrol) |
1601 | { | 1602 | { |
1602 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1603 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1603 | u16 *reg_cache = codec->reg_cache; | ||
1604 | int ret; | 1604 | int ret; |
1605 | 1605 | ||
1606 | /* Apply the update (if any) */ | 1606 | /* Apply the update (if any) */ |
@@ -1609,16 +1609,19 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, | |||
1609 | return 0; | 1609 | return 0; |
1610 | 1610 | ||
1611 | /* If the left PGA is enabled hit that VU bit... */ | 1611 | /* If the left PGA is enabled hit that VU bit... */ |
1612 | if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) | 1612 | ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); |
1613 | return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, | 1613 | if (ret & WM8962_HPOUTL_PGA_ENA) { |
1614 | reg_cache[WM8962_HPOUTL_VOLUME]); | 1614 | snd_soc_write(codec, WM8962_HPOUTL_VOLUME, |
1615 | snd_soc_read(codec, WM8962_HPOUTL_VOLUME)); | ||
1616 | return 1; | ||
1617 | } | ||
1615 | 1618 | ||
1616 | /* ...otherwise the right. The VU is stereo. */ | 1619 | /* ...otherwise the right. The VU is stereo. */ |
1617 | if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) | 1620 | if (ret & WM8962_HPOUTR_PGA_ENA) |
1618 | return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, | 1621 | snd_soc_write(codec, WM8962_HPOUTR_VOLUME, |
1619 | reg_cache[WM8962_HPOUTR_VOLUME]); | 1622 | snd_soc_read(codec, WM8962_HPOUTR_VOLUME)); |
1620 | 1623 | ||
1621 | return 0; | 1624 | return 1; |
1622 | } | 1625 | } |
1623 | 1626 | ||
1624 | /* The VU bits for the speakers are in a different register to the mute | 1627 | /* The VU bits for the speakers are in a different register to the mute |
@@ -2345,12 +2348,13 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = { | |||
2345 | 2348 | ||
2346 | static int wm8962_add_widgets(struct snd_soc_codec *codec) | 2349 | static int wm8962_add_widgets(struct snd_soc_codec *codec) |
2347 | { | 2350 | { |
2348 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 2351 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2352 | struct wm8962_pdata *pdata = &wm8962->pdata; | ||
2349 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2353 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
2350 | 2354 | ||
2351 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, | 2355 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, |
2352 | ARRAY_SIZE(wm8962_snd_controls)); | 2356 | ARRAY_SIZE(wm8962_snd_controls)); |
2353 | if (pdata && pdata->spk_mono) | 2357 | if (pdata->spk_mono) |
2354 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, | 2358 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, |
2355 | ARRAY_SIZE(wm8962_spk_mono_controls)); | 2359 | ARRAY_SIZE(wm8962_spk_mono_controls)); |
2356 | else | 2360 | else |
@@ -2360,7 +2364,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
2360 | 2364 | ||
2361 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, | 2365 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, |
2362 | ARRAY_SIZE(wm8962_dapm_widgets)); | 2366 | ARRAY_SIZE(wm8962_dapm_widgets)); |
2363 | if (pdata && pdata->spk_mono) | 2367 | if (pdata->spk_mono) |
2364 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, | 2368 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, |
2365 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); | 2369 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); |
2366 | else | 2370 | else |
@@ -2369,7 +2373,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
2369 | 2373 | ||
2370 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, | 2374 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, |
2371 | ARRAY_SIZE(wm8962_intercon)); | 2375 | ARRAY_SIZE(wm8962_intercon)); |
2372 | if (pdata && pdata->spk_mono) | 2376 | if (pdata->spk_mono) |
2373 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, | 2377 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, |
2374 | ARRAY_SIZE(wm8962_spk_mono_intercon)); | 2378 | ARRAY_SIZE(wm8962_spk_mono_intercon)); |
2375 | else | 2379 | else |
@@ -3333,14 +3337,14 @@ static struct gpio_chip wm8962_template_chip = { | |||
3333 | static void wm8962_init_gpio(struct snd_soc_codec *codec) | 3337 | static void wm8962_init_gpio(struct snd_soc_codec *codec) |
3334 | { | 3338 | { |
3335 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3339 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3336 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3340 | struct wm8962_pdata *pdata = &wm8962->pdata; |
3337 | int ret; | 3341 | int ret; |
3338 | 3342 | ||
3339 | wm8962->gpio_chip = wm8962_template_chip; | 3343 | wm8962->gpio_chip = wm8962_template_chip; |
3340 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; | 3344 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; |
3341 | wm8962->gpio_chip.dev = codec->dev; | 3345 | wm8962->gpio_chip.dev = codec->dev; |
3342 | 3346 | ||
3343 | if (pdata && pdata->gpio_base) | 3347 | if (pdata->gpio_base) |
3344 | wm8962->gpio_chip.base = pdata->gpio_base; | 3348 | wm8962->gpio_chip.base = pdata->gpio_base; |
3345 | else | 3349 | else |
3346 | wm8962->gpio_chip.base = -1; | 3350 | wm8962->gpio_chip.base = -1; |
@@ -3374,7 +3378,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3374 | int ret; | 3378 | int ret; |
3375 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3379 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3376 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3380 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); |
3377 | u16 *reg_cache = codec->reg_cache; | ||
3378 | int i, trigger, irq_pol; | 3381 | int i, trigger, irq_pol; |
3379 | bool dmicclk, dmicdat; | 3382 | bool dmicclk, dmicdat; |
3380 | 3383 | ||
@@ -3421,30 +3424,29 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3421 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, | 3424 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, |
3422 | 0); | 3425 | 0); |
3423 | 3426 | ||
3424 | if (pdata) { | 3427 | /* Apply static configuration for GPIOs */ |
3425 | /* Apply static configuration for GPIOs */ | 3428 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) |
3426 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) | 3429 | if (pdata->gpio_init[i]) { |
3427 | if (pdata->gpio_init[i]) { | 3430 | wm8962_set_gpio_mode(codec, i + 1); |
3428 | wm8962_set_gpio_mode(codec, i + 1); | 3431 | snd_soc_write(codec, 0x200 + i, |
3429 | snd_soc_write(codec, 0x200 + i, | 3432 | pdata->gpio_init[i] & 0xffff); |
3430 | pdata->gpio_init[i] & 0xffff); | 3433 | } |
3431 | } | ||
3432 | 3434 | ||
3433 | /* Put the speakers into mono mode? */ | ||
3434 | if (pdata->spk_mono) | ||
3435 | reg_cache[WM8962_CLASS_D_CONTROL_2] | ||
3436 | |= WM8962_SPK_MONO; | ||
3437 | 3435 | ||
3438 | /* Micbias setup, detection enable and detection | 3436 | /* Put the speakers into mono mode? */ |
3439 | * threasholds. */ | 3437 | if (pdata->spk_mono) |
3440 | if (pdata->mic_cfg) | 3438 | snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2, |
3441 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, | 3439 | WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); |
3442 | WM8962_MICDET_ENA | | 3440 | |
3443 | WM8962_MICDET_THR_MASK | | 3441 | /* Micbias setup, detection enable and detection |
3444 | WM8962_MICSHORT_THR_MASK | | 3442 | * threasholds. */ |
3445 | WM8962_MICBIAS_LVL, | 3443 | if (pdata->mic_cfg) |
3446 | pdata->mic_cfg); | 3444 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, |
3447 | } | 3445 | WM8962_MICDET_ENA | |
3446 | WM8962_MICDET_THR_MASK | | ||
3447 | WM8962_MICSHORT_THR_MASK | | ||
3448 | WM8962_MICBIAS_LVL, | ||
3449 | pdata->mic_cfg); | ||
3448 | 3450 | ||
3449 | /* Latch volume update bits */ | 3451 | /* Latch volume update bits */ |
3450 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, | 3452 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, |
@@ -3506,7 +3508,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3506 | wm8962_init_gpio(codec); | 3508 | wm8962_init_gpio(codec); |
3507 | 3509 | ||
3508 | if (wm8962->irq) { | 3510 | if (wm8962->irq) { |
3509 | if (pdata && pdata->irq_active_low) { | 3511 | if (pdata->irq_active_low) { |
3510 | trigger = IRQF_TRIGGER_LOW; | 3512 | trigger = IRQF_TRIGGER_LOW; |
3511 | irq_pol = WM8962_IRQ_POL; | 3513 | irq_pol = WM8962_IRQ_POL; |
3512 | } else { | 3514 | } else { |
@@ -3584,6 +3586,34 @@ static const struct regmap_config wm8962_regmap = { | |||
3584 | .cache_type = REGCACHE_RBTREE, | 3586 | .cache_type = REGCACHE_RBTREE, |
3585 | }; | 3587 | }; |
3586 | 3588 | ||
3589 | static int wm8962_set_pdata_from_of(struct i2c_client *i2c, | ||
3590 | struct wm8962_pdata *pdata) | ||
3591 | { | ||
3592 | const struct device_node *np = i2c->dev.of_node; | ||
3593 | u32 val32; | ||
3594 | int i; | ||
3595 | |||
3596 | if (of_property_read_bool(np, "spk-mono")) | ||
3597 | pdata->spk_mono = true; | ||
3598 | |||
3599 | if (of_property_read_u32(np, "mic-cfg", &val32) >= 0) | ||
3600 | pdata->mic_cfg = val32; | ||
3601 | |||
3602 | if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_init, | ||
3603 | ARRAY_SIZE(pdata->gpio_init)) >= 0) | ||
3604 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) { | ||
3605 | /* | ||
3606 | * The range of GPIO register value is [0x0, 0xffff] | ||
3607 | * While the default value of each register is 0x0 | ||
3608 | * Any other value will be regarded as default value | ||
3609 | */ | ||
3610 | if (pdata->gpio_init[i] > 0xffff) | ||
3611 | pdata->gpio_init[i] = 0x0; | ||
3612 | } | ||
3613 | |||
3614 | return 0; | ||
3615 | } | ||
3616 | |||
3587 | static int wm8962_i2c_probe(struct i2c_client *i2c, | 3617 | static int wm8962_i2c_probe(struct i2c_client *i2c, |
3588 | const struct i2c_device_id *id) | 3618 | const struct i2c_device_id *id) |
3589 | { | 3619 | { |
@@ -3603,6 +3633,15 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3603 | init_completion(&wm8962->fll_lock); | 3633 | init_completion(&wm8962->fll_lock); |
3604 | wm8962->irq = i2c->irq; | 3634 | wm8962->irq = i2c->irq; |
3605 | 3635 | ||
3636 | /* If platform data was supplied, update the default data in priv */ | ||
3637 | if (pdata) { | ||
3638 | memcpy(&wm8962->pdata, pdata, sizeof(struct wm8962_pdata)); | ||
3639 | } else if (i2c->dev.of_node) { | ||
3640 | ret = wm8962_set_pdata_from_of(i2c, &wm8962->pdata); | ||
3641 | if (ret != 0) | ||
3642 | return ret; | ||
3643 | } | ||
3644 | |||
3606 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3645 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
3607 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3646 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
3608 | 3647 | ||
@@ -3666,7 +3705,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3666 | goto err_enable; | 3705 | goto err_enable; |
3667 | } | 3706 | } |
3668 | 3707 | ||
3669 | if (pdata && pdata->in4_dc_measure) { | 3708 | if (wm8962->pdata.in4_dc_measure) { |
3670 | ret = regmap_register_patch(wm8962->regmap, | 3709 | ret = regmap_register_patch(wm8962->regmap, |
3671 | wm8962_dc_measure, | 3710 | wm8962_dc_measure, |
3672 | ARRAY_SIZE(wm8962_dc_measure)); | 3711 | ARRAY_SIZE(wm8962_dc_measure)); |
@@ -3719,8 +3758,34 @@ static int wm8962_runtime_resume(struct device *dev) | |||
3719 | 3758 | ||
3720 | wm8962_reset(wm8962); | 3759 | wm8962_reset(wm8962); |
3721 | 3760 | ||
3761 | /* SYSCLK defaults to on; make sure it is off so we can safely | ||
3762 | * write to registers if the device is declocked. | ||
3763 | */ | ||
3764 | regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, | ||
3765 | WM8962_SYSCLK_ENA, 0); | ||
3766 | |||
3767 | /* Ensure we have soft control over all registers */ | ||
3768 | regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, | ||
3769 | WM8962_CLKREG_OVD, WM8962_CLKREG_OVD); | ||
3770 | |||
3771 | /* Ensure that the oscillator and PLLs are disabled */ | ||
3772 | regmap_update_bits(wm8962->regmap, WM8962_PLL2, | ||
3773 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, | ||
3774 | 0); | ||
3775 | |||
3722 | regcache_sync(wm8962->regmap); | 3776 | regcache_sync(wm8962->regmap); |
3723 | 3777 | ||
3778 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, | ||
3779 | WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, | ||
3780 | WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); | ||
3781 | |||
3782 | /* Bias enable at 2*5k (fast start-up) */ | ||
3783 | regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, | ||
3784 | WM8962_BIAS_ENA | WM8962_VMID_SEL_MASK, | ||
3785 | WM8962_BIAS_ENA | 0x180); | ||
3786 | |||
3787 | msleep(5); | ||
3788 | |||
3724 | return 0; | 3789 | return 0; |
3725 | } | 3790 | } |
3726 | 3791 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9e13edd81292..1d4b1ec66e36 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/gcd.h> | ||
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
@@ -1494,6 +1495,24 @@ static const char *aif1dac_text[] = { | |||
1494 | "AIF1DACDAT", "AIF3DACDAT", | 1495 | "AIF1DACDAT", "AIF3DACDAT", |
1495 | }; | 1496 | }; |
1496 | 1497 | ||
1498 | static const char *loopback_text[] = { | ||
1499 | "None", "ADCDAT", | ||
1500 | }; | ||
1501 | |||
1502 | static const struct soc_enum aif1_loopback_enum = | ||
1503 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2, | ||
1504 | loopback_text); | ||
1505 | |||
1506 | static const struct snd_kcontrol_new aif1_loopback = | ||
1507 | SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum); | ||
1508 | |||
1509 | static const struct soc_enum aif2_loopback_enum = | ||
1510 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2, | ||
1511 | loopback_text); | ||
1512 | |||
1513 | static const struct snd_kcontrol_new aif2_loopback = | ||
1514 | SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum); | ||
1515 | |||
1497 | static const struct soc_enum aif1dac_enum = | 1516 | static const struct soc_enum aif1dac_enum = |
1498 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); | 1517 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); |
1499 | 1518 | ||
@@ -1740,6 +1759,9 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), | |||
1740 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | 1759 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), |
1741 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | 1760 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
1742 | 1761 | ||
1762 | SND_SOC_DAPM_MUX("AIF1 Loopback", SND_SOC_NOPM, 0, 0, &aif1_loopback), | ||
1763 | SND_SOC_DAPM_MUX("AIF2 Loopback", SND_SOC_NOPM, 0, 0, &aif2_loopback), | ||
1764 | |||
1743 | SND_SOC_DAPM_POST("Debug log", post_ev), | 1765 | SND_SOC_DAPM_POST("Debug log", post_ev), |
1744 | }; | 1766 | }; |
1745 | 1767 | ||
@@ -1871,9 +1893,9 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1871 | { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, | 1893 | { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, |
1872 | { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, | 1894 | { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, |
1873 | 1895 | ||
1874 | { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, | 1896 | { "AIF1DAC Mux", "AIF1DACDAT", "AIF1 Loopback" }, |
1875 | { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | 1897 | { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, |
1876 | { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, | 1898 | { "AIF2DAC Mux", "AIF2DACDAT", "AIF2 Loopback" }, |
1877 | { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | 1899 | { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, |
1878 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, | 1900 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, |
1879 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, | 1901 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, |
@@ -1924,6 +1946,12 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1924 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, | 1946 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, |
1925 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, | 1947 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, |
1926 | 1948 | ||
1949 | /* Loopback */ | ||
1950 | { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" }, | ||
1951 | { "AIF1 Loopback", "None", "AIF1DACDAT" }, | ||
1952 | { "AIF2 Loopback", "ADCDAT", "AIF2ADCDAT" }, | ||
1953 | { "AIF2 Loopback", "None", "AIF2DACDAT" }, | ||
1954 | |||
1927 | /* Sidetone */ | 1955 | /* Sidetone */ |
1928 | { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, | 1956 | { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, |
1929 | { "Left Sidetone", "DMIC2", "DMIC2L" }, | 1957 | { "Left Sidetone", "DMIC2", "DMIC2L" }, |
@@ -2006,15 +2034,16 @@ struct fll_div { | |||
2006 | u16 outdiv; | 2034 | u16 outdiv; |
2007 | u16 n; | 2035 | u16 n; |
2008 | u16 k; | 2036 | u16 k; |
2037 | u16 lambda; | ||
2009 | u16 clk_ref_div; | 2038 | u16 clk_ref_div; |
2010 | u16 fll_fratio; | 2039 | u16 fll_fratio; |
2011 | }; | 2040 | }; |
2012 | 2041 | ||
2013 | static int wm8994_get_fll_config(struct fll_div *fll, | 2042 | static int wm8994_get_fll_config(struct wm8994 *control, struct fll_div *fll, |
2014 | int freq_in, int freq_out) | 2043 | int freq_in, int freq_out) |
2015 | { | 2044 | { |
2016 | u64 Kpart; | 2045 | u64 Kpart; |
2017 | unsigned int K, Ndiv, Nmod; | 2046 | unsigned int K, Ndiv, Nmod, gcd_fll; |
2018 | 2047 | ||
2019 | pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); | 2048 | pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); |
2020 | 2049 | ||
@@ -2063,20 +2092,32 @@ static int wm8994_get_fll_config(struct fll_div *fll, | |||
2063 | Nmod = freq_out % freq_in; | 2092 | Nmod = freq_out % freq_in; |
2064 | pr_debug("Nmod=%d\n", Nmod); | 2093 | pr_debug("Nmod=%d\n", Nmod); |
2065 | 2094 | ||
2066 | /* Calculate fractional part - scale up so we can round. */ | 2095 | switch (control->type) { |
2067 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | 2096 | case WM8994: |
2097 | /* Calculate fractional part - scale up so we can round. */ | ||
2098 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
2099 | |||
2100 | do_div(Kpart, freq_in); | ||
2101 | |||
2102 | K = Kpart & 0xFFFFFFFF; | ||
2068 | 2103 | ||
2069 | do_div(Kpart, freq_in); | 2104 | if ((K % 10) >= 5) |
2105 | K += 5; | ||
2070 | 2106 | ||
2071 | K = Kpart & 0xFFFFFFFF; | 2107 | /* Move down to proper range now rounding is done */ |
2108 | fll->k = K / 10; | ||
2109 | fll->lambda = 0; | ||
2072 | 2110 | ||
2073 | if ((K % 10) >= 5) | 2111 | pr_debug("N=%x K=%x\n", fll->n, fll->k); |
2074 | K += 5; | 2112 | break; |
2075 | 2113 | ||
2076 | /* Move down to proper range now rounding is done */ | 2114 | default: |
2077 | fll->k = K / 10; | 2115 | gcd_fll = gcd(freq_out, freq_in); |
2078 | 2116 | ||
2079 | pr_debug("N=%x K=%x\n", fll->n, fll->k); | 2117 | fll->k = (freq_out - (freq_in * fll->n)) / gcd_fll; |
2118 | fll->lambda = freq_in / gcd_fll; | ||
2119 | |||
2120 | } | ||
2080 | 2121 | ||
2081 | return 0; | 2122 | return 0; |
2082 | } | 2123 | } |
@@ -2140,9 +2181,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2140 | * analysis bugs spewing warnings. | 2181 | * analysis bugs spewing warnings. |
2141 | */ | 2182 | */ |
2142 | if (freq_out) | 2183 | if (freq_out) |
2143 | ret = wm8994_get_fll_config(&fll, freq_in, freq_out); | 2184 | ret = wm8994_get_fll_config(control, &fll, freq_in, freq_out); |
2144 | else | 2185 | else |
2145 | ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, | 2186 | ret = wm8994_get_fll_config(control, &fll, wm8994->fll[id].in, |
2146 | wm8994->fll[id].out); | 2187 | wm8994->fll[id].out); |
2147 | if (ret < 0) | 2188 | if (ret < 0) |
2148 | return ret; | 2189 | return ret; |
@@ -2187,6 +2228,17 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2187 | WM8994_FLL1_N_MASK, | 2228 | WM8994_FLL1_N_MASK, |
2188 | fll.n << WM8994_FLL1_N_SHIFT); | 2229 | fll.n << WM8994_FLL1_N_SHIFT); |
2189 | 2230 | ||
2231 | if (fll.lambda) { | ||
2232 | snd_soc_update_bits(codec, WM8958_FLL1_EFS_1 + reg_offset, | ||
2233 | WM8958_FLL1_LAMBDA_MASK, | ||
2234 | fll.lambda); | ||
2235 | snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset, | ||
2236 | WM8958_FLL1_EFS_ENA, WM8958_FLL1_EFS_ENA); | ||
2237 | } else { | ||
2238 | snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset, | ||
2239 | WM8958_FLL1_EFS_ENA, 0); | ||
2240 | } | ||
2241 | |||
2190 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | 2242 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, |
2191 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | | 2243 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
2192 | WM8994_FLL1_REFCLK_DIV_MASK | | 2244 | WM8994_FLL1_REFCLK_DIV_MASK | |
@@ -2551,17 +2603,24 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2551 | struct wm8994 *control = wm8994->wm8994; | 2603 | struct wm8994 *control = wm8994->wm8994; |
2552 | int ms_reg; | 2604 | int ms_reg; |
2553 | int aif1_reg; | 2605 | int aif1_reg; |
2606 | int dac_reg; | ||
2607 | int adc_reg; | ||
2554 | int ms = 0; | 2608 | int ms = 0; |
2555 | int aif1 = 0; | 2609 | int aif1 = 0; |
2610 | int lrclk = 0; | ||
2556 | 2611 | ||
2557 | switch (dai->id) { | 2612 | switch (dai->id) { |
2558 | case 1: | 2613 | case 1: |
2559 | ms_reg = WM8994_AIF1_MASTER_SLAVE; | 2614 | ms_reg = WM8994_AIF1_MASTER_SLAVE; |
2560 | aif1_reg = WM8994_AIF1_CONTROL_1; | 2615 | aif1_reg = WM8994_AIF1_CONTROL_1; |
2616 | dac_reg = WM8994_AIF1DAC_LRCLK; | ||
2617 | adc_reg = WM8994_AIF1ADC_LRCLK; | ||
2561 | break; | 2618 | break; |
2562 | case 2: | 2619 | case 2: |
2563 | ms_reg = WM8994_AIF2_MASTER_SLAVE; | 2620 | ms_reg = WM8994_AIF2_MASTER_SLAVE; |
2564 | aif1_reg = WM8994_AIF2_CONTROL_1; | 2621 | aif1_reg = WM8994_AIF2_CONTROL_1; |
2622 | dac_reg = WM8994_AIF1DAC_LRCLK; | ||
2623 | adc_reg = WM8994_AIF1ADC_LRCLK; | ||
2565 | break; | 2624 | break; |
2566 | default: | 2625 | default: |
2567 | return -EINVAL; | 2626 | return -EINVAL; |
@@ -2580,6 +2639,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2580 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 2639 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
2581 | case SND_SOC_DAIFMT_DSP_B: | 2640 | case SND_SOC_DAIFMT_DSP_B: |
2582 | aif1 |= WM8994_AIF1_LRCLK_INV; | 2641 | aif1 |= WM8994_AIF1_LRCLK_INV; |
2642 | lrclk |= WM8958_AIF1_LRCLK_INV; | ||
2583 | case SND_SOC_DAIFMT_DSP_A: | 2643 | case SND_SOC_DAIFMT_DSP_A: |
2584 | aif1 |= 0x18; | 2644 | aif1 |= 0x18; |
2585 | break; | 2645 | break; |
@@ -2618,12 +2678,14 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2618 | break; | 2678 | break; |
2619 | case SND_SOC_DAIFMT_IB_IF: | 2679 | case SND_SOC_DAIFMT_IB_IF: |
2620 | aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; | 2680 | aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; |
2681 | lrclk |= WM8958_AIF1_LRCLK_INV; | ||
2621 | break; | 2682 | break; |
2622 | case SND_SOC_DAIFMT_IB_NF: | 2683 | case SND_SOC_DAIFMT_IB_NF: |
2623 | aif1 |= WM8994_AIF1_BCLK_INV; | 2684 | aif1 |= WM8994_AIF1_BCLK_INV; |
2624 | break; | 2685 | break; |
2625 | case SND_SOC_DAIFMT_NB_IF: | 2686 | case SND_SOC_DAIFMT_NB_IF: |
2626 | aif1 |= WM8994_AIF1_LRCLK_INV; | 2687 | aif1 |= WM8994_AIF1_LRCLK_INV; |
2688 | lrclk |= WM8958_AIF1_LRCLK_INV; | ||
2627 | break; | 2689 | break; |
2628 | default: | 2690 | default: |
2629 | return -EINVAL; | 2691 | return -EINVAL; |
@@ -2654,6 +2716,10 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2654 | aif1); | 2716 | aif1); |
2655 | snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, | 2717 | snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, |
2656 | ms); | 2718 | ms); |
2719 | snd_soc_update_bits(codec, dac_reg, | ||
2720 | WM8958_AIF1_LRCLK_INV, lrclk); | ||
2721 | snd_soc_update_bits(codec, adc_reg, | ||
2722 | WM8958_AIF1_LRCLK_INV, lrclk); | ||
2657 | 2723 | ||
2658 | return 0; | 2724 | return 0; |
2659 | } | 2725 | } |
@@ -3092,24 +3158,7 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec) | |||
3092 | static int wm8994_codec_resume(struct snd_soc_codec *codec) | 3158 | static int wm8994_codec_resume(struct snd_soc_codec *codec) |
3093 | { | 3159 | { |
3094 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3160 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3095 | struct wm8994 *control = wm8994->wm8994; | ||
3096 | int i, ret; | 3161 | int i, ret; |
3097 | unsigned int val, mask; | ||
3098 | |||
3099 | if (control->revision < 4) { | ||
3100 | /* force a HW read */ | ||
3101 | ret = regmap_read(control->regmap, | ||
3102 | WM8994_POWER_MANAGEMENT_5, &val); | ||
3103 | |||
3104 | /* modify the cache only */ | ||
3105 | codec->cache_only = 1; | ||
3106 | mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA | | ||
3107 | WM8994_DAC2R_ENA | WM8994_DAC2L_ENA; | ||
3108 | val &= mask; | ||
3109 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, | ||
3110 | mask, val); | ||
3111 | codec->cache_only = 0; | ||
3112 | } | ||
3113 | 3162 | ||
3114 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 3163 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3115 | if (!wm8994->fll_suspend[i].out) | 3164 | if (!wm8994->fll_suspend[i].out) |
@@ -3491,6 +3540,31 @@ static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) | |||
3491 | wm8994->btn_mask); | 3540 | wm8994->btn_mask); |
3492 | } | 3541 | } |
3493 | 3542 | ||
3543 | static void wm8958_open_circuit_work(struct work_struct *work) | ||
3544 | { | ||
3545 | struct wm8994_priv *wm8994 = container_of(work, | ||
3546 | struct wm8994_priv, | ||
3547 | open_circuit_work.work); | ||
3548 | struct device *dev = wm8994->wm8994->dev; | ||
3549 | |||
3550 | wm1811_micd_stop(wm8994->hubs.codec); | ||
3551 | |||
3552 | mutex_lock(&wm8994->accdet_lock); | ||
3553 | |||
3554 | dev_dbg(dev, "Reporting open circuit\n"); | ||
3555 | |||
3556 | wm8994->jack_mic = false; | ||
3557 | wm8994->mic_detecting = true; | ||
3558 | |||
3559 | wm8958_micd_set_rate(wm8994->hubs.codec); | ||
3560 | |||
3561 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | ||
3562 | wm8994->btn_mask | | ||
3563 | SND_JACK_HEADSET); | ||
3564 | |||
3565 | mutex_unlock(&wm8994->accdet_lock); | ||
3566 | } | ||
3567 | |||
3494 | static void wm8958_mic_id(void *data, u16 status) | 3568 | static void wm8958_mic_id(void *data, u16 status) |
3495 | { | 3569 | { |
3496 | struct snd_soc_codec *codec = data; | 3570 | struct snd_soc_codec *codec = data; |
@@ -3500,16 +3574,9 @@ static void wm8958_mic_id(void *data, u16 status) | |||
3500 | if (!(status & WM8958_MICD_STS)) { | 3574 | if (!(status & WM8958_MICD_STS)) { |
3501 | /* If nothing present then clear our statuses */ | 3575 | /* If nothing present then clear our statuses */ |
3502 | dev_dbg(codec->dev, "Detected open circuit\n"); | 3576 | dev_dbg(codec->dev, "Detected open circuit\n"); |
3503 | wm8994->jack_mic = false; | ||
3504 | wm8994->mic_detecting = true; | ||
3505 | |||
3506 | wm1811_micd_stop(codec); | ||
3507 | |||
3508 | wm8958_micd_set_rate(codec); | ||
3509 | 3577 | ||
3510 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3578 | schedule_delayed_work(&wm8994->open_circuit_work, |
3511 | wm8994->btn_mask | | 3579 | msecs_to_jiffies(2500)); |
3512 | SND_JACK_HEADSET); | ||
3513 | return; | 3580 | return; |
3514 | } | 3581 | } |
3515 | 3582 | ||
@@ -3594,6 +3661,8 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3594 | 3661 | ||
3595 | pm_runtime_get_sync(codec->dev); | 3662 | pm_runtime_get_sync(codec->dev); |
3596 | 3663 | ||
3664 | cancel_delayed_work_sync(&wm8994->mic_complete_work); | ||
3665 | |||
3597 | mutex_lock(&wm8994->accdet_lock); | 3666 | mutex_lock(&wm8994->accdet_lock); |
3598 | 3667 | ||
3599 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); | 3668 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); |
@@ -3776,11 +3845,33 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3776 | } | 3845 | } |
3777 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); | 3846 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); |
3778 | 3847 | ||
3848 | static void wm8958_mic_work(struct work_struct *work) | ||
3849 | { | ||
3850 | struct wm8994_priv *wm8994 = container_of(work, | ||
3851 | struct wm8994_priv, | ||
3852 | mic_complete_work.work); | ||
3853 | struct snd_soc_codec *codec = wm8994->hubs.codec; | ||
3854 | |||
3855 | dev_crit(codec->dev, "MIC WORK %x\n", wm8994->mic_status); | ||
3856 | |||
3857 | pm_runtime_get_sync(codec->dev); | ||
3858 | |||
3859 | mutex_lock(&wm8994->accdet_lock); | ||
3860 | |||
3861 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, wm8994->mic_status); | ||
3862 | |||
3863 | mutex_unlock(&wm8994->accdet_lock); | ||
3864 | |||
3865 | pm_runtime_put(codec->dev); | ||
3866 | |||
3867 | dev_crit(codec->dev, "MIC WORK %x DONE\n", wm8994->mic_status); | ||
3868 | } | ||
3869 | |||
3779 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3870 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
3780 | { | 3871 | { |
3781 | struct wm8994_priv *wm8994 = data; | 3872 | struct wm8994_priv *wm8994 = data; |
3782 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3873 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3783 | int reg, count, ret; | 3874 | int reg, count, ret, id_delay; |
3784 | 3875 | ||
3785 | /* | 3876 | /* |
3786 | * Jack detection may have detected a removal simulataneously | 3877 | * Jack detection may have detected a removal simulataneously |
@@ -3790,6 +3881,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3790 | if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) | 3881 | if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) |
3791 | return IRQ_HANDLED; | 3882 | return IRQ_HANDLED; |
3792 | 3883 | ||
3884 | cancel_delayed_work_sync(&wm8994->mic_complete_work); | ||
3885 | cancel_delayed_work_sync(&wm8994->open_circuit_work); | ||
3886 | |||
3793 | pm_runtime_get_sync(codec->dev); | 3887 | pm_runtime_get_sync(codec->dev); |
3794 | 3888 | ||
3795 | /* We may occasionally read a detection without an impedence | 3889 | /* We may occasionally read a detection without an impedence |
@@ -3842,8 +3936,12 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3842 | goto out; | 3936 | goto out; |
3843 | } | 3937 | } |
3844 | 3938 | ||
3939 | wm8994->mic_status = reg; | ||
3940 | id_delay = wm8994->wm8994->pdata.mic_id_delay; | ||
3941 | |||
3845 | if (wm8994->mic_detecting) | 3942 | if (wm8994->mic_detecting) |
3846 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); | 3943 | schedule_delayed_work(&wm8994->mic_complete_work, |
3944 | msecs_to_jiffies(id_delay)); | ||
3847 | else | 3945 | else |
3848 | wm8958_button_det(codec, reg); | 3946 | wm8958_button_det(codec, reg); |
3849 | 3947 | ||
@@ -3895,6 +3993,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3895 | mutex_init(&wm8994->accdet_lock); | 3993 | mutex_init(&wm8994->accdet_lock); |
3896 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | 3994 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, |
3897 | wm1811_jackdet_bootstrap); | 3995 | wm1811_jackdet_bootstrap); |
3996 | INIT_DELAYED_WORK(&wm8994->open_circuit_work, | ||
3997 | wm8958_open_circuit_work); | ||
3898 | 3998 | ||
3899 | switch (control->type) { | 3999 | switch (control->type) { |
3900 | case WM8994: | 4000 | case WM8994: |
@@ -3907,6 +4007,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3907 | break; | 4007 | break; |
3908 | } | 4008 | } |
3909 | 4009 | ||
4010 | INIT_DELAYED_WORK(&wm8994->mic_complete_work, wm8958_mic_work); | ||
4011 | |||
3910 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 4012 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3911 | init_completion(&wm8994->fll_locked[i]); | 4013 | init_completion(&wm8994->fll_locked[i]); |
3912 | 4014 | ||
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 55ddf4d57d9b..6536f8d45ac6 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -134,6 +134,9 @@ struct wm8994_priv { | |||
134 | struct mutex accdet_lock; | 134 | struct mutex accdet_lock; |
135 | struct wm8994_micdet micdet[2]; | 135 | struct wm8994_micdet micdet[2]; |
136 | struct delayed_work mic_work; | 136 | struct delayed_work mic_work; |
137 | struct delayed_work open_circuit_work; | ||
138 | struct delayed_work mic_complete_work; | ||
139 | u16 mic_status; | ||
137 | bool mic_detecting; | 140 | bool mic_detecting; |
138 | bool jack_mic; | 141 | bool jack_mic; |
139 | int btn_mask; | 142 | int btn_mask; |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ddba3fea39eb..05252ac936a3 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -310,7 +310,7 @@ static const struct soc_enum wm_adsp2_rate_enum[] = { | |||
310 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | 310 | ARIZONA_DSP1_RATE_SHIFT, 0xf, |
311 | ARIZONA_RATE_ENUM_SIZE, | 311 | ARIZONA_RATE_ENUM_SIZE, |
312 | arizona_rate_text, arizona_rate_val), | 312 | arizona_rate_text, arizona_rate_val), |
313 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, | 313 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1, |
314 | ARIZONA_DSP1_RATE_SHIFT, 0xf, | 314 | ARIZONA_DSP1_RATE_SHIFT, 0xf, |
315 | ARIZONA_RATE_ENUM_SIZE, | 315 | ARIZONA_RATE_ENUM_SIZE, |
316 | arizona_rate_text, arizona_rate_val), | 316 | arizona_rate_text, arizona_rate_val), |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 9e11a14d1b45..c82f89c9475b 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -54,16 +54,6 @@ config SND_DM6467_SOC_EVM | |||
54 | help | 54 | help |
55 | Say Y if you want to add support for SoC audio on TI | 55 | Say Y if you want to add support for SoC audio on TI |
56 | 56 | ||
57 | config SND_DAVINCI_SOC_SFFSDR | ||
58 | tristate "SoC Audio support for SFFSDR" | ||
59 | depends on SND_DAVINCI_SOC && MACH_SFFSDR | ||
60 | select SND_DAVINCI_SOC_I2S | ||
61 | select SND_SOC_PCM3008 | ||
62 | select SFFSDR_FPGA | ||
63 | help | ||
64 | Say Y if you want to add support for SoC audio on | ||
65 | Lyrtech SFFSDR board. | ||
66 | |||
67 | config SND_DA830_SOC_EVM | 57 | config SND_DA830_SOC_EVM |
68 | tristate "SoC Audio support for DA830/OMAP-L137 EVM" | 58 | tristate "SoC Audio support for DA830/OMAP-L137 EVM" |
69 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM | 59 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM |
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index a93679d618cd..a396ab6d6d5e 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -11,10 +11,8 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o | |||
11 | 11 | ||
12 | # DAVINCI Machine Support | 12 | # DAVINCI Machine Support |
13 | snd-soc-evm-objs := davinci-evm.o | 13 | snd-soc-evm-objs := davinci-evm.o |
14 | snd-soc-sffsdr-objs := davinci-sffsdr.o | ||
15 | 14 | ||
16 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o | 15 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o |
17 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o | 16 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o |
18 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o | 17 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o |
19 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o | 18 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o |
20 | obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o | ||
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 81490febac6d..32ddb7fe5034 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -1024,7 +1024,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
1024 | struct device_node *np = pdev->dev.of_node; | 1024 | struct device_node *np = pdev->dev.of_node; |
1025 | struct snd_platform_data *pdata = NULL; | 1025 | struct snd_platform_data *pdata = NULL; |
1026 | const struct of_device_id *match = | 1026 | const struct of_device_id *match = |
1027 | of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); | 1027 | of_match_device(mcasp_dt_ids, &pdev->dev); |
1028 | 1028 | ||
1029 | const u32 *of_serial_dir32; | 1029 | const u32 *of_serial_dir32; |
1030 | u8 *of_serial_dir; | 1030 | u8 *of_serial_dir; |
@@ -1257,7 +1257,7 @@ static struct platform_driver davinci_mcasp_driver = { | |||
1257 | .driver = { | 1257 | .driver = { |
1258 | .name = "davinci-mcasp", | 1258 | .name = "davinci-mcasp", |
1259 | .owner = THIS_MODULE, | 1259 | .owner = THIS_MODULE, |
1260 | .of_match_table = of_match_ptr(mcasp_dt_ids), | 1260 | .of_match_table = mcasp_dt_ids, |
1261 | }, | 1261 | }, |
1262 | }; | 1262 | }; |
1263 | 1263 | ||
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c deleted file mode 100644 index 5be65aae7e0e..000000000000 --- a/sound/soc/davinci/davinci-sffsdr.c +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | /* | ||
2 | * ASoC driver for Lyrtech SFFSDR board. | ||
3 | * | ||
4 | * Author: Hugo Villeneuve | ||
5 | * Copyright (C) 2008 Lyrtech inc | ||
6 | * | ||
7 | * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow: | ||
8 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | ||
24 | |||
25 | #include <asm/dma.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | #ifdef CONFIG_SFFSDR_FPGA | ||
28 | #include <asm/plat-sffsdr/sffsdr-fpga.h> | ||
29 | #endif | ||
30 | |||
31 | #include <mach/edma.h> | ||
32 | |||
33 | #include "../codecs/pcm3008.h" | ||
34 | #include "davinci-pcm.h" | ||
35 | #include "davinci-i2s.h" | ||
36 | |||
37 | /* | ||
38 | * CLKX and CLKR are the inputs for the Sample Rate Generator. | ||
39 | * FSX and FSR are outputs, driven by the sample Rate Generator. | ||
40 | */ | ||
41 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | ||
42 | SND_SOC_DAIFMT_CBM_CFS | \ | ||
43 | SND_SOC_DAIFMT_IB_NF) | ||
44 | |||
45 | static int sffsdr_hw_params(struct snd_pcm_substream *substream, | ||
46 | struct snd_pcm_hw_params *params) | ||
47 | { | ||
48 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
50 | int fs; | ||
51 | int ret = 0; | ||
52 | |||
53 | /* Fsref can be 32000, 44100 or 48000. */ | ||
54 | fs = params_rate(params); | ||
55 | |||
56 | #ifndef CONFIG_SFFSDR_FPGA | ||
57 | /* Without the FPGA module, the Fs is fixed at 44100 Hz */ | ||
58 | if (fs != 44100) { | ||
59 | pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | #endif | ||
63 | |||
64 | /* set cpu DAI configuration */ | ||
65 | ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); | ||
70 | |||
71 | #ifndef CONFIG_SFFSDR_FPGA | ||
72 | return 0; | ||
73 | #else | ||
74 | return sffsdr_fpga_set_codec_fs(fs); | ||
75 | #endif | ||
76 | } | ||
77 | |||
78 | static struct snd_soc_ops sffsdr_ops = { | ||
79 | .hw_params = sffsdr_hw_params, | ||
80 | }; | ||
81 | |||
82 | /* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */ | ||
83 | static struct snd_soc_dai_link sffsdr_dai = { | ||
84 | .name = "PCM3008", /* Codec name */ | ||
85 | .stream_name = "PCM3008 HiFi", | ||
86 | .cpu_dai_name = "davinci-mcbsp", | ||
87 | .codec_dai_name = "pcm3008-hifi", | ||
88 | .codec_name = "pcm3008-codec", | ||
89 | .platform_name = "davinci-mcbsp", | ||
90 | .ops = &sffsdr_ops, | ||
91 | }; | ||
92 | |||
93 | /* davinci-sffsdr audio machine driver */ | ||
94 | static struct snd_soc_card snd_soc_sffsdr = { | ||
95 | .name = "DaVinci SFFSDR", | ||
96 | .owner = THIS_MODULE, | ||
97 | .dai_link = &sffsdr_dai, | ||
98 | .num_links = 1, | ||
99 | }; | ||
100 | |||
101 | /* sffsdr audio private data */ | ||
102 | static struct pcm3008_setup_data sffsdr_pcm3008_setup = { | ||
103 | .dem0_pin = GPIO(45), | ||
104 | .dem1_pin = GPIO(46), | ||
105 | .pdad_pin = GPIO(47), | ||
106 | .pdda_pin = GPIO(38), | ||
107 | }; | ||
108 | |||
109 | struct platform_device pcm3008_codec = { | ||
110 | .name = "pcm3008-codec", | ||
111 | .id = 0, | ||
112 | .dev = { | ||
113 | .platform_data = &sffsdr_pcm3008_setup, | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | static struct resource sffsdr_snd_resources[] = { | ||
118 | { | ||
119 | .start = DAVINCI_MCBSP_BASE, | ||
120 | .end = DAVINCI_MCBSP_BASE + SZ_8K - 1, | ||
121 | .flags = IORESOURCE_MEM, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static struct evm_snd_platform_data sffsdr_snd_data = { | ||
126 | .tx_dma_ch = DAVINCI_DMA_MCBSP_TX, | ||
127 | .rx_dma_ch = DAVINCI_DMA_MCBSP_RX, | ||
128 | }; | ||
129 | |||
130 | static struct platform_device *sffsdr_snd_device; | ||
131 | |||
132 | static int __init sffsdr_init(void) | ||
133 | { | ||
134 | int ret; | ||
135 | |||
136 | if (!machine_is_sffsdr()) | ||
137 | return -EINVAL; | ||
138 | |||
139 | platform_device_register(&pcm3008_codec); | ||
140 | |||
141 | sffsdr_snd_device = platform_device_alloc("soc-audio", 0); | ||
142 | if (!sffsdr_snd_device) { | ||
143 | printk(KERN_ERR "platform device allocation failed\n"); | ||
144 | return -ENOMEM; | ||
145 | } | ||
146 | |||
147 | platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr); | ||
148 | platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, | ||
149 | sizeof(sffsdr_snd_data)); | ||
150 | |||
151 | ret = platform_device_add_resources(sffsdr_snd_device, | ||
152 | sffsdr_snd_resources, | ||
153 | ARRAY_SIZE(sffsdr_snd_resources)); | ||
154 | if (ret) { | ||
155 | printk(KERN_ERR "platform device add resources failed\n"); | ||
156 | goto error; | ||
157 | } | ||
158 | |||
159 | ret = platform_device_add(sffsdr_snd_device); | ||
160 | if (ret) | ||
161 | goto error; | ||
162 | |||
163 | return ret; | ||
164 | |||
165 | error: | ||
166 | platform_device_put(sffsdr_snd_device); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static void __exit sffsdr_exit(void) | ||
171 | { | ||
172 | platform_device_unregister(sffsdr_snd_device); | ||
173 | platform_device_unregister(&pcm3008_codec); | ||
174 | } | ||
175 | |||
176 | module_init(sffsdr_init); | ||
177 | module_exit(sffsdr_exit); | ||
178 | |||
179 | MODULE_AUTHOR("Hugo Villeneuve"); | ||
180 | MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver"); | ||
181 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index 593a3ea12d4c..70eb37a5dd16 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA SoC Synopsys I2S Audio Layer | 2 | * ALSA SoC Synopsys I2S Audio Layer |
3 | * | 3 | * |
4 | * sound/soc/spear/designware_i2s.c | 4 | * sound/soc/dwc/designware_i2s.c |
5 | * | 5 | * |
6 | * Copyright (C) 2010 ST Microelectronics | 6 | * Copyright (C) 2010 ST Microelectronics |
7 | * Rajeev Kumar <rajeev-dlh.kumar@st.com> | 7 | * Rajeev Kumar <rajeev-dlh.kumar@st.com> |
@@ -396,7 +396,7 @@ static int dw_i2s_probe(struct platform_device *pdev) | |||
396 | } | 396 | } |
397 | 397 | ||
398 | if (cap & DWC_I2S_PLAY) { | 398 | if (cap & DWC_I2S_PLAY) { |
399 | dev_dbg(&pdev->dev, " SPEAr: play supported\n"); | 399 | dev_dbg(&pdev->dev, " designware: play supported\n"); |
400 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; | 400 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; |
401 | dw_i2s_dai->playback.channels_max = pdata->channel; | 401 | dw_i2s_dai->playback.channels_max = pdata->channel; |
402 | dw_i2s_dai->playback.formats = pdata->snd_fmts; | 402 | dw_i2s_dai->playback.formats = pdata->snd_fmts; |
@@ -404,7 +404,7 @@ static int dw_i2s_probe(struct platform_device *pdev) | |||
404 | } | 404 | } |
405 | 405 | ||
406 | if (cap & DWC_I2S_RECORD) { | 406 | if (cap & DWC_I2S_RECORD) { |
407 | dev_dbg(&pdev->dev, "SPEAr: record supported\n"); | 407 | dev_dbg(&pdev->dev, "designware: record supported\n"); |
408 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; | 408 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; |
409 | dw_i2s_dai->capture.channels_max = pdata->channel; | 409 | dw_i2s_dai->capture.channels_max = pdata->channel; |
410 | dw_i2s_dai->capture.formats = pdata->snd_fmts; | 410 | dw_i2s_dai->capture.formats = pdata->snd_fmts; |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3843a18d4e56..aa438546c912 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -108,18 +108,13 @@ if SND_IMX_SOC | |||
108 | config SND_SOC_IMX_SSI | 108 | config SND_SOC_IMX_SSI |
109 | tristate | 109 | tristate |
110 | 110 | ||
111 | config SND_SOC_IMX_PCM | ||
112 | tristate | ||
113 | |||
114 | config SND_SOC_IMX_PCM_FIQ | 111 | config SND_SOC_IMX_PCM_FIQ |
115 | bool | 112 | bool |
116 | select FIQ | 113 | select FIQ |
117 | select SND_SOC_IMX_PCM | ||
118 | 114 | ||
119 | config SND_SOC_IMX_PCM_DMA | 115 | config SND_SOC_IMX_PCM_DMA |
120 | bool | 116 | bool |
121 | select SND_SOC_GENERIC_DMAENGINE_PCM | 117 | select SND_SOC_GENERIC_DMAENGINE_PCM |
122 | select SND_SOC_IMX_PCM | ||
123 | 118 | ||
124 | config SND_SOC_IMX_AUDMUX | 119 | config SND_SOC_IMX_AUDMUX |
125 | tristate | 120 | tristate |
@@ -173,6 +168,18 @@ config SND_SOC_EUKREA_TLV320 | |||
173 | Enable I2S based access to the TLV320AIC23B codec attached | 168 | Enable I2S based access to the TLV320AIC23B codec attached |
174 | to the SSI interface | 169 | to the SSI interface |
175 | 170 | ||
171 | config SND_SOC_IMX_WM8962 | ||
172 | tristate "SoC Audio support for i.MX boards with wm8962" | ||
173 | depends on OF && I2C | ||
174 | select SND_SOC_WM8962 | ||
175 | select SND_SOC_IMX_PCM_DMA | ||
176 | select SND_SOC_IMX_AUDMUX | ||
177 | select SND_SOC_FSL_SSI | ||
178 | select SND_SOC_FSL_UTILS | ||
179 | help | ||
180 | Say Y if you want to add support for SoC audio on an i.MX board with | ||
181 | a wm8962 codec. | ||
182 | |||
176 | config SND_SOC_IMX_SGTL5000 | 183 | config SND_SOC_IMX_SGTL5000 |
177 | tristate "SoC Audio support for i.MX boards with sgtl5000" | 184 | tristate "SoC Audio support for i.MX boards with sgtl5000" |
178 | depends on OF && I2C | 185 | depends on OF && I2C |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index afd34794db53..d4b4aa8b5649 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -30,18 +30,11 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o | |||
30 | # i.MX Platform Support | 30 | # i.MX Platform Support |
31 | snd-soc-imx-ssi-objs := imx-ssi.o | 31 | snd-soc-imx-ssi-objs := imx-ssi.o |
32 | snd-soc-imx-audmux-objs := imx-audmux.o | 32 | snd-soc-imx-audmux-objs := imx-audmux.o |
33 | snd-soc-imx-pcm-objs := imx-pcm.o | ||
34 | ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),) | ||
35 | snd-soc-imx-pcm-objs += imx-pcm-fiq.o | ||
36 | endif | ||
37 | ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),) | ||
38 | snd-soc-imx-pcm-objs += imx-pcm-dma.o | ||
39 | endif | ||
40 | |||
41 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o | 33 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o |
42 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o | 34 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o |
43 | 35 | ||
44 | obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o | 36 | obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o |
37 | obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o | ||
45 | 38 | ||
46 | # i.MX Machine Support | 39 | # i.MX Machine Support |
47 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | 40 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o |
@@ -49,6 +42,7 @@ snd-soc-phycore-ac97-objs := phycore-ac97.o | |||
49 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | 42 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o |
50 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 43 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
51 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o | 44 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o |
45 | snd-soc-imx-wm8962-objs := imx-wm8962.o | ||
52 | snd-soc-imx-mc13783-objs := imx-mc13783.o | 46 | snd-soc-imx-mc13783-objs := imx-mc13783.o |
53 | 47 | ||
54 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | 48 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o |
@@ -56,4 +50,5 @@ obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o | |||
56 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | 50 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o |
57 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 51 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
58 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o | 52 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o |
53 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o | ||
59 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o | 54 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o |
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 75ffdf0e2aad..9a4a0ca2c1de 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
@@ -80,7 +80,7 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { | |||
80 | .name = "tlv320aic23", | 80 | .name = "tlv320aic23", |
81 | .stream_name = "TLV320AIC23", | 81 | .stream_name = "TLV320AIC23", |
82 | .codec_dai_name = "tlv320aic23-hifi", | 82 | .codec_dai_name = "tlv320aic23-hifi", |
83 | .platform_name = "imx-fiq-pcm-audio.0", | 83 | .platform_name = "imx-ssi.0", |
84 | .codec_name = "tlv320aic23-codec.0-001a", | 84 | .codec_name = "tlv320aic23-codec.0-001a", |
85 | .cpu_dai_name = "imx-ssi.0", | 85 | .cpu_dai_name = "imx-ssi.0", |
86 | .ops = &eukrea_tlv320_snd_ops, | 86 | .ops = &eukrea_tlv320_snd_ops, |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 0f0bed6def9e..2f2d837df07f 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -122,7 +122,6 @@ struct fsl_ssi_private { | |||
122 | bool new_binding; | 122 | bool new_binding; |
123 | bool ssi_on_imx; | 123 | bool ssi_on_imx; |
124 | struct clk *clk; | 124 | struct clk *clk; |
125 | struct platform_device *imx_pcm_pdev; | ||
126 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 125 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
127 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 126 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
128 | struct imx_dma_data filter_data_tx; | 127 | struct imx_dma_data filter_data_tx; |
@@ -809,13 +808,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
809 | } | 808 | } |
810 | 809 | ||
811 | if (ssi_private->ssi_on_imx) { | 810 | if (ssi_private->ssi_on_imx) { |
812 | ssi_private->imx_pcm_pdev = | 811 | ret = imx_pcm_dma_init(pdev); |
813 | platform_device_register_simple("imx-pcm-audio", | 812 | if (ret) |
814 | -1, NULL, 0); | ||
815 | if (IS_ERR(ssi_private->imx_pcm_pdev)) { | ||
816 | ret = PTR_ERR(ssi_private->imx_pcm_pdev); | ||
817 | goto error_dev; | 813 | goto error_dev; |
818 | } | ||
819 | } | 814 | } |
820 | 815 | ||
821 | /* | 816 | /* |
@@ -854,7 +849,7 @@ done: | |||
854 | 849 | ||
855 | error_dai: | 850 | error_dai: |
856 | if (ssi_private->ssi_on_imx) | 851 | if (ssi_private->ssi_on_imx) |
857 | platform_device_unregister(ssi_private->imx_pcm_pdev); | 852 | imx_pcm_dma_exit(pdev); |
858 | snd_soc_unregister_component(&pdev->dev); | 853 | snd_soc_unregister_component(&pdev->dev); |
859 | 854 | ||
860 | error_dev: | 855 | error_dev: |
@@ -889,7 +884,7 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
889 | if (!ssi_private->new_binding) | 884 | if (!ssi_private->new_binding) |
890 | platform_device_unregister(ssi_private->pdev); | 885 | platform_device_unregister(ssi_private->pdev); |
891 | if (ssi_private->ssi_on_imx) { | 886 | if (ssi_private->ssi_on_imx) { |
892 | platform_device_unregister(ssi_private->imx_pcm_pdev); | 887 | imx_pcm_dma_exit(pdev); |
893 | clk_disable_unprepare(ssi_private->clk); | 888 | clk_disable_unprepare(ssi_private->clk); |
894 | clk_put(ssi_private->clk); | 889 | clk_put(ssi_private->clk); |
895 | } | 890 | } |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 47f046a8fdab..e260f1f899db 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/pinctrl/consumer.h> | ||
30 | 29 | ||
31 | #include "imx-audmux.h" | 30 | #include "imx-audmux.h" |
32 | 31 | ||
@@ -247,7 +246,6 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); | |||
247 | static int imx_audmux_probe(struct platform_device *pdev) | 246 | static int imx_audmux_probe(struct platform_device *pdev) |
248 | { | 247 | { |
249 | struct resource *res; | 248 | struct resource *res; |
250 | struct pinctrl *pinctrl; | ||
251 | const struct of_device_id *of_id = | 249 | const struct of_device_id *of_id = |
252 | of_match_device(imx_audmux_dt_ids, &pdev->dev); | 250 | of_match_device(imx_audmux_dt_ids, &pdev->dev); |
253 | 251 | ||
@@ -256,12 +254,6 @@ static int imx_audmux_probe(struct platform_device *pdev) | |||
256 | if (IS_ERR(audmux_base)) | 254 | if (IS_ERR(audmux_base)) |
257 | return PTR_ERR(audmux_base); | 255 | return PTR_ERR(audmux_base); |
258 | 256 | ||
259 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
260 | if (IS_ERR(pinctrl)) { | ||
261 | dev_err(&pdev->dev, "setup pinctrl failed!"); | ||
262 | return PTR_ERR(pinctrl); | ||
263 | } | ||
264 | |||
265 | audmux_clk = devm_clk_get(&pdev->dev, "audmux"); | 257 | audmux_clk = devm_clk_get(&pdev->dev, "audmux"); |
266 | if (IS_ERR(audmux_clk)) { | 258 | if (IS_ERR(audmux_clk)) { |
267 | dev_dbg(&pdev->dev, "cannot get clock: %ld\n", | 259 | dev_dbg(&pdev->dev, "cannot get clock: %ld\n", |
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 4ae30f21fdb5..9df173c091a6 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
@@ -64,7 +64,7 @@ static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = { | |||
64 | .codec_dai_name = "mc13783-hifi", | 64 | .codec_dai_name = "mc13783-hifi", |
65 | .codec_name = "mc13783-codec", | 65 | .codec_name = "mc13783-codec", |
66 | .cpu_dai_name = "imx-ssi.0", | 66 | .cpu_dai_name = "imx-ssi.0", |
67 | .platform_name = "imx-pcm-audio.0", | 67 | .platform_name = "imx-ssi.0", |
68 | .ops = &imx_mc13783_hifi_ops, | 68 | .ops = &imx_mc13783_hifi_ops, |
69 | .symmetric_rates = 1, | 69 | .symmetric_rates = 1, |
70 | .dai_fmt = FMT_SSI, | 70 | .dai_fmt = FMT_SSI, |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index c246fb514930..fde4d2ea68c8 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -67,8 +67,10 @@ int imx_pcm_dma_init(struct platform_device *pdev) | |||
67 | SND_DMAENGINE_PCM_FLAG_NO_DT | | 67 | SND_DMAENGINE_PCM_FLAG_NO_DT | |
68 | SND_DMAENGINE_PCM_FLAG_COMPAT); | 68 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
69 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | ||
70 | 71 | ||
71 | void imx_pcm_dma_exit(struct platform_device *pdev) | 72 | void imx_pcm_dma_exit(struct platform_device *pdev) |
72 | { | 73 | { |
73 | snd_dmaengine_pcm_unregister(&pdev->dev); | 74 | snd_dmaengine_pcm_unregister(&pdev->dev); |
74 | } | 75 | } |
76 | EXPORT_SYMBOL_GPL(imx_pcm_dma_exit); | ||
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 670b96b0ce2f..310d90290320 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
@@ -225,6 +225,22 @@ static int snd_imx_close(struct snd_pcm_substream *substream) | |||
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | ||
229 | struct vm_area_struct *vma) | ||
230 | { | ||
231 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
232 | int ret; | ||
233 | |||
234 | ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
235 | runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); | ||
236 | |||
237 | pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, | ||
238 | runtime->dma_area, | ||
239 | runtime->dma_addr, | ||
240 | runtime->dma_bytes); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
228 | static struct snd_pcm_ops imx_pcm_ops = { | 244 | static struct snd_pcm_ops imx_pcm_ops = { |
229 | .open = snd_imx_open, | 245 | .open = snd_imx_open, |
230 | .close = snd_imx_close, | 246 | .close = snd_imx_close, |
@@ -236,6 +252,54 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
236 | .mmap = snd_imx_pcm_mmap, | 252 | .mmap = snd_imx_pcm_mmap, |
237 | }; | 253 | }; |
238 | 254 | ||
255 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
256 | { | ||
257 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
258 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
259 | size_t size = IMX_SSI_DMABUF_SIZE; | ||
260 | |||
261 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
262 | buf->dev.dev = pcm->card->dev; | ||
263 | buf->private_data = NULL; | ||
264 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
265 | &buf->addr, GFP_KERNEL); | ||
266 | if (!buf->area) | ||
267 | return -ENOMEM; | ||
268 | buf->bytes = size; | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); | ||
274 | |||
275 | static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
276 | { | ||
277 | struct snd_card *card = rtd->card->snd_card; | ||
278 | struct snd_pcm *pcm = rtd->pcm; | ||
279 | int ret = 0; | ||
280 | |||
281 | if (!card->dev->dma_mask) | ||
282 | card->dev->dma_mask = &imx_pcm_dmamask; | ||
283 | if (!card->dev->coherent_dma_mask) | ||
284 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
285 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
286 | ret = imx_pcm_preallocate_dma_buffer(pcm, | ||
287 | SNDRV_PCM_STREAM_PLAYBACK); | ||
288 | if (ret) | ||
289 | goto out; | ||
290 | } | ||
291 | |||
292 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
293 | ret = imx_pcm_preallocate_dma_buffer(pcm, | ||
294 | SNDRV_PCM_STREAM_CAPTURE); | ||
295 | if (ret) | ||
296 | goto out; | ||
297 | } | ||
298 | |||
299 | out: | ||
300 | return ret; | ||
301 | } | ||
302 | |||
239 | static int ssi_irq = 0; | 303 | static int ssi_irq = 0; |
240 | 304 | ||
241 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) | 305 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) |
@@ -268,6 +332,27 @@ static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) | |||
268 | return 0; | 332 | return 0; |
269 | } | 333 | } |
270 | 334 | ||
335 | static void imx_pcm_free(struct snd_pcm *pcm) | ||
336 | { | ||
337 | struct snd_pcm_substream *substream; | ||
338 | struct snd_dma_buffer *buf; | ||
339 | int stream; | ||
340 | |||
341 | for (stream = 0; stream < 2; stream++) { | ||
342 | substream = pcm->streams[stream].substream; | ||
343 | if (!substream) | ||
344 | continue; | ||
345 | |||
346 | buf = &substream->dma_buffer; | ||
347 | if (!buf->area) | ||
348 | continue; | ||
349 | |||
350 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
351 | buf->area, buf->addr); | ||
352 | buf->area = NULL; | ||
353 | } | ||
354 | } | ||
355 | |||
271 | static void imx_pcm_fiq_free(struct snd_pcm *pcm) | 356 | static void imx_pcm_fiq_free(struct snd_pcm *pcm) |
272 | { | 357 | { |
273 | mxc_set_irq_fiq(ssi_irq, 0); | 358 | mxc_set_irq_fiq(ssi_irq, 0); |
@@ -314,3 +399,10 @@ failed_register: | |||
314 | 399 | ||
315 | return ret; | 400 | return ret; |
316 | } | 401 | } |
402 | EXPORT_SYMBOL_GPL(imx_pcm_fiq_init); | ||
403 | |||
404 | void imx_pcm_fiq_exit(struct platform_device *pdev) | ||
405 | { | ||
406 | snd_soc_unregister_platform(&pdev->dev); | ||
407 | } | ||
408 | EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit); | ||
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c deleted file mode 100644 index c49896442d8e..000000000000 --- a/sound/soc/fsl/imx-pcm.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> | ||
3 | * | ||
4 | * This code is based on code copyrighted by Freescale, | ||
5 | * Liam Girdwood, Javier Martin and probably others. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | ||
17 | #include "imx-pcm.h" | ||
18 | |||
19 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | ||
20 | struct vm_area_struct *vma) | ||
21 | { | ||
22 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
23 | int ret; | ||
24 | |||
25 | ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
26 | runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); | ||
27 | |||
28 | pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, | ||
29 | runtime->dma_area, | ||
30 | runtime->dma_addr, | ||
31 | runtime->dma_bytes); | ||
32 | return ret; | ||
33 | } | ||
34 | EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); | ||
35 | |||
36 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
37 | { | ||
38 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
39 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
40 | size_t size = IMX_SSI_DMABUF_SIZE; | ||
41 | |||
42 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
43 | buf->dev.dev = pcm->card->dev; | ||
44 | buf->private_data = NULL; | ||
45 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
46 | &buf->addr, GFP_KERNEL); | ||
47 | if (!buf->area) | ||
48 | return -ENOMEM; | ||
49 | buf->bytes = size; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); | ||
55 | |||
56 | int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
57 | { | ||
58 | struct snd_card *card = rtd->card->snd_card; | ||
59 | struct snd_pcm *pcm = rtd->pcm; | ||
60 | int ret = 0; | ||
61 | |||
62 | if (!card->dev->dma_mask) | ||
63 | card->dev->dma_mask = &imx_pcm_dmamask; | ||
64 | if (!card->dev->coherent_dma_mask) | ||
65 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
66 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
67 | ret = imx_pcm_preallocate_dma_buffer(pcm, | ||
68 | SNDRV_PCM_STREAM_PLAYBACK); | ||
69 | if (ret) | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
74 | ret = imx_pcm_preallocate_dma_buffer(pcm, | ||
75 | SNDRV_PCM_STREAM_CAPTURE); | ||
76 | if (ret) | ||
77 | goto out; | ||
78 | } | ||
79 | |||
80 | out: | ||
81 | return ret; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(imx_pcm_new); | ||
84 | |||
85 | void imx_pcm_free(struct snd_pcm *pcm) | ||
86 | { | ||
87 | struct snd_pcm_substream *substream; | ||
88 | struct snd_dma_buffer *buf; | ||
89 | int stream; | ||
90 | |||
91 | for (stream = 0; stream < 2; stream++) { | ||
92 | substream = pcm->streams[stream].substream; | ||
93 | if (!substream) | ||
94 | continue; | ||
95 | |||
96 | buf = &substream->dma_buffer; | ||
97 | if (!buf->area) | ||
98 | continue; | ||
99 | |||
100 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
101 | buf->area, buf->addr); | ||
102 | buf->area = NULL; | ||
103 | } | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(imx_pcm_free); | ||
106 | |||
107 | static int imx_pcm_probe(struct platform_device *pdev) | ||
108 | { | ||
109 | if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0) | ||
110 | return imx_pcm_fiq_init(pdev); | ||
111 | |||
112 | return imx_pcm_dma_init(pdev); | ||
113 | } | ||
114 | |||
115 | static int imx_pcm_remove(struct platform_device *pdev) | ||
116 | { | ||
117 | if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0) | ||
118 | snd_soc_unregister_platform(&pdev->dev); | ||
119 | else | ||
120 | imx_pcm_dma_exit(pdev); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct platform_device_id imx_pcm_devtype[] = { | ||
126 | { .name = "imx-pcm-audio", }, | ||
127 | { .name = "imx-fiq-pcm-audio", }, | ||
128 | { /* sentinel */ } | ||
129 | }; | ||
130 | MODULE_DEVICE_TABLE(platform, imx_pcm_devtype); | ||
131 | |||
132 | static struct platform_driver imx_pcm_driver = { | ||
133 | .driver = { | ||
134 | .name = "imx-pcm", | ||
135 | .owner = THIS_MODULE, | ||
136 | }, | ||
137 | .id_table = imx_pcm_devtype, | ||
138 | .probe = imx_pcm_probe, | ||
139 | .remove = imx_pcm_remove, | ||
140 | }; | ||
141 | module_platform_driver(imx_pcm_driver); | ||
142 | |||
143 | MODULE_DESCRIPTION("Freescale i.MX PCM driver"); | ||
144 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
145 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index b7fa0d75c687..67f656c7c320 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h | |||
@@ -32,11 +32,6 @@ imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, | |||
32 | dma_data->peripheral_type = IMX_DMATYPE_SSI; | 32 | dma_data->peripheral_type = IMX_DMATYPE_SSI; |
33 | } | 33 | } |
34 | 34 | ||
35 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | ||
36 | struct vm_area_struct *vma); | ||
37 | int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); | ||
38 | void imx_pcm_free(struct snd_pcm *pcm); | ||
39 | |||
40 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA | 35 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA |
41 | int imx_pcm_dma_init(struct platform_device *pdev); | 36 | int imx_pcm_dma_init(struct platform_device *pdev); |
42 | void imx_pcm_dma_exit(struct platform_device *pdev); | 37 | void imx_pcm_dma_exit(struct platform_device *pdev); |
@@ -53,11 +48,16 @@ static inline void imx_pcm_dma_exit(struct platform_device *pdev) | |||
53 | 48 | ||
54 | #ifdef CONFIG_SND_SOC_IMX_PCM_FIQ | 49 | #ifdef CONFIG_SND_SOC_IMX_PCM_FIQ |
55 | int imx_pcm_fiq_init(struct platform_device *pdev); | 50 | int imx_pcm_fiq_init(struct platform_device *pdev); |
51 | void imx_pcm_fiq_exit(struct platform_device *pdev); | ||
56 | #else | 52 | #else |
57 | static inline int imx_pcm_fiq_init(struct platform_device *pdev) | 53 | static inline int imx_pcm_fiq_init(struct platform_device *pdev) |
58 | { | 54 | { |
59 | return -ENODEV; | 55 | return -ENODEV; |
60 | } | 56 | } |
57 | |||
58 | static inline void imx_pcm_fiq_exit(struct platform_device *pdev) | ||
59 | { | ||
60 | } | ||
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | #endif /* _IMX_PCM_H */ | 63 | #endif /* _IMX_PCM_H */ |
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 9584e78858df..7a8bc1220b2e 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c | |||
@@ -128,28 +128,18 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
128 | goto fail; | 128 | goto fail; |
129 | } | 129 | } |
130 | 130 | ||
131 | data->codec_clk = clk_get(&codec_dev->dev, NULL); | 131 | data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); |
132 | if (IS_ERR(data->codec_clk)) { | 132 | if (IS_ERR(data->codec_clk)) |
133 | /* assuming clock enabled by default */ | 133 | goto fail; |
134 | data->codec_clk = NULL; | 134 | |
135 | ret = of_property_read_u32(codec_np, "clock-frequency", | 135 | data->clk_frequency = clk_get_rate(data->codec_clk); |
136 | &data->clk_frequency); | ||
137 | if (ret) { | ||
138 | dev_err(&codec_dev->dev, | ||
139 | "clock-frequency missing or invalid\n"); | ||
140 | goto fail; | ||
141 | } | ||
142 | } else { | ||
143 | data->clk_frequency = clk_get_rate(data->codec_clk); | ||
144 | clk_prepare_enable(data->codec_clk); | ||
145 | } | ||
146 | 136 | ||
147 | data->dai.name = "HiFi"; | 137 | data->dai.name = "HiFi"; |
148 | data->dai.stream_name = "HiFi"; | 138 | data->dai.stream_name = "HiFi"; |
149 | data->dai.codec_dai_name = "sgtl5000"; | 139 | data->dai.codec_dai_name = "sgtl5000"; |
150 | data->dai.codec_of_node = codec_np; | 140 | data->dai.codec_of_node = codec_np; |
151 | data->dai.cpu_of_node = ssi_np; | 141 | data->dai.cpu_of_node = ssi_np; |
152 | data->dai.platform_name = "imx-pcm-audio"; | 142 | data->dai.platform_of_node = ssi_np; |
153 | data->dai.init = &imx_sgtl5000_dai_init; | 143 | data->dai.init = &imx_sgtl5000_dai_init; |
154 | data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 144 | data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
155 | SND_SOC_DAIFMT_CBM_CFM; | 145 | SND_SOC_DAIFMT_CBM_CFM; |
@@ -157,10 +147,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
157 | data->card.dev = &pdev->dev; | 147 | data->card.dev = &pdev->dev; |
158 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 148 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
159 | if (ret) | 149 | if (ret) |
160 | goto clk_fail; | 150 | goto fail; |
161 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); | 151 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); |
162 | if (ret) | 152 | if (ret) |
163 | goto clk_fail; | 153 | goto fail; |
164 | data->card.num_links = 1; | 154 | data->card.num_links = 1; |
165 | data->card.owner = THIS_MODULE; | 155 | data->card.owner = THIS_MODULE; |
166 | data->card.dai_link = &data->dai; | 156 | data->card.dai_link = &data->dai; |
@@ -170,12 +160,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
170 | ret = snd_soc_register_card(&data->card); | 160 | ret = snd_soc_register_card(&data->card); |
171 | if (ret) { | 161 | if (ret) { |
172 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 162 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
173 | goto clk_fail; | 163 | goto fail; |
174 | } | 164 | } |
175 | 165 | ||
176 | platform_set_drvdata(pdev, data); | 166 | platform_set_drvdata(pdev, data); |
177 | clk_fail: | 167 | of_node_put(ssi_np); |
178 | clk_put(data->codec_clk); | 168 | of_node_put(codec_np); |
169 | |||
170 | return 0; | ||
171 | |||
179 | fail: | 172 | fail: |
180 | if (ssi_np) | 173 | if (ssi_np) |
181 | of_node_put(ssi_np); | 174 | of_node_put(ssi_np); |
@@ -189,10 +182,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev) | |||
189 | { | 182 | { |
190 | struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); | 183 | struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); |
191 | 184 | ||
192 | if (data->codec_clk) { | ||
193 | clk_disable_unprepare(data->codec_clk); | ||
194 | clk_put(data->codec_clk); | ||
195 | } | ||
196 | snd_soc_unregister_card(&data->card); | 185 | snd_soc_unregister_card(&data->card); |
197 | 186 | ||
198 | return 0; | 187 | return 0; |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index bd40849454a8..51be3772cba9 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -595,41 +595,19 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
595 | goto failed_register; | 595 | goto failed_register; |
596 | } | 596 | } |
597 | 597 | ||
598 | ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); | 598 | ret = imx_pcm_fiq_init(pdev); |
599 | if (!ssi->soc_platform_pdev_fiq) { | 599 | if (ret) |
600 | ret = -ENOMEM; | 600 | goto failed_pcm_fiq; |
601 | goto failed_pdev_fiq_alloc; | ||
602 | } | ||
603 | |||
604 | platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi); | ||
605 | ret = platform_device_add(ssi->soc_platform_pdev_fiq); | ||
606 | if (ret) { | ||
607 | dev_err(&pdev->dev, "failed to add platform device\n"); | ||
608 | goto failed_pdev_fiq_add; | ||
609 | } | ||
610 | 601 | ||
611 | ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id); | 602 | ret = imx_pcm_dma_init(pdev); |
612 | if (!ssi->soc_platform_pdev) { | 603 | if (ret) |
613 | ret = -ENOMEM; | 604 | goto failed_pcm_dma; |
614 | goto failed_pdev_alloc; | ||
615 | } | ||
616 | |||
617 | platform_set_drvdata(ssi->soc_platform_pdev, ssi); | ||
618 | ret = platform_device_add(ssi->soc_platform_pdev); | ||
619 | if (ret) { | ||
620 | dev_err(&pdev->dev, "failed to add platform device\n"); | ||
621 | goto failed_pdev_add; | ||
622 | } | ||
623 | 605 | ||
624 | return 0; | 606 | return 0; |
625 | 607 | ||
626 | failed_pdev_add: | 608 | failed_pcm_dma: |
627 | platform_device_put(ssi->soc_platform_pdev); | 609 | imx_pcm_fiq_exit(pdev); |
628 | failed_pdev_alloc: | 610 | failed_pcm_fiq: |
629 | platform_device_del(ssi->soc_platform_pdev_fiq); | ||
630 | failed_pdev_fiq_add: | ||
631 | platform_device_put(ssi->soc_platform_pdev_fiq); | ||
632 | failed_pdev_fiq_alloc: | ||
633 | snd_soc_unregister_component(&pdev->dev); | 611 | snd_soc_unregister_component(&pdev->dev); |
634 | failed_register: | 612 | failed_register: |
635 | release_mem_region(res->start, resource_size(res)); | 613 | release_mem_region(res->start, resource_size(res)); |
@@ -645,8 +623,8 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
645 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 623 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
646 | struct imx_ssi *ssi = platform_get_drvdata(pdev); | 624 | struct imx_ssi *ssi = platform_get_drvdata(pdev); |
647 | 625 | ||
648 | platform_device_unregister(ssi->soc_platform_pdev); | 626 | imx_pcm_dma_exit(pdev); |
649 | platform_device_unregister(ssi->soc_platform_pdev_fiq); | 627 | imx_pcm_fiq_exit(pdev); |
650 | 628 | ||
651 | snd_soc_unregister_component(&pdev->dev); | 629 | snd_soc_unregister_component(&pdev->dev); |
652 | 630 | ||
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h index bb6b3dbb13fd..d5003cefca8d 100644 --- a/sound/soc/fsl/imx-ssi.h +++ b/sound/soc/fsl/imx-ssi.h | |||
@@ -211,9 +211,6 @@ struct imx_ssi { | |||
211 | struct imx_dma_data filter_data_rx; | 211 | struct imx_dma_data filter_data_rx; |
212 | 212 | ||
213 | int enabled; | 213 | int enabled; |
214 | |||
215 | struct platform_device *soc_platform_pdev; | ||
216 | struct platform_device *soc_platform_pdev_fiq; | ||
217 | }; | 214 | }; |
218 | 215 | ||
219 | #endif /* _IMX_SSI_H */ | 216 | #endif /* _IMX_SSI_H */ |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c new file mode 100644 index 000000000000..52a36a90f4f4 --- /dev/null +++ b/sound/soc/fsl/imx-wm8962.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * Based on imx-sgtl5000.c | ||
5 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
6 | * Copyright 2012 Linaro Ltd. | ||
7 | * | ||
8 | * The code contained herein is licensed under the GNU General Public | ||
9 | * License. You may obtain a copy of the GNU General Public License | ||
10 | * Version 2 or later at the following locations: | ||
11 | * | ||
12 | * http://www.opensource.org/licenses/gpl-license.html | ||
13 | * http://www.gnu.org/copyleft/gpl.html | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/of_i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc-dapm.h> | ||
24 | #include <linux/pinctrl/consumer.h> | ||
25 | |||
26 | #include "../codecs/wm8962.h" | ||
27 | #include "imx-audmux.h" | ||
28 | |||
29 | #define DAI_NAME_SIZE 32 | ||
30 | |||
31 | struct imx_wm8962_data { | ||
32 | struct snd_soc_dai_link dai; | ||
33 | struct snd_soc_card card; | ||
34 | char codec_dai_name[DAI_NAME_SIZE]; | ||
35 | char platform_name[DAI_NAME_SIZE]; | ||
36 | struct clk *codec_clk; | ||
37 | unsigned int clk_frequency; | ||
38 | }; | ||
39 | |||
40 | struct imx_priv { | ||
41 | struct platform_device *pdev; | ||
42 | }; | ||
43 | static struct imx_priv card_priv; | ||
44 | |||
45 | static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = { | ||
46 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
47 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
48 | SND_SOC_DAPM_MIC("AMIC", NULL), | ||
49 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
50 | }; | ||
51 | |||
52 | static int sample_rate = 44100; | ||
53 | static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE; | ||
54 | |||
55 | static int imx_hifi_hw_params(struct snd_pcm_substream *substream, | ||
56 | struct snd_pcm_hw_params *params) | ||
57 | { | ||
58 | sample_rate = params_rate(params); | ||
59 | sample_format = params_format(params); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static struct snd_soc_ops imx_hifi_ops = { | ||
65 | .hw_params = imx_hifi_hw_params, | ||
66 | }; | ||
67 | |||
68 | static int imx_wm8962_set_bias_level(struct snd_soc_card *card, | ||
69 | struct snd_soc_dapm_context *dapm, | ||
70 | enum snd_soc_bias_level level) | ||
71 | { | ||
72 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
73 | struct imx_priv *priv = &card_priv; | ||
74 | struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); | ||
75 | struct device *dev = &priv->pdev->dev; | ||
76 | unsigned int pll_out; | ||
77 | int ret; | ||
78 | |||
79 | if (dapm->dev != codec_dai->dev) | ||
80 | return 0; | ||
81 | |||
82 | switch (level) { | ||
83 | case SND_SOC_BIAS_PREPARE: | ||
84 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
85 | if (sample_format == SNDRV_PCM_FORMAT_S24_LE) | ||
86 | pll_out = sample_rate * 384; | ||
87 | else | ||
88 | pll_out = sample_rate * 256; | ||
89 | |||
90 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | ||
91 | WM8962_FLL_MCLK, data->clk_frequency, | ||
92 | pll_out); | ||
93 | if (ret < 0) { | ||
94 | dev_err(dev, "failed to start FLL: %d\n", ret); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
99 | WM8962_SYSCLK_FLL, pll_out, | ||
100 | SND_SOC_CLOCK_IN); | ||
101 | if (ret < 0) { | ||
102 | dev_err(dev, "failed to set SYSCLK: %d\n", ret); | ||
103 | return ret; | ||
104 | } | ||
105 | } | ||
106 | break; | ||
107 | |||
108 | case SND_SOC_BIAS_STANDBY: | ||
109 | if (dapm->bias_level == SND_SOC_BIAS_PREPARE) { | ||
110 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
111 | WM8962_SYSCLK_MCLK, data->clk_frequency, | ||
112 | SND_SOC_CLOCK_IN); | ||
113 | if (ret < 0) { | ||
114 | dev_err(dev, | ||
115 | "failed to switch away from FLL: %d\n", | ||
116 | ret); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | ||
121 | 0, 0, 0); | ||
122 | if (ret < 0) { | ||
123 | dev_err(dev, "failed to stop FLL: %d\n", ret); | ||
124 | return ret; | ||
125 | } | ||
126 | } | ||
127 | break; | ||
128 | |||
129 | default: | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | dapm->bias_level = level; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int imx_wm8962_late_probe(struct snd_soc_card *card) | ||
139 | { | ||
140 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
141 | struct imx_priv *priv = &card_priv; | ||
142 | struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); | ||
143 | struct device *dev = &priv->pdev->dev; | ||
144 | int ret; | ||
145 | |||
146 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, | ||
147 | data->clk_frequency, SND_SOC_CLOCK_IN); | ||
148 | if (ret < 0) | ||
149 | dev_err(dev, "failed to set sysclk in %s\n", __func__); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int imx_wm8962_probe(struct platform_device *pdev) | ||
155 | { | ||
156 | struct device_node *np = pdev->dev.of_node; | ||
157 | struct device_node *ssi_np, *codec_np; | ||
158 | struct platform_device *ssi_pdev; | ||
159 | struct imx_priv *priv = &card_priv; | ||
160 | struct i2c_client *codec_dev; | ||
161 | struct imx_wm8962_data *data; | ||
162 | int int_port, ext_port; | ||
163 | int ret; | ||
164 | |||
165 | priv->pdev = pdev; | ||
166 | |||
167 | ret = of_property_read_u32(np, "mux-int-port", &int_port); | ||
168 | if (ret) { | ||
169 | dev_err(&pdev->dev, "mux-int-port missing or invalid\n"); | ||
170 | return ret; | ||
171 | } | ||
172 | ret = of_property_read_u32(np, "mux-ext-port", &ext_port); | ||
173 | if (ret) { | ||
174 | dev_err(&pdev->dev, "mux-ext-port missing or invalid\n"); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * The port numbering in the hardware manual starts at 1, while | ||
180 | * the audmux API expects it starts at 0. | ||
181 | */ | ||
182 | int_port--; | ||
183 | ext_port--; | ||
184 | ret = imx_audmux_v2_configure_port(int_port, | ||
185 | IMX_AUDMUX_V2_PTCR_SYN | | ||
186 | IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | | ||
187 | IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | | ||
188 | IMX_AUDMUX_V2_PTCR_TFSDIR | | ||
189 | IMX_AUDMUX_V2_PTCR_TCLKDIR, | ||
190 | IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); | ||
191 | if (ret) { | ||
192 | dev_err(&pdev->dev, "audmux internal port setup failed\n"); | ||
193 | return ret; | ||
194 | } | ||
195 | imx_audmux_v2_configure_port(ext_port, | ||
196 | IMX_AUDMUX_V2_PTCR_SYN, | ||
197 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | ||
198 | if (ret) { | ||
199 | dev_err(&pdev->dev, "audmux external port setup failed\n"); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0); | ||
204 | codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); | ||
205 | if (!ssi_np || !codec_np) { | ||
206 | dev_err(&pdev->dev, "phandle missing or invalid\n"); | ||
207 | ret = -EINVAL; | ||
208 | goto fail; | ||
209 | } | ||
210 | |||
211 | ssi_pdev = of_find_device_by_node(ssi_np); | ||
212 | if (!ssi_pdev) { | ||
213 | dev_err(&pdev->dev, "failed to find SSI platform device\n"); | ||
214 | ret = -EINVAL; | ||
215 | goto fail; | ||
216 | } | ||
217 | codec_dev = of_find_i2c_device_by_node(codec_np); | ||
218 | if (!codec_dev || !codec_dev->driver) { | ||
219 | dev_err(&pdev->dev, "failed to find codec platform device\n"); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
224 | if (!data) { | ||
225 | ret = -ENOMEM; | ||
226 | goto fail; | ||
227 | } | ||
228 | |||
229 | data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); | ||
230 | if (IS_ERR(data->codec_clk)) { | ||
231 | ret = PTR_ERR(data->codec_clk); | ||
232 | dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret); | ||
233 | goto fail; | ||
234 | } | ||
235 | |||
236 | data->clk_frequency = clk_get_rate(data->codec_clk); | ||
237 | ret = clk_prepare_enable(data->codec_clk); | ||
238 | if (ret) { | ||
239 | dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret); | ||
240 | goto fail; | ||
241 | } | ||
242 | |||
243 | data->dai.name = "HiFi"; | ||
244 | data->dai.stream_name = "HiFi"; | ||
245 | data->dai.codec_dai_name = "wm8962"; | ||
246 | data->dai.codec_of_node = codec_np; | ||
247 | data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev); | ||
248 | data->dai.platform_of_node = ssi_np; | ||
249 | data->dai.ops = &imx_hifi_ops; | ||
250 | data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
251 | SND_SOC_DAIFMT_CBM_CFM; | ||
252 | |||
253 | data->card.dev = &pdev->dev; | ||
254 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | ||
255 | if (ret) | ||
256 | goto clk_fail; | ||
257 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); | ||
258 | if (ret) | ||
259 | goto clk_fail; | ||
260 | data->card.num_links = 1; | ||
261 | data->card.dai_link = &data->dai; | ||
262 | data->card.dapm_widgets = imx_wm8962_dapm_widgets; | ||
263 | data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8962_dapm_widgets); | ||
264 | |||
265 | data->card.late_probe = imx_wm8962_late_probe; | ||
266 | data->card.set_bias_level = imx_wm8962_set_bias_level; | ||
267 | |||
268 | ret = snd_soc_register_card(&data->card); | ||
269 | if (ret) { | ||
270 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | ||
271 | goto clk_fail; | ||
272 | } | ||
273 | |||
274 | platform_set_drvdata(pdev, data); | ||
275 | of_node_put(ssi_np); | ||
276 | of_node_put(codec_np); | ||
277 | |||
278 | return 0; | ||
279 | |||
280 | clk_fail: | ||
281 | if (!IS_ERR(data->codec_clk)) | ||
282 | clk_disable_unprepare(data->codec_clk); | ||
283 | fail: | ||
284 | if (ssi_np) | ||
285 | of_node_put(ssi_np); | ||
286 | if (codec_np) | ||
287 | of_node_put(codec_np); | ||
288 | |||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static int imx_wm8962_remove(struct platform_device *pdev) | ||
293 | { | ||
294 | struct imx_wm8962_data *data = platform_get_drvdata(pdev); | ||
295 | |||
296 | if (!IS_ERR(data->codec_clk)) | ||
297 | clk_disable_unprepare(data->codec_clk); | ||
298 | snd_soc_unregister_card(&data->card); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static const struct of_device_id imx_wm8962_dt_ids[] = { | ||
304 | { .compatible = "fsl,imx-audio-wm8962", }, | ||
305 | { /* sentinel */ } | ||
306 | }; | ||
307 | MODULE_DEVICE_TABLE(of, imx_wm8962_dt_ids); | ||
308 | |||
309 | static struct platform_driver imx_wm8962_driver = { | ||
310 | .driver = { | ||
311 | .name = "imx-wm8962", | ||
312 | .owner = THIS_MODULE, | ||
313 | .of_match_table = imx_wm8962_dt_ids, | ||
314 | }, | ||
315 | .probe = imx_wm8962_probe, | ||
316 | .remove = imx_wm8962_remove, | ||
317 | }; | ||
318 | module_platform_driver(imx_wm8962_driver); | ||
319 | |||
320 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
321 | MODULE_DESCRIPTION("Freescale i.MX WM8962 ASoC machine driver"); | ||
322 | MODULE_LICENSE("GPL v2"); | ||
323 | MODULE_ALIAS("platform:imx-wm8962"); | ||
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index 3d1074179057..f4c3bda5e69e 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c | |||
@@ -161,7 +161,7 @@ static struct snd_soc_dai_link mx27vis_aic32x4_dai = { | |||
161 | .name = "tlv320aic32x4", | 161 | .name = "tlv320aic32x4", |
162 | .stream_name = "TLV320AIC32X4", | 162 | .stream_name = "TLV320AIC32X4", |
163 | .codec_dai_name = "tlv320aic32x4-hifi", | 163 | .codec_dai_name = "tlv320aic32x4-hifi", |
164 | .platform_name = "imx-pcm-audio.0", | 164 | .platform_name = "imx-ssi.0", |
165 | .codec_name = "tlv320aic32x4.0-0018", | 165 | .codec_name = "tlv320aic32x4.0-0018", |
166 | .cpu_dai_name = "imx-ssi.0", | 166 | .cpu_dai_name = "imx-ssi.0", |
167 | .ops = &mx27vis_aic32x4_snd_ops, | 167 | .ops = &mx27vis_aic32x4_snd_ops, |
diff --git a/sound/soc/fsl/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c index f8da6dd115ed..ae403c29688f 100644 --- a/sound/soc/fsl/phycore-ac97.c +++ b/sound/soc/fsl/phycore-ac97.c | |||
@@ -33,7 +33,7 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { | |||
33 | .codec_dai_name = "wm9712-hifi", | 33 | .codec_dai_name = "wm9712-hifi", |
34 | .codec_name = "wm9712-codec", | 34 | .codec_name = "wm9712-codec", |
35 | .cpu_dai_name = "imx-ssi.0", | 35 | .cpu_dai_name = "imx-ssi.0", |
36 | .platform_name = "imx-fiq-pcm-audio.0", | 36 | .platform_name = "imx-ssi.0", |
37 | .ops = &imx_phycore_hifi_ops, | 37 | .ops = &imx_phycore_hifi_ops, |
38 | }, | 38 | }, |
39 | }; | 39 | }; |
diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index fe54a69073e5..fce63252bdbb 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c | |||
@@ -245,7 +245,7 @@ static struct snd_soc_dai_link wm1133_ev1_dai = { | |||
245 | .stream_name = "Audio", | 245 | .stream_name = "Audio", |
246 | .cpu_dai_name = "imx-ssi.0", | 246 | .cpu_dai_name = "imx-ssi.0", |
247 | .codec_dai_name = "wm8350-hifi", | 247 | .codec_dai_name = "wm8350-hifi", |
248 | .platform_name = "imx-fiq-pcm-audio.0", | 248 | .platform_name = "imx-ssi.0", |
249 | .codec_name = "wm8350-codec.0-0x1a", | 249 | .codec_name = "wm8350-codec.0-0x1a", |
250 | .init = wm1133_ev1_init, | 250 | .init = wm1133_ev1_init, |
251 | .ops = &wm1133_ev1_ops, | 251 | .ops = &wm1133_ev1_ops, |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 9a126441c5f3..4c849a49c72a 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -118,7 +118,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream, | |||
118 | ctrl |= JZ_AIC_CTRL_FLUSH; | 118 | ctrl |= JZ_AIC_CTRL_FLUSH; |
119 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 119 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
120 | 120 | ||
121 | clk_enable(i2s->clk_i2s); | 121 | clk_prepare_enable(i2s->clk_i2s); |
122 | 122 | ||
123 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); | 123 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); |
124 | conf |= JZ_AIC_CONF_ENABLE; | 124 | conf |= JZ_AIC_CONF_ENABLE; |
@@ -140,7 +140,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, | |||
140 | conf &= ~JZ_AIC_CONF_ENABLE; | 140 | conf &= ~JZ_AIC_CONF_ENABLE; |
141 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); | 141 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); |
142 | 142 | ||
143 | clk_disable(i2s->clk_i2s); | 143 | clk_disable_unprepare(i2s->clk_i2s); |
144 | } | 144 | } |
145 | 145 | ||
146 | static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 146 | static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
@@ -314,10 +314,10 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai) | |||
314 | conf &= ~JZ_AIC_CONF_ENABLE; | 314 | conf &= ~JZ_AIC_CONF_ENABLE; |
315 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); | 315 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); |
316 | 316 | ||
317 | clk_disable(i2s->clk_i2s); | 317 | clk_disable_unprepare(i2s->clk_i2s); |
318 | } | 318 | } |
319 | 319 | ||
320 | clk_disable(i2s->clk_aic); | 320 | clk_disable_unprepare(i2s->clk_aic); |
321 | 321 | ||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
@@ -327,10 +327,10 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai) | |||
327 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 327 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
328 | uint32_t conf; | 328 | uint32_t conf; |
329 | 329 | ||
330 | clk_enable(i2s->clk_aic); | 330 | clk_prepare_enable(i2s->clk_aic); |
331 | 331 | ||
332 | if (dai->active) { | 332 | if (dai->active) { |
333 | clk_enable(i2s->clk_i2s); | 333 | clk_prepare_enable(i2s->clk_i2s); |
334 | 334 | ||
335 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); | 335 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); |
336 | conf |= JZ_AIC_CONF_ENABLE; | 336 | conf |= JZ_AIC_CONF_ENABLE; |
@@ -368,7 +368,7 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | |||
368 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 368 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
369 | uint32_t conf; | 369 | uint32_t conf; |
370 | 370 | ||
371 | clk_enable(i2s->clk_aic); | 371 | clk_prepare_enable(i2s->clk_aic); |
372 | 372 | ||
373 | jz4740_i2c_init_pcm_config(i2s); | 373 | jz4740_i2c_init_pcm_config(i2s); |
374 | 374 | ||
@@ -388,7 +388,7 @@ static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) | |||
388 | { | 388 | { |
389 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 389 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
390 | 390 | ||
391 | clk_disable(i2s->clk_aic); | 391 | clk_disable_unprepare(i2s->clk_aic); |
392 | return 0; | 392 | return 0; |
393 | } | 393 | } |
394 | 394 | ||
@@ -509,7 +509,6 @@ static int jz4740_i2s_dev_remove(struct platform_device *pdev) | |||
509 | iounmap(i2s->base); | 509 | iounmap(i2s->base); |
510 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); | 510 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); |
511 | 511 | ||
512 | platform_set_drvdata(pdev, NULL); | ||
513 | kfree(i2s); | 512 | kfree(i2s); |
514 | 513 | ||
515 | return 0; | 514 | return 0; |
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index d3d4bdca1cc6..a9f14530c3db 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -289,7 +289,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream | |||
289 | return count; | 289 | return count; |
290 | } | 290 | } |
291 | 291 | ||
292 | struct snd_pcm_ops kirkwood_dma_ops = { | 292 | static struct snd_pcm_ops kirkwood_dma_ops = { |
293 | .open = kirkwood_dma_open, | 293 | .open = kirkwood_dma_open, |
294 | .close = kirkwood_dma_close, | 294 | .close = kirkwood_dma_close, |
295 | .ioctl = snd_pcm_lib_ioctl, | 295 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index b41fffc056fb..b16abbbf7764 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -49,24 +49,8 @@ static const struct snd_pcm_hardware snd_mxs_hardware = { | |||
49 | .fifo_size = 32, | 49 | .fifo_size = 32, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static bool filter(struct dma_chan *chan, void *param) | ||
53 | { | ||
54 | struct mxs_pcm_dma_params *dma_params = param; | ||
55 | |||
56 | if (!mxs_dma_is_apbx(chan)) | ||
57 | return false; | ||
58 | |||
59 | if (chan->chan_id != dma_params->chan_num) | ||
60 | return false; | ||
61 | |||
62 | chan->private = &dma_params->dma_data; | ||
63 | |||
64 | return true; | ||
65 | } | ||
66 | |||
67 | static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { | 52 | static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { |
68 | .pcm_hardware = &snd_mxs_hardware, | 53 | .pcm_hardware = &snd_mxs_hardware, |
69 | .compat_filter_fn = filter, | ||
70 | .prealloc_buffer_size = 64 * 1024, | 54 | .prealloc_buffer_size = 64 * 1024, |
71 | }; | 55 | }; |
72 | 56 | ||
@@ -74,8 +58,6 @@ int mxs_pcm_platform_register(struct device *dev) | |||
74 | { | 58 | { |
75 | return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, | 59 | return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, |
76 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 60 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
77 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
78 | SND_DMAENGINE_PCM_FLAG_COMPAT | | ||
79 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); | 61 | SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); |
80 | } | 62 | } |
81 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); | 63 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); |
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h index 3aa918f9ed3e..bc685b67cac7 100644 --- a/sound/soc/mxs/mxs-pcm.h +++ b/sound/soc/mxs/mxs-pcm.h | |||
@@ -19,13 +19,6 @@ | |||
19 | #ifndef _MXS_PCM_H | 19 | #ifndef _MXS_PCM_H |
20 | #define _MXS_PCM_H | 20 | #define _MXS_PCM_H |
21 | 21 | ||
22 | #include <linux/fsl/mxs-dma.h> | ||
23 | |||
24 | struct mxs_pcm_dma_params { | ||
25 | struct mxs_dma_data dma_data; | ||
26 | int chan_num; | ||
27 | }; | ||
28 | |||
29 | int mxs_pcm_platform_register(struct device *dev); | 22 | int mxs_pcm_platform_register(struct device *dev); |
30 | void mxs_pcm_platform_unregister(struct device *dev); | 23 | void mxs_pcm_platform_unregister(struct device *dev); |
31 | 24 | ||
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index d31dc52fa862..49d870034bc3 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -26,8 +26,6 @@ | |||
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/fsl/mxs-dma.h> | ||
30 | #include <linux/pinctrl/consumer.h> | ||
31 | #include <sound/core.h> | 29 | #include <sound/core.h> |
32 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
@@ -605,8 +603,6 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai) | |||
605 | struct mxs_saif *saif = dev_get_drvdata(dai->dev); | 603 | struct mxs_saif *saif = dev_get_drvdata(dai->dev); |
606 | 604 | ||
607 | snd_soc_dai_set_drvdata(dai, saif); | 605 | snd_soc_dai_set_drvdata(dai, saif); |
608 | dai->playback_dma_data = &saif->dma_param; | ||
609 | dai->capture_dma_data = &saif->dma_param; | ||
610 | 606 | ||
611 | return 0; | 607 | return 0; |
612 | } | 608 | } |
@@ -665,9 +661,8 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id) | |||
665 | static int mxs_saif_probe(struct platform_device *pdev) | 661 | static int mxs_saif_probe(struct platform_device *pdev) |
666 | { | 662 | { |
667 | struct device_node *np = pdev->dev.of_node; | 663 | struct device_node *np = pdev->dev.of_node; |
668 | struct resource *iores, *dmares; | 664 | struct resource *iores; |
669 | struct mxs_saif *saif; | 665 | struct mxs_saif *saif; |
670 | struct pinctrl *pinctrl; | ||
671 | int ret = 0; | 666 | int ret = 0; |
672 | struct device_node *master; | 667 | struct device_node *master; |
673 | 668 | ||
@@ -707,12 +702,6 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
707 | 702 | ||
708 | mxs_saif[saif->id] = saif; | 703 | mxs_saif[saif->id] = saif; |
709 | 704 | ||
710 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
711 | if (IS_ERR(pinctrl)) { | ||
712 | ret = PTR_ERR(pinctrl); | ||
713 | return ret; | ||
714 | } | ||
715 | |||
716 | saif->clk = devm_clk_get(&pdev->dev, NULL); | 705 | saif->clk = devm_clk_get(&pdev->dev, NULL); |
717 | if (IS_ERR(saif->clk)) { | 706 | if (IS_ERR(saif->clk)) { |
718 | ret = PTR_ERR(saif->clk); | 707 | ret = PTR_ERR(saif->clk); |
@@ -727,22 +716,6 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
727 | if (IS_ERR(saif->base)) | 716 | if (IS_ERR(saif->base)) |
728 | return PTR_ERR(saif->base); | 717 | return PTR_ERR(saif->base); |
729 | 718 | ||
730 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
731 | if (!dmares) { | ||
732 | /* | ||
733 | * TODO: This is a temporary solution and should be changed | ||
734 | * to use generic DMA binding later when the helplers get in. | ||
735 | */ | ||
736 | ret = of_property_read_u32(np, "fsl,saif-dma-channel", | ||
737 | &saif->dma_param.chan_num); | ||
738 | if (ret) { | ||
739 | dev_err(&pdev->dev, "failed to get dma channel\n"); | ||
740 | return ret; | ||
741 | } | ||
742 | } else { | ||
743 | saif->dma_param.chan_num = dmares->start; | ||
744 | } | ||
745 | |||
746 | saif->irq = platform_get_irq(pdev, 0); | 719 | saif->irq = platform_get_irq(pdev, 0); |
747 | if (saif->irq < 0) { | 720 | if (saif->irq < 0) { |
748 | ret = saif->irq; | 721 | ret = saif->irq; |
@@ -759,14 +732,6 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
759 | return ret; | 732 | return ret; |
760 | } | 733 | } |
761 | 734 | ||
762 | saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1); | ||
763 | if (saif->dma_param.dma_data.chan_irq < 0) { | ||
764 | ret = saif->dma_param.dma_data.chan_irq; | ||
765 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | ||
766 | ret); | ||
767 | return ret; | ||
768 | } | ||
769 | |||
770 | platform_set_drvdata(pdev, saif); | 735 | platform_set_drvdata(pdev, saif); |
771 | 736 | ||
772 | ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, | 737 | ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, |
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h index 3cb342e5bc90..53eaa4bf0e27 100644 --- a/sound/soc/mxs/mxs-saif.h +++ b/sound/soc/mxs/mxs-saif.h | |||
@@ -117,7 +117,6 @@ struct mxs_saif { | |||
117 | unsigned int mclk_in_use; | 117 | unsigned int mclk_in_use; |
118 | void __iomem *base; | 118 | void __iomem *base; |
119 | int irq; | 119 | int irq; |
120 | struct mxs_pcm_dma_params dma_param; | ||
121 | unsigned int id; | 120 | unsigned int id; |
122 | unsigned int master_id; | 121 | unsigned int master_id; |
123 | unsigned int cur_rate; | 122 | unsigned int cur_rate; |
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index b1d9b5ebeeeb..1b134d72f120 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
@@ -90,17 +90,11 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { | |||
90 | .name = "HiFi Tx", | 90 | .name = "HiFi Tx", |
91 | .stream_name = "HiFi Playback", | 91 | .stream_name = "HiFi Playback", |
92 | .codec_dai_name = "sgtl5000", | 92 | .codec_dai_name = "sgtl5000", |
93 | .codec_name = "sgtl5000.0-000a", | ||
94 | .cpu_dai_name = "mxs-saif.0", | ||
95 | .platform_name = "mxs-saif.0", | ||
96 | .ops = &mxs_sgtl5000_hifi_ops, | 93 | .ops = &mxs_sgtl5000_hifi_ops, |
97 | }, { | 94 | }, { |
98 | .name = "HiFi Rx", | 95 | .name = "HiFi Rx", |
99 | .stream_name = "HiFi Capture", | 96 | .stream_name = "HiFi Capture", |
100 | .codec_dai_name = "sgtl5000", | 97 | .codec_dai_name = "sgtl5000", |
101 | .codec_name = "sgtl5000.0-000a", | ||
102 | .cpu_dai_name = "mxs-saif.1", | ||
103 | .platform_name = "mxs-saif.1", | ||
104 | .ops = &mxs_sgtl5000_hifi_ops, | 98 | .ops = &mxs_sgtl5000_hifi_ops, |
105 | }, | 99 | }, |
106 | }; | 100 | }; |
@@ -116,7 +110,7 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) | |||
116 | { | 110 | { |
117 | struct device_node *np = pdev->dev.of_node; | 111 | struct device_node *np = pdev->dev.of_node; |
118 | struct device_node *saif_np[2], *codec_np; | 112 | struct device_node *saif_np[2], *codec_np; |
119 | int i, ret = 0; | 113 | int i; |
120 | 114 | ||
121 | if (!np) | 115 | if (!np) |
122 | return 1; /* no device tree */ | 116 | return 1; /* no device tree */ |
@@ -142,7 +136,7 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) | |||
142 | of_node_put(saif_np[0]); | 136 | of_node_put(saif_np[0]); |
143 | of_node_put(saif_np[1]); | 137 | of_node_put(saif_np[1]); |
144 | 138 | ||
145 | return ret; | 139 | return 0; |
146 | } | 140 | } |
147 | 141 | ||
148 | static int mxs_sgtl5000_probe(struct platform_device *pdev) | 142 | static int mxs_sgtl5000_probe(struct platform_device *pdev) |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 60259f2f3f2c..9f5d55e6b17a 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -103,7 +103,7 @@ config SND_OMAP_SOC_OMAP_HDMI | |||
103 | tristate "SoC Audio support for Texas Instruments OMAP HDMI" | 103 | tristate "SoC Audio support for Texas Instruments OMAP HDMI" |
104 | depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS | 104 | depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS |
105 | select SND_OMAP_SOC_HDMI | 105 | select SND_OMAP_SOC_HDMI |
106 | select SND_SOC_OMAP_HDMI_CODEC | 106 | select SND_SOC_HDMI_CODEC |
107 | select OMAP4_DSS_HDMI_AUDIO | 107 | select OMAP4_DSS_HDMI_AUDIO |
108 | help | 108 | help |
109 | Say Y if you want to add support for SoC HDMI audio on Texas Instruments | 109 | Say Y if you want to add support for SoC HDMI audio on Texas Instruments |
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 2b225945359b..a725905b2c68 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -26,7 +26,6 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | |||
26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | 26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o |
27 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
28 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
29 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o | ||
30 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o |
31 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o | 30 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o |
32 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o | 31 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o |
diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c index d4eaa92e518e..7e66e9cba5a8 100644 --- a/sound/soc/omap/omap-hdmi-card.c +++ b/sound/soc/omap/omap-hdmi-card.c | |||
@@ -35,7 +35,7 @@ static struct snd_soc_dai_link omap_hdmi_dai = { | |||
35 | .cpu_dai_name = "omap-hdmi-audio-dai", | 35 | .cpu_dai_name = "omap-hdmi-audio-dai", |
36 | .platform_name = "omap-pcm-audio", | 36 | .platform_name = "omap-pcm-audio", |
37 | .codec_name = "hdmi-audio-codec", | 37 | .codec_name = "hdmi-audio-codec", |
38 | .codec_dai_name = "omap-hdmi-hifi", | 38 | .codec_dai_name = "hdmi-hifi", |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static struct snd_soc_card snd_soc_omap_hdmi = { | 41 | static struct snd_soc_card snd_soc_omap_hdmi = { |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index eadbfb6b5000..7483efb6dc67 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -814,8 +814,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) | |||
814 | 814 | ||
815 | clk_put(mcbsp->fclk); | 815 | clk_put(mcbsp->fclk); |
816 | 816 | ||
817 | platform_set_drvdata(pdev, NULL); | ||
818 | |||
819 | return 0; | 817 | return 0; |
820 | } | 818 | } |
821 | 819 | ||
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 4d2e46fae77c..b35809467547 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -130,26 +130,6 @@ config SND_PXA2XX_SOC_PALM27X | |||
130 | Say Y if you want to add support for SoC audio on | 130 | Say Y if you want to add support for SoC audio on |
131 | Palm T|X, T5, E2 or LifeDrive handheld computer. | 131 | Palm T|X, T5, E2 or LifeDrive handheld computer. |
132 | 132 | ||
133 | config SND_SOC_SAARB | ||
134 | tristate "SoC Audio support for Marvell Saarb" | ||
135 | depends on SND_PXA2XX_SOC && MACH_SAARB | ||
136 | select MFD_88PM860X | ||
137 | select SND_PXA_SOC_SSP | ||
138 | select SND_SOC_88PM860X | ||
139 | help | ||
140 | Say Y if you want to add support for SoC audio on the | ||
141 | Marvell Saarb reference platform. | ||
142 | |||
143 | config SND_SOC_TAVOREVB3 | ||
144 | tristate "SoC Audio support for Marvell Tavor EVB3" | ||
145 | depends on SND_PXA2XX_SOC && MACH_TAVOREVB3 | ||
146 | select MFD_88PM860X | ||
147 | select SND_PXA_SOC_SSP | ||
148 | select SND_SOC_88PM860X | ||
149 | help | ||
150 | Say Y if you want to add support for SoC audio on the | ||
151 | Marvell Saarb reference platform. | ||
152 | |||
153 | config SND_PXA910_SOC | 133 | config SND_PXA910_SOC |
154 | tristate "SoC Audio for Marvell PXA910 chip" | 134 | tristate "SoC Audio for Marvell PXA910 chip" |
155 | depends on ARCH_MMP && SND | 135 | depends on ARCH_MMP && SND |
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index d8a265d2d5d7..2cff67b61dc3 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -23,8 +23,6 @@ snd-soc-e800-objs := e800_wm9712.o | |||
23 | snd-soc-spitz-objs := spitz.o | 23 | snd-soc-spitz-objs := spitz.o |
24 | snd-soc-em-x270-objs := em-x270.o | 24 | snd-soc-em-x270-objs := em-x270.o |
25 | snd-soc-palm27x-objs := palm27x.o | 25 | snd-soc-palm27x-objs := palm27x.o |
26 | snd-soc-saarb-objs := saarb.o | ||
27 | snd-soc-tavorevb3-objs := tavorevb3.o | ||
28 | snd-soc-zylonite-objs := zylonite.o | 26 | snd-soc-zylonite-objs := zylonite.o |
29 | snd-soc-hx4700-objs := hx4700.o | 27 | snd-soc-hx4700-objs := hx4700.o |
30 | snd-soc-magician-objs := magician.o | 28 | snd-soc-magician-objs := magician.o |
@@ -48,8 +46,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_HX4700) += snd-soc-hx4700.o | |||
48 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o | 46 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o |
49 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o | 47 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o |
50 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o | 48 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o |
51 | obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o | ||
52 | obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o | ||
53 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | 49 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o |
54 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o | 50 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o |
55 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o | 51 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o |
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 349930015264..5d57e071cdf5 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -147,7 +147,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream, | |||
147 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | 147 | vma->vm_end - vma->vm_start, vma->vm_page_prot); |
148 | } | 148 | } |
149 | 149 | ||
150 | struct snd_pcm_ops mmp_pcm_ops = { | 150 | static struct snd_pcm_ops mmp_pcm_ops = { |
151 | .open = mmp_pcm_open, | 151 | .open = mmp_pcm_open, |
152 | .close = snd_dmaengine_pcm_close_release_chan, | 152 | .close = snd_dmaengine_pcm_close_release_chan, |
153 | .ioctl = snd_pcm_lib_ioctl, | 153 | .ioctl = snd_pcm_lib_ioctl, |
@@ -208,7 +208,7 @@ static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream, | |||
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
210 | 210 | ||
211 | int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) | 211 | static int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) |
212 | { | 212 | { |
213 | struct snd_pcm_substream *substream; | 213 | struct snd_pcm_substream *substream; |
214 | struct snd_pcm *pcm = rtd->pcm; | 214 | struct snd_pcm *pcm = rtd->pcm; |
@@ -229,7 +229,7 @@ err: | |||
229 | return ret; | 229 | return ret; |
230 | } | 230 | } |
231 | 231 | ||
232 | struct snd_soc_platform_driver mmp_soc_platform = { | 232 | static struct snd_soc_platform_driver mmp_soc_platform = { |
233 | .ops = &mmp_pcm_ops, | 233 | .ops = &mmp_pcm_ops, |
234 | .pcm_new = mmp_pcm_new, | 234 | .pcm_new = mmp_pcm_new, |
235 | .pcm_free = mmp_pcm_free_dma_buffers, | 235 | .pcm_free = mmp_pcm_free_dma_buffers, |
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index a64779980177..62142ce367c7 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c | |||
@@ -388,7 +388,7 @@ static struct snd_soc_dai_ops mmp_sspa_dai_ops = { | |||
388 | .set_fmt = mmp_sspa_set_dai_fmt, | 388 | .set_fmt = mmp_sspa_set_dai_fmt, |
389 | }; | 389 | }; |
390 | 390 | ||
391 | struct snd_soc_dai_driver mmp_sspa_dai = { | 391 | static struct snd_soc_dai_driver mmp_sspa_dai = { |
392 | .probe = mmp_sspa_probe, | 392 | .probe = mmp_sspa_probe, |
393 | .playback = { | 393 | .playback = { |
394 | .channels_min = 1, | 394 | .channels_min = 1, |
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c deleted file mode 100644 index c34146b776b4..000000000000 --- a/sound/soc/pxa/saarb.c +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | /* | ||
2 | * saarb.c -- SoC audio for saarb | ||
3 | * | ||
4 | * Copyright (C) 2010 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/jack.h> | ||
22 | |||
23 | #include <asm/mach-types.h> | ||
24 | |||
25 | #include "../codecs/88pm860x-codec.h" | ||
26 | #include "pxa-ssp.h" | ||
27 | |||
28 | static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd); | ||
29 | |||
30 | static struct platform_device *saarb_snd_device; | ||
31 | |||
32 | static struct snd_soc_jack hs_jack, mic_jack; | ||
33 | |||
34 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
35 | { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, | ||
36 | }; | ||
37 | |||
38 | static struct snd_soc_jack_pin mic_jack_pins[] = { | ||
39 | { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, | ||
40 | }; | ||
41 | |||
42 | /* saarb machine dapm widgets */ | ||
43 | static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = { | ||
44 | SND_SOC_DAPM_HP("Headphone Stereophone", NULL), | ||
45 | SND_SOC_DAPM_LINE("Lineout Out 1", NULL), | ||
46 | SND_SOC_DAPM_LINE("Lineout Out 2", NULL), | ||
47 | SND_SOC_DAPM_SPK("Ext Speaker", NULL), | ||
48 | SND_SOC_DAPM_MIC("Ext Mic 1", NULL), | ||
49 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
50 | SND_SOC_DAPM_MIC("Ext Mic 3", NULL), | ||
51 | }; | ||
52 | |||
53 | /* saarb machine audio map */ | ||
54 | static const struct snd_soc_dapm_route saarb_audio_map[] = { | ||
55 | {"Headset Stereophone", NULL, "HS1"}, | ||
56 | {"Headset Stereophone", NULL, "HS2"}, | ||
57 | |||
58 | {"Ext Speaker", NULL, "LSP"}, | ||
59 | {"Ext Speaker", NULL, "LSN"}, | ||
60 | |||
61 | {"Lineout Out 1", NULL, "LINEOUT1"}, | ||
62 | {"Lineout Out 2", NULL, "LINEOUT2"}, | ||
63 | |||
64 | {"MIC1P", NULL, "Mic1 Bias"}, | ||
65 | {"MIC1N", NULL, "Mic1 Bias"}, | ||
66 | {"Mic1 Bias", NULL, "Ext Mic 1"}, | ||
67 | |||
68 | {"MIC2P", NULL, "Mic1 Bias"}, | ||
69 | {"MIC2N", NULL, "Mic1 Bias"}, | ||
70 | {"Mic1 Bias", NULL, "Headset Mic 2"}, | ||
71 | |||
72 | {"MIC3P", NULL, "Mic3 Bias"}, | ||
73 | {"MIC3N", NULL, "Mic3 Bias"}, | ||
74 | {"Mic3 Bias", NULL, "Ext Mic 3"}, | ||
75 | }; | ||
76 | |||
77 | static int saarb_i2s_hw_params(struct snd_pcm_substream *substream, | ||
78 | struct snd_pcm_hw_params *params) | ||
79 | { | ||
80 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
81 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
82 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
83 | int width = snd_pcm_format_physical_width(params_format(params)); | ||
84 | int ret; | ||
85 | |||
86 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, | ||
87 | PM860X_CLK_DIR_OUT); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
91 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static struct snd_soc_ops saarb_i2s_ops = { | ||
101 | .hw_params = saarb_i2s_hw_params, | ||
102 | }; | ||
103 | |||
104 | static struct snd_soc_dai_link saarb_dai[] = { | ||
105 | { | ||
106 | .name = "88PM860x I2S", | ||
107 | .stream_name = "I2S Audio", | ||
108 | .cpu_dai_name = "pxa-ssp-dai.1", | ||
109 | .codec_dai_name = "88pm860x-i2s", | ||
110 | .platform_name = "pxa-pcm-audio", | ||
111 | .codec_name = "88pm860x-codec", | ||
112 | .init = saarb_pm860x_init, | ||
113 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
114 | SND_SOC_DAIFMT_CBM_CFM, | ||
115 | .ops = &saarb_i2s_ops, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static struct snd_soc_card snd_soc_card_saarb = { | ||
120 | .name = "Saarb", | ||
121 | .owner = THIS_MODULE, | ||
122 | .dai_link = saarb_dai, | ||
123 | .num_links = ARRAY_SIZE(saarb_dai), | ||
124 | |||
125 | .dapm_widgets = saarb_dapm_widgets, | ||
126 | .num_dapm_widgets = ARRAY_SIZE(saarb_dapm_widgets), | ||
127 | .dapm_routes = saarb_audio_map, | ||
128 | .num_dapm_routes = ARRAY_SIZE(saarb_audio_map), | ||
129 | }; | ||
130 | |||
131 | static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd) | ||
132 | { | ||
133 | struct snd_soc_codec *codec = rtd->codec; | ||
134 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
135 | |||
136 | /* connected pins */ | ||
137 | snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); | ||
138 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); | ||
139 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); | ||
140 | snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); | ||
141 | snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); | ||
142 | |||
143 | /* Headset jack detection */ | ||
144 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE | ||
145 | | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, | ||
146 | &hs_jack); | ||
147 | snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), | ||
148 | hs_jack_pins); | ||
149 | snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, | ||
150 | &mic_jack); | ||
151 | snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), | ||
152 | mic_jack_pins); | ||
153 | |||
154 | /* headphone, microphone detection & headset short detection */ | ||
155 | pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, | ||
156 | SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); | ||
157 | pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int __init saarb_init(void) | ||
162 | { | ||
163 | int ret; | ||
164 | |||
165 | if (!machine_is_saarb()) | ||
166 | return -ENODEV; | ||
167 | saarb_snd_device = platform_device_alloc("soc-audio", -1); | ||
168 | if (!saarb_snd_device) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb); | ||
172 | |||
173 | ret = platform_device_add(saarb_snd_device); | ||
174 | if (ret) | ||
175 | platform_device_put(saarb_snd_device); | ||
176 | |||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static void __exit saarb_exit(void) | ||
181 | { | ||
182 | platform_device_unregister(saarb_snd_device); | ||
183 | } | ||
184 | |||
185 | module_init(saarb_init); | ||
186 | module_exit(saarb_exit); | ||
187 | |||
188 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
189 | MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb"); | ||
190 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c deleted file mode 100644 index 8b5ab8f72726..000000000000 --- a/sound/soc/pxa/tavorevb3.c +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | * tavorevb3.c -- SoC audio for Tavor EVB3 | ||
3 | * | ||
4 | * Copyright (C) 2010 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/jack.h> | ||
22 | |||
23 | #include <asm/mach-types.h> | ||
24 | |||
25 | #include "../codecs/88pm860x-codec.h" | ||
26 | #include "pxa-ssp.h" | ||
27 | |||
28 | static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd); | ||
29 | |||
30 | static struct platform_device *evb3_snd_device; | ||
31 | |||
32 | static struct snd_soc_jack hs_jack, mic_jack; | ||
33 | |||
34 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
35 | { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, | ||
36 | }; | ||
37 | |||
38 | static struct snd_soc_jack_pin mic_jack_pins[] = { | ||
39 | { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, | ||
40 | }; | ||
41 | |||
42 | /* tavorevb3 machine dapm widgets */ | ||
43 | static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = { | ||
44 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
45 | SND_SOC_DAPM_LINE("Lineout Out 1", NULL), | ||
46 | SND_SOC_DAPM_LINE("Lineout Out 2", NULL), | ||
47 | SND_SOC_DAPM_SPK("Ext Speaker", NULL), | ||
48 | SND_SOC_DAPM_MIC("Ext Mic 1", NULL), | ||
49 | SND_SOC_DAPM_MIC("Headset Mic 2", NULL), | ||
50 | SND_SOC_DAPM_MIC("Ext Mic 3", NULL), | ||
51 | }; | ||
52 | |||
53 | /* tavorevb3 machine audio map */ | ||
54 | static const struct snd_soc_dapm_route evb3_audio_map[] = { | ||
55 | {"Headset Stereophone", NULL, "HS1"}, | ||
56 | {"Headset Stereophone", NULL, "HS2"}, | ||
57 | |||
58 | {"Ext Speaker", NULL, "LSP"}, | ||
59 | {"Ext Speaker", NULL, "LSN"}, | ||
60 | |||
61 | {"Lineout Out 1", NULL, "LINEOUT1"}, | ||
62 | {"Lineout Out 2", NULL, "LINEOUT2"}, | ||
63 | |||
64 | {"MIC1P", NULL, "Mic1 Bias"}, | ||
65 | {"MIC1N", NULL, "Mic1 Bias"}, | ||
66 | {"Mic1 Bias", NULL, "Ext Mic 1"}, | ||
67 | |||
68 | {"MIC2P", NULL, "Mic1 Bias"}, | ||
69 | {"MIC2N", NULL, "Mic1 Bias"}, | ||
70 | {"Mic1 Bias", NULL, "Headset Mic 2"}, | ||
71 | |||
72 | {"MIC3P", NULL, "Mic3 Bias"}, | ||
73 | {"MIC3N", NULL, "Mic3 Bias"}, | ||
74 | {"Mic3 Bias", NULL, "Ext Mic 3"}, | ||
75 | }; | ||
76 | |||
77 | static int evb3_i2s_hw_params(struct snd_pcm_substream *substream, | ||
78 | struct snd_pcm_hw_params *params) | ||
79 | { | ||
80 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
81 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
82 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
83 | int width = snd_pcm_format_physical_width(params_format(params)); | ||
84 | int ret; | ||
85 | |||
86 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, | ||
87 | PM860X_CLK_DIR_OUT); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
91 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static struct snd_soc_ops evb3_i2s_ops = { | ||
100 | .hw_params = evb3_i2s_hw_params, | ||
101 | }; | ||
102 | |||
103 | static struct snd_soc_dai_link evb3_dai[] = { | ||
104 | { | ||
105 | .name = "88PM860x I2S", | ||
106 | .stream_name = "I2S Audio", | ||
107 | .cpu_dai_name = "pxa-ssp-dai.1", | ||
108 | .codec_dai_name = "88pm860x-i2s", | ||
109 | .platform_name = "pxa-pcm-audio", | ||
110 | .codec_name = "88pm860x-codec", | ||
111 | .init = evb3_pm860x_init, | ||
112 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
113 | SND_SOC_DAIFMT_CBM_CFM, | ||
114 | .ops = &evb3_i2s_ops, | ||
115 | }, | ||
116 | }; | ||
117 | |||
118 | static struct snd_soc_card snd_soc_card_evb3 = { | ||
119 | .name = "Tavor EVB3", | ||
120 | .owner = THIS_MODULE, | ||
121 | .dai_link = evb3_dai, | ||
122 | .num_links = ARRAY_SIZE(evb3_dai), | ||
123 | |||
124 | .dapm_widgets = evb3_dapm_widgets, | ||
125 | .num_dapm_widgets = ARRAY_SIZE(evb3_dapm_widgets), | ||
126 | .dapm_routes = evb3_audio_map, | ||
127 | .num_dapm_routes = ARRAY_SIZE(evb3_audio_map), | ||
128 | }; | ||
129 | |||
130 | static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd) | ||
131 | { | ||
132 | struct snd_soc_codec *codec = rtd->codec; | ||
133 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
134 | |||
135 | /* connected pins */ | ||
136 | snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); | ||
137 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); | ||
138 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); | ||
139 | snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); | ||
140 | snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); | ||
141 | |||
142 | /* Headset jack detection */ | ||
143 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE | ||
144 | | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, | ||
145 | &hs_jack); | ||
146 | snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), | ||
147 | hs_jack_pins); | ||
148 | snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, | ||
149 | &mic_jack); | ||
150 | snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), | ||
151 | mic_jack_pins); | ||
152 | |||
153 | /* headphone, microphone detection & headset short detection */ | ||
154 | pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, | ||
155 | SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); | ||
156 | pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int __init tavorevb3_init(void) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | if (!machine_is_tavorevb3()) | ||
165 | return -ENODEV; | ||
166 | evb3_snd_device = platform_device_alloc("soc-audio", -1); | ||
167 | if (!evb3_snd_device) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3); | ||
171 | |||
172 | ret = platform_device_add(evb3_snd_device); | ||
173 | if (ret) | ||
174 | platform_device_put(evb3_snd_device); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static void __exit tavorevb3_exit(void) | ||
180 | { | ||
181 | platform_device_unregister(evb3_snd_device); | ||
182 | } | ||
183 | |||
184 | module_init(tavorevb3_init); | ||
185 | module_exit(tavorevb3_exit); | ||
186 | |||
187 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
188 | MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3"); | ||
189 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index ceb656695b0f..db8aadf8932d 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -256,7 +256,6 @@ static struct snd_soc_card zylonite = { | |||
256 | .resume_pre = &zylonite_resume_pre, | 256 | .resume_pre = &zylonite_resume_pre, |
257 | .dai_link = zylonite_dai, | 257 | .dai_link = zylonite_dai, |
258 | .num_links = ARRAY_SIZE(zylonite_dai), | 258 | .num_links = ARRAY_SIZE(zylonite_dai), |
259 | .owner = THIS_MODULE, | ||
260 | }; | 259 | }; |
261 | 260 | ||
262 | static struct platform_device *zylonite_snd_ac97_device; | 261 | static struct platform_device *zylonite_snd_ac97_device; |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 475fb0d8b3c6..9855dfc3e3ec 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -39,7 +39,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753 | |||
39 | depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02 | 39 | depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02 |
40 | select SND_S3C24XX_I2S | 40 | select SND_S3C24XX_I2S |
41 | select SND_SOC_WM8753 | 41 | select SND_SOC_WM8753 |
42 | select SND_SOC_DFBMCS320 | 42 | select SND_SOC_BT_SCO |
43 | help | 43 | help |
44 | Say Y here to enable audio support for the Openmoko Neo1973 | 44 | Say Y here to enable audio support for the Openmoko Neo1973 |
45 | Smartphones. | 45 | Smartphones. |
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index ceed466af9ff..29e246803626 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c | |||
@@ -350,8 +350,16 @@ static struct snd_soc_codec_conf bells_codec_conf[] = { | |||
350 | }, | 350 | }, |
351 | }; | 351 | }; |
352 | 352 | ||
353 | static struct snd_soc_dapm_widget bells_widgets[] = { | ||
354 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
355 | }; | ||
356 | |||
353 | static struct snd_soc_dapm_route bells_routes[] = { | 357 | static struct snd_soc_dapm_route bells_routes[] = { |
354 | { "Sub CLK_SYS", NULL, "OPCLK" }, | 358 | { "Sub CLK_SYS", NULL, "OPCLK" }, |
359 | |||
360 | { "DMIC", NULL, "MICBIAS2" }, | ||
361 | { "IN2L", NULL, "DMIC" }, | ||
362 | { "IN2R", NULL, "DMIC" }, | ||
355 | }; | 363 | }; |
356 | 364 | ||
357 | static struct snd_soc_card bells_cards[] = { | 365 | static struct snd_soc_card bells_cards[] = { |
@@ -365,6 +373,8 @@ static struct snd_soc_card bells_cards[] = { | |||
365 | 373 | ||
366 | .late_probe = bells_late_probe, | 374 | .late_probe = bells_late_probe, |
367 | 375 | ||
376 | .dapm_widgets = bells_widgets, | ||
377 | .num_dapm_widgets = ARRAY_SIZE(bells_widgets), | ||
368 | .dapm_routes = bells_routes, | 378 | .dapm_routes = bells_routes, |
369 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | 379 | .num_dapm_routes = ARRAY_SIZE(bells_routes), |
370 | 380 | ||
@@ -383,6 +393,8 @@ static struct snd_soc_card bells_cards[] = { | |||
383 | 393 | ||
384 | .late_probe = bells_late_probe, | 394 | .late_probe = bells_late_probe, |
385 | 395 | ||
396 | .dapm_widgets = bells_widgets, | ||
397 | .num_dapm_widgets = ARRAY_SIZE(bells_widgets), | ||
386 | .dapm_routes = bells_routes, | 398 | .dapm_routes = bells_routes, |
387 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | 399 | .num_dapm_routes = ARRAY_SIZE(bells_routes), |
388 | 400 | ||
@@ -401,6 +413,8 @@ static struct snd_soc_card bells_cards[] = { | |||
401 | 413 | ||
402 | .late_probe = bells_late_probe, | 414 | .late_probe = bells_late_probe, |
403 | 415 | ||
416 | .dapm_widgets = bells_widgets, | ||
417 | .num_dapm_widgets = ARRAY_SIZE(bells_widgets), | ||
404 | .dapm_routes = bells_routes, | 418 | .dapm_routes = bells_routes, |
405 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | 419 | .num_dapm_routes = ARRAY_SIZE(bells_routes), |
406 | 420 | ||
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index e591c386917a..807db417d234 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -373,7 +373,7 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
373 | { /* Voice via BT */ | 373 | { /* Voice via BT */ |
374 | .name = "Bluetooth", | 374 | .name = "Bluetooth", |
375 | .stream_name = "Voice", | 375 | .stream_name = "Voice", |
376 | .cpu_dai_name = "dfbmcs320-pcm", | 376 | .cpu_dai_name = "bt-sco-pcm", |
377 | .codec_dai_name = "wm8753-voice", | 377 | .codec_dai_name = "wm8753-voice", |
378 | .codec_name = "wm8753.0-001a", | 378 | .codec_name = "wm8753.0-001a", |
379 | .ops = &neo1973_voice_ops, | 379 | .ops = &neo1973_voice_ops, |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index e43bd4294f99..23a9204b106d 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -176,7 +176,6 @@ static int snd_smdk_probe(struct platform_device *pdev) | |||
176 | static int snd_smdk_remove(struct platform_device *pdev) | 176 | static int snd_smdk_remove(struct platform_device *pdev) |
177 | { | 177 | { |
178 | snd_soc_unregister_card(&smdk_pcm); | 178 | snd_soc_unregister_card(&smdk_pcm); |
179 | platform_set_drvdata(pdev, NULL); | ||
180 | return 0; | 179 | return 0; |
181 | } | 180 | } |
182 | 181 | ||
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 3688a32000a2..0c84ca099612 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c | |||
@@ -146,7 +146,6 @@ static int snd_smdk_probe(struct platform_device *pdev) | |||
146 | static int snd_smdk_remove(struct platform_device *pdev) | 146 | static int snd_smdk_remove(struct platform_device *pdev) |
147 | { | 147 | { |
148 | snd_soc_unregister_card(&smdk_pcm); | 148 | snd_soc_unregister_card(&smdk_pcm); |
149 | platform_set_drvdata(pdev, NULL); | ||
150 | return 0; | 149 | return 0; |
151 | } | 150 | } |
152 | 151 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index f830c41f97dd..30390260bb67 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -276,7 +276,7 @@ struct fsi_stream_handler { | |||
276 | int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); | 276 | int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); |
277 | int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); | 277 | int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); |
278 | int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); | 278 | int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); |
279 | void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, | 279 | int (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, |
280 | int enable); | 280 | int enable); |
281 | }; | 281 | }; |
282 | #define fsi_stream_handler_call(io, func, args...) \ | 282 | #define fsi_stream_handler_call(io, func, args...) \ |
@@ -1188,7 +1188,7 @@ static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1188 | samples); | 1188 | samples); |
1189 | } | 1189 | } |
1190 | 1190 | ||
1191 | static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1191 | static int fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
1192 | int enable) | 1192 | int enable) |
1193 | { | 1193 | { |
1194 | struct fsi_master *master = fsi_get_master(fsi); | 1194 | struct fsi_master *master = fsi_get_master(fsi); |
@@ -1201,6 +1201,8 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1201 | 1201 | ||
1202 | if (fsi_is_clk_master(fsi)) | 1202 | if (fsi_is_clk_master(fsi)) |
1203 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); | 1203 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
1204 | |||
1205 | return 0; | ||
1204 | } | 1206 | } |
1205 | 1207 | ||
1206 | static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) | 1208 | static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) |
@@ -1409,7 +1411,7 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1409 | return 0; | 1411 | return 0; |
1410 | } | 1412 | } |
1411 | 1413 | ||
1412 | static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1414 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
1413 | int start) | 1415 | int start) |
1414 | { | 1416 | { |
1415 | struct fsi_master *master = fsi_get_master(fsi); | 1417 | struct fsi_master *master = fsi_get_master(fsi); |
@@ -1422,6 +1424,8 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1422 | 1424 | ||
1423 | if (fsi_is_clk_master(fsi)) | 1425 | if (fsi_is_clk_master(fsi)) |
1424 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); | 1426 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
1427 | |||
1428 | return 0; | ||
1425 | } | 1429 | } |
1426 | 1430 | ||
1427 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) | 1431 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 562d72e04e6e..309e5c91167b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -272,8 +272,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
272 | codec->debugfs_codec_root = debugfs_create_dir(codec->name, | 272 | codec->debugfs_codec_root = debugfs_create_dir(codec->name, |
273 | debugfs_card_root); | 273 | debugfs_card_root); |
274 | if (!codec->debugfs_codec_root) { | 274 | if (!codec->debugfs_codec_root) { |
275 | dev_warn(codec->dev, "ASoC: Failed to create codec debugfs" | 275 | dev_warn(codec->dev, |
276 | " directory\n"); | 276 | "ASoC: Failed to create codec debugfs directory\n"); |
277 | return; | 277 | return; |
278 | } | 278 | } |
279 | 279 | ||
@@ -286,8 +286,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
286 | codec->debugfs_codec_root, | 286 | codec->debugfs_codec_root, |
287 | codec, &codec_reg_fops); | 287 | codec, &codec_reg_fops); |
288 | if (!codec->debugfs_reg) | 288 | if (!codec->debugfs_reg) |
289 | dev_warn(codec->dev, "ASoC: Failed to create codec register" | 289 | dev_warn(codec->dev, |
290 | " debugfs file\n"); | 290 | "ASoC: Failed to create codec register debugfs file\n"); |
291 | 291 | ||
292 | snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); | 292 | snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); |
293 | } | 293 | } |
@@ -631,8 +631,7 @@ int snd_soc_suspend(struct device *dev) | |||
631 | */ | 631 | */ |
632 | if (codec->dapm.idle_bias_off) { | 632 | if (codec->dapm.idle_bias_off) { |
633 | dev_dbg(codec->dev, | 633 | dev_dbg(codec->dev, |
634 | "ASoC: idle_bias_off CODEC on" | 634 | "ASoC: idle_bias_off CODEC on over suspend\n"); |
635 | " over suspend\n"); | ||
636 | break; | 635 | break; |
637 | } | 636 | } |
638 | case SND_SOC_BIAS_OFF: | 637 | case SND_SOC_BIAS_OFF: |
@@ -643,8 +642,8 @@ int snd_soc_suspend(struct device *dev) | |||
643 | regcache_mark_dirty(codec->control_data); | 642 | regcache_mark_dirty(codec->control_data); |
644 | break; | 643 | break; |
645 | default: | 644 | default: |
646 | dev_dbg(codec->dev, "ASoC: CODEC is on" | 645 | dev_dbg(codec->dev, |
647 | " over suspend\n"); | 646 | "ASoC: CODEC is on over suspend\n"); |
648 | break; | 647 | break; |
649 | } | 648 | } |
650 | } | 649 | } |
@@ -713,8 +712,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
713 | codec->suspended = 0; | 712 | codec->suspended = 0; |
714 | break; | 713 | break; |
715 | default: | 714 | default: |
716 | dev_dbg(codec->dev, "ASoC: CODEC was on over" | 715 | dev_dbg(codec->dev, |
717 | " suspend\n"); | 716 | "ASoC: CODEC was on over suspend\n"); |
718 | break; | 717 | break; |
719 | } | 718 | } |
720 | } | 719 | } |
@@ -1110,8 +1109,8 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1110 | } | 1109 | } |
1111 | WARN(codec->dapm.idle_bias_off && | 1110 | WARN(codec->dapm.idle_bias_off && |
1112 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, | 1111 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, |
1113 | "codec %s can not start from non-off bias" | 1112 | "codec %s can not start from non-off bias with idle_bias_off==1\n", |
1114 | " with idle_bias_off==1\n", codec->name); | 1113 | codec->name); |
1115 | } | 1114 | } |
1116 | 1115 | ||
1117 | /* If the driver didn't set I/O up try regmap */ | 1116 | /* If the driver didn't set I/O up try regmap */ |
@@ -1582,8 +1581,9 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, | |||
1582 | codec->compress_type = compress_type; | 1581 | codec->compress_type = compress_type; |
1583 | ret = snd_soc_cache_init(codec); | 1582 | ret = snd_soc_cache_init(codec); |
1584 | if (ret < 0) { | 1583 | if (ret < 0) { |
1585 | dev_err(codec->dev, "ASoC: Failed to set cache compression" | 1584 | dev_err(codec->dev, |
1586 | " type: %d\n", ret); | 1585 | "ASoC: Failed to set cache compression type: %d\n", |
1586 | ret); | ||
1587 | return ret; | 1587 | return ret; |
1588 | } | 1588 | } |
1589 | codec->cache_init = 1; | 1589 | codec->cache_init = 1; |
@@ -1639,8 +1639,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1639 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1639 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
1640 | card->owner, 0, &card->snd_card); | 1640 | card->owner, 0, &card->snd_card); |
1641 | if (ret < 0) { | 1641 | if (ret < 0) { |
1642 | dev_err(card->dev, "ASoC: can't create sound card for" | 1642 | dev_err(card->dev, |
1643 | " card %s: %d\n", card->name, ret); | 1643 | "ASoC: can't create sound card for card %s: %d\n", |
1644 | card->name, ret); | ||
1644 | goto base_error; | 1645 | goto base_error; |
1645 | } | 1646 | } |
1646 | card->snd_card->dev = card->dev; | 1647 | card->snd_card->dev = card->dev; |
@@ -1815,8 +1816,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1815 | for (i = 0; i < card->num_rtd; i++) { | 1816 | for (i = 0; i < card->num_rtd; i++) { |
1816 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | 1817 | ret = soc_register_ac97_dai_link(&card->rtd[i]); |
1817 | if (ret < 0) { | 1818 | if (ret < 0) { |
1818 | dev_err(card->dev, "ASoC: failed to register AC97:" | 1819 | dev_err(card->dev, |
1819 | " %d\n", ret); | 1820 | "ASoC: failed to register AC97: %d\n", ret); |
1820 | while (--i >= 0) | 1821 | while (--i >= 0) |
1821 | soc_unregister_ac97_dai_link(card->rtd[i].codec); | 1822 | soc_unregister_ac97_dai_link(card->rtd[i].codec); |
1822 | goto probe_aux_dev_err; | 1823 | goto probe_aux_dev_err; |
@@ -2235,29 +2236,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, | |||
2235 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); | 2236 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); |
2236 | 2237 | ||
2237 | /** | 2238 | /** |
2238 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters | ||
2239 | * @substream: the pcm substream | ||
2240 | * @hw: the hardware parameters | ||
2241 | * | ||
2242 | * Sets the substream runtime hardware parameters. | ||
2243 | */ | ||
2244 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | ||
2245 | const struct snd_pcm_hardware *hw) | ||
2246 | { | ||
2247 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2248 | runtime->hw.info = hw->info; | ||
2249 | runtime->hw.formats = hw->formats; | ||
2250 | runtime->hw.period_bytes_min = hw->period_bytes_min; | ||
2251 | runtime->hw.period_bytes_max = hw->period_bytes_max; | ||
2252 | runtime->hw.periods_min = hw->periods_min; | ||
2253 | runtime->hw.periods_max = hw->periods_max; | ||
2254 | runtime->hw.buffer_bytes_max = hw->buffer_bytes_max; | ||
2255 | runtime->hw.fifo_size = hw->fifo_size; | ||
2256 | return 0; | ||
2257 | } | ||
2258 | EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); | ||
2259 | |||
2260 | /** | ||
2261 | * snd_soc_cnew - create new control | 2239 | * snd_soc_cnew - create new control |
2262 | * @_template: control template | 2240 | * @_template: control template |
2263 | * @data: control private data | 2241 | * @data: control private data |
@@ -2275,7 +2253,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
2275 | struct snd_kcontrol_new template; | 2253 | struct snd_kcontrol_new template; |
2276 | struct snd_kcontrol *kcontrol; | 2254 | struct snd_kcontrol *kcontrol; |
2277 | char *name = NULL; | 2255 | char *name = NULL; |
2278 | int name_len; | ||
2279 | 2256 | ||
2280 | memcpy(&template, _template, sizeof(template)); | 2257 | memcpy(&template, _template, sizeof(template)); |
2281 | template.index = 0; | 2258 | template.index = 0; |
@@ -2284,13 +2261,10 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
2284 | long_name = template.name; | 2261 | long_name = template.name; |
2285 | 2262 | ||
2286 | if (prefix) { | 2263 | if (prefix) { |
2287 | name_len = strlen(long_name) + strlen(prefix) + 2; | 2264 | name = kasprintf(GFP_KERNEL, "%s %s", prefix, long_name); |
2288 | name = kmalloc(name_len, GFP_KERNEL); | ||
2289 | if (!name) | 2265 | if (!name) |
2290 | return NULL; | 2266 | return NULL; |
2291 | 2267 | ||
2292 | snprintf(name, name_len, "%s %s", prefix, long_name); | ||
2293 | |||
2294 | template.name = name; | 2268 | template.name = name; |
2295 | } else { | 2269 | } else { |
2296 | template.name = long_name; | 2270 | template.name = long_name; |
@@ -3602,14 +3576,16 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3602 | * not both or neither. | 3576 | * not both or neither. |
3603 | */ | 3577 | */ |
3604 | if (!!link->codec_name == !!link->codec_of_node) { | 3578 | if (!!link->codec_name == !!link->codec_of_node) { |
3605 | dev_err(card->dev, "ASoC: Neither/both codec" | 3579 | dev_err(card->dev, |
3606 | " name/of_node are set for %s\n", link->name); | 3580 | "ASoC: Neither/both codec name/of_node are set for %s\n", |
3581 | link->name); | ||
3607 | return -EINVAL; | 3582 | return -EINVAL; |
3608 | } | 3583 | } |
3609 | /* Codec DAI name must be specified */ | 3584 | /* Codec DAI name must be specified */ |
3610 | if (!link->codec_dai_name) { | 3585 | if (!link->codec_dai_name) { |
3611 | dev_err(card->dev, "ASoC: codec_dai_name not" | 3586 | dev_err(card->dev, |
3612 | " set for %s\n", link->name); | 3587 | "ASoC: codec_dai_name not set for %s\n", |
3588 | link->name); | ||
3613 | return -EINVAL; | 3589 | return -EINVAL; |
3614 | } | 3590 | } |
3615 | 3591 | ||
@@ -3618,8 +3594,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3618 | * can be left unspecified, and a dummy platform will be used. | 3594 | * can be left unspecified, and a dummy platform will be used. |
3619 | */ | 3595 | */ |
3620 | if (link->platform_name && link->platform_of_node) { | 3596 | if (link->platform_name && link->platform_of_node) { |
3621 | dev_err(card->dev, "ASoC: Both platform name/of_node" | 3597 | dev_err(card->dev, |
3622 | " are set for %s\n", link->name); | 3598 | "ASoC: Both platform name/of_node are set for %s\n", |
3599 | link->name); | ||
3623 | return -EINVAL; | 3600 | return -EINVAL; |
3624 | } | 3601 | } |
3625 | 3602 | ||
@@ -3629,8 +3606,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3629 | * name alone.. | 3606 | * name alone.. |
3630 | */ | 3607 | */ |
3631 | if (link->cpu_name && link->cpu_of_node) { | 3608 | if (link->cpu_name && link->cpu_of_node) { |
3632 | dev_err(card->dev, "ASoC: Neither/both " | 3609 | dev_err(card->dev, |
3633 | "cpu name/of_node are set for %s\n",link->name); | 3610 | "ASoC: Neither/both cpu name/of_node are set for %s\n", |
3611 | link->name); | ||
3634 | return -EINVAL; | 3612 | return -EINVAL; |
3635 | } | 3613 | } |
3636 | /* | 3614 | /* |
@@ -3639,8 +3617,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3639 | */ | 3617 | */ |
3640 | if (!link->cpu_dai_name && | 3618 | if (!link->cpu_dai_name && |
3641 | !(link->cpu_name || link->cpu_of_node)) { | 3619 | !(link->cpu_name || link->cpu_of_node)) { |
3642 | dev_err(card->dev, "ASoC: Neither cpu_dai_name nor " | 3620 | dev_err(card->dev, |
3643 | "cpu_name/of_node are set for %s\n", link->name); | 3621 | "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", |
3622 | link->name); | ||
3644 | return -EINVAL; | 3623 | return -EINVAL; |
3645 | } | 3624 | } |
3646 | } | 3625 | } |
@@ -3744,8 +3723,9 @@ static inline char *fmt_multiple_name(struct device *dev, | |||
3744 | struct snd_soc_dai_driver *dai_drv) | 3723 | struct snd_soc_dai_driver *dai_drv) |
3745 | { | 3724 | { |
3746 | if (dai_drv->name == NULL) { | 3725 | if (dai_drv->name == NULL) { |
3747 | dev_err(dev, "ASoC: error - multiple DAI %s registered with" | 3726 | dev_err(dev, |
3748 | " no name\n", dev_name(dev)); | 3727 | "ASoC: error - multiple DAI %s registered with no name\n", |
3728 | dev_name(dev)); | ||
3749 | return NULL; | 3729 | return NULL; |
3750 | } | 3730 | } |
3751 | 3731 | ||
@@ -3875,8 +3855,9 @@ static int snd_soc_register_dais(struct device *dev, | |||
3875 | 3855 | ||
3876 | list_for_each_entry(codec, &codec_list, list) { | 3856 | list_for_each_entry(codec, &codec_list, list) { |
3877 | if (codec->dev == dev) { | 3857 | if (codec->dev == dev) { |
3878 | dev_dbg(dev, "ASoC: Mapped DAI %s to " | 3858 | dev_dbg(dev, |
3879 | "CODEC %s\n", dai->name, codec->name); | 3859 | "ASoC: Mapped DAI %s to CODEC %s\n", |
3860 | dai->name, codec->name); | ||
3880 | dai->codec = codec; | 3861 | dai->codec = codec; |
3881 | break; | 3862 | break; |
3882 | } | 3863 | } |
@@ -4312,8 +4293,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4312 | 4293 | ||
4313 | num_routes = of_property_count_strings(np, propname); | 4294 | num_routes = of_property_count_strings(np, propname); |
4314 | if (num_routes < 0 || num_routes & 1) { | 4295 | if (num_routes < 0 || num_routes & 1) { |
4315 | dev_err(card->dev, "ASoC: Property '%s' does not exist or its" | 4296 | dev_err(card->dev, |
4316 | " length is not even\n", propname); | 4297 | "ASoC: Property '%s' does not exist or its length is not even\n", |
4298 | propname); | ||
4317 | return -EINVAL; | 4299 | return -EINVAL; |
4318 | } | 4300 | } |
4319 | num_routes /= 2; | 4301 | num_routes /= 2; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c7051c457b75..b94190820e8c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -64,6 +64,7 @@ static int dapm_up_seq[] = { | |||
64 | [snd_soc_dapm_virt_mux] = 5, | 64 | [snd_soc_dapm_virt_mux] = 5, |
65 | [snd_soc_dapm_value_mux] = 5, | 65 | [snd_soc_dapm_value_mux] = 5, |
66 | [snd_soc_dapm_dac] = 6, | 66 | [snd_soc_dapm_dac] = 6, |
67 | [snd_soc_dapm_switch] = 7, | ||
67 | [snd_soc_dapm_mixer] = 7, | 68 | [snd_soc_dapm_mixer] = 7, |
68 | [snd_soc_dapm_mixer_named_ctl] = 7, | 69 | [snd_soc_dapm_mixer_named_ctl] = 7, |
69 | [snd_soc_dapm_pga] = 8, | 70 | [snd_soc_dapm_pga] = 8, |
@@ -83,6 +84,7 @@ static int dapm_down_seq[] = { | |||
83 | [snd_soc_dapm_line] = 2, | 84 | [snd_soc_dapm_line] = 2, |
84 | [snd_soc_dapm_out_drv] = 2, | 85 | [snd_soc_dapm_out_drv] = 2, |
85 | [snd_soc_dapm_pga] = 4, | 86 | [snd_soc_dapm_pga] = 4, |
87 | [snd_soc_dapm_switch] = 5, | ||
86 | [snd_soc_dapm_mixer_named_ctl] = 5, | 88 | [snd_soc_dapm_mixer_named_ctl] = 5, |
87 | [snd_soc_dapm_mixer] = 5, | 89 | [snd_soc_dapm_mixer] = 5, |
88 | [snd_soc_dapm_dac] = 6, | 90 | [snd_soc_dapm_dac] = 6, |
@@ -365,11 +367,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
365 | val = soc_widget_read(w, e->reg); | 367 | val = soc_widget_read(w, e->reg); |
366 | item = (val >> e->shift_l) & e->mask; | 368 | item = (val >> e->shift_l) & e->mask; |
367 | 369 | ||
368 | p->connect = 0; | 370 | if (item < e->max && !strcmp(p->name, e->texts[item])) |
369 | for (i = 0; i < e->max; i++) { | 371 | p->connect = 1; |
370 | if (!(strcmp(p->name, e->texts[i])) && item == i) | 372 | else |
371 | p->connect = 1; | 373 | p->connect = 0; |
372 | } | ||
373 | } | 374 | } |
374 | break; | 375 | break; |
375 | case snd_soc_dapm_virt_mux: { | 376 | case snd_soc_dapm_virt_mux: { |
@@ -399,11 +400,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
399 | break; | 400 | break; |
400 | } | 401 | } |
401 | 402 | ||
402 | p->connect = 0; | 403 | if (item < e->max && !strcmp(p->name, e->texts[item])) |
403 | for (i = 0; i < e->max; i++) { | 404 | p->connect = 1; |
404 | if (!(strcmp(p->name, e->texts[i])) && item == i) | 405 | else |
405 | p->connect = 1; | 406 | p->connect = 0; |
406 | } | ||
407 | } | 407 | } |
408 | break; | 408 | break; |
409 | /* does not affect routing - always connected */ | 409 | /* does not affect routing - always connected */ |
@@ -507,6 +507,11 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) | ||
511 | { | ||
512 | kfree(kctl->private_data); | ||
513 | } | ||
514 | |||
510 | /* | 515 | /* |
511 | * Determine if a kcontrol is shared. If it is, look it up. If it isn't, | 516 | * Determine if a kcontrol is shared. If it is, look it up. If it isn't, |
512 | * create it. Either way, add the widget into the control's widget list | 517 | * create it. Either way, add the widget into the control's widget list |
@@ -524,7 +529,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
524 | int wlistentries; | 529 | int wlistentries; |
525 | size_t wlistsize; | 530 | size_t wlistsize; |
526 | bool wname_in_long_name, kcname_in_long_name; | 531 | bool wname_in_long_name, kcname_in_long_name; |
527 | size_t name_len; | ||
528 | char *long_name; | 532 | char *long_name; |
529 | const char *name; | 533 | const char *name; |
530 | int ret; | 534 | int ret; |
@@ -589,25 +593,19 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
589 | } | 593 | } |
590 | 594 | ||
591 | if (wname_in_long_name && kcname_in_long_name) { | 595 | if (wname_in_long_name && kcname_in_long_name) { |
592 | name_len = strlen(w->name) - prefix_len + 1 + | ||
593 | strlen(w->kcontrol_news[kci].name) + 1; | ||
594 | |||
595 | long_name = kmalloc(name_len, GFP_KERNEL); | ||
596 | if (long_name == NULL) { | ||
597 | kfree(wlist); | ||
598 | return -ENOMEM; | ||
599 | } | ||
600 | |||
601 | /* | 596 | /* |
602 | * The control will get a prefix from the control | 597 | * The control will get a prefix from the control |
603 | * creation process but we're also using the same | 598 | * creation process but we're also using the same |
604 | * prefix for widgets so cut the prefix off the | 599 | * prefix for widgets so cut the prefix off the |
605 | * front of the widget name. | 600 | * front of the widget name. |
606 | */ | 601 | */ |
607 | snprintf(long_name, name_len, "%s %s", | 602 | long_name = kasprintf(GFP_KERNEL, "%s %s", |
608 | w->name + prefix_len, | 603 | w->name + prefix_len, |
609 | w->kcontrol_news[kci].name); | 604 | w->kcontrol_news[kci].name); |
610 | long_name[name_len - 1] = '\0'; | 605 | if (long_name == NULL) { |
606 | kfree(wlist); | ||
607 | return -ENOMEM; | ||
608 | } | ||
611 | 609 | ||
612 | name = long_name; | 610 | name = long_name; |
613 | } else if (wname_in_long_name) { | 611 | } else if (wname_in_long_name) { |
@@ -620,17 +618,16 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
620 | 618 | ||
621 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, | 619 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, |
622 | prefix); | 620 | prefix); |
621 | kcontrol->private_free = dapm_kcontrol_free; | ||
622 | kfree(long_name); | ||
623 | ret = snd_ctl_add(card, kcontrol); | 623 | ret = snd_ctl_add(card, kcontrol); |
624 | if (ret < 0) { | 624 | if (ret < 0) { |
625 | dev_err(dapm->dev, | 625 | dev_err(dapm->dev, |
626 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", | 626 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", |
627 | w->name, name, ret); | 627 | w->name, name, ret); |
628 | kfree(wlist); | 628 | kfree(wlist); |
629 | kfree(long_name); | ||
630 | return ret; | 629 | return ret; |
631 | } | 630 | } |
632 | |||
633 | path->long_name = long_name; | ||
634 | } | 631 | } |
635 | 632 | ||
636 | kcontrol->private_data = wlist; | 633 | kcontrol->private_data = wlist; |
@@ -1270,6 +1267,14 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, | |||
1270 | ev_name = "POST_PMD"; | 1267 | ev_name = "POST_PMD"; |
1271 | power = 0; | 1268 | power = 0; |
1272 | break; | 1269 | break; |
1270 | case SND_SOC_DAPM_WILL_PMU: | ||
1271 | ev_name = "WILL_PMU"; | ||
1272 | power = 1; | ||
1273 | break; | ||
1274 | case SND_SOC_DAPM_WILL_PMD: | ||
1275 | ev_name = "WILL_PMD"; | ||
1276 | power = 0; | ||
1277 | break; | ||
1273 | default: | 1278 | default: |
1274 | BUG(); | 1279 | BUG(); |
1275 | return; | 1280 | return; |
@@ -1730,6 +1735,14 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1730 | &async_domain); | 1735 | &async_domain); |
1731 | async_synchronize_full_domain(&async_domain); | 1736 | async_synchronize_full_domain(&async_domain); |
1732 | 1737 | ||
1738 | list_for_each_entry(w, &down_list, power_list) { | ||
1739 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD); | ||
1740 | } | ||
1741 | |||
1742 | list_for_each_entry(w, &up_list, power_list) { | ||
1743 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU); | ||
1744 | } | ||
1745 | |||
1733 | /* Power down widgets first; try to avoid amplifying pops. */ | 1746 | /* Power down widgets first; try to avoid amplifying pops. */ |
1734 | dapm_seq_run(dapm, &down_list, event, false); | 1747 | dapm_seq_run(dapm, &down_list, event, false); |
1735 | 1748 | ||
@@ -2094,6 +2107,14 @@ static void snd_soc_dapm_sys_remove(struct device *dev) | |||
2094 | device_remove_file(dev, &dev_attr_dapm_widget); | 2107 | device_remove_file(dev, &dev_attr_dapm_widget); |
2095 | } | 2108 | } |
2096 | 2109 | ||
2110 | static void dapm_free_path(struct snd_soc_dapm_path *path) | ||
2111 | { | ||
2112 | list_del(&path->list_sink); | ||
2113 | list_del(&path->list_source); | ||
2114 | list_del(&path->list); | ||
2115 | kfree(path); | ||
2116 | } | ||
2117 | |||
2097 | /* free all dapm widgets and resources */ | 2118 | /* free all dapm widgets and resources */ |
2098 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | 2119 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) |
2099 | { | 2120 | { |
@@ -2109,20 +2130,12 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | |||
2109 | * While removing the path, remove reference to it from both | 2130 | * While removing the path, remove reference to it from both |
2110 | * source and sink widgets so that path is removed only once. | 2131 | * source and sink widgets so that path is removed only once. |
2111 | */ | 2132 | */ |
2112 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { | 2133 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) |
2113 | list_del(&p->list_sink); | 2134 | dapm_free_path(p); |
2114 | list_del(&p->list_source); | 2135 | |
2115 | list_del(&p->list); | 2136 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) |
2116 | kfree(p->long_name); | 2137 | dapm_free_path(p); |
2117 | kfree(p); | 2138 | |
2118 | } | ||
2119 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { | ||
2120 | list_del(&p->list_sink); | ||
2121 | list_del(&p->list_source); | ||
2122 | list_del(&p->list); | ||
2123 | kfree(p->long_name); | ||
2124 | kfree(p); | ||
2125 | } | ||
2126 | kfree(w->kcontrols); | 2139 | kfree(w->kcontrols); |
2127 | kfree(w->name); | 2140 | kfree(w->name); |
2128 | kfree(w); | 2141 | kfree(w); |
@@ -2398,10 +2411,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2398 | dapm_mark_dirty(path->source, "Route removed"); | 2411 | dapm_mark_dirty(path->source, "Route removed"); |
2399 | dapm_mark_dirty(path->sink, "Route removed"); | 2412 | dapm_mark_dirty(path->sink, "Route removed"); |
2400 | 2413 | ||
2401 | list_del(&path->list); | 2414 | dapm_free_path(path); |
2402 | list_del(&path->list_sink); | ||
2403 | list_del(&path->list_source); | ||
2404 | kfree(path); | ||
2405 | } else { | 2415 | } else { |
2406 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", | 2416 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", |
2407 | source, sink); | 2417 | source, sink); |
@@ -3055,7 +3065,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3055 | const struct snd_soc_dapm_widget *widget) | 3065 | const struct snd_soc_dapm_widget *widget) |
3056 | { | 3066 | { |
3057 | struct snd_soc_dapm_widget *w; | 3067 | struct snd_soc_dapm_widget *w; |
3058 | size_t name_len; | ||
3059 | int ret; | 3068 | int ret; |
3060 | 3069 | ||
3061 | if ((w = dapm_cnew_widget(widget)) == NULL) | 3070 | if ((w = dapm_cnew_widget(widget)) == NULL) |
@@ -3096,19 +3105,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3096 | break; | 3105 | break; |
3097 | } | 3106 | } |
3098 | 3107 | ||
3099 | name_len = strlen(widget->name) + 1; | ||
3100 | if (dapm->codec && dapm->codec->name_prefix) | 3108 | if (dapm->codec && dapm->codec->name_prefix) |
3101 | name_len += 1 + strlen(dapm->codec->name_prefix); | 3109 | w->name = kasprintf(GFP_KERNEL, "%s %s", |
3102 | w->name = kmalloc(name_len, GFP_KERNEL); | 3110 | dapm->codec->name_prefix, widget->name); |
3111 | else | ||
3112 | w->name = kasprintf(GFP_KERNEL, "%s", widget->name); | ||
3113 | |||
3103 | if (w->name == NULL) { | 3114 | if (w->name == NULL) { |
3104 | kfree(w); | 3115 | kfree(w); |
3105 | return NULL; | 3116 | return NULL; |
3106 | } | 3117 | } |
3107 | if (dapm->codec && dapm->codec->name_prefix) | ||
3108 | snprintf((char *)w->name, name_len, "%s %s", | ||
3109 | dapm->codec->name_prefix, widget->name); | ||
3110 | else | ||
3111 | snprintf((char *)w->name, name_len, "%s", widget->name); | ||
3112 | 3118 | ||
3113 | switch (w->id) { | 3119 | switch (w->id) { |
3114 | case snd_soc_dapm_switch: | 3120 | case snd_soc_dapm_switch: |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ccb6be4d658d..b6c640332a17 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -33,6 +33,29 @@ | |||
33 | 33 | ||
34 | #define DPCM_MAX_BE_USERS 8 | 34 | #define DPCM_MAX_BE_USERS 8 |
35 | 35 | ||
36 | /** | ||
37 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters | ||
38 | * @substream: the pcm substream | ||
39 | * @hw: the hardware parameters | ||
40 | * | ||
41 | * Sets the substream runtime hardware parameters. | ||
42 | */ | ||
43 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | ||
44 | const struct snd_pcm_hardware *hw) | ||
45 | { | ||
46 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
47 | runtime->hw.info = hw->info; | ||
48 | runtime->hw.formats = hw->formats; | ||
49 | runtime->hw.period_bytes_min = hw->period_bytes_min; | ||
50 | runtime->hw.period_bytes_max = hw->period_bytes_max; | ||
51 | runtime->hw.periods_min = hw->periods_min; | ||
52 | runtime->hw.periods_max = hw->periods_max; | ||
53 | runtime->hw.buffer_bytes_max = hw->buffer_bytes_max; | ||
54 | runtime->hw.fifo_size = hw->fifo_size; | ||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); | ||
58 | |||
36 | /* DPCM stream event, send event to FE and all active BEs. */ | 59 | /* DPCM stream event, send event to FE and all active BEs. */ |
37 | static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, | 60 | static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, |
38 | int event) | 61 | int event) |
@@ -124,6 +147,26 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream, | |||
124 | } | 147 | } |
125 | } | 148 | } |
126 | 149 | ||
150 | static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw, | ||
151 | struct snd_soc_pcm_stream *codec_stream, | ||
152 | struct snd_soc_pcm_stream *cpu_stream) | ||
153 | { | ||
154 | hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min); | ||
155 | hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max); | ||
156 | hw->channels_min = max(codec_stream->channels_min, | ||
157 | cpu_stream->channels_min); | ||
158 | hw->channels_max = min(codec_stream->channels_max, | ||
159 | cpu_stream->channels_max); | ||
160 | hw->formats = codec_stream->formats & cpu_stream->formats; | ||
161 | hw->rates = codec_stream->rates & cpu_stream->rates; | ||
162 | if (codec_stream->rates | ||
163 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
164 | hw->rates |= cpu_stream->rates; | ||
165 | if (cpu_stream->rates | ||
166 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
167 | hw->rates |= codec_stream->rates; | ||
168 | } | ||
169 | |||
127 | /* | 170 | /* |
128 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is | 171 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is |
129 | * then initialized and any private data can be allocated. This also calls | 172 | * then initialized and any private data can be allocated. This also calls |
@@ -189,51 +232,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
189 | 232 | ||
190 | /* Check that the codec and cpu DAIs are compatible */ | 233 | /* Check that the codec and cpu DAIs are compatible */ |
191 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 234 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
192 | runtime->hw.rate_min = | 235 | soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback, |
193 | max(codec_dai_drv->playback.rate_min, | 236 | &cpu_dai_drv->playback); |
194 | cpu_dai_drv->playback.rate_min); | ||
195 | runtime->hw.rate_max = | ||
196 | min(codec_dai_drv->playback.rate_max, | ||
197 | cpu_dai_drv->playback.rate_max); | ||
198 | runtime->hw.channels_min = | ||
199 | max(codec_dai_drv->playback.channels_min, | ||
200 | cpu_dai_drv->playback.channels_min); | ||
201 | runtime->hw.channels_max = | ||
202 | min(codec_dai_drv->playback.channels_max, | ||
203 | cpu_dai_drv->playback.channels_max); | ||
204 | runtime->hw.formats = | ||
205 | codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; | ||
206 | runtime->hw.rates = | ||
207 | codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; | ||
208 | if (codec_dai_drv->playback.rates | ||
209 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
210 | runtime->hw.rates |= cpu_dai_drv->playback.rates; | ||
211 | if (cpu_dai_drv->playback.rates | ||
212 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
213 | runtime->hw.rates |= codec_dai_drv->playback.rates; | ||
214 | } else { | 237 | } else { |
215 | runtime->hw.rate_min = | 238 | soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture, |
216 | max(codec_dai_drv->capture.rate_min, | 239 | &cpu_dai_drv->capture); |
217 | cpu_dai_drv->capture.rate_min); | ||
218 | runtime->hw.rate_max = | ||
219 | min(codec_dai_drv->capture.rate_max, | ||
220 | cpu_dai_drv->capture.rate_max); | ||
221 | runtime->hw.channels_min = | ||
222 | max(codec_dai_drv->capture.channels_min, | ||
223 | cpu_dai_drv->capture.channels_min); | ||
224 | runtime->hw.channels_max = | ||
225 | min(codec_dai_drv->capture.channels_max, | ||
226 | cpu_dai_drv->capture.channels_max); | ||
227 | runtime->hw.formats = | ||
228 | codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; | ||
229 | runtime->hw.rates = | ||
230 | codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; | ||
231 | if (codec_dai_drv->capture.rates | ||
232 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
233 | runtime->hw.rates |= cpu_dai_drv->capture.rates; | ||
234 | if (cpu_dai_drv->capture.rates | ||
235 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
236 | runtime->hw.rates |= codec_dai_drv->capture.rates; | ||
237 | } | 240 | } |
238 | 241 | ||
239 | ret = -EINVAL; | 242 | ret = -EINVAL; |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 4b3be6c3c91e..29b211e9c060 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -159,15 +159,10 @@ int __init snd_soc_util_init(void) | |||
159 | { | 159 | { |
160 | int ret; | 160 | int ret; |
161 | 161 | ||
162 | soc_dummy_dev = platform_device_alloc("snd-soc-dummy", -1); | 162 | soc_dummy_dev = |
163 | if (!soc_dummy_dev) | 163 | platform_device_register_simple("snd-soc-dummy", -1, NULL, 0); |
164 | return -ENOMEM; | 164 | if (IS_ERR(soc_dummy_dev)) |
165 | 165 | return PTR_ERR(soc_dummy_dev); | |
166 | ret = platform_device_add(soc_dummy_dev); | ||
167 | if (ret != 0) { | ||
168 | platform_device_put(soc_dummy_dev); | ||
169 | return ret; | ||
170 | } | ||
171 | 166 | ||
172 | ret = platform_driver_register(&soc_dummy_driver); | 167 | ret = platform_driver_register(&soc_dummy_driver); |
173 | if (ret != 0) | 168 | if (ret != 0) |
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig new file mode 100644 index 000000000000..3567d73b218e --- /dev/null +++ b/sound/soc/spear/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config SND_SPEAR_SOC | ||
2 | tristate | ||
3 | select SND_SOC_DMAENGINE_PCM | ||
4 | |||
5 | config SND_SPEAR_SPDIF_OUT | ||
6 | tristate | ||
7 | |||
8 | config SND_SPEAR_SPDIF_IN | ||
9 | tristate | ||
diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile new file mode 100644 index 000000000000..c4ea7161056c --- /dev/null +++ b/sound/soc/spear/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # SPEAR Platform Support | ||
2 | snd-soc-spear-pcm-objs := spear_pcm.o | ||
3 | snd-soc-spear-spdif-in-objs := spdif_in.o | ||
4 | snd-soc-spear-spdif-out-objs := spdif_out.o | ||
5 | |||
6 | obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o | ||
7 | obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o | ||
8 | obj-$(CONFIG_SND_SPEAR_SPDIF_OUT) += snd-soc-spear-spdif-out.o | ||
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 14d57e89bcba..63acfeb4b69d 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
@@ -49,15 +49,12 @@ static void spdif_in_configure(struct spdif_in_dev *host) | |||
49 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); | 49 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); |
50 | } | 50 | } |
51 | 51 | ||
52 | static int spdif_in_startup(struct snd_pcm_substream *substream, | 52 | static int spdif_in_dai_probe(struct snd_soc_dai *dai) |
53 | struct snd_soc_dai *cpu_dai) | ||
54 | { | 53 | { |
55 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | 54 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); |
56 | 55 | ||
57 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | 56 | dai->capture_dma_data = &host->dma_params; |
58 | return -EINVAL; | ||
59 | 57 | ||
60 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
61 | return 0; | 58 | return 0; |
62 | } | 59 | } |
63 | 60 | ||
@@ -70,7 +67,6 @@ static void spdif_in_shutdown(struct snd_pcm_substream *substream, | |||
70 | return; | 67 | return; |
71 | 68 | ||
72 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); | 69 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); |
73 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
74 | } | 70 | } |
75 | 71 | ||
76 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) | 72 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) |
@@ -151,13 +147,13 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, | |||
151 | } | 147 | } |
152 | 148 | ||
153 | static struct snd_soc_dai_ops spdif_in_dai_ops = { | 149 | static struct snd_soc_dai_ops spdif_in_dai_ops = { |
154 | .startup = spdif_in_startup, | ||
155 | .shutdown = spdif_in_shutdown, | 150 | .shutdown = spdif_in_shutdown, |
156 | .trigger = spdif_in_trigger, | 151 | .trigger = spdif_in_trigger, |
157 | .hw_params = spdif_in_hw_params, | 152 | .hw_params = spdif_in_hw_params, |
158 | }; | 153 | }; |
159 | 154 | ||
160 | struct snd_soc_dai_driver spdif_in_dai = { | 155 | static struct snd_soc_dai_driver spdif_in_dai = { |
156 | .probe = spdif_in_dai_probe, | ||
161 | .capture = { | 157 | .capture = { |
162 | .channels_min = 2, | 158 | .channels_min = 2, |
163 | .channels_max = 2, | 159 | .channels_max = 2, |
@@ -235,7 +231,7 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
235 | if (host->irq < 0) | 231 | if (host->irq < 0) |
236 | return -EINVAL; | 232 | return -EINVAL; |
237 | 233 | ||
238 | host->clk = clk_get(&pdev->dev, NULL); | 234 | host->clk = devm_clk_get(&pdev->dev, NULL); |
239 | if (IS_ERR(host->clk)) | 235 | if (IS_ERR(host->clk)) |
240 | return PTR_ERR(host->clk); | 236 | return PTR_ERR(host->clk); |
241 | 237 | ||
@@ -257,34 +253,21 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
257 | ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, | 253 | ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, |
258 | "spdif-in", host); | 254 | "spdif-in", host); |
259 | if (ret) { | 255 | if (ret) { |
260 | clk_put(host->clk); | ||
261 | dev_warn(&pdev->dev, "request_irq failed\n"); | 256 | dev_warn(&pdev->dev, "request_irq failed\n"); |
262 | return ret; | 257 | return ret; |
263 | } | 258 | } |
264 | 259 | ||
265 | ret = snd_soc_register_component(&pdev->dev, &spdif_in_component, | 260 | return snd_soc_register_component(&pdev->dev, &spdif_in_component, |
266 | &spdif_in_dai, 1); | 261 | &spdif_in_dai, 1); |
267 | if (ret != 0) { | ||
268 | clk_put(host->clk); | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | return 0; | ||
273 | } | 262 | } |
274 | 263 | ||
275 | static int spdif_in_remove(struct platform_device *pdev) | 264 | static int spdif_in_remove(struct platform_device *pdev) |
276 | { | 265 | { |
277 | struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev); | ||
278 | |||
279 | snd_soc_unregister_component(&pdev->dev); | 266 | snd_soc_unregister_component(&pdev->dev); |
280 | dev_set_drvdata(&pdev->dev, NULL); | ||
281 | |||
282 | clk_put(host->clk); | ||
283 | 267 | ||
284 | return 0; | 268 | return 0; |
285 | } | 269 | } |
286 | 270 | ||
287 | |||
288 | static struct platform_driver spdif_in_driver = { | 271 | static struct platform_driver spdif_in_driver = { |
289 | .probe = spdif_in_probe, | 272 | .probe = spdif_in_probe, |
290 | .remove = spdif_in_remove, | 273 | .remove = spdif_in_remove, |
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index 1e3c3dda3598..2fdf68c98d22 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c | |||
@@ -62,8 +62,6 @@ static int spdif_out_startup(struct snd_pcm_substream *substream, | |||
62 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | 62 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) |
63 | return -EINVAL; | 63 | return -EINVAL; |
64 | 64 | ||
65 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
66 | |||
67 | ret = clk_enable(host->clk); | 65 | ret = clk_enable(host->clk); |
68 | if (ret) | 66 | if (ret) |
69 | return ret; | 67 | return ret; |
@@ -84,7 +82,6 @@ static void spdif_out_shutdown(struct snd_pcm_substream *substream, | |||
84 | 82 | ||
85 | clk_disable(host->clk); | 83 | clk_disable(host->clk); |
86 | host->running = false; | 84 | host->running = false; |
87 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
88 | } | 85 | } |
89 | 86 | ||
90 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, | 87 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, |
@@ -243,8 +240,12 @@ static const struct snd_kcontrol_new spdif_out_controls[] = { | |||
243 | spdif_mute_get, spdif_mute_put), | 240 | spdif_mute_get, spdif_mute_put), |
244 | }; | 241 | }; |
245 | 242 | ||
246 | int spdif_soc_dai_probe(struct snd_soc_dai *dai) | 243 | static int spdif_soc_dai_probe(struct snd_soc_dai *dai) |
247 | { | 244 | { |
245 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
246 | |||
247 | dai->playback_dma_data = &host->dma_params; | ||
248 | |||
248 | return snd_soc_add_dai_controls(dai, spdif_out_controls, | 249 | return snd_soc_add_dai_controls(dai, spdif_out_controls, |
249 | ARRAY_SIZE(spdif_out_controls)); | 250 | ARRAY_SIZE(spdif_out_controls)); |
250 | } | 251 | } |
@@ -281,30 +282,18 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
281 | struct resource *res; | 282 | struct resource *res; |
282 | int ret; | 283 | int ret; |
283 | 284 | ||
284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
285 | if (!res) | ||
286 | return -EINVAL; | ||
287 | |||
288 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
289 | resource_size(res), pdev->name)) { | ||
290 | dev_warn(&pdev->dev, "Failed to get memory resourse\n"); | ||
291 | return -ENOENT; | ||
292 | } | ||
293 | |||
294 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 285 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
295 | if (!host) { | 286 | if (!host) { |
296 | dev_warn(&pdev->dev, "kzalloc fail\n"); | 287 | dev_warn(&pdev->dev, "kzalloc fail\n"); |
297 | return -ENOMEM; | 288 | return -ENOMEM; |
298 | } | 289 | } |
299 | 290 | ||
300 | host->io_base = devm_ioremap(&pdev->dev, res->start, | 291 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
301 | resource_size(res)); | 292 | host->io_base = devm_ioremap_resource(&pdev->dev, res); |
302 | if (!host->io_base) { | 293 | if (IS_ERR(host->io_base)) |
303 | dev_warn(&pdev->dev, "ioremap failed\n"); | 294 | return PTR_ERR(host->io_base); |
304 | return -ENOMEM; | ||
305 | } | ||
306 | 295 | ||
307 | host->clk = clk_get(&pdev->dev, NULL); | 296 | host->clk = devm_clk_get(&pdev->dev, NULL); |
308 | if (IS_ERR(host->clk)) | 297 | if (IS_ERR(host->clk)) |
309 | return PTR_ERR(host->clk); | 298 | return PTR_ERR(host->clk); |
310 | 299 | ||
@@ -320,22 +309,12 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
320 | 309 | ||
321 | ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, | 310 | ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, |
322 | &spdif_out_dai, 1); | 311 | &spdif_out_dai, 1); |
323 | if (ret != 0) { | 312 | return ret; |
324 | clk_put(host->clk); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | return 0; | ||
329 | } | 313 | } |
330 | 314 | ||
331 | static int spdif_out_remove(struct platform_device *pdev) | 315 | static int spdif_out_remove(struct platform_device *pdev) |
332 | { | 316 | { |
333 | struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); | ||
334 | |||
335 | snd_soc_unregister_component(&pdev->dev); | 317 | snd_soc_unregister_component(&pdev->dev); |
336 | dev_set_drvdata(&pdev->dev, NULL); | ||
337 | |||
338 | clk_put(host->clk); | ||
339 | 318 | ||
340 | return 0; | 319 | return 0; |
341 | } | 320 | } |
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 2fbd4899d8ef..4707f2b862c3 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c | |||
@@ -13,19 +13,13 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
19 | #include <linux/scatterlist.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/dmaengine_pcm.h> | 17 | #include <sound/dmaengine_pcm.h> |
23 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
26 | #include <sound/spear_dma.h> | 20 | #include <sound/spear_dma.h> |
27 | 21 | ||
28 | static struct snd_pcm_hardware spear_pcm_hardware = { | 22 | static const struct snd_pcm_hardware spear_pcm_hardware = { |
29 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 23 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
30 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 24 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
31 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | 25 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), |
@@ -37,149 +31,33 @@ static struct snd_pcm_hardware spear_pcm_hardware = { | |||
37 | .fifo_size = 0, /* fifo size in bytes */ | 31 | .fifo_size = 0, /* fifo size in bytes */ |
38 | }; | 32 | }; |
39 | 33 | ||
40 | static int spear_pcm_hw_params(struct snd_pcm_substream *substream, | 34 | static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, |
41 | struct snd_pcm_hw_params *params) | 35 | struct snd_pcm_substream *substream) |
42 | { | 36 | { |
43 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 37 | struct spear_dma_data *dma_data; |
44 | 38 | ||
45 | return 0; | 39 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
46 | } | ||
47 | |||
48 | static int spear_pcm_hw_free(struct snd_pcm_substream *substream) | ||
49 | { | ||
50 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int spear_pcm_open(struct snd_pcm_substream *substream) | ||
56 | { | ||
57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
58 | |||
59 | struct spear_dma_data *dma_data = (struct spear_dma_data *) | ||
60 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
61 | int ret; | ||
62 | |||
63 | ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | 40 | ||
67 | return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, | 41 | return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data); |
68 | dma_data); | ||
69 | } | 42 | } |
70 | 43 | ||
71 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, | 44 | static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = { |
72 | struct vm_area_struct *vma) | 45 | .pcm_hardware = &spear_pcm_hardware, |
73 | { | 46 | .compat_request_channel = spear_pcm_request_chan, |
74 | struct snd_pcm_runtime *runtime = substream->runtime; | 47 | .prealloc_buffer_size = 16 * 1024, |
75 | |||
76 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
77 | runtime->dma_area, runtime->dma_addr, | ||
78 | runtime->dma_bytes); | ||
79 | } | ||
80 | |||
81 | static struct snd_pcm_ops spear_pcm_ops = { | ||
82 | .open = spear_pcm_open, | ||
83 | .close = snd_dmaengine_pcm_close_release_chan, | ||
84 | .ioctl = snd_pcm_lib_ioctl, | ||
85 | .hw_params = spear_pcm_hw_params, | ||
86 | .hw_free = spear_pcm_hw_free, | ||
87 | .trigger = snd_dmaengine_pcm_trigger, | ||
88 | .pointer = snd_dmaengine_pcm_pointer, | ||
89 | .mmap = spear_pcm_mmap, | ||
90 | }; | ||
91 | |||
92 | static int | ||
93 | spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, | ||
94 | size_t size) | ||
95 | { | ||
96 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
97 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
98 | |||
99 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
100 | buf->dev.dev = pcm->card->dev; | ||
101 | buf->private_data = NULL; | ||
102 | |||
103 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
104 | &buf->addr, GFP_KERNEL); | ||
105 | if (!buf->area) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | dev_info(buf->dev.dev, | ||
109 | " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | ||
110 | (void *)buf->area, (void *)buf->addr, size); | ||
111 | |||
112 | buf->bytes = size; | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void spear_pcm_free(struct snd_pcm *pcm) | ||
117 | { | ||
118 | struct snd_pcm_substream *substream; | ||
119 | struct snd_dma_buffer *buf; | ||
120 | int stream; | ||
121 | |||
122 | for (stream = 0; stream < 2; stream++) { | ||
123 | substream = pcm->streams[stream].substream; | ||
124 | if (!substream) | ||
125 | continue; | ||
126 | |||
127 | buf = &substream->dma_buffer; | ||
128 | if (!buf || !buf->area) | ||
129 | continue; | ||
130 | |||
131 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
132 | buf->area, buf->addr); | ||
133 | buf->area = NULL; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static u64 spear_pcm_dmamask = DMA_BIT_MASK(32); | ||
138 | |||
139 | static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
140 | { | ||
141 | struct snd_card *card = rtd->card->snd_card; | ||
142 | int ret; | ||
143 | |||
144 | if (!card->dev->dma_mask) | ||
145 | card->dev->dma_mask = &spear_pcm_dmamask; | ||
146 | if (!card->dev->coherent_dma_mask) | ||
147 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
148 | |||
149 | if (rtd->cpu_dai->driver->playback.channels_min) { | ||
150 | ret = spear_pcm_preallocate_dma_buffer(rtd->pcm, | ||
151 | SNDRV_PCM_STREAM_PLAYBACK, | ||
152 | spear_pcm_hardware.buffer_bytes_max); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | if (rtd->cpu_dai->driver->capture.channels_min) { | ||
158 | ret = spear_pcm_preallocate_dma_buffer(rtd->pcm, | ||
159 | SNDRV_PCM_STREAM_CAPTURE, | ||
160 | spear_pcm_hardware.buffer_bytes_max); | ||
161 | if (ret) | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static struct snd_soc_platform_driver spear_soc_platform = { | ||
169 | .ops = &spear_pcm_ops, | ||
170 | .pcm_new = spear_pcm_new, | ||
171 | .pcm_free = spear_pcm_free, | ||
172 | }; | 48 | }; |
173 | 49 | ||
174 | static int spear_soc_platform_probe(struct platform_device *pdev) | 50 | static int spear_soc_platform_probe(struct platform_device *pdev) |
175 | { | 51 | { |
176 | return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); | 52 | return snd_dmaengine_pcm_register(&pdev->dev, |
53 | &spear_dmaengine_pcm_config, | ||
54 | SND_DMAENGINE_PCM_FLAG_NO_DT | | ||
55 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
177 | } | 56 | } |
178 | 57 | ||
179 | static int spear_soc_platform_remove(struct platform_device *pdev) | 58 | static int spear_soc_platform_remove(struct platform_device *pdev) |
180 | { | 59 | { |
181 | snd_soc_unregister_platform(&pdev->dev); | 60 | snd_dmaengine_pcm_unregister(&pdev->dev); |
182 | |||
183 | return 0; | 61 | return 0; |
184 | } | 62 | } |
185 | 63 | ||
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index b1c9d573da05..995b120c2cd0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -59,6 +59,16 @@ config SND_SOC_TEGRA30_I2S | |||
59 | Tegra30 I2S interface. You will also need to select the individual | 59 | Tegra30 I2S interface. You will also need to select the individual |
60 | machine drivers to support below. | 60 | machine drivers to support below. |
61 | 61 | ||
62 | config SND_SOC_TEGRA_RT5640 | ||
63 | tristate "SoC Audio support for Tegra boards using an RT5640 codec" | ||
64 | depends on SND_SOC_TEGRA && I2C | ||
65 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | ||
66 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | ||
67 | select SND_SOC_RT5640 | ||
68 | help | ||
69 | Say Y or M here if you want to add support for SoC audio on Tegra | ||
70 | boards using the RT5640 codec, such as Dalmore. | ||
71 | |||
62 | config SND_SOC_TEGRA_WM8753 | 72 | config SND_SOC_TEGRA_WM8753 |
63 | tristate "SoC Audio support for Tegra boards using a WM8753 codec" | 73 | tristate "SoC Audio support for Tegra boards using a WM8753 codec" |
64 | depends on SND_SOC_TEGRA && I2C | 74 | depends on SND_SOC_TEGRA && I2C |
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 416a14bde41b..21d2550a08a4 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile | |||
@@ -18,12 +18,14 @@ obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o | |||
18 | obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o | 18 | obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o |
19 | 19 | ||
20 | # Tegra machine Support | 20 | # Tegra machine Support |
21 | snd-soc-tegra-rt5640-objs := tegra_rt5640.o | ||
21 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o | 22 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o |
22 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o | 23 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o |
23 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o | 24 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o |
24 | snd-soc-tegra-trimslice-objs := trimslice.o | 25 | snd-soc-tegra-trimslice-objs := trimslice.o |
25 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o | 26 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o |
26 | 27 | ||
28 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o | ||
27 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o | 29 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o |
28 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o | 30 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o |
29 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o | 31 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o |
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 23e592f453fa..d554d46d08b5 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -627,9 +627,34 @@ static int tegra30_ahub_remove(struct platform_device *pdev) | |||
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
629 | 629 | ||
630 | #ifdef CONFIG_PM_SLEEP | ||
631 | static int tegra30_ahub_suspend(struct device *dev) | ||
632 | { | ||
633 | regcache_mark_dirty(ahub->regmap_ahub); | ||
634 | regcache_mark_dirty(ahub->regmap_apbif); | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | static int tegra30_ahub_resume(struct device *dev) | ||
640 | { | ||
641 | int ret; | ||
642 | |||
643 | ret = pm_runtime_get_sync(dev); | ||
644 | if (ret < 0) | ||
645 | return ret; | ||
646 | ret = regcache_sync(ahub->regmap_ahub); | ||
647 | ret |= regcache_sync(ahub->regmap_apbif); | ||
648 | pm_runtime_put(dev); | ||
649 | |||
650 | return ret; | ||
651 | } | ||
652 | #endif | ||
653 | |||
630 | static const struct dev_pm_ops tegra30_ahub_pm_ops = { | 654 | static const struct dev_pm_ops tegra30_ahub_pm_ops = { |
631 | SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, | 655 | SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, |
632 | tegra30_ahub_runtime_resume, NULL) | 656 | tegra30_ahub_runtime_resume, NULL) |
657 | SET_SYSTEM_SLEEP_PM_OPS(tegra30_ahub_suspend, tegra30_ahub_resume) | ||
633 | }; | 658 | }; |
634 | 659 | ||
635 | static struct platform_driver tegra30_ahub_driver = { | 660 | static struct platform_driver tegra30_ahub_driver = { |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 31d092d83c71..d04146cad61f 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -514,6 +514,31 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) | |||
514 | return 0; | 514 | return 0; |
515 | } | 515 | } |
516 | 516 | ||
517 | #ifdef CONFIG_PM_SLEEP | ||
518 | static int tegra30_i2s_suspend(struct device *dev) | ||
519 | { | ||
520 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); | ||
521 | |||
522 | regcache_mark_dirty(i2s->regmap); | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int tegra30_i2s_resume(struct device *dev) | ||
528 | { | ||
529 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); | ||
530 | int ret; | ||
531 | |||
532 | ret = pm_runtime_get_sync(dev); | ||
533 | if (ret < 0) | ||
534 | return ret; | ||
535 | ret = regcache_sync(i2s->regmap); | ||
536 | pm_runtime_put(dev); | ||
537 | |||
538 | return ret; | ||
539 | } | ||
540 | #endif | ||
541 | |||
517 | static const struct of_device_id tegra30_i2s_of_match[] = { | 542 | static const struct of_device_id tegra30_i2s_of_match[] = { |
518 | { .compatible = "nvidia,tegra30-i2s", }, | 543 | { .compatible = "nvidia,tegra30-i2s", }, |
519 | {}, | 544 | {}, |
@@ -522,6 +547,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = { | |||
522 | static const struct dev_pm_ops tegra30_i2s_pm_ops = { | 547 | static const struct dev_pm_ops tegra30_i2s_pm_ops = { |
523 | SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, | 548 | SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, |
524 | tegra30_i2s_runtime_resume, NULL) | 549 | tegra30_i2s_runtime_resume, NULL) |
550 | SET_SYSTEM_SLEEP_PM_OPS(tegra30_i2s_suspend, tegra30_i2s_resume) | ||
525 | }; | 551 | }; |
526 | 552 | ||
527 | static struct platform_driver tegra30_i2s_driver = { | 553 | static struct platform_driver tegra30_i2s_driver = { |
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 24fb001be7f4..d173880f290d 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c | |||
@@ -173,7 +173,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | |||
173 | struct device *dev) | 173 | struct device *dev) |
174 | { | 174 | { |
175 | int ret; | 175 | int ret; |
176 | bool new_clocks = false; | ||
177 | 176 | ||
178 | data->dev = dev; | 177 | data->dev = dev; |
179 | 178 | ||
@@ -181,40 +180,28 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | |||
181 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; | 180 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; |
182 | else if (of_machine_is_compatible("nvidia,tegra30")) | 181 | else if (of_machine_is_compatible("nvidia,tegra30")) |
183 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; | 182 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; |
184 | else if (of_machine_is_compatible("nvidia,tegra114")) { | 183 | else if (of_machine_is_compatible("nvidia,tegra114")) |
185 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; | 184 | data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; |
186 | new_clocks = true; | 185 | else { |
187 | } else { | ||
188 | dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); | 186 | dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); |
189 | return -EINVAL; | 187 | return -EINVAL; |
190 | } | 188 | } |
191 | 189 | ||
192 | if (new_clocks) | 190 | data->clk_pll_a = clk_get(dev, "pll_a"); |
193 | data->clk_pll_a = clk_get(dev, "pll_a"); | ||
194 | else | ||
195 | data->clk_pll_a = clk_get_sys(NULL, "pll_a"); | ||
196 | if (IS_ERR(data->clk_pll_a)) { | 191 | if (IS_ERR(data->clk_pll_a)) { |
197 | dev_err(data->dev, "Can't retrieve clk pll_a\n"); | 192 | dev_err(data->dev, "Can't retrieve clk pll_a\n"); |
198 | ret = PTR_ERR(data->clk_pll_a); | 193 | ret = PTR_ERR(data->clk_pll_a); |
199 | goto err; | 194 | goto err; |
200 | } | 195 | } |
201 | 196 | ||
202 | if (new_clocks) | 197 | data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0"); |
203 | data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0"); | ||
204 | else | ||
205 | data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); | ||
206 | if (IS_ERR(data->clk_pll_a_out0)) { | 198 | if (IS_ERR(data->clk_pll_a_out0)) { |
207 | dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); | 199 | dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); |
208 | ret = PTR_ERR(data->clk_pll_a_out0); | 200 | ret = PTR_ERR(data->clk_pll_a_out0); |
209 | goto err_put_pll_a; | 201 | goto err_put_pll_a; |
210 | } | 202 | } |
211 | 203 | ||
212 | if (new_clocks) | 204 | data->clk_cdev1 = clk_get(dev, "mclk"); |
213 | data->clk_cdev1 = clk_get(dev, "mclk"); | ||
214 | else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) | ||
215 | data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); | ||
216 | else | ||
217 | data->clk_cdev1 = clk_get_sys("extern1", NULL); | ||
218 | if (IS_ERR(data->clk_cdev1)) { | 205 | if (IS_ERR(data->clk_cdev1)) { |
219 | dev_err(data->dev, "Can't retrieve clk cdev1\n"); | 206 | dev_err(data->dev, "Can't retrieve clk cdev1\n"); |
220 | ret = PTR_ERR(data->clk_cdev1); | 207 | ret = PTR_ERR(data->clk_cdev1); |
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c new file mode 100644 index 000000000000..08794f915a94 --- /dev/null +++ b/sound/soc/tegra/tegra_rt5640.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * tegra_rt5640.c - Tegra machine ASoC driver for boards using WM8903 codec. | ||
3 | * | ||
4 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Based on code copyright/by: | ||
19 | * | ||
20 | * Copyright (C) 2010-2012 - NVIDIA, Inc. | ||
21 | * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> | ||
22 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
23 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/of_gpio.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/jack.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/soc.h> | ||
37 | |||
38 | #include "../codecs/rt5640.h" | ||
39 | |||
40 | #include "tegra_asoc_utils.h" | ||
41 | |||
42 | #define DRV_NAME "tegra-snd-rt5640" | ||
43 | |||
44 | struct tegra_rt5640 { | ||
45 | struct tegra_asoc_utils_data util_data; | ||
46 | int gpio_hp_det; | ||
47 | }; | ||
48 | |||
49 | static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream, | ||
50 | struct snd_pcm_hw_params *params) | ||
51 | { | ||
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
54 | struct snd_soc_codec *codec = codec_dai->codec; | ||
55 | struct snd_soc_card *card = codec->card; | ||
56 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); | ||
57 | int srate, mclk; | ||
58 | int err; | ||
59 | |||
60 | srate = params_rate(params); | ||
61 | mclk = 256 * srate; | ||
62 | |||
63 | err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); | ||
64 | if (err < 0) { | ||
65 | dev_err(card->dev, "Can't configure clocks\n"); | ||
66 | return err; | ||
67 | } | ||
68 | |||
69 | err = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, mclk, | ||
70 | SND_SOC_CLOCK_IN); | ||
71 | if (err < 0) { | ||
72 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
73 | return err; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct snd_soc_ops tegra_rt5640_ops = { | ||
80 | .hw_params = tegra_rt5640_asoc_hw_params, | ||
81 | }; | ||
82 | |||
83 | static struct snd_soc_jack tegra_rt5640_hp_jack; | ||
84 | |||
85 | static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = { | ||
86 | { | ||
87 | .pin = "Headphones", | ||
88 | .mask = SND_JACK_HEADPHONE, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = { | ||
93 | .name = "Headphone detection", | ||
94 | .report = SND_JACK_HEADPHONE, | ||
95 | .debounce_time = 150, | ||
96 | .invert = 1, | ||
97 | }; | ||
98 | |||
99 | static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = { | ||
100 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
101 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
102 | }; | ||
103 | |||
104 | static const struct snd_kcontrol_new tegra_rt5640_controls[] = { | ||
105 | SOC_DAPM_PIN_SWITCH("Speakers"), | ||
106 | }; | ||
107 | |||
108 | static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
109 | { | ||
110 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
111 | struct snd_soc_codec *codec = codec_dai->codec; | ||
112 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card); | ||
113 | |||
114 | snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE, | ||
115 | &tegra_rt5640_hp_jack); | ||
116 | snd_soc_jack_add_pins(&tegra_rt5640_hp_jack, | ||
117 | ARRAY_SIZE(tegra_rt5640_hp_jack_pins), | ||
118 | tegra_rt5640_hp_jack_pins); | ||
119 | |||
120 | if (gpio_is_valid(machine->gpio_hp_det)) { | ||
121 | tegra_rt5640_hp_jack_gpio.gpio = machine->gpio_hp_det; | ||
122 | snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack, | ||
123 | 1, | ||
124 | &tegra_rt5640_hp_jack_gpio); | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static struct snd_soc_dai_link tegra_rt5640_dai = { | ||
131 | .name = "RT5640", | ||
132 | .stream_name = "RT5640 PCM", | ||
133 | .codec_dai_name = "rt5640-aif1", | ||
134 | .init = tegra_rt5640_asoc_init, | ||
135 | .ops = &tegra_rt5640_ops, | ||
136 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
137 | SND_SOC_DAIFMT_CBS_CFS, | ||
138 | }; | ||
139 | |||
140 | static struct snd_soc_card snd_soc_tegra_rt5640 = { | ||
141 | .name = "tegra-rt5640", | ||
142 | .owner = THIS_MODULE, | ||
143 | .dai_link = &tegra_rt5640_dai, | ||
144 | .num_links = 1, | ||
145 | .controls = tegra_rt5640_controls, | ||
146 | .num_controls = ARRAY_SIZE(tegra_rt5640_controls), | ||
147 | .dapm_widgets = tegra_rt5640_dapm_widgets, | ||
148 | .num_dapm_widgets = ARRAY_SIZE(tegra_rt5640_dapm_widgets), | ||
149 | .fully_routed = true, | ||
150 | }; | ||
151 | |||
152 | static int tegra_rt5640_probe(struct platform_device *pdev) | ||
153 | { | ||
154 | struct device_node *np = pdev->dev.of_node; | ||
155 | struct snd_soc_card *card = &snd_soc_tegra_rt5640; | ||
156 | struct tegra_rt5640 *machine; | ||
157 | int ret; | ||
158 | |||
159 | machine = devm_kzalloc(&pdev->dev, | ||
160 | sizeof(struct tegra_rt5640), GFP_KERNEL); | ||
161 | if (!machine) { | ||
162 | dev_err(&pdev->dev, "Can't allocate tegra_rt5640\n"); | ||
163 | return -ENOMEM; | ||
164 | } | ||
165 | |||
166 | card->dev = &pdev->dev; | ||
167 | platform_set_drvdata(pdev, card); | ||
168 | snd_soc_card_set_drvdata(card, machine); | ||
169 | |||
170 | machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); | ||
171 | if (machine->gpio_hp_det == -EPROBE_DEFER) | ||
172 | return -EPROBE_DEFER; | ||
173 | |||
174 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | ||
175 | if (ret) | ||
176 | goto err; | ||
177 | |||
178 | ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); | ||
179 | if (ret) | ||
180 | goto err; | ||
181 | |||
182 | tegra_rt5640_dai.codec_of_node = of_parse_phandle(np, | ||
183 | "nvidia,audio-codec", 0); | ||
184 | if (!tegra_rt5640_dai.codec_of_node) { | ||
185 | dev_err(&pdev->dev, | ||
186 | "Property 'nvidia,audio-codec' missing or invalid\n"); | ||
187 | ret = -EINVAL; | ||
188 | goto err; | ||
189 | } | ||
190 | |||
191 | tegra_rt5640_dai.cpu_of_node = of_parse_phandle(np, | ||
192 | "nvidia,i2s-controller", 0); | ||
193 | if (!tegra_rt5640_dai.cpu_of_node) { | ||
194 | dev_err(&pdev->dev, | ||
195 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | ||
196 | ret = -EINVAL; | ||
197 | goto err; | ||
198 | } | ||
199 | |||
200 | tegra_rt5640_dai.platform_of_node = tegra_rt5640_dai.cpu_of_node; | ||
201 | |||
202 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | ||
203 | if (ret) | ||
204 | goto err; | ||
205 | |||
206 | ret = snd_soc_register_card(card); | ||
207 | if (ret) { | ||
208 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
209 | ret); | ||
210 | goto err_fini_utils; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | |||
215 | err_fini_utils: | ||
216 | tegra_asoc_utils_fini(&machine->util_data); | ||
217 | err: | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int tegra_rt5640_remove(struct platform_device *pdev) | ||
222 | { | ||
223 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
224 | struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); | ||
225 | |||
226 | snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack, 1, | ||
227 | &tegra_rt5640_hp_jack_gpio); | ||
228 | |||
229 | snd_soc_unregister_card(card); | ||
230 | |||
231 | tegra_asoc_utils_fini(&machine->util_data); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static const struct of_device_id tegra_rt5640_of_match[] = { | ||
237 | { .compatible = "nvidia,tegra-audio-rt5640", }, | ||
238 | {}, | ||
239 | }; | ||
240 | |||
241 | static struct platform_driver tegra_rt5640_driver = { | ||
242 | .driver = { | ||
243 | .name = DRV_NAME, | ||
244 | .owner = THIS_MODULE, | ||
245 | .pm = &snd_soc_pm_ops, | ||
246 | .of_match_table = tegra_rt5640_of_match, | ||
247 | }, | ||
248 | .probe = tegra_rt5640_probe, | ||
249 | .remove = tegra_rt5640_remove, | ||
250 | }; | ||
251 | module_platform_driver(tegra_rt5640_driver); | ||
252 | |||
253 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
254 | MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver"); | ||
255 | MODULE_LICENSE("GPL v2"); | ||
256 | MODULE_ALIAS("platform:" DRV_NAME); | ||
257 | MODULE_DEVICE_TABLE(of, tegra_rt5640_of_match); | ||
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 204b899c2311..8f5cd00a6e46 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "mop500_ab8500.h" | 27 | #include "mop500_ab8500.h" |
28 | 28 | ||
29 | /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ | 29 | /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ |
30 | struct snd_soc_dai_link mop500_dai_links[] = { | 30 | static struct snd_soc_dai_link mop500_dai_links[] = { |
31 | { | 31 | { |
32 | .name = "ab8500_0", | 32 | .name = "ab8500_0", |
33 | .stream_name = "ab8500_0", | 33 | .stream_name = "ab8500_0", |
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 892ad9a05c9f..7e923ecf8901 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/mutex.h> | ||
19 | 20 | ||
20 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
21 | #include <sound/soc-dapm.h> | 22 | #include <sound/soc-dapm.h> |
@@ -24,6 +25,7 @@ | |||
24 | 25 | ||
25 | #include "ux500_pcm.h" | 26 | #include "ux500_pcm.h" |
26 | #include "ux500_msp_dai.h" | 27 | #include "ux500_msp_dai.h" |
28 | #include "mop500_ab8500.h" | ||
27 | #include "../codecs/ab8500-codec.h" | 29 | #include "../codecs/ab8500-codec.h" |
28 | 30 | ||
29 | #define TX_SLOT_MONO 0x0008 | 31 | #define TX_SLOT_MONO 0x0008 |
@@ -43,6 +45,12 @@ | |||
43 | static unsigned int tx_slots = DEF_TX_SLOTS; | 45 | static unsigned int tx_slots = DEF_TX_SLOTS; |
44 | static unsigned int rx_slots = DEF_RX_SLOTS; | 46 | static unsigned int rx_slots = DEF_RX_SLOTS; |
45 | 47 | ||
48 | /* Configuration consistency parameters */ | ||
49 | static DEFINE_MUTEX(mop500_ab8500_params_lock); | ||
50 | static unsigned long mop500_ab8500_usage; | ||
51 | static int mop500_ab8500_rate; | ||
52 | static int mop500_ab8500_channels; | ||
53 | |||
46 | /* Clocks */ | 54 | /* Clocks */ |
47 | static const char * const enum_mclk[] = { | 55 | static const char * const enum_mclk[] = { |
48 | "SYSCLK", | 56 | "SYSCLK", |
@@ -125,9 +133,9 @@ static int mop500_ab8500_set_mclk(struct device *dev, | |||
125 | static int mclk_input_control_get(struct snd_kcontrol *kcontrol, | 133 | static int mclk_input_control_get(struct snd_kcontrol *kcontrol, |
126 | struct snd_ctl_elem_value *ucontrol) | 134 | struct snd_ctl_elem_value *ucontrol) |
127 | { | 135 | { |
128 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 136 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
129 | struct mop500_ab8500_drvdata *drvdata = | 137 | struct mop500_ab8500_drvdata *drvdata = |
130 | snd_soc_card_get_drvdata(codec->card); | 138 | snd_soc_card_get_drvdata(card); |
131 | 139 | ||
132 | ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; | 140 | ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; |
133 | 141 | ||
@@ -137,9 +145,9 @@ static int mclk_input_control_get(struct snd_kcontrol *kcontrol, | |||
137 | static int mclk_input_control_put(struct snd_kcontrol *kcontrol, | 145 | static int mclk_input_control_put(struct snd_kcontrol *kcontrol, |
138 | struct snd_ctl_elem_value *ucontrol) | 146 | struct snd_ctl_elem_value *ucontrol) |
139 | { | 147 | { |
140 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 148 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
141 | struct mop500_ab8500_drvdata *drvdata = | 149 | struct mop500_ab8500_drvdata *drvdata = |
142 | snd_soc_card_get_drvdata(codec->card); | 150 | snd_soc_card_get_drvdata(card); |
143 | unsigned int val = ucontrol->value.enumerated.item[0]; | 151 | unsigned int val = ucontrol->value.enumerated.item[0]; |
144 | 152 | ||
145 | if (val > (unsigned int)MCLK_ULPCLK) | 153 | if (val > (unsigned int)MCLK_ULPCLK) |
@@ -160,16 +168,6 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { | |||
160 | SOC_ENUM_EXT("Master Clock Select", | 168 | SOC_ENUM_EXT("Master Clock Select", |
161 | soc_enum_mclk, | 169 | soc_enum_mclk, |
162 | mclk_input_control_get, mclk_input_control_put), | 170 | mclk_input_control_get, mclk_input_control_put), |
163 | /* Digital interface - Clocks */ | ||
164 | SOC_SINGLE("Digital Interface Master Generator Switch", | ||
165 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN, | ||
166 | 1, 0), | ||
167 | SOC_SINGLE("Digital Interface 0 Bit-clock Switch", | ||
168 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0, | ||
169 | 1, 0), | ||
170 | SOC_SINGLE("Digital Interface 1 Bit-clock Switch", | ||
171 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1, | ||
172 | 1, 0), | ||
173 | SOC_DAPM_PIN_SWITCH("Headset Left"), | 171 | SOC_DAPM_PIN_SWITCH("Headset Left"), |
174 | SOC_DAPM_PIN_SWITCH("Headset Right"), | 172 | SOC_DAPM_PIN_SWITCH("Headset Right"), |
175 | SOC_DAPM_PIN_SWITCH("Earpiece"), | 173 | SOC_DAPM_PIN_SWITCH("Earpiece"), |
@@ -193,7 +191,7 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { | |||
193 | 191 | ||
194 | /* ASoC */ | 192 | /* ASoC */ |
195 | 193 | ||
196 | int mop500_ab8500_startup(struct snd_pcm_substream *substream) | 194 | static int mop500_ab8500_startup(struct snd_pcm_substream *substream) |
197 | { | 195 | { |
198 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
199 | 197 | ||
@@ -202,7 +200,7 @@ int mop500_ab8500_startup(struct snd_pcm_substream *substream) | |||
202 | snd_soc_card_get_drvdata(rtd->card)); | 200 | snd_soc_card_get_drvdata(rtd->card)); |
203 | } | 201 | } |
204 | 202 | ||
205 | void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) | 203 | static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) |
206 | { | 204 | { |
207 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 205 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
208 | struct device *dev = rtd->card->dev; | 206 | struct device *dev = rtd->card->dev; |
@@ -216,7 +214,7 @@ void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) | |||
216 | rx_slots = DEF_RX_SLOTS; | 214 | rx_slots = DEF_RX_SLOTS; |
217 | } | 215 | } |
218 | 216 | ||
219 | int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | 217 | static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, |
220 | struct snd_pcm_hw_params *params) | 218 | struct snd_pcm_hw_params *params) |
221 | { | 219 | { |
222 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 220 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -240,6 +238,21 @@ int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | |||
240 | substream->name, | 238 | substream->name, |
241 | substream->number); | 239 | substream->number); |
242 | 240 | ||
241 | /* Ensure configuration consistency between DAIs */ | ||
242 | mutex_lock(&mop500_ab8500_params_lock); | ||
243 | if (mop500_ab8500_usage) { | ||
244 | if (mop500_ab8500_rate != params_rate(params) || | ||
245 | mop500_ab8500_channels != params_channels(params)) { | ||
246 | mutex_unlock(&mop500_ab8500_params_lock); | ||
247 | return -EBUSY; | ||
248 | } | ||
249 | } else { | ||
250 | mop500_ab8500_rate = params_rate(params); | ||
251 | mop500_ab8500_channels = params_channels(params); | ||
252 | } | ||
253 | __set_bit(cpu_dai->id, &mop500_ab8500_usage); | ||
254 | mutex_unlock(&mop500_ab8500_params_lock); | ||
255 | |||
243 | channels = params_channels(params); | 256 | channels = params_channels(params); |
244 | 257 | ||
245 | switch (params_format(params)) { | 258 | switch (params_format(params)) { |
@@ -338,9 +351,22 @@ int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | |||
338 | return 0; | 351 | return 0; |
339 | } | 352 | } |
340 | 353 | ||
354 | static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream) | ||
355 | { | ||
356 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
357 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
358 | |||
359 | mutex_lock(&mop500_ab8500_params_lock); | ||
360 | __clear_bit(cpu_dai->id, &mop500_ab8500_usage); | ||
361 | mutex_unlock(&mop500_ab8500_params_lock); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
341 | struct snd_soc_ops mop500_ab8500_ops[] = { | 366 | struct snd_soc_ops mop500_ab8500_ops[] = { |
342 | { | 367 | { |
343 | .hw_params = mop500_ab8500_hw_params, | 368 | .hw_params = mop500_ab8500_hw_params, |
369 | .hw_free = mop500_ab8500_hw_free, | ||
344 | .startup = mop500_ab8500_startup, | 370 | .startup = mop500_ab8500_startup, |
345 | .shutdown = mop500_ab8500_shutdown, | 371 | .shutdown = mop500_ab8500_shutdown, |
346 | } | 372 | } |
@@ -385,7 +411,7 @@ int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) | |||
385 | drvdata->mclk_sel = MCLK_ULPCLK; | 411 | drvdata->mclk_sel = MCLK_ULPCLK; |
386 | 412 | ||
387 | /* Add controls */ | 413 | /* Add controls */ |
388 | ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, | 414 | ret = snd_soc_add_card_controls(codec->card, mop500_ab8500_ctrls, |
389 | ARRAY_SIZE(mop500_ab8500_ctrls)); | 415 | ARRAY_SIZE(mop500_ab8500_ctrls)); |
390 | if (ret < 0) { | 416 | if (ret < 0) { |
391 | pr_err("%s: Failed to add machine-controls (%d)!\n", | 417 | pr_err("%s: Failed to add machine-controls (%d)!\n", |
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 7d5fc1328523..c6fb5cce980e 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -658,14 +658,11 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai) | |||
658 | { | 658 | { |
659 | struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); | 659 | struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); |
660 | 660 | ||
661 | drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx; | 661 | dai->playback_dma_data = &drvdata->msp->playback_dma_data; |
662 | drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx; | 662 | dai->capture_dma_data = &drvdata->msp->capture_dma_data; |
663 | 663 | ||
664 | dai->playback_dma_data = &drvdata->playback_dma_data; | 664 | drvdata->msp->playback_dma_data.data_size = drvdata->slot_width; |
665 | dai->capture_dma_data = &drvdata->capture_dma_data; | 665 | drvdata->msp->capture_dma_data.data_size = drvdata->slot_width; |
666 | |||
667 | drvdata->playback_dma_data.data_size = drvdata->slot_width; | ||
668 | drvdata->capture_dma_data.data_size = drvdata->slot_width; | ||
669 | 666 | ||
670 | return 0; | 667 | return 0; |
671 | } | 668 | } |
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h index f53104359f15..312ae535e351 100644 --- a/sound/soc/ux500/ux500_msp_dai.h +++ b/sound/soc/ux500/ux500_msp_dai.h | |||
@@ -51,15 +51,11 @@ enum ux500_msp_clock_id { | |||
51 | struct ux500_msp_i2s_drvdata { | 51 | struct ux500_msp_i2s_drvdata { |
52 | struct ux500_msp *msp; | 52 | struct ux500_msp *msp; |
53 | struct regulator *reg_vape; | 53 | struct regulator *reg_vape; |
54 | struct ux500_msp_dma_params playback_dma_data; | ||
55 | struct ux500_msp_dma_params capture_dma_data; | ||
56 | unsigned int fmt; | 54 | unsigned int fmt; |
57 | unsigned int tx_mask; | 55 | unsigned int tx_mask; |
58 | unsigned int rx_mask; | 56 | unsigned int rx_mask; |
59 | int slots; | 57 | int slots; |
60 | int slot_width; | 58 | int slot_width; |
61 | u8 configured; | ||
62 | int data_delay; | ||
63 | 59 | ||
64 | /* Clocks */ | 60 | /* Clocks */ |
65 | unsigned int master_clk; | 61 | unsigned int master_clk; |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index f2db6c90a9e2..1ca8b08ae993 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/pinctrl/consumer.h> | ||
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
@@ -26,9 +25,6 @@ | |||
26 | 25 | ||
27 | #include "ux500_msp_i2s.h" | 26 | #include "ux500_msp_i2s.h" |
28 | 27 | ||
29 | /* MSP1/3 Tx/Rx usage protection */ | ||
30 | static DEFINE_SPINLOCK(msp_rxtx_lock); | ||
31 | |||
32 | /* Protocol desciptors */ | 28 | /* Protocol desciptors */ |
33 | static const struct msp_protdesc prot_descs[] = { | 29 | static const struct msp_protdesc prot_descs[] = { |
34 | { /* I2S */ | 30 | { /* I2S */ |
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp, | |||
356 | 352 | ||
357 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) | 353 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) |
358 | { | 354 | { |
359 | int status = 0, retval = 0; | 355 | int status = 0; |
360 | u32 reg_val_DMACR, reg_val_GCR; | 356 | u32 reg_val_DMACR, reg_val_GCR; |
361 | unsigned long flags; | ||
362 | |||
363 | /* Check msp state whether in RUN or CONFIGURED Mode */ | ||
364 | if (msp->msp_state == MSP_STATE_IDLE) { | ||
365 | spin_lock_irqsave(&msp_rxtx_lock, flags); | ||
366 | if (msp->pinctrl_rxtx_ref == 0 && | ||
367 | !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) { | ||
368 | retval = pinctrl_select_state(msp->pinctrl_p, | ||
369 | msp->pinctrl_def); | ||
370 | if (retval) | ||
371 | pr_err("could not set MSP defstate\n"); | ||
372 | } | ||
373 | if (!retval) | ||
374 | msp->pinctrl_rxtx_ref++; | ||
375 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
376 | } | ||
377 | 357 | ||
378 | /* Configure msp with protocol dependent settings */ | 358 | /* Configure msp with protocol dependent settings */ |
379 | configure_protocol(msp, config); | 359 | configure_protocol(msp, config); |
@@ -387,12 +367,14 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) | |||
387 | } | 367 | } |
388 | 368 | ||
389 | /* Make sure the correct DMA-directions are configured */ | 369 | /* Make sure the correct DMA-directions are configured */ |
390 | if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) { | 370 | if ((config->direction & MSP_DIR_RX) && |
371 | !msp->capture_dma_data.dma_cfg) { | ||
391 | dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!", | 372 | dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!", |
392 | __func__); | 373 | __func__); |
393 | return -EINVAL; | 374 | return -EINVAL; |
394 | } | 375 | } |
395 | if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) { | 376 | if ((config->direction == MSP_DIR_TX) && |
377 | !msp->playback_dma_data.dma_cfg) { | ||
396 | dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!", | 378 | dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!", |
397 | __func__); | 379 | __func__); |
398 | return -EINVAL; | 380 | return -EINVAL; |
@@ -630,8 +612,7 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction) | |||
630 | 612 | ||
631 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | 613 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) |
632 | { | 614 | { |
633 | int status = 0, retval = 0; | 615 | int status = 0; |
634 | unsigned long flags; | ||
635 | 616 | ||
636 | dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); | 617 | dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); |
637 | 618 | ||
@@ -643,18 +624,6 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | |||
643 | (~(FRAME_GEN_ENABLE | SRG_ENABLE))), | 624 | (~(FRAME_GEN_ENABLE | SRG_ENABLE))), |
644 | msp->registers + MSP_GCR); | 625 | msp->registers + MSP_GCR); |
645 | 626 | ||
646 | spin_lock_irqsave(&msp_rxtx_lock, flags); | ||
647 | WARN_ON(!msp->pinctrl_rxtx_ref); | ||
648 | msp->pinctrl_rxtx_ref--; | ||
649 | if (msp->pinctrl_rxtx_ref == 0 && | ||
650 | !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) { | ||
651 | retval = pinctrl_select_state(msp->pinctrl_p, | ||
652 | msp->pinctrl_sleep); | ||
653 | if (retval) | ||
654 | pr_err("could not set MSP sleepstate\n"); | ||
655 | } | ||
656 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
657 | |||
658 | writel(0, msp->registers + MSP_GCR); | 627 | writel(0, msp->registers + MSP_GCR); |
659 | writel(0, msp->registers + MSP_TCF); | 628 | writel(0, msp->registers + MSP_TCF); |
660 | writel(0, msp->registers + MSP_RCF); | 629 | writel(0, msp->registers + MSP_RCF); |
@@ -682,7 +651,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
682 | struct msp_i2s_platform_data *platform_data) | 651 | struct msp_i2s_platform_data *platform_data) |
683 | { | 652 | { |
684 | struct resource *res = NULL; | 653 | struct resource *res = NULL; |
685 | struct i2s_controller *i2s_cont; | ||
686 | struct device_node *np = pdev->dev.of_node; | 654 | struct device_node *np = pdev->dev.of_node; |
687 | struct ux500_msp *msp; | 655 | struct ux500_msp *msp; |
688 | 656 | ||
@@ -707,8 +675,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
707 | 675 | ||
708 | msp->id = platform_data->id; | 676 | msp->id = platform_data->id; |
709 | msp->dev = &pdev->dev; | 677 | msp->dev = &pdev->dev; |
710 | msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; | 678 | msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx; |
711 | msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; | 679 | msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx; |
712 | 680 | ||
713 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 681 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
714 | if (res == NULL) { | 682 | if (res == NULL) { |
@@ -717,6 +685,9 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
717 | return -ENOMEM; | 685 | return -ENOMEM; |
718 | } | 686 | } |
719 | 687 | ||
688 | msp->playback_dma_data.tx_rx_addr = res->start + MSP_DR; | ||
689 | msp->capture_dma_data.tx_rx_addr = res->start + MSP_DR; | ||
690 | |||
720 | msp->registers = devm_ioremap(&pdev->dev, res->start, | 691 | msp->registers = devm_ioremap(&pdev->dev, res->start, |
721 | resource_size(res)); | 692 | resource_size(res)); |
722 | if (msp->registers == NULL) { | 693 | if (msp->registers == NULL) { |
@@ -727,41 +698,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
727 | msp->msp_state = MSP_STATE_IDLE; | 698 | msp->msp_state = MSP_STATE_IDLE; |
728 | msp->loopback_enable = 0; | 699 | msp->loopback_enable = 0; |
729 | 700 | ||
730 | /* I2S-controller is allocated and added in I2S controller class. */ | ||
731 | i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL); | ||
732 | if (!i2s_cont) { | ||
733 | dev_err(&pdev->dev, | ||
734 | "%s: ERROR: Failed to allocate I2S-controller!\n", | ||
735 | __func__); | ||
736 | return -ENOMEM; | ||
737 | } | ||
738 | i2s_cont->dev.parent = &pdev->dev; | ||
739 | i2s_cont->data = (void *)msp; | ||
740 | i2s_cont->id = (s16)msp->id; | ||
741 | snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x", | ||
742 | msp->id); | ||
743 | dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name); | ||
744 | msp->i2s_cont = i2s_cont; | ||
745 | |||
746 | msp->pinctrl_p = pinctrl_get(msp->dev); | ||
747 | if (IS_ERR(msp->pinctrl_p)) | ||
748 | dev_err(&pdev->dev, "could not get MSP pinctrl\n"); | ||
749 | else { | ||
750 | msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p, | ||
751 | PINCTRL_STATE_DEFAULT); | ||
752 | if (IS_ERR(msp->pinctrl_def)) { | ||
753 | dev_err(&pdev->dev, | ||
754 | "could not get MSP defstate (%li)\n", | ||
755 | PTR_ERR(msp->pinctrl_def)); | ||
756 | } | ||
757 | msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p, | ||
758 | PINCTRL_STATE_SLEEP); | ||
759 | if (IS_ERR(msp->pinctrl_sleep)) | ||
760 | dev_err(&pdev->dev, | ||
761 | "could not get MSP idlestate (%li)\n", | ||
762 | PTR_ERR(msp->pinctrl_def)); | ||
763 | } | ||
764 | |||
765 | return 0; | 701 | return 0; |
766 | } | 702 | } |
767 | 703 | ||
@@ -769,8 +705,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, | |||
769 | struct ux500_msp *msp) | 705 | struct ux500_msp *msp) |
770 | { | 706 | { |
771 | dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); | 707 | dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); |
772 | |||
773 | device_unregister(&msp->i2s_cont->dev); | ||
774 | } | 708 | } |
775 | 709 | ||
776 | MODULE_LICENSE("GPL v2"); | 710 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index e5cd105c90f9..258d0bcee0bd 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define UX500_MSP_I2S_H | 16 | #define UX500_MSP_I2S_H |
17 | 17 | ||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/platform_data/asoc-ux500-msp.h> | ||
19 | 20 | ||
20 | #define MSP_INPUT_FREQ_APB 48000000 | 21 | #define MSP_INPUT_FREQ_APB 48000000 |
21 | 22 | ||
@@ -341,11 +342,6 @@ enum msp_compress_mode { | |||
341 | MSP_COMPRESS_MODE_A_LAW = 3 | 342 | MSP_COMPRESS_MODE_A_LAW = 3 |
342 | }; | 343 | }; |
343 | 344 | ||
344 | enum msp_spi_burst_mode { | ||
345 | MSP_SPI_BURST_MODE_DISABLE = 0, | ||
346 | MSP_SPI_BURST_MODE_ENABLE = 1 | ||
347 | }; | ||
348 | |||
349 | enum msp_expand_mode { | 345 | enum msp_expand_mode { |
350 | MSP_EXPAND_MODE_LINEAR = 0, | 346 | MSP_EXPAND_MODE_LINEAR = 0, |
351 | MSP_EXPAND_MODE_LINEAR_SIGNED = 1, | 347 | MSP_EXPAND_MODE_LINEAR_SIGNED = 1, |
@@ -370,13 +366,6 @@ enum msp_protocol { | |||
370 | */ | 366 | */ |
371 | #define MAX_MSP_BACKUP_REGS 36 | 367 | #define MAX_MSP_BACKUP_REGS 36 |
372 | 368 | ||
373 | enum enum_i2s_controller { | ||
374 | MSP_0_I2S_CONTROLLER = 0, | ||
375 | MSP_1_I2S_CONTROLLER, | ||
376 | MSP_2_I2S_CONTROLLER, | ||
377 | MSP_3_I2S_CONTROLLER, | ||
378 | }; | ||
379 | |||
380 | enum i2s_direction_t { | 369 | enum i2s_direction_t { |
381 | MSP_DIR_TX = 0x01, | 370 | MSP_DIR_TX = 0x01, |
382 | MSP_DIR_RX = 0x02, | 371 | MSP_DIR_RX = 0x02, |
@@ -454,32 +443,6 @@ struct msp_protdesc { | |||
454 | u32 clocks_per_frame; | 443 | u32 clocks_per_frame; |
455 | }; | 444 | }; |
456 | 445 | ||
457 | struct i2s_message { | ||
458 | enum i2s_direction_t i2s_direction; | ||
459 | void *txdata; | ||
460 | void *rxdata; | ||
461 | size_t txbytes; | ||
462 | size_t rxbytes; | ||
463 | int dma_flag; | ||
464 | int tx_offset; | ||
465 | int rx_offset; | ||
466 | bool cyclic_dma; | ||
467 | dma_addr_t buf_addr; | ||
468 | size_t buf_len; | ||
469 | size_t period_len; | ||
470 | }; | ||
471 | |||
472 | struct i2s_controller { | ||
473 | struct module *owner; | ||
474 | unsigned int id; | ||
475 | unsigned int class; | ||
476 | const struct i2s_algorithm *algo; /* the algorithm to access the bus */ | ||
477 | void *data; | ||
478 | struct mutex bus_lock; | ||
479 | struct device dev; /* the controller device */ | ||
480 | char name[48]; | ||
481 | }; | ||
482 | |||
483 | struct ux500_msp_config { | 446 | struct ux500_msp_config { |
484 | unsigned int f_inputclk; | 447 | unsigned int f_inputclk; |
485 | unsigned int rx_clk_sel; | 448 | unsigned int rx_clk_sel; |
@@ -491,8 +454,6 @@ struct ux500_msp_config { | |||
491 | unsigned int tx_fsync_sel; | 454 | unsigned int tx_fsync_sel; |
492 | unsigned int rx_fifo_config; | 455 | unsigned int rx_fifo_config; |
493 | unsigned int tx_fifo_config; | 456 | unsigned int tx_fifo_config; |
494 | unsigned int spi_clk_mode; | ||
495 | unsigned int spi_burst_mode; | ||
496 | unsigned int loopback_enable; | 457 | unsigned int loopback_enable; |
497 | unsigned int tx_data_enable; | 458 | unsigned int tx_data_enable; |
498 | unsigned int default_protdesc; | 459 | unsigned int default_protdesc; |
@@ -502,43 +463,28 @@ struct ux500_msp_config { | |||
502 | unsigned int direction; | 463 | unsigned int direction; |
503 | unsigned int protocol; | 464 | unsigned int protocol; |
504 | unsigned int frame_freq; | 465 | unsigned int frame_freq; |
505 | unsigned int frame_size; | ||
506 | enum msp_data_size data_size; | 466 | enum msp_data_size data_size; |
507 | unsigned int def_elem_len; | 467 | unsigned int def_elem_len; |
508 | unsigned int iodelay; | 468 | unsigned int iodelay; |
509 | void (*handler) (void *data); | 469 | }; |
510 | void *tx_callback_data; | 470 | |
511 | void *rx_callback_data; | 471 | struct ux500_msp_dma_params { |
472 | unsigned int data_size; | ||
473 | dma_addr_t tx_rx_addr; | ||
474 | struct stedma40_chan_cfg *dma_cfg; | ||
512 | }; | 475 | }; |
513 | 476 | ||
514 | struct ux500_msp { | 477 | struct ux500_msp { |
515 | enum enum_i2s_controller id; | 478 | enum msp_i2s_id id; |
516 | void __iomem *registers; | 479 | void __iomem *registers; |
517 | struct device *dev; | 480 | struct device *dev; |
518 | struct i2s_controller *i2s_cont; | 481 | struct ux500_msp_dma_params playback_dma_data; |
519 | struct stedma40_chan_cfg *dma_cfg_rx; | 482 | struct ux500_msp_dma_params capture_dma_data; |
520 | struct stedma40_chan_cfg *dma_cfg_tx; | ||
521 | struct dma_chan *tx_pipeid; | ||
522 | struct dma_chan *rx_pipeid; | ||
523 | enum msp_state msp_state; | 483 | enum msp_state msp_state; |
524 | int (*transfer) (struct ux500_msp *msp, struct i2s_message *message); | ||
525 | struct timer_list notify_timer; | ||
526 | int def_elem_len; | 484 | int def_elem_len; |
527 | unsigned int dir_busy; | 485 | unsigned int dir_busy; |
528 | int loopback_enable; | 486 | int loopback_enable; |
529 | u32 backup_regs[MAX_MSP_BACKUP_REGS]; | ||
530 | unsigned int f_bitclk; | 487 | unsigned int f_bitclk; |
531 | /* Pin modes */ | ||
532 | struct pinctrl *pinctrl_p; | ||
533 | struct pinctrl_state *pinctrl_def; | ||
534 | struct pinctrl_state *pinctrl_sleep; | ||
535 | /* Reference Count */ | ||
536 | int pinctrl_rxtx_ref; | ||
537 | }; | ||
538 | |||
539 | struct ux500_msp_dma_params { | ||
540 | unsigned int data_size; | ||
541 | struct stedma40_chan_cfg *dma_cfg; | ||
542 | }; | 488 | }; |
543 | 489 | ||
544 | struct msp_i2s_platform_data; | 490 | struct msp_i2s_platform_data; |
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index b6e5ae277299..5f01c19776bf 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c | |||
@@ -103,10 +103,40 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, | |||
103 | return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); | 103 | return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); |
104 | } | 104 | } |
105 | 105 | ||
106 | static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, | ||
107 | struct snd_pcm_hw_params *params, | ||
108 | struct dma_slave_config *slave_config) | ||
109 | { | ||
110 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
111 | struct ux500_msp_dma_params *dma_params; | ||
112 | struct stedma40_chan_cfg *dma_cfg; | ||
113 | int ret; | ||
114 | |||
115 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
116 | dma_cfg = dma_params->dma_cfg; | ||
117 | |||
118 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); | ||
119 | if (ret) | ||
120 | return ret; | ||
121 | |||
122 | slave_config->dst_maxburst = 4; | ||
123 | slave_config->dst_addr_width = dma_cfg->dst_info.data_width; | ||
124 | slave_config->src_maxburst = 4; | ||
125 | slave_config->src_addr_width = dma_cfg->src_info.data_width; | ||
126 | |||
127 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
128 | slave_config->dst_addr = dma_params->tx_rx_addr; | ||
129 | else | ||
130 | slave_config->src_addr = dma_params->tx_rx_addr; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
106 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { | 135 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { |
107 | .pcm_hardware = &ux500_pcm_hw, | 136 | .pcm_hardware = &ux500_pcm_hw, |
108 | .compat_request_channel = ux500_pcm_request_chan, | 137 | .compat_request_channel = ux500_pcm_request_chan, |
109 | .prealloc_buffer_size = 128 * 1024, | 138 | .prealloc_buffer_size = 128 * 1024, |
139 | .prepare_slave_config = ux500_pcm_prepare_slave_config, | ||
110 | }; | 140 | }; |
111 | 141 | ||
112 | int ux500_pcm_register_platform(struct platform_device *pdev) | 142 | int ux500_pcm_register_platform(struct platform_device *pdev) |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 75e6016d3efe..eee7afcae375 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -2670,8 +2670,6 @@ static int dbri_remove(struct platform_device *op) | |||
2670 | snd_dbri_free(card->private_data); | 2670 | snd_dbri_free(card->private_data); |
2671 | snd_card_free(card); | 2671 | snd_card_free(card); |
2672 | 2672 | ||
2673 | dev_set_drvdata(&op->dev, NULL); | ||
2674 | |||
2675 | return 0; | 2673 | return 0; |
2676 | } | 2674 | } |
2677 | 2675 | ||
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index a1a24b979ed2..8e3d9a6c7a3b 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c | |||
@@ -1070,7 +1070,6 @@ out: | |||
1070 | 1070 | ||
1071 | ssc_free(chip->ssc); | 1071 | ssc_free(chip->ssc); |
1072 | snd_card_free(card); | 1072 | snd_card_free(card); |
1073 | dev_set_drvdata(&spi->dev, NULL); | ||
1074 | 1073 | ||
1075 | return 0; | 1074 | return 0; |
1076 | } | 1075 | } |
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 4394ae796356..c39c77978468 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c | |||
@@ -30,7 +30,7 @@ | |||
30 | MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>"); | 30 | MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>"); |
31 | MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver"); | 31 | MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver"); |
32 | MODULE_LICENSE("GPL v2"); | 32 | MODULE_LICENSE("GPL v2"); |
33 | MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}"); | 33 | MODULE_SUPPORTED_DEVICE("{{TerraTec,DMX 6Fire USB}}"); |
34 | 34 | ||
35 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | 35 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ |
36 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ | 36 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ |
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index 40dd50a80f55..c5b9cac37dc4 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c | |||
@@ -450,13 +450,13 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) | |||
450 | static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub, | 450 | static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub, |
451 | struct snd_pcm_hw_params *hw_params) | 451 | struct snd_pcm_hw_params *hw_params) |
452 | { | 452 | { |
453 | return snd_pcm_lib_malloc_pages(alsa_sub, | 453 | return snd_pcm_lib_alloc_vmalloc_buffer(alsa_sub, |
454 | params_buffer_bytes(hw_params)); | 454 | params_buffer_bytes(hw_params)); |
455 | } | 455 | } |
456 | 456 | ||
457 | static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub) | 457 | static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub) |
458 | { | 458 | { |
459 | return snd_pcm_lib_free_pages(alsa_sub); | 459 | return snd_pcm_lib_free_vmalloc_buffer(alsa_sub); |
460 | } | 460 | } |
461 | 461 | ||
462 | static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | 462 | static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) |
@@ -560,6 +560,8 @@ static struct snd_pcm_ops pcm_ops = { | |||
560 | .prepare = usb6fire_pcm_prepare, | 560 | .prepare = usb6fire_pcm_prepare, |
561 | .trigger = usb6fire_pcm_trigger, | 561 | .trigger = usb6fire_pcm_trigger, |
562 | .pointer = usb6fire_pcm_pointer, | 562 | .pointer = usb6fire_pcm_pointer, |
563 | .page = snd_pcm_lib_get_vmalloc_page, | ||
564 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
563 | }; | 565 | }; |
564 | 566 | ||
565 | static void usb6fire_pcm_init_urb(struct pcm_urb *urb, | 567 | static void usb6fire_pcm_init_urb(struct pcm_urb *urb, |
@@ -622,10 +624,6 @@ int usb6fire_pcm_init(struct sfire_chip *chip) | |||
622 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); | 624 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); |
623 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); | 625 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); |
624 | 626 | ||
625 | ret = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
626 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
627 | snd_dma_continuous_data(GFP_KERNEL), | ||
628 | MAX_BUFSIZE, MAX_BUFSIZE); | ||
629 | if (ret) { | 627 | if (ret) { |
630 | kfree(rt); | 628 | kfree(rt); |
631 | snd_printk(KERN_ERR PREFIX | 629 | snd_printk(KERN_ERR PREFIX |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 225dfd737265..de9408b83f75 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -115,5 +115,36 @@ config SND_USB_6FIRE | |||
115 | and further help can be found at | 115 | and further help can be found at |
116 | http://sixfireusb.sourceforge.net | 116 | http://sixfireusb.sourceforge.net |
117 | 117 | ||
118 | config SND_USB_HIFACE | ||
119 | tristate "M2Tech hiFace USB-SPDIF driver" | ||
120 | select SND_PCM | ||
121 | help | ||
122 | Select this option to include support for M2Tech hiFace USB-SPDIF | ||
123 | interface. | ||
124 | |||
125 | This driver supports the original M2Tech hiFace and some other | ||
126 | compatible devices. The supported products are: | ||
127 | |||
128 | * M2Tech Young | ||
129 | * M2Tech hiFace | ||
130 | * M2Tech North Star | ||
131 | * M2Tech W4S Young | ||
132 | * M2Tech Corrson | ||
133 | * M2Tech AUDIA | ||
134 | * M2Tech SL Audio | ||
135 | * M2Tech Empirical | ||
136 | * M2Tech Rockna | ||
137 | * M2Tech Pathos | ||
138 | * M2Tech Metronome | ||
139 | * M2Tech CAD | ||
140 | * M2Tech Audio Esclusive | ||
141 | * M2Tech Rotel | ||
142 | * M2Tech Eeaudio | ||
143 | * The Chord Company CHORD | ||
144 | * AVA Group A/S Vitus | ||
145 | |||
146 | To compile this driver as a module, choose M here: the module | ||
147 | will be called snd-usb-hiface. | ||
148 | |||
118 | endif # SND_USB | 149 | endif # SND_USB |
119 | 150 | ||
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index ac256dc4c6be..abe668f660d1 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o | |||
23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o | 23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o |
24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o | 24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o |
25 | 25 | ||
26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ | 26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ |
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index c1916184e2e1..7103b0908d13 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c | |||
@@ -183,14 +183,15 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) | |||
183 | static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, | 183 | static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, |
184 | struct snd_pcm_hw_params *hw_params) | 184 | struct snd_pcm_hw_params *hw_params) |
185 | { | 185 | { |
186 | return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); | 186 | return snd_pcm_lib_alloc_vmalloc_buffer(sub, |
187 | params_buffer_bytes(hw_params)); | ||
187 | } | 188 | } |
188 | 189 | ||
189 | static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) | 190 | static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) |
190 | { | 191 | { |
191 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); | 192 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
192 | deactivate_substream(cdev, sub); | 193 | deactivate_substream(cdev, sub); |
193 | return snd_pcm_lib_free_pages(sub); | 194 | return snd_pcm_lib_free_vmalloc_buffer(sub); |
194 | } | 195 | } |
195 | 196 | ||
196 | /* this should probably go upstream */ | 197 | /* this should probably go upstream */ |
@@ -345,7 +346,9 @@ static struct snd_pcm_ops snd_usb_caiaq_ops = { | |||
345 | .hw_free = snd_usb_caiaq_pcm_hw_free, | 346 | .hw_free = snd_usb_caiaq_pcm_hw_free, |
346 | .prepare = snd_usb_caiaq_pcm_prepare, | 347 | .prepare = snd_usb_caiaq_pcm_prepare, |
347 | .trigger = snd_usb_caiaq_pcm_trigger, | 348 | .trigger = snd_usb_caiaq_pcm_trigger, |
348 | .pointer = snd_usb_caiaq_pcm_pointer | 349 | .pointer = snd_usb_caiaq_pcm_pointer, |
350 | .page = snd_pcm_lib_get_vmalloc_page, | ||
351 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
349 | }; | 352 | }; |
350 | 353 | ||
351 | static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, | 354 | static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, |
@@ -852,11 +855,6 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) | |||
852 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE, | 855 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE, |
853 | &snd_usb_caiaq_ops); | 856 | &snd_usb_caiaq_ops); |
854 | 857 | ||
855 | snd_pcm_lib_preallocate_pages_for_all(cdev->pcm, | ||
856 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
857 | snd_dma_continuous_data(GFP_KERNEL), | ||
858 | MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); | ||
859 | |||
860 | cdev->data_cb_info = | 858 | cdev->data_cb_info = |
861 | kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, | 859 | kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, |
862 | GFP_KERNEL); | 860 | GFP_KERNEL); |
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 48b63ccc78c7..1a61dd12fe38 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -39,25 +39,24 @@ | |||
39 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 39 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
40 | MODULE_DESCRIPTION("caiaq USB audio"); | 40 | MODULE_DESCRIPTION("caiaq USB audio"); |
41 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
42 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 42 | MODULE_SUPPORTED_DEVICE("{{Native Instruments,RigKontrol2}," |
43 | "{Native Instruments, RigKontrol3}," | 43 | "{Native Instruments,RigKontrol3}," |
44 | "{Native Instruments, Kore Controller}," | 44 | "{Native Instruments,Kore Controller}," |
45 | "{Native Instruments, Kore Controller 2}," | 45 | "{Native Instruments,Kore Controller 2}," |
46 | "{Native Instruments, Audio Kontrol 1}," | 46 | "{Native Instruments,Audio Kontrol 1}," |
47 | "{Native Instruments, Audio 2 DJ}," | 47 | "{Native Instruments,Audio 2 DJ}," |
48 | "{Native Instruments, Audio 4 DJ}," | 48 | "{Native Instruments,Audio 4 DJ}," |
49 | "{Native Instruments, Audio 8 DJ}," | 49 | "{Native Instruments,Audio 8 DJ}," |
50 | "{Native Instruments, Traktor Audio 2}," | 50 | "{Native Instruments,Traktor Audio 2}," |
51 | "{Native Instruments, Session I/O}," | 51 | "{Native Instruments,Session I/O}," |
52 | "{Native Instruments, GuitarRig mobile}," | 52 | "{Native Instruments,GuitarRig mobile}," |
53 | "{Native Instruments, Traktor Kontrol X1}," | 53 | "{Native Instruments,Traktor Kontrol X1}," |
54 | "{Native Instruments, Traktor Kontrol S4}," | 54 | "{Native Instruments,Traktor Kontrol S4}," |
55 | "{Native Instruments, Maschine Controller}}"); | 55 | "{Native Instruments,Maschine Controller}}"); |
56 | 56 | ||
57 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | 57 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ |
58 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ | 58 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ |
59 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 59 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
60 | static int snd_card_used[SNDRV_CARDS]; | ||
61 | 60 | ||
62 | module_param_array(index, int, NULL, 0444); | 61 | module_param_array(index, int, NULL, 0444); |
63 | MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); | 62 | MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); |
@@ -388,7 +387,7 @@ static int create_card(struct usb_device *usb_dev, | |||
388 | struct snd_usb_caiaqdev *cdev; | 387 | struct snd_usb_caiaqdev *cdev; |
389 | 388 | ||
390 | for (devnum = 0; devnum < SNDRV_CARDS; devnum++) | 389 | for (devnum = 0; devnum < SNDRV_CARDS; devnum++) |
391 | if (enable[devnum] && !snd_card_used[devnum]) | 390 | if (enable[devnum]) |
392 | break; | 391 | break; |
393 | 392 | ||
394 | if (devnum >= SNDRV_CARDS) | 393 | if (devnum >= SNDRV_CARDS) |
diff --git a/sound/usb/card.h b/sound/usb/card.h index bf2889a2cae5..5ecacaa90b53 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -21,6 +21,7 @@ struct audioformat { | |||
21 | unsigned char endpoint; /* endpoint */ | 21 | unsigned char endpoint; /* endpoint */ |
22 | unsigned char ep_attr; /* endpoint attributes */ | 22 | unsigned char ep_attr; /* endpoint attributes */ |
23 | unsigned char datainterval; /* log_2 of data packet interval */ | 23 | unsigned char datainterval; /* log_2 of data packet interval */ |
24 | unsigned char protocol; /* UAC_VERSION_1/2 */ | ||
24 | unsigned int maxpacksize; /* max. packet size */ | 25 | unsigned int maxpacksize; /* max. packet size */ |
25 | unsigned int rates; /* rate bitmasks */ | 26 | unsigned int rates; /* rate bitmasks */ |
26 | unsigned int rate_min, rate_max; /* min/max rates */ | 27 | unsigned int rate_min, rate_max; /* min/max rates */ |
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 3a2ce390e278..86f80c60b21f 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
@@ -407,9 +407,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | |||
407 | struct usb_host_interface *alts, | 407 | struct usb_host_interface *alts, |
408 | struct audioformat *fmt, int rate) | 408 | struct audioformat *fmt, int rate) |
409 | { | 409 | { |
410 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | 410 | switch (fmt->protocol) { |
411 | |||
412 | switch (altsd->bInterfaceProtocol) { | ||
413 | case UAC_VERSION_1: | 411 | case UAC_VERSION_1: |
414 | default: | 412 | default: |
415 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); | 413 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); |
diff --git a/sound/usb/format.c b/sound/usb/format.c index 99299ffb33ac..3525231c6b97 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -43,13 +43,12 @@ | |||
43 | */ | 43 | */ |
44 | static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | 44 | static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, |
45 | struct audioformat *fp, | 45 | struct audioformat *fp, |
46 | unsigned int format, void *_fmt, | 46 | unsigned int format, void *_fmt) |
47 | int protocol) | ||
48 | { | 47 | { |
49 | int sample_width, sample_bytes; | 48 | int sample_width, sample_bytes; |
50 | u64 pcm_formats = 0; | 49 | u64 pcm_formats = 0; |
51 | 50 | ||
52 | switch (protocol) { | 51 | switch (fp->protocol) { |
53 | case UAC_VERSION_1: | 52 | case UAC_VERSION_1: |
54 | default: { | 53 | default: { |
55 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; | 54 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; |
@@ -360,11 +359,8 @@ err: | |||
360 | */ | 359 | */ |
361 | static int parse_audio_format_i(struct snd_usb_audio *chip, | 360 | static int parse_audio_format_i(struct snd_usb_audio *chip, |
362 | struct audioformat *fp, unsigned int format, | 361 | struct audioformat *fp, unsigned int format, |
363 | struct uac_format_type_i_continuous_descriptor *fmt, | 362 | struct uac_format_type_i_continuous_descriptor *fmt) |
364 | struct usb_host_interface *iface) | ||
365 | { | 363 | { |
366 | struct usb_interface_descriptor *altsd = get_iface_desc(iface); | ||
367 | int protocol = altsd->bInterfaceProtocol; | ||
368 | snd_pcm_format_t pcm_format; | 364 | snd_pcm_format_t pcm_format; |
369 | int ret; | 365 | int ret; |
370 | 366 | ||
@@ -387,8 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
387 | } | 383 | } |
388 | fp->formats = pcm_format_to_bits(pcm_format); | 384 | fp->formats = pcm_format_to_bits(pcm_format); |
389 | } else { | 385 | } else { |
390 | fp->formats = parse_audio_format_i_type(chip, fp, format, | 386 | fp->formats = parse_audio_format_i_type(chip, fp, format, fmt); |
391 | fmt, protocol); | ||
392 | if (!fp->formats) | 387 | if (!fp->formats) |
393 | return -EINVAL; | 388 | return -EINVAL; |
394 | } | 389 | } |
@@ -398,11 +393,8 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
398 | * proprietary class specific descriptor. | 393 | * proprietary class specific descriptor. |
399 | * audio class v2 uses class specific EP0 range requests for that. | 394 | * audio class v2 uses class specific EP0 range requests for that. |
400 | */ | 395 | */ |
401 | switch (protocol) { | 396 | switch (fp->protocol) { |
402 | default: | 397 | default: |
403 | snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", | ||
404 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
405 | /* fall through */ | ||
406 | case UAC_VERSION_1: | 398 | case UAC_VERSION_1: |
407 | fp->channels = fmt->bNrChannels; | 399 | fp->channels = fmt->bNrChannels; |
408 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); | 400 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); |
@@ -427,12 +419,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
427 | */ | 419 | */ |
428 | static int parse_audio_format_ii(struct snd_usb_audio *chip, | 420 | static int parse_audio_format_ii(struct snd_usb_audio *chip, |
429 | struct audioformat *fp, | 421 | struct audioformat *fp, |
430 | int format, void *_fmt, | 422 | int format, void *_fmt) |
431 | struct usb_host_interface *iface) | ||
432 | { | 423 | { |
433 | int brate, framesize, ret; | 424 | int brate, framesize, ret; |
434 | struct usb_interface_descriptor *altsd = get_iface_desc(iface); | ||
435 | int protocol = altsd->bInterfaceProtocol; | ||
436 | 425 | ||
437 | switch (format) { | 426 | switch (format) { |
438 | case UAC_FORMAT_TYPE_II_AC3: | 427 | case UAC_FORMAT_TYPE_II_AC3: |
@@ -452,11 +441,8 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
452 | 441 | ||
453 | fp->channels = 1; | 442 | fp->channels = 1; |
454 | 443 | ||
455 | switch (protocol) { | 444 | switch (fp->protocol) { |
456 | default: | 445 | default: |
457 | snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", | ||
458 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
459 | /* fall through */ | ||
460 | case UAC_VERSION_1: { | 446 | case UAC_VERSION_1: { |
461 | struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; | 447 | struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; |
462 | brate = le16_to_cpu(fmt->wMaxBitRate); | 448 | brate = le16_to_cpu(fmt->wMaxBitRate); |
@@ -483,17 +469,17 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
483 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, | 469 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, |
484 | struct audioformat *fp, unsigned int format, | 470 | struct audioformat *fp, unsigned int format, |
485 | struct uac_format_type_i_continuous_descriptor *fmt, | 471 | struct uac_format_type_i_continuous_descriptor *fmt, |
486 | int stream, struct usb_host_interface *iface) | 472 | int stream) |
487 | { | 473 | { |
488 | int err; | 474 | int err; |
489 | 475 | ||
490 | switch (fmt->bFormatType) { | 476 | switch (fmt->bFormatType) { |
491 | case UAC_FORMAT_TYPE_I: | 477 | case UAC_FORMAT_TYPE_I: |
492 | case UAC_FORMAT_TYPE_III: | 478 | case UAC_FORMAT_TYPE_III: |
493 | err = parse_audio_format_i(chip, fp, format, fmt, iface); | 479 | err = parse_audio_format_i(chip, fp, format, fmt); |
494 | break; | 480 | break; |
495 | case UAC_FORMAT_TYPE_II: | 481 | case UAC_FORMAT_TYPE_II: |
496 | err = parse_audio_format_ii(chip, fp, format, fmt, iface); | 482 | err = parse_audio_format_ii(chip, fp, format, fmt); |
497 | break; | 483 | break; |
498 | default: | 484 | default: |
499 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", | 485 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", |
diff --git a/sound/usb/format.h b/sound/usb/format.h index 6f315226f320..4b8a01129f24 100644 --- a/sound/usb/format.h +++ b/sound/usb/format.h | |||
@@ -4,6 +4,6 @@ | |||
4 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, | 4 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, |
5 | struct audioformat *fp, unsigned int format, | 5 | struct audioformat *fp, unsigned int format, |
6 | struct uac_format_type_i_continuous_descriptor *fmt, | 6 | struct uac_format_type_i_continuous_descriptor *fmt, |
7 | int stream, struct usb_host_interface *iface); | 7 | int stream); |
8 | 8 | ||
9 | #endif /* __USBAUDIO_FORMAT_H */ | 9 | #endif /* __USBAUDIO_FORMAT_H */ |
diff --git a/sound/usb/hiface/Makefile b/sound/usb/hiface/Makefile new file mode 100644 index 000000000000..463b136d1d89 --- /dev/null +++ b/sound/usb/hiface/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | snd-usb-hiface-objs := chip.o pcm.o | ||
2 | obj-$(CONFIG_SND_USB_HIFACE) += snd-usb-hiface.o | ||
diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c new file mode 100644 index 000000000000..b0dcb3924ce5 --- /dev/null +++ b/sound/usb/hiface/chip.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Linux driver for M2Tech hiFace compatible devices | ||
3 | * | ||
4 | * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V. | ||
5 | * | ||
6 | * Authors: Michael Trimarchi <michael@amarulasolutions.com> | ||
7 | * Antonio Ospite <ao2@amarulasolutions.com> | ||
8 | * | ||
9 | * The driver is based on the work done in TerraTec DMX 6Fire USB | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <sound/initval.h> | ||
20 | |||
21 | #include "chip.h" | ||
22 | #include "pcm.h" | ||
23 | |||
24 | MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>"); | ||
25 | MODULE_AUTHOR("Antonio Ospite <ao2@amarulasolutions.com>"); | ||
26 | MODULE_DESCRIPTION("M2Tech hiFace USB-SPDIF audio driver"); | ||
27 | MODULE_LICENSE("GPL v2"); | ||
28 | MODULE_SUPPORTED_DEVICE("{{M2Tech,Young}," | ||
29 | "{M2Tech,hiFace}," | ||
30 | "{M2Tech,North Star}," | ||
31 | "{M2Tech,W4S Young}," | ||
32 | "{M2Tech,Corrson}," | ||
33 | "{M2Tech,AUDIA}," | ||
34 | "{M2Tech,SL Audio}," | ||
35 | "{M2Tech,Empirical}," | ||
36 | "{M2Tech,Rockna}," | ||
37 | "{M2Tech,Pathos}," | ||
38 | "{M2Tech,Metronome}," | ||
39 | "{M2Tech,CAD}," | ||
40 | "{M2Tech,Audio Esclusive}," | ||
41 | "{M2Tech,Rotel}," | ||
42 | "{M2Tech,Eeaudio}," | ||
43 | "{The Chord Company,CHORD}," | ||
44 | "{AVA Group A/S,Vitus}}"); | ||
45 | |||
46 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | ||
47 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ | ||
48 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | ||
49 | |||
50 | #define DRIVER_NAME "snd-usb-hiface" | ||
51 | #define CARD_NAME "hiFace" | ||
52 | |||
53 | module_param_array(index, int, NULL, 0444); | ||
54 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | ||
55 | module_param_array(id, charp, NULL, 0444); | ||
56 | MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); | ||
57 | module_param_array(enable, bool, NULL, 0444); | ||
58 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | ||
59 | |||
60 | static DEFINE_MUTEX(register_mutex); | ||
61 | |||
62 | struct hiface_vendor_quirk { | ||
63 | const char *device_name; | ||
64 | u8 extra_freq; | ||
65 | }; | ||
66 | |||
67 | static int hiface_chip_create(struct usb_device *device, int idx, | ||
68 | const struct hiface_vendor_quirk *quirk, | ||
69 | struct hiface_chip **rchip) | ||
70 | { | ||
71 | struct snd_card *card = NULL; | ||
72 | struct hiface_chip *chip; | ||
73 | int ret; | ||
74 | int len; | ||
75 | |||
76 | *rchip = NULL; | ||
77 | |||
78 | /* if we are here, card can be registered in alsa. */ | ||
79 | ret = snd_card_create(index[idx], id[idx], THIS_MODULE, sizeof(*chip), &card); | ||
80 | if (ret < 0) { | ||
81 | dev_err(&device->dev, "cannot create alsa card.\n"); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); | ||
86 | |||
87 | if (quirk && quirk->device_name) | ||
88 | strlcpy(card->shortname, quirk->device_name, sizeof(card->shortname)); | ||
89 | else | ||
90 | strlcpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname)); | ||
91 | |||
92 | strlcat(card->longname, card->shortname, sizeof(card->longname)); | ||
93 | len = strlcat(card->longname, " at ", sizeof(card->longname)); | ||
94 | if (len < sizeof(card->longname)) | ||
95 | usb_make_path(device, card->longname + len, | ||
96 | sizeof(card->longname) - len); | ||
97 | |||
98 | chip = card->private_data; | ||
99 | chip->dev = device; | ||
100 | chip->card = card; | ||
101 | |||
102 | *rchip = chip; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int hiface_chip_probe(struct usb_interface *intf, | ||
107 | const struct usb_device_id *usb_id) | ||
108 | { | ||
109 | const struct hiface_vendor_quirk *quirk = (struct hiface_vendor_quirk *)usb_id->driver_info; | ||
110 | int ret; | ||
111 | int i; | ||
112 | struct hiface_chip *chip; | ||
113 | struct usb_device *device = interface_to_usbdev(intf); | ||
114 | |||
115 | ret = usb_set_interface(device, 0, 0); | ||
116 | if (ret != 0) { | ||
117 | dev_err(&device->dev, "can't set first interface for " CARD_NAME " device.\n"); | ||
118 | return -EIO; | ||
119 | } | ||
120 | |||
121 | /* check whether the card is already registered */ | ||
122 | chip = NULL; | ||
123 | mutex_lock(®ister_mutex); | ||
124 | |||
125 | for (i = 0; i < SNDRV_CARDS; i++) | ||
126 | if (enable[i]) | ||
127 | break; | ||
128 | |||
129 | if (i >= SNDRV_CARDS) { | ||
130 | dev_err(&device->dev, "no available " CARD_NAME " audio device\n"); | ||
131 | ret = -ENODEV; | ||
132 | goto err; | ||
133 | } | ||
134 | |||
135 | ret = hiface_chip_create(device, i, quirk, &chip); | ||
136 | if (ret < 0) | ||
137 | goto err; | ||
138 | |||
139 | snd_card_set_dev(chip->card, &intf->dev); | ||
140 | |||
141 | ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0); | ||
142 | if (ret < 0) | ||
143 | goto err_chip_destroy; | ||
144 | |||
145 | ret = snd_card_register(chip->card); | ||
146 | if (ret < 0) { | ||
147 | dev_err(&device->dev, "cannot register " CARD_NAME " card\n"); | ||
148 | goto err_chip_destroy; | ||
149 | } | ||
150 | |||
151 | mutex_unlock(®ister_mutex); | ||
152 | |||
153 | usb_set_intfdata(intf, chip); | ||
154 | return 0; | ||
155 | |||
156 | err_chip_destroy: | ||
157 | snd_card_free(chip->card); | ||
158 | err: | ||
159 | mutex_unlock(®ister_mutex); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static void hiface_chip_disconnect(struct usb_interface *intf) | ||
164 | { | ||
165 | struct hiface_chip *chip; | ||
166 | struct snd_card *card; | ||
167 | |||
168 | chip = usb_get_intfdata(intf); | ||
169 | if (!chip) | ||
170 | return; | ||
171 | |||
172 | card = chip->card; | ||
173 | |||
174 | /* Make sure that the userspace cannot create new request */ | ||
175 | snd_card_disconnect(card); | ||
176 | |||
177 | hiface_pcm_abort(chip); | ||
178 | snd_card_free_when_closed(card); | ||
179 | } | ||
180 | |||
181 | static const struct usb_device_id device_table[] = { | ||
182 | { | ||
183 | USB_DEVICE(0x04b4, 0x0384), | ||
184 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
185 | .device_name = "Young", | ||
186 | .extra_freq = 1, | ||
187 | } | ||
188 | }, | ||
189 | { | ||
190 | USB_DEVICE(0x04b4, 0x930b), | ||
191 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
192 | .device_name = "hiFace", | ||
193 | } | ||
194 | }, | ||
195 | { | ||
196 | USB_DEVICE(0x04b4, 0x931b), | ||
197 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
198 | .device_name = "North Star", | ||
199 | } | ||
200 | }, | ||
201 | { | ||
202 | USB_DEVICE(0x04b4, 0x931c), | ||
203 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
204 | .device_name = "W4S Young", | ||
205 | } | ||
206 | }, | ||
207 | { | ||
208 | USB_DEVICE(0x04b4, 0x931d), | ||
209 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
210 | .device_name = "Corrson", | ||
211 | } | ||
212 | }, | ||
213 | { | ||
214 | USB_DEVICE(0x04b4, 0x931e), | ||
215 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
216 | .device_name = "AUDIA", | ||
217 | } | ||
218 | }, | ||
219 | { | ||
220 | USB_DEVICE(0x04b4, 0x931f), | ||
221 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
222 | .device_name = "SL Audio", | ||
223 | } | ||
224 | }, | ||
225 | { | ||
226 | USB_DEVICE(0x04b4, 0x9320), | ||
227 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
228 | .device_name = "Empirical", | ||
229 | } | ||
230 | }, | ||
231 | { | ||
232 | USB_DEVICE(0x04b4, 0x9321), | ||
233 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
234 | .device_name = "Rockna", | ||
235 | } | ||
236 | }, | ||
237 | { | ||
238 | USB_DEVICE(0x249c, 0x9001), | ||
239 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
240 | .device_name = "Pathos", | ||
241 | } | ||
242 | }, | ||
243 | { | ||
244 | USB_DEVICE(0x249c, 0x9002), | ||
245 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
246 | .device_name = "Metronome", | ||
247 | } | ||
248 | }, | ||
249 | { | ||
250 | USB_DEVICE(0x249c, 0x9006), | ||
251 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
252 | .device_name = "CAD", | ||
253 | } | ||
254 | }, | ||
255 | { | ||
256 | USB_DEVICE(0x249c, 0x9008), | ||
257 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
258 | .device_name = "Audio Esclusive", | ||
259 | } | ||
260 | }, | ||
261 | { | ||
262 | USB_DEVICE(0x249c, 0x931c), | ||
263 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
264 | .device_name = "Rotel", | ||
265 | } | ||
266 | }, | ||
267 | { | ||
268 | USB_DEVICE(0x249c, 0x932c), | ||
269 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
270 | .device_name = "Eeaudio", | ||
271 | } | ||
272 | }, | ||
273 | { | ||
274 | USB_DEVICE(0x245f, 0x931c), | ||
275 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
276 | .device_name = "CHORD", | ||
277 | } | ||
278 | }, | ||
279 | { | ||
280 | USB_DEVICE(0x25c6, 0x9002), | ||
281 | .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) { | ||
282 | .device_name = "Vitus", | ||
283 | } | ||
284 | }, | ||
285 | {} | ||
286 | }; | ||
287 | |||
288 | MODULE_DEVICE_TABLE(usb, device_table); | ||
289 | |||
290 | static struct usb_driver hiface_usb_driver = { | ||
291 | .name = DRIVER_NAME, | ||
292 | .probe = hiface_chip_probe, | ||
293 | .disconnect = hiface_chip_disconnect, | ||
294 | .id_table = device_table, | ||
295 | }; | ||
296 | |||
297 | module_usb_driver(hiface_usb_driver); | ||
diff --git a/sound/usb/hiface/chip.h b/sound/usb/hiface/chip.h new file mode 100644 index 000000000000..189a1371b7c4 --- /dev/null +++ b/sound/usb/hiface/chip.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Linux driver for M2Tech hiFace compatible devices | ||
3 | * | ||
4 | * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V. | ||
5 | * | ||
6 | * Authors: Michael Trimarchi <michael@amarulasolutions.com> | ||
7 | * Antonio Ospite <ao2@amarulasolutions.com> | ||
8 | * | ||
9 | * The driver is based on the work done in TerraTec DMX 6Fire USB | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #ifndef HIFACE_CHIP_H | ||
18 | #define HIFACE_CHIP_H | ||
19 | |||
20 | #include <linux/usb.h> | ||
21 | #include <sound/core.h> | ||
22 | |||
23 | struct pcm_runtime; | ||
24 | |||
25 | struct hiface_chip { | ||
26 | struct usb_device *dev; | ||
27 | struct snd_card *card; | ||
28 | struct pcm_runtime *pcm; | ||
29 | }; | ||
30 | #endif /* HIFACE_CHIP_H */ | ||
diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c new file mode 100644 index 000000000000..6430ed2a9f65 --- /dev/null +++ b/sound/usb/hiface/pcm.c | |||
@@ -0,0 +1,621 @@ | |||
1 | /* | ||
2 | * Linux driver for M2Tech hiFace compatible devices | ||
3 | * | ||
4 | * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V. | ||
5 | * | ||
6 | * Authors: Michael Trimarchi <michael@amarulasolutions.com> | ||
7 | * Antonio Ospite <ao2@amarulasolutions.com> | ||
8 | * | ||
9 | * The driver is based on the work done in TerraTec DMX 6Fire USB | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <sound/pcm.h> | ||
19 | |||
20 | #include "pcm.h" | ||
21 | #include "chip.h" | ||
22 | |||
23 | #define OUT_EP 0x2 | ||
24 | #define PCM_N_URBS 8 | ||
25 | #define PCM_PACKET_SIZE 4096 | ||
26 | #define PCM_BUFFER_SIZE (2 * PCM_N_URBS * PCM_PACKET_SIZE) | ||
27 | |||
28 | struct pcm_urb { | ||
29 | struct hiface_chip *chip; | ||
30 | |||
31 | struct urb instance; | ||
32 | struct usb_anchor submitted; | ||
33 | u8 *buffer; | ||
34 | }; | ||
35 | |||
36 | struct pcm_substream { | ||
37 | spinlock_t lock; | ||
38 | struct snd_pcm_substream *instance; | ||
39 | |||
40 | bool active; | ||
41 | snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */ | ||
42 | snd_pcm_uframes_t period_off; /* current position in current period */ | ||
43 | }; | ||
44 | |||
45 | enum { /* pcm streaming states */ | ||
46 | STREAM_DISABLED, /* no pcm streaming */ | ||
47 | STREAM_STARTING, /* pcm streaming requested, waiting to become ready */ | ||
48 | STREAM_RUNNING, /* pcm streaming running */ | ||
49 | STREAM_STOPPING | ||
50 | }; | ||
51 | |||
52 | struct pcm_runtime { | ||
53 | struct hiface_chip *chip; | ||
54 | struct snd_pcm *instance; | ||
55 | |||
56 | struct pcm_substream playback; | ||
57 | bool panic; /* if set driver won't do anymore pcm on device */ | ||
58 | |||
59 | struct pcm_urb out_urbs[PCM_N_URBS]; | ||
60 | |||
61 | struct mutex stream_mutex; | ||
62 | u8 stream_state; /* one of STREAM_XXX */ | ||
63 | u8 extra_freq; | ||
64 | wait_queue_head_t stream_wait_queue; | ||
65 | bool stream_wait_cond; | ||
66 | }; | ||
67 | |||
68 | static const unsigned int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000, | ||
69 | 352800, 384000 }; | ||
70 | static const struct snd_pcm_hw_constraint_list constraints_extra_rates = { | ||
71 | .count = ARRAY_SIZE(rates), | ||
72 | .list = rates, | ||
73 | .mask = 0, | ||
74 | }; | ||
75 | |||
76 | static const struct snd_pcm_hardware pcm_hw = { | ||
77 | .info = SNDRV_PCM_INFO_MMAP | | ||
78 | SNDRV_PCM_INFO_INTERLEAVED | | ||
79 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
80 | SNDRV_PCM_INFO_PAUSE | | ||
81 | SNDRV_PCM_INFO_MMAP_VALID | | ||
82 | SNDRV_PCM_INFO_BATCH, | ||
83 | |||
84 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
85 | |||
86 | .rates = SNDRV_PCM_RATE_44100 | | ||
87 | SNDRV_PCM_RATE_48000 | | ||
88 | SNDRV_PCM_RATE_88200 | | ||
89 | SNDRV_PCM_RATE_96000 | | ||
90 | SNDRV_PCM_RATE_176400 | | ||
91 | SNDRV_PCM_RATE_192000, | ||
92 | |||
93 | .rate_min = 44100, | ||
94 | .rate_max = 192000, /* changes in hiface_pcm_open to support extra rates */ | ||
95 | .channels_min = 2, | ||
96 | .channels_max = 2, | ||
97 | .buffer_bytes_max = PCM_BUFFER_SIZE, | ||
98 | .period_bytes_min = PCM_PACKET_SIZE, | ||
99 | .period_bytes_max = PCM_BUFFER_SIZE, | ||
100 | .periods_min = 2, | ||
101 | .periods_max = 1024 | ||
102 | }; | ||
103 | |||
104 | /* message values used to change the sample rate */ | ||
105 | #define HIFACE_SET_RATE_REQUEST 0xb0 | ||
106 | |||
107 | #define HIFACE_RATE_44100 0x43 | ||
108 | #define HIFACE_RATE_48000 0x4b | ||
109 | #define HIFACE_RATE_88200 0x42 | ||
110 | #define HIFACE_RATE_96000 0x4a | ||
111 | #define HIFACE_RATE_176400 0x40 | ||
112 | #define HIFACE_RATE_192000 0x48 | ||
113 | #define HIFACE_RATE_352000 0x58 | ||
114 | #define HIFACE_RATE_384000 0x68 | ||
115 | |||
116 | static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate) | ||
117 | { | ||
118 | struct usb_device *device = rt->chip->dev; | ||
119 | u16 rate_value; | ||
120 | int ret; | ||
121 | |||
122 | /* We are already sure that the rate is supported here thanks to | ||
123 | * ALSA constraints | ||
124 | */ | ||
125 | switch (rate) { | ||
126 | case 44100: | ||
127 | rate_value = HIFACE_RATE_44100; | ||
128 | break; | ||
129 | case 48000: | ||
130 | rate_value = HIFACE_RATE_48000; | ||
131 | break; | ||
132 | case 88200: | ||
133 | rate_value = HIFACE_RATE_88200; | ||
134 | break; | ||
135 | case 96000: | ||
136 | rate_value = HIFACE_RATE_96000; | ||
137 | break; | ||
138 | case 176400: | ||
139 | rate_value = HIFACE_RATE_176400; | ||
140 | break; | ||
141 | case 192000: | ||
142 | rate_value = HIFACE_RATE_192000; | ||
143 | break; | ||
144 | case 352000: | ||
145 | rate_value = HIFACE_RATE_352000; | ||
146 | break; | ||
147 | case 384000: | ||
148 | rate_value = HIFACE_RATE_384000; | ||
149 | break; | ||
150 | default: | ||
151 | dev_err(&device->dev, "Unsupported rate %d\n", rate); | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * USBIO: Vendor 0xb0(wValue=0x0043, wIndex=0x0000) | ||
157 | * 43 b0 43 00 00 00 00 00 | ||
158 | * USBIO: Vendor 0xb0(wValue=0x004b, wIndex=0x0000) | ||
159 | * 43 b0 4b 00 00 00 00 00 | ||
160 | * This control message doesn't have any ack from the | ||
161 | * other side | ||
162 | */ | ||
163 | ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), | ||
164 | HIFACE_SET_RATE_REQUEST, | ||
165 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
166 | rate_value, 0, NULL, 0, 100); | ||
167 | if (ret < 0) { | ||
168 | dev_err(&device->dev, "Error setting samplerate %d.\n", rate); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static struct pcm_substream *hiface_pcm_get_substream(struct snd_pcm_substream | ||
176 | *alsa_sub) | ||
177 | { | ||
178 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
179 | struct device *device = &rt->chip->dev->dev; | ||
180 | |||
181 | if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
182 | return &rt->playback; | ||
183 | |||
184 | dev_err(device, "Error getting pcm substream slot.\n"); | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | /* call with stream_mutex locked */ | ||
189 | static void hiface_pcm_stream_stop(struct pcm_runtime *rt) | ||
190 | { | ||
191 | int i, time; | ||
192 | |||
193 | if (rt->stream_state != STREAM_DISABLED) { | ||
194 | rt->stream_state = STREAM_STOPPING; | ||
195 | |||
196 | for (i = 0; i < PCM_N_URBS; i++) { | ||
197 | time = usb_wait_anchor_empty_timeout( | ||
198 | &rt->out_urbs[i].submitted, 100); | ||
199 | if (!time) | ||
200 | usb_kill_anchored_urbs( | ||
201 | &rt->out_urbs[i].submitted); | ||
202 | usb_kill_urb(&rt->out_urbs[i].instance); | ||
203 | } | ||
204 | |||
205 | rt->stream_state = STREAM_DISABLED; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* call with stream_mutex locked */ | ||
210 | static int hiface_pcm_stream_start(struct pcm_runtime *rt) | ||
211 | { | ||
212 | int ret = 0; | ||
213 | int i; | ||
214 | |||
215 | if (rt->stream_state == STREAM_DISABLED) { | ||
216 | |||
217 | /* reset panic state when starting a new stream */ | ||
218 | rt->panic = false; | ||
219 | |||
220 | /* submit our out urbs zero init */ | ||
221 | rt->stream_state = STREAM_STARTING; | ||
222 | for (i = 0; i < PCM_N_URBS; i++) { | ||
223 | memset(rt->out_urbs[i].buffer, 0, PCM_PACKET_SIZE); | ||
224 | usb_anchor_urb(&rt->out_urbs[i].instance, | ||
225 | &rt->out_urbs[i].submitted); | ||
226 | ret = usb_submit_urb(&rt->out_urbs[i].instance, | ||
227 | GFP_ATOMIC); | ||
228 | if (ret) { | ||
229 | hiface_pcm_stream_stop(rt); | ||
230 | return ret; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | /* wait for first out urb to return (sent in in urb handler) */ | ||
235 | wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond, | ||
236 | HZ); | ||
237 | if (rt->stream_wait_cond) { | ||
238 | struct device *device = &rt->chip->dev->dev; | ||
239 | dev_dbg(device, "%s: Stream is running wakeup event\n", | ||
240 | __func__); | ||
241 | rt->stream_state = STREAM_RUNNING; | ||
242 | } else { | ||
243 | hiface_pcm_stream_stop(rt); | ||
244 | return -EIO; | ||
245 | } | ||
246 | } | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | /* The hardware wants word-swapped 32-bit values */ | ||
251 | static void memcpy_swahw32(u8 *dest, u8 *src, unsigned int n) | ||
252 | { | ||
253 | unsigned int i; | ||
254 | |||
255 | for (i = 0; i < n / 4; i++) | ||
256 | ((u32 *)dest)[i] = swahw32(((u32 *)src)[i]); | ||
257 | } | ||
258 | |||
259 | /* call with substream locked */ | ||
260 | /* returns true if a period elapsed */ | ||
261 | static bool hiface_pcm_playback(struct pcm_substream *sub, struct pcm_urb *urb) | ||
262 | { | ||
263 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; | ||
264 | struct device *device = &urb->chip->dev->dev; | ||
265 | u8 *source; | ||
266 | unsigned int pcm_buffer_size; | ||
267 | |||
268 | WARN_ON(alsa_rt->format != SNDRV_PCM_FORMAT_S32_LE); | ||
269 | |||
270 | pcm_buffer_size = snd_pcm_lib_buffer_bytes(sub->instance); | ||
271 | |||
272 | if (sub->dma_off + PCM_PACKET_SIZE <= pcm_buffer_size) { | ||
273 | dev_dbg(device, "%s: (1) buffer_size %#x dma_offset %#x\n", __func__, | ||
274 | (unsigned int) pcm_buffer_size, | ||
275 | (unsigned int) sub->dma_off); | ||
276 | |||
277 | source = alsa_rt->dma_area + sub->dma_off; | ||
278 | memcpy_swahw32(urb->buffer, source, PCM_PACKET_SIZE); | ||
279 | } else { | ||
280 | /* wrap around at end of ring buffer */ | ||
281 | unsigned int len; | ||
282 | |||
283 | dev_dbg(device, "%s: (2) buffer_size %#x dma_offset %#x\n", __func__, | ||
284 | (unsigned int) pcm_buffer_size, | ||
285 | (unsigned int) sub->dma_off); | ||
286 | |||
287 | len = pcm_buffer_size - sub->dma_off; | ||
288 | |||
289 | source = alsa_rt->dma_area + sub->dma_off; | ||
290 | memcpy_swahw32(urb->buffer, source, len); | ||
291 | |||
292 | source = alsa_rt->dma_area; | ||
293 | memcpy_swahw32(urb->buffer + len, source, | ||
294 | PCM_PACKET_SIZE - len); | ||
295 | } | ||
296 | sub->dma_off += PCM_PACKET_SIZE; | ||
297 | if (sub->dma_off >= pcm_buffer_size) | ||
298 | sub->dma_off -= pcm_buffer_size; | ||
299 | |||
300 | sub->period_off += PCM_PACKET_SIZE; | ||
301 | if (sub->period_off >= alsa_rt->period_size) { | ||
302 | sub->period_off %= alsa_rt->period_size; | ||
303 | return true; | ||
304 | } | ||
305 | return false; | ||
306 | } | ||
307 | |||
308 | static void hiface_pcm_out_urb_handler(struct urb *usb_urb) | ||
309 | { | ||
310 | struct pcm_urb *out_urb = usb_urb->context; | ||
311 | struct pcm_runtime *rt = out_urb->chip->pcm; | ||
312 | struct pcm_substream *sub; | ||
313 | bool do_period_elapsed = false; | ||
314 | unsigned long flags; | ||
315 | int ret; | ||
316 | |||
317 | if (rt->panic || rt->stream_state == STREAM_STOPPING) | ||
318 | return; | ||
319 | |||
320 | if (unlikely(usb_urb->status == -ENOENT || /* unlinked */ | ||
321 | usb_urb->status == -ENODEV || /* device removed */ | ||
322 | usb_urb->status == -ECONNRESET || /* unlinked */ | ||
323 | usb_urb->status == -ESHUTDOWN)) { /* device disabled */ | ||
324 | goto out_fail; | ||
325 | } | ||
326 | |||
327 | if (rt->stream_state == STREAM_STARTING) { | ||
328 | rt->stream_wait_cond = true; | ||
329 | wake_up(&rt->stream_wait_queue); | ||
330 | } | ||
331 | |||
332 | /* now send our playback data (if a free out urb was found) */ | ||
333 | sub = &rt->playback; | ||
334 | spin_lock_irqsave(&sub->lock, flags); | ||
335 | if (sub->active) | ||
336 | do_period_elapsed = hiface_pcm_playback(sub, out_urb); | ||
337 | else | ||
338 | memset(out_urb->buffer, 0, PCM_PACKET_SIZE); | ||
339 | |||
340 | spin_unlock_irqrestore(&sub->lock, flags); | ||
341 | |||
342 | if (do_period_elapsed) | ||
343 | snd_pcm_period_elapsed(sub->instance); | ||
344 | |||
345 | ret = usb_submit_urb(&out_urb->instance, GFP_ATOMIC); | ||
346 | if (ret < 0) | ||
347 | goto out_fail; | ||
348 | |||
349 | return; | ||
350 | |||
351 | out_fail: | ||
352 | rt->panic = true; | ||
353 | } | ||
354 | |||
355 | static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub) | ||
356 | { | ||
357 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
358 | struct pcm_substream *sub = NULL; | ||
359 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | ||
360 | int ret; | ||
361 | |||
362 | if (rt->panic) | ||
363 | return -EPIPE; | ||
364 | |||
365 | mutex_lock(&rt->stream_mutex); | ||
366 | alsa_rt->hw = pcm_hw; | ||
367 | |||
368 | if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
369 | sub = &rt->playback; | ||
370 | |||
371 | if (!sub) { | ||
372 | struct device *device = &rt->chip->dev->dev; | ||
373 | mutex_unlock(&rt->stream_mutex); | ||
374 | dev_err(device, "Invalid stream type\n"); | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | if (rt->extra_freq) { | ||
379 | alsa_rt->hw.rates |= SNDRV_PCM_RATE_KNOT; | ||
380 | alsa_rt->hw.rate_max = 384000; | ||
381 | |||
382 | /* explicit constraints needed as we added SNDRV_PCM_RATE_KNOT */ | ||
383 | ret = snd_pcm_hw_constraint_list(alsa_sub->runtime, 0, | ||
384 | SNDRV_PCM_HW_PARAM_RATE, | ||
385 | &constraints_extra_rates); | ||
386 | if (ret < 0) { | ||
387 | mutex_unlock(&rt->stream_mutex); | ||
388 | return ret; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | sub->instance = alsa_sub; | ||
393 | sub->active = false; | ||
394 | mutex_unlock(&rt->stream_mutex); | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int hiface_pcm_close(struct snd_pcm_substream *alsa_sub) | ||
399 | { | ||
400 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
401 | struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); | ||
402 | unsigned long flags; | ||
403 | |||
404 | if (rt->panic) | ||
405 | return 0; | ||
406 | |||
407 | mutex_lock(&rt->stream_mutex); | ||
408 | if (sub) { | ||
409 | hiface_pcm_stream_stop(rt); | ||
410 | |||
411 | /* deactivate substream */ | ||
412 | spin_lock_irqsave(&sub->lock, flags); | ||
413 | sub->instance = NULL; | ||
414 | sub->active = false; | ||
415 | spin_unlock_irqrestore(&sub->lock, flags); | ||
416 | |||
417 | } | ||
418 | mutex_unlock(&rt->stream_mutex); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int hiface_pcm_hw_params(struct snd_pcm_substream *alsa_sub, | ||
423 | struct snd_pcm_hw_params *hw_params) | ||
424 | { | ||
425 | return snd_pcm_lib_alloc_vmalloc_buffer(alsa_sub, | ||
426 | params_buffer_bytes(hw_params)); | ||
427 | } | ||
428 | |||
429 | static int hiface_pcm_hw_free(struct snd_pcm_substream *alsa_sub) | ||
430 | { | ||
431 | return snd_pcm_lib_free_vmalloc_buffer(alsa_sub); | ||
432 | } | ||
433 | |||
434 | static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub) | ||
435 | { | ||
436 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
437 | struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); | ||
438 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | ||
439 | int ret; | ||
440 | |||
441 | if (rt->panic) | ||
442 | return -EPIPE; | ||
443 | if (!sub) | ||
444 | return -ENODEV; | ||
445 | |||
446 | mutex_lock(&rt->stream_mutex); | ||
447 | |||
448 | sub->dma_off = 0; | ||
449 | sub->period_off = 0; | ||
450 | |||
451 | if (rt->stream_state == STREAM_DISABLED) { | ||
452 | |||
453 | ret = hiface_pcm_set_rate(rt, alsa_rt->rate); | ||
454 | if (ret) { | ||
455 | mutex_unlock(&rt->stream_mutex); | ||
456 | return ret; | ||
457 | } | ||
458 | ret = hiface_pcm_stream_start(rt); | ||
459 | if (ret) { | ||
460 | mutex_unlock(&rt->stream_mutex); | ||
461 | return ret; | ||
462 | } | ||
463 | } | ||
464 | mutex_unlock(&rt->stream_mutex); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int hiface_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd) | ||
469 | { | ||
470 | struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); | ||
471 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
472 | |||
473 | if (rt->panic) | ||
474 | return -EPIPE; | ||
475 | if (!sub) | ||
476 | return -ENODEV; | ||
477 | |||
478 | switch (cmd) { | ||
479 | case SNDRV_PCM_TRIGGER_START: | ||
480 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
481 | spin_lock_irq(&sub->lock); | ||
482 | sub->active = true; | ||
483 | spin_unlock_irq(&sub->lock); | ||
484 | return 0; | ||
485 | |||
486 | case SNDRV_PCM_TRIGGER_STOP: | ||
487 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
488 | spin_lock_irq(&sub->lock); | ||
489 | sub->active = false; | ||
490 | spin_unlock_irq(&sub->lock); | ||
491 | return 0; | ||
492 | |||
493 | default: | ||
494 | return -EINVAL; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub) | ||
499 | { | ||
500 | struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub); | ||
501 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
502 | unsigned long flags; | ||
503 | snd_pcm_uframes_t dma_offset; | ||
504 | |||
505 | if (rt->panic || !sub) | ||
506 | return SNDRV_PCM_STATE_XRUN; | ||
507 | |||
508 | spin_lock_irqsave(&sub->lock, flags); | ||
509 | dma_offset = sub->dma_off; | ||
510 | spin_unlock_irqrestore(&sub->lock, flags); | ||
511 | return bytes_to_frames(alsa_sub->runtime, dma_offset); | ||
512 | } | ||
513 | |||
514 | static struct snd_pcm_ops pcm_ops = { | ||
515 | .open = hiface_pcm_open, | ||
516 | .close = hiface_pcm_close, | ||
517 | .ioctl = snd_pcm_lib_ioctl, | ||
518 | .hw_params = hiface_pcm_hw_params, | ||
519 | .hw_free = hiface_pcm_hw_free, | ||
520 | .prepare = hiface_pcm_prepare, | ||
521 | .trigger = hiface_pcm_trigger, | ||
522 | .pointer = hiface_pcm_pointer, | ||
523 | .page = snd_pcm_lib_get_vmalloc_page, | ||
524 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
525 | }; | ||
526 | |||
527 | static int hiface_pcm_init_urb(struct pcm_urb *urb, | ||
528 | struct hiface_chip *chip, | ||
529 | unsigned int ep, | ||
530 | void (*handler)(struct urb *)) | ||
531 | { | ||
532 | urb->chip = chip; | ||
533 | usb_init_urb(&urb->instance); | ||
534 | |||
535 | urb->buffer = kzalloc(PCM_PACKET_SIZE, GFP_KERNEL); | ||
536 | if (!urb->buffer) | ||
537 | return -ENOMEM; | ||
538 | |||
539 | usb_fill_bulk_urb(&urb->instance, chip->dev, | ||
540 | usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer, | ||
541 | PCM_PACKET_SIZE, handler, urb); | ||
542 | init_usb_anchor(&urb->submitted); | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | void hiface_pcm_abort(struct hiface_chip *chip) | ||
548 | { | ||
549 | struct pcm_runtime *rt = chip->pcm; | ||
550 | |||
551 | if (rt) { | ||
552 | rt->panic = true; | ||
553 | |||
554 | mutex_lock(&rt->stream_mutex); | ||
555 | hiface_pcm_stream_stop(rt); | ||
556 | mutex_unlock(&rt->stream_mutex); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static void hiface_pcm_destroy(struct hiface_chip *chip) | ||
561 | { | ||
562 | struct pcm_runtime *rt = chip->pcm; | ||
563 | int i; | ||
564 | |||
565 | for (i = 0; i < PCM_N_URBS; i++) | ||
566 | kfree(rt->out_urbs[i].buffer); | ||
567 | |||
568 | kfree(chip->pcm); | ||
569 | chip->pcm = NULL; | ||
570 | } | ||
571 | |||
572 | static void hiface_pcm_free(struct snd_pcm *pcm) | ||
573 | { | ||
574 | struct pcm_runtime *rt = pcm->private_data; | ||
575 | |||
576 | if (rt) | ||
577 | hiface_pcm_destroy(rt->chip); | ||
578 | } | ||
579 | |||
580 | int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq) | ||
581 | { | ||
582 | int i; | ||
583 | int ret; | ||
584 | struct snd_pcm *pcm; | ||
585 | struct pcm_runtime *rt; | ||
586 | |||
587 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
588 | if (!rt) | ||
589 | return -ENOMEM; | ||
590 | |||
591 | rt->chip = chip; | ||
592 | rt->stream_state = STREAM_DISABLED; | ||
593 | if (extra_freq) | ||
594 | rt->extra_freq = 1; | ||
595 | |||
596 | init_waitqueue_head(&rt->stream_wait_queue); | ||
597 | mutex_init(&rt->stream_mutex); | ||
598 | spin_lock_init(&rt->playback.lock); | ||
599 | |||
600 | for (i = 0; i < PCM_N_URBS; i++) | ||
601 | hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP, | ||
602 | hiface_pcm_out_urb_handler); | ||
603 | |||
604 | ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm); | ||
605 | if (ret < 0) { | ||
606 | kfree(rt); | ||
607 | dev_err(&chip->dev->dev, "Cannot create pcm instance\n"); | ||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | pcm->private_data = rt; | ||
612 | pcm->private_free = hiface_pcm_free; | ||
613 | |||
614 | strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name)); | ||
615 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); | ||
616 | |||
617 | rt->instance = pcm; | ||
618 | |||
619 | chip->pcm = rt; | ||
620 | return 0; | ||
621 | } | ||
diff --git a/sound/usb/hiface/pcm.h b/sound/usb/hiface/pcm.h new file mode 100644 index 000000000000..77edd7c12e19 --- /dev/null +++ b/sound/usb/hiface/pcm.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Linux driver for M2Tech hiFace compatible devices | ||
3 | * | ||
4 | * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V. | ||
5 | * | ||
6 | * Authors: Michael Trimarchi <michael@amarulasolutions.com> | ||
7 | * Antonio Ospite <ao2@amarulasolutions.com> | ||
8 | * | ||
9 | * The driver is based on the work done in TerraTec DMX 6Fire USB | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #ifndef HIFACE_PCM_H | ||
18 | #define HIFACE_PCM_H | ||
19 | |||
20 | struct hiface_chip; | ||
21 | |||
22 | int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq); | ||
23 | void hiface_pcm_abort(struct hiface_chip *chip); | ||
24 | #endif /* HIFACE_PCM_H */ | ||
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 8e01fa4991c5..b901f468b67a 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -1575,8 +1575,41 @@ static struct port_info { | |||
1575 | EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), | 1575 | EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), |
1576 | EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), | 1576 | EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), |
1577 | EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), | 1577 | EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), |
1578 | /* BOSS GT-PRO */ | ||
1579 | CONTROL_PORT(0x0582, 0x0089, 0, "%s Control"), | ||
1578 | /* Edirol UM-3EX */ | 1580 | /* Edirol UM-3EX */ |
1579 | CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), | 1581 | CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), |
1582 | /* Roland VG-99 */ | ||
1583 | CONTROL_PORT(0x0582, 0x00b2, 0, "%s Control"), | ||
1584 | EXTERNAL_PORT(0x0582, 0x00b2, 1, "%s MIDI"), | ||
1585 | /* Cakewalk Sonar V-Studio 100 */ | ||
1586 | EXTERNAL_PORT(0x0582, 0x00eb, 0, "%s MIDI"), | ||
1587 | CONTROL_PORT(0x0582, 0x00eb, 1, "%s Control"), | ||
1588 | /* Roland VB-99 */ | ||
1589 | CONTROL_PORT(0x0582, 0x0102, 0, "%s Control"), | ||
1590 | EXTERNAL_PORT(0x0582, 0x0102, 1, "%s MIDI"), | ||
1591 | /* Roland A-PRO */ | ||
1592 | EXTERNAL_PORT(0x0582, 0x010f, 0, "%s MIDI"), | ||
1593 | CONTROL_PORT(0x0582, 0x010f, 1, "%s 1"), | ||
1594 | CONTROL_PORT(0x0582, 0x010f, 2, "%s 2"), | ||
1595 | /* Roland SD-50 */ | ||
1596 | ROLAND_SYNTH_PORT(0x0582, 0x0114, 0, "%s Synth", 128), | ||
1597 | EXTERNAL_PORT(0x0582, 0x0114, 1, "%s MIDI"), | ||
1598 | CONTROL_PORT(0x0582, 0x0114, 2, "%s Control"), | ||
1599 | /* Roland OCTA-CAPTURE */ | ||
1600 | EXTERNAL_PORT(0x0582, 0x0120, 0, "%s MIDI"), | ||
1601 | CONTROL_PORT(0x0582, 0x0120, 1, "%s Control"), | ||
1602 | EXTERNAL_PORT(0x0582, 0x0121, 0, "%s MIDI"), | ||
1603 | CONTROL_PORT(0x0582, 0x0121, 1, "%s Control"), | ||
1604 | /* Roland SPD-SX */ | ||
1605 | CONTROL_PORT(0x0582, 0x0145, 0, "%s Control"), | ||
1606 | EXTERNAL_PORT(0x0582, 0x0145, 1, "%s MIDI"), | ||
1607 | /* Roland A-Series */ | ||
1608 | CONTROL_PORT(0x0582, 0x0156, 0, "%s Keyboard"), | ||
1609 | EXTERNAL_PORT(0x0582, 0x0156, 1, "%s MIDI"), | ||
1610 | /* Roland INTEGRA-7 */ | ||
1611 | ROLAND_SYNTH_PORT(0x0582, 0x015b, 0, "%s Synth", 128), | ||
1612 | CONTROL_PORT(0x0582, 0x015b, 1, "%s Control"), | ||
1580 | /* M-Audio MidiSport 8x8 */ | 1613 | /* M-Audio MidiSport 8x8 */ |
1581 | CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), | 1614 | CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), |
1582 | CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), | 1615 | CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), |
@@ -1948,6 +1981,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | |||
1948 | } | 1981 | } |
1949 | 1982 | ||
1950 | /* | 1983 | /* |
1984 | * Detects the endpoints and ports of Roland devices. | ||
1985 | */ | ||
1986 | static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi, | ||
1987 | struct snd_usb_midi_endpoint_info* endpoint) | ||
1988 | { | ||
1989 | struct usb_interface* intf; | ||
1990 | struct usb_host_interface *hostif; | ||
1991 | u8* cs_desc; | ||
1992 | |||
1993 | intf = umidi->iface; | ||
1994 | if (!intf) | ||
1995 | return -ENOENT; | ||
1996 | hostif = intf->altsetting; | ||
1997 | /* | ||
1998 | * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>, | ||
1999 | * some have standard class descriptors, or both kinds, or neither. | ||
2000 | */ | ||
2001 | for (cs_desc = hostif->extra; | ||
2002 | cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; | ||
2003 | cs_desc += cs_desc[0]) { | ||
2004 | if (cs_desc[0] >= 6 && | ||
2005 | cs_desc[1] == USB_DT_CS_INTERFACE && | ||
2006 | cs_desc[2] == 0xf1 && | ||
2007 | cs_desc[3] == 0x02) { | ||
2008 | endpoint->in_cables = (1 << cs_desc[4]) - 1; | ||
2009 | endpoint->out_cables = (1 << cs_desc[5]) - 1; | ||
2010 | return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); | ||
2011 | } else if (cs_desc[0] >= 7 && | ||
2012 | cs_desc[1] == USB_DT_CS_INTERFACE && | ||
2013 | cs_desc[2] == UAC_HEADER) { | ||
2014 | return snd_usbmidi_get_ms_info(umidi, endpoint); | ||
2015 | } | ||
2016 | } | ||
2017 | |||
2018 | return -ENODEV; | ||
2019 | } | ||
2020 | |||
2021 | /* | ||
1951 | * Creates the endpoints and their ports for Midiman devices. | 2022 | * Creates the endpoints and their ports for Midiman devices. |
1952 | */ | 2023 | */ |
1953 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | 2024 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, |
@@ -2162,6 +2233,9 @@ int snd_usbmidi_create(struct snd_card *card, | |||
2162 | case QUIRK_MIDI_YAMAHA: | 2233 | case QUIRK_MIDI_YAMAHA: |
2163 | err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); | 2234 | err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); |
2164 | break; | 2235 | break; |
2236 | case QUIRK_MIDI_ROLAND: | ||
2237 | err = snd_usbmidi_detect_roland(umidi, &endpoints[0]); | ||
2238 | break; | ||
2165 | case QUIRK_MIDI_MIDIMAN: | 2239 | case QUIRK_MIDI_MIDIMAN: |
2166 | umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; | 2240 | umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; |
2167 | memcpy(&endpoints[0], quirk->data, | 2241 | memcpy(&endpoints[0], quirk->data, |
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 6ad617b94732..8b5d2c564e04 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c | |||
@@ -1349,7 +1349,7 @@ static void ua101_disconnect(struct usb_interface *interface) | |||
1349 | snd_card_disconnect(ua->card); | 1349 | snd_card_disconnect(ua->card); |
1350 | 1350 | ||
1351 | /* make sure that there are no pending USB requests */ | 1351 | /* make sure that there are no pending USB requests */ |
1352 | __list_for_each(midi, &ua->midi_list) | 1352 | list_for_each(midi, &ua->midi_list) |
1353 | snd_usbmidi_disconnect(midi); | 1353 | snd_usbmidi_disconnect(midi); |
1354 | abort_alsa_playback(ua); | 1354 | abort_alsa_playback(ua); |
1355 | abort_alsa_capture(ua); | 1355 | abort_alsa_capture(ua); |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 93b6e32cfead..15b151ed4899 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -202,13 +202,11 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, | |||
202 | struct usb_host_interface *alts, | 202 | struct usb_host_interface *alts, |
203 | struct audioformat *fmt) | 203 | struct audioformat *fmt) |
204 | { | 204 | { |
205 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | ||
206 | |||
207 | /* if endpoint doesn't have pitch control, bail out */ | 205 | /* if endpoint doesn't have pitch control, bail out */ |
208 | if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) | 206 | if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) |
209 | return 0; | 207 | return 0; |
210 | 208 | ||
211 | switch (altsd->bInterfaceProtocol) { | 209 | switch (fmt->protocol) { |
212 | case UAC_VERSION_1: | 210 | case UAC_VERSION_1: |
213 | default: | 211 | default: |
214 | return init_pitch_v1(chip, iface, alts, fmt); | 212 | return init_pitch_v1(chip, iface, alts, fmt); |
@@ -300,6 +298,35 @@ static int deactivate_endpoints(struct snd_usb_substream *subs) | |||
300 | return 0; | 298 | return 0; |
301 | } | 299 | } |
302 | 300 | ||
301 | static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, | ||
302 | unsigned int altsetting, | ||
303 | struct usb_host_interface **alts, | ||
304 | unsigned int *ep) | ||
305 | { | ||
306 | struct usb_interface *iface; | ||
307 | struct usb_interface_descriptor *altsd; | ||
308 | struct usb_endpoint_descriptor *epd; | ||
309 | |||
310 | iface = usb_ifnum_to_if(dev, ifnum); | ||
311 | if (!iface || iface->num_altsetting < altsetting + 1) | ||
312 | return -ENOENT; | ||
313 | *alts = &iface->altsetting[altsetting]; | ||
314 | altsd = get_iface_desc(*alts); | ||
315 | if (altsd->bAlternateSetting != altsetting || | ||
316 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC || | ||
317 | (altsd->bInterfaceSubClass != 2 && | ||
318 | altsd->bInterfaceProtocol != 2 ) || | ||
319 | altsd->bNumEndpoints < 1) | ||
320 | return -ENOENT; | ||
321 | epd = get_endpoint(*alts, 0); | ||
322 | if (!usb_endpoint_is_isoc_in(epd) || | ||
323 | (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != | ||
324 | USB_ENDPOINT_USAGE_IMPLICIT_FB) | ||
325 | return -ENOENT; | ||
326 | *ep = epd->bEndpointAddress; | ||
327 | return 0; | ||
328 | } | ||
329 | |||
303 | /* | 330 | /* |
304 | * find a matching format and set up the interface | 331 | * find a matching format and set up the interface |
305 | */ | 332 | */ |
@@ -395,6 +422,18 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
395 | goto add_sync_ep; | 422 | goto add_sync_ep; |
396 | } | 423 | } |
397 | } | 424 | } |
425 | if (is_playback && | ||
426 | attr == USB_ENDPOINT_SYNC_ASYNC && | ||
427 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && | ||
428 | altsd->bInterfaceProtocol == 2 && | ||
429 | altsd->bNumEndpoints == 1 && | ||
430 | USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ && | ||
431 | search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1, | ||
432 | altsd->bAlternateSetting, | ||
433 | &alts, &ep) >= 0) { | ||
434 | implicit_fb = 1; | ||
435 | goto add_sync_ep; | ||
436 | } | ||
398 | 437 | ||
399 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || | 438 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || |
400 | (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && | 439 | (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 8b75bcf136f6..9c636c2d99f6 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -461,6 +461,17 @@ YAMAHA_DEVICE(0x7000, "DTX"), | |||
461 | YAMAHA_DEVICE(0x7010, "UB99"), | 461 | YAMAHA_DEVICE(0x7010, "UB99"), |
462 | #undef YAMAHA_DEVICE | 462 | #undef YAMAHA_DEVICE |
463 | #undef YAMAHA_INTERFACE | 463 | #undef YAMAHA_INTERFACE |
464 | /* this catches most recent vendor-specific Yamaha devices */ | ||
465 | { | ||
466 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
467 | USB_DEVICE_ID_MATCH_INT_CLASS, | ||
468 | .idVendor = 0x0499, | ||
469 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
470 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
471 | .ifnum = QUIRK_ANY_INTERFACE, | ||
472 | .type = QUIRK_AUTODETECT | ||
473 | } | ||
474 | }, | ||
464 | 475 | ||
465 | /* | 476 | /* |
466 | * Roland/RolandED/Edirol/BOSS devices | 477 | * Roland/RolandED/Edirol/BOSS devices |
@@ -1136,7 +1147,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1136 | } | 1147 | } |
1137 | } | 1148 | } |
1138 | }, | 1149 | }, |
1139 | /* TODO: add Roland M-1000 support */ | ||
1140 | { | 1150 | { |
1141 | /* | 1151 | /* |
1142 | * Has ID 0x0038 when not in "Advanced Driver" mode; | 1152 | * Has ID 0x0038 when not in "Advanced Driver" mode; |
@@ -1251,7 +1261,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1251 | } | 1261 | } |
1252 | } | 1262 | } |
1253 | }, | 1263 | }, |
1254 | /* TODO: add Edirol M-100FX support */ | ||
1255 | { | 1264 | { |
1256 | /* has ID 0x004e when not in "Advanced Driver" mode */ | 1265 | /* has ID 0x004e when not in "Advanced Driver" mode */ |
1257 | USB_DEVICE(0x0582, 0x004c), | 1266 | USB_DEVICE(0x0582, 0x004c), |
@@ -1371,20 +1380,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1371 | } | 1380 | } |
1372 | }, | 1381 | }, |
1373 | { | 1382 | { |
1374 | /* has ID 0x006b when not in "Advanced Driver" mode */ | ||
1375 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a), | ||
1376 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1377 | .vendor_name = "Roland", | ||
1378 | .product_name = "SP-606", | ||
1379 | .ifnum = 3, | ||
1380 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1381 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1382 | .out_cables = 0x0001, | ||
1383 | .in_cables = 0x0001 | ||
1384 | } | ||
1385 | } | ||
1386 | }, | ||
1387 | { | ||
1388 | /* has ID 0x006e when not in "Advanced Driver" mode */ | 1383 | /* has ID 0x006e when not in "Advanced Driver" mode */ |
1389 | USB_DEVICE(0x0582, 0x006d), | 1384 | USB_DEVICE(0x0582, 0x006d), |
1390 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1385 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
@@ -1471,8 +1466,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1471 | } | 1466 | } |
1472 | } | 1467 | } |
1473 | }, | 1468 | }, |
1474 | /* TODO: add Roland V-SYNTH XT support */ | ||
1475 | /* TODO: add BOSS GT-PRO support */ | ||
1476 | { | 1469 | { |
1477 | /* has ID 0x008c when not in "Advanced Driver" mode */ | 1470 | /* has ID 0x008c when not in "Advanced Driver" mode */ |
1478 | USB_DEVICE(0x0582, 0x008b), | 1471 | USB_DEVICE(0x0582, 0x008b), |
@@ -1487,42 +1480,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1487 | } | 1480 | } |
1488 | } | 1481 | } |
1489 | }, | 1482 | }, |
1490 | /* TODO: add Edirol PC-80 support */ | ||
1491 | { | ||
1492 | USB_DEVICE(0x0582, 0x0096), | ||
1493 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1494 | .vendor_name = "EDIROL", | ||
1495 | .product_name = "UA-1EX", | ||
1496 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1497 | .type = QUIRK_COMPOSITE, | ||
1498 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1499 | { | ||
1500 | .ifnum = 0, | ||
1501 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1502 | }, | ||
1503 | { | ||
1504 | .ifnum = 1, | ||
1505 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1506 | }, | ||
1507 | { | ||
1508 | .ifnum = -1 | ||
1509 | } | ||
1510 | } | ||
1511 | } | ||
1512 | }, | ||
1513 | { | ||
1514 | USB_DEVICE(0x0582, 0x009a), | ||
1515 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1516 | .vendor_name = "EDIROL", | ||
1517 | .product_name = "UM-3EX", | ||
1518 | .ifnum = 0, | ||
1519 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1520 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1521 | .out_cables = 0x000f, | ||
1522 | .in_cables = 0x000f | ||
1523 | } | ||
1524 | } | ||
1525 | }, | ||
1526 | { | 1483 | { |
1527 | /* | 1484 | /* |
1528 | * This quirk is for the "Advanced Driver" mode. If off, the UA-4FX | 1485 | * This quirk is for the "Advanced Driver" mode. If off, the UA-4FX |
@@ -1553,124 +1510,8 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1553 | } | 1510 | } |
1554 | } | 1511 | } |
1555 | }, | 1512 | }, |
1556 | /* TODO: add Edirol MD-P1 support */ | ||
1557 | { | ||
1558 | USB_DEVICE(0x582, 0x00a6), | ||
1559 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1560 | .vendor_name = "Roland", | ||
1561 | .product_name = "Juno-G", | ||
1562 | .ifnum = 0, | ||
1563 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1564 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1565 | .out_cables = 0x0001, | ||
1566 | .in_cables = 0x0001 | ||
1567 | } | ||
1568 | } | ||
1569 | }, | ||
1570 | { | ||
1571 | /* Roland SH-201 */ | ||
1572 | USB_DEVICE(0x0582, 0x00ad), | ||
1573 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1574 | .vendor_name = "Roland", | ||
1575 | .product_name = "SH-201", | ||
1576 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1577 | .type = QUIRK_COMPOSITE, | ||
1578 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1579 | { | ||
1580 | .ifnum = 0, | ||
1581 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1582 | }, | ||
1583 | { | ||
1584 | .ifnum = 1, | ||
1585 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1586 | }, | ||
1587 | { | ||
1588 | .ifnum = 2, | ||
1589 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1590 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1591 | .out_cables = 0x0001, | ||
1592 | .in_cables = 0x0001 | ||
1593 | } | ||
1594 | }, | ||
1595 | { | ||
1596 | .ifnum = -1 | ||
1597 | } | ||
1598 | } | ||
1599 | } | ||
1600 | }, | ||
1601 | { | ||
1602 | /* Advanced mode of the Roland VG-99, with MIDI and 24-bit PCM at 44.1 | ||
1603 | * kHz. In standard mode, the device has ID 0582:00b3, and offers | ||
1604 | * 16-bit PCM at 44.1 kHz with no MIDI. | ||
1605 | */ | ||
1606 | USB_DEVICE(0x0582, 0x00b2), | ||
1607 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1608 | .vendor_name = "Roland", | ||
1609 | .product_name = "VG-99", | ||
1610 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1611 | .type = QUIRK_COMPOSITE, | ||
1612 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1613 | { | ||
1614 | .ifnum = 0, | ||
1615 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1616 | }, | ||
1617 | { | ||
1618 | .ifnum = 1, | ||
1619 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1620 | }, | ||
1621 | { | ||
1622 | .ifnum = 2, | ||
1623 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1624 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1625 | .out_cables = 0x0003, | ||
1626 | .in_cables = 0x0003 | ||
1627 | } | ||
1628 | }, | ||
1629 | { | ||
1630 | .ifnum = -1 | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | }, | ||
1635 | { | ||
1636 | /* Roland SonicCell */ | ||
1637 | USB_DEVICE(0x0582, 0x00c2), | ||
1638 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1639 | .vendor_name = "Roland", | ||
1640 | .product_name = "SonicCell", | ||
1641 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1642 | .type = QUIRK_COMPOSITE, | ||
1643 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1644 | { | ||
1645 | .ifnum = 0, | ||
1646 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1647 | }, | ||
1648 | { | ||
1649 | .ifnum = 1, | ||
1650 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1651 | }, | ||
1652 | { | ||
1653 | .ifnum = 2, | ||
1654 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1655 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1656 | .out_cables = 0x0001, | ||
1657 | .in_cables = 0x0001 | ||
1658 | } | ||
1659 | }, | ||
1660 | { | ||
1661 | .ifnum = -1 | ||
1662 | } | ||
1663 | } | ||
1664 | } | ||
1665 | }, | ||
1666 | { | 1513 | { |
1667 | /* Edirol M-16DX */ | 1514 | /* Edirol M-16DX */ |
1668 | /* FIXME: This quirk gives a good-working capture stream but the | ||
1669 | * playback seems problematic because of lacking of sync | ||
1670 | * with capture stream. It needs to sync with the capture | ||
1671 | * clock. As now, you'll get frequent sound distortions | ||
1672 | * via the playback. | ||
1673 | */ | ||
1674 | USB_DEVICE(0x0582, 0x00c4), | 1515 | USB_DEVICE(0x0582, 0x00c4), |
1675 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1516 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1676 | .ifnum = QUIRK_ANY_INTERFACE, | 1517 | .ifnum = QUIRK_ANY_INTERFACE, |
@@ -1699,35 +1540,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1699 | } | 1540 | } |
1700 | }, | 1541 | }, |
1701 | { | 1542 | { |
1702 | /* BOSS GT-10 */ | ||
1703 | USB_DEVICE(0x0582, 0x00da), | ||
1704 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1705 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1706 | .type = QUIRK_COMPOSITE, | ||
1707 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1708 | { | ||
1709 | .ifnum = 0, | ||
1710 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1711 | }, | ||
1712 | { | ||
1713 | .ifnum = 1, | ||
1714 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1715 | }, | ||
1716 | { | ||
1717 | .ifnum = 2, | ||
1718 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1719 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1720 | .out_cables = 0x0001, | ||
1721 | .in_cables = 0x0001 | ||
1722 | } | ||
1723 | }, | ||
1724 | { | ||
1725 | .ifnum = -1 | ||
1726 | } | ||
1727 | } | ||
1728 | } | ||
1729 | }, | ||
1730 | { | ||
1731 | /* Advanced modes of the Edirol UA-25EX. | 1543 | /* Advanced modes of the Edirol UA-25EX. |
1732 | * For the standard mode, UA-25EX has ID 0582:00e7, which | 1544 | * For the standard mode, UA-25EX has ID 0582:00e7, which |
1733 | * offers only 16-bit PCM at 44.1 kHz and no MIDI. | 1545 | * offers only 16-bit PCM at 44.1 kHz and no MIDI. |
@@ -1758,42 +1570,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1758 | } | 1570 | } |
1759 | }, | 1571 | }, |
1760 | { | 1572 | { |
1761 | /* has ID 0x00ea when not in Advanced Driver mode */ | ||
1762 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e9), | ||
1763 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1764 | /* .vendor_name = "Roland", */ | ||
1765 | /* .product_name = "UA-1G", */ | ||
1766 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1767 | .type = QUIRK_COMPOSITE, | ||
1768 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1769 | { | ||
1770 | .ifnum = 0, | ||
1771 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1772 | }, | ||
1773 | { | ||
1774 | .ifnum = 1, | ||
1775 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1776 | }, | ||
1777 | { | ||
1778 | .ifnum = -1 | ||
1779 | } | ||
1780 | } | ||
1781 | } | ||
1782 | }, | ||
1783 | { | ||
1784 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x0104), | ||
1785 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1786 | /* .vendor_name = "Roland", */ | ||
1787 | /* .product_name = "UM-1G", */ | ||
1788 | .ifnum = 0, | ||
1789 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1790 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1791 | .out_cables = 0x0001, | ||
1792 | .in_cables = 0x0001 | ||
1793 | } | ||
1794 | } | ||
1795 | }, | ||
1796 | { | ||
1797 | /* Edirol UM-3G */ | 1573 | /* Edirol UM-3G */ |
1798 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), | 1574 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), |
1799 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1575 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
@@ -1806,92 +1582,49 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1806 | } | 1582 | } |
1807 | }, | 1583 | }, |
1808 | { | 1584 | { |
1809 | /* Boss JS-8 Jam Station */ | 1585 | /* only 44.1 kHz works at the moment */ |
1810 | USB_DEVICE(0x0582, 0x0109), | 1586 | USB_DEVICE(0x0582, 0x0120), |
1811 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1812 | /* .vendor_name = "BOSS", */ | ||
1813 | /* .product_name = "JS-8", */ | ||
1814 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1815 | .type = QUIRK_COMPOSITE, | ||
1816 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1817 | { | ||
1818 | .ifnum = 0, | ||
1819 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1820 | }, | ||
1821 | { | ||
1822 | .ifnum = 1, | ||
1823 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1824 | }, | ||
1825 | { | ||
1826 | .ifnum = 2, | ||
1827 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
1828 | }, | ||
1829 | { | ||
1830 | .ifnum = -1 | ||
1831 | } | ||
1832 | } | ||
1833 | } | ||
1834 | }, | ||
1835 | { | ||
1836 | /* has ID 0x0110 when not in Advanced Driver mode */ | ||
1837 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f), | ||
1838 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1587 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1839 | /* .vendor_name = "Roland", */ | 1588 | /* .vendor_name = "Roland", */ |
1840 | /* .product_name = "A-PRO", */ | 1589 | /* .product_name = "OCTO-CAPTURE", */ |
1841 | .ifnum = 0, | ||
1842 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1843 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1844 | .out_cables = 0x0003, | ||
1845 | .in_cables = 0x0007 | ||
1846 | } | ||
1847 | } | ||
1848 | }, | ||
1849 | { | ||
1850 | /* Roland GAIA SH-01 */ | ||
1851 | USB_DEVICE(0x0582, 0x0111), | ||
1852 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
1853 | .vendor_name = "Roland", | ||
1854 | .product_name = "GAIA", | ||
1855 | .ifnum = QUIRK_ANY_INTERFACE, | 1590 | .ifnum = QUIRK_ANY_INTERFACE, |
1856 | .type = QUIRK_COMPOSITE, | 1591 | .type = QUIRK_COMPOSITE, |
1857 | .data = (const struct snd_usb_audio_quirk[]) { | 1592 | .data = (const struct snd_usb_audio_quirk[]) { |
1858 | { | 1593 | { |
1859 | .ifnum = 0, | 1594 | .ifnum = 0, |
1860 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1595 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, |
1861 | }, | 1596 | .data = & (const struct audioformat) { |
1862 | { | 1597 | .formats = SNDRV_PCM_FMTBIT_S32_LE, |
1863 | .ifnum = 1, | 1598 | .channels = 10, |
1864 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1599 | .iface = 0, |
1865 | }, | 1600 | .altsetting = 1, |
1866 | { | 1601 | .altset_idx = 1, |
1867 | .ifnum = 2, | 1602 | .endpoint = 0x05, |
1868 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 1603 | .ep_attr = 0x05, |
1869 | .data = &(const struct snd_usb_midi_endpoint_info) { | 1604 | .rates = SNDRV_PCM_RATE_44100, |
1870 | .out_cables = 0x0003, | 1605 | .rate_min = 44100, |
1871 | .in_cables = 0x0003 | 1606 | .rate_max = 44100, |
1607 | .nr_rates = 1, | ||
1608 | .rate_table = (unsigned int[]) { 44100 } | ||
1872 | } | 1609 | } |
1873 | }, | 1610 | }, |
1874 | { | 1611 | { |
1875 | .ifnum = -1 | ||
1876 | } | ||
1877 | } | ||
1878 | } | ||
1879 | }, | ||
1880 | { | ||
1881 | USB_DEVICE(0x0582, 0x0113), | ||
1882 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1883 | /* .vendor_name = "BOSS", */ | ||
1884 | /* .product_name = "ME-25", */ | ||
1885 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1886 | .type = QUIRK_COMPOSITE, | ||
1887 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1888 | { | ||
1889 | .ifnum = 0, | ||
1890 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1891 | }, | ||
1892 | { | ||
1893 | .ifnum = 1, | 1612 | .ifnum = 1, |
1894 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1613 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, |
1614 | .data = & (const struct audioformat) { | ||
1615 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
1616 | .channels = 12, | ||
1617 | .iface = 1, | ||
1618 | .altsetting = 1, | ||
1619 | .altset_idx = 1, | ||
1620 | .endpoint = 0x85, | ||
1621 | .ep_attr = 0x25, | ||
1622 | .rates = SNDRV_PCM_RATE_44100, | ||
1623 | .rate_min = 44100, | ||
1624 | .rate_max = 44100, | ||
1625 | .nr_rates = 1, | ||
1626 | .rate_table = (unsigned int[]) { 44100 } | ||
1627 | } | ||
1895 | }, | 1628 | }, |
1896 | { | 1629 | { |
1897 | .ifnum = 2, | 1630 | .ifnum = 2, |
@@ -1902,30 +1635,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1902 | } | 1635 | } |
1903 | }, | 1636 | }, |
1904 | { | 1637 | { |
1905 | .ifnum = -1 | 1638 | .ifnum = 3, |
1906 | } | 1639 | .type = QUIRK_IGNORE_INTERFACE |
1907 | } | ||
1908 | } | ||
1909 | }, | ||
1910 | { | ||
1911 | USB_DEVICE(0x0582, 0x0127), | ||
1912 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1913 | /* .vendor_name = "Roland", */ | ||
1914 | /* .product_name = "GR-55", */ | ||
1915 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1916 | .type = QUIRK_COMPOSITE, | ||
1917 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1918 | { | ||
1919 | .ifnum = 0, | ||
1920 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1921 | }, | ||
1922 | { | ||
1923 | .ifnum = 1, | ||
1924 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1925 | }, | 1640 | }, |
1926 | { | 1641 | { |
1927 | .ifnum = 2, | 1642 | .ifnum = 4, |
1928 | .type = QUIRK_MIDI_STANDARD_INTERFACE | 1643 | .type = QUIRK_IGNORE_INTERFACE |
1929 | }, | 1644 | }, |
1930 | { | 1645 | { |
1931 | .ifnum = -1 | 1646 | .ifnum = -1 |
@@ -1934,34 +1649,49 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1934 | } | 1649 | } |
1935 | }, | 1650 | }, |
1936 | { | 1651 | { |
1937 | /* Added support for Roland UM-ONE which differs from UM-1 */ | 1652 | /* only 44.1 kHz works at the moment */ |
1938 | USB_DEVICE(0x0582, 0x012a), | 1653 | USB_DEVICE(0x0582, 0x012f), |
1939 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1654 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1940 | /* .vendor_name = "ROLAND", */ | 1655 | /* .vendor_name = "Roland", */ |
1941 | /* .product_name = "UM-ONE", */ | 1656 | /* .product_name = "QUAD-CAPTURE", */ |
1942 | .ifnum = 0, | ||
1943 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1944 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1945 | .out_cables = 0x0001, | ||
1946 | .in_cables = 0x0003 | ||
1947 | } | ||
1948 | } | ||
1949 | }, | ||
1950 | { | ||
1951 | USB_DEVICE(0x0582, 0x011e), | ||
1952 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1953 | /* .vendor_name = "BOSS", */ | ||
1954 | /* .product_name = "BR-800", */ | ||
1955 | .ifnum = QUIRK_ANY_INTERFACE, | 1657 | .ifnum = QUIRK_ANY_INTERFACE, |
1956 | .type = QUIRK_COMPOSITE, | 1658 | .type = QUIRK_COMPOSITE, |
1957 | .data = (const struct snd_usb_audio_quirk[]) { | 1659 | .data = (const struct snd_usb_audio_quirk[]) { |
1958 | { | 1660 | { |
1959 | .ifnum = 0, | 1661 | .ifnum = 0, |
1960 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1662 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, |
1663 | .data = & (const struct audioformat) { | ||
1664 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
1665 | .channels = 4, | ||
1666 | .iface = 0, | ||
1667 | .altsetting = 1, | ||
1668 | .altset_idx = 1, | ||
1669 | .endpoint = 0x05, | ||
1670 | .ep_attr = 0x05, | ||
1671 | .rates = SNDRV_PCM_RATE_44100, | ||
1672 | .rate_min = 44100, | ||
1673 | .rate_max = 44100, | ||
1674 | .nr_rates = 1, | ||
1675 | .rate_table = (unsigned int[]) { 44100 } | ||
1676 | } | ||
1961 | }, | 1677 | }, |
1962 | { | 1678 | { |
1963 | .ifnum = 1, | 1679 | .ifnum = 1, |
1964 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1680 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, |
1681 | .data = & (const struct audioformat) { | ||
1682 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
1683 | .channels = 6, | ||
1684 | .iface = 1, | ||
1685 | .altsetting = 1, | ||
1686 | .altset_idx = 1, | ||
1687 | .endpoint = 0x85, | ||
1688 | .ep_attr = 0x25, | ||
1689 | .rates = SNDRV_PCM_RATE_44100, | ||
1690 | .rate_min = 44100, | ||
1691 | .rate_max = 44100, | ||
1692 | .nr_rates = 1, | ||
1693 | .rate_table = (unsigned int[]) { 44100 } | ||
1694 | } | ||
1965 | }, | 1695 | }, |
1966 | { | 1696 | { |
1967 | .ifnum = 2, | 1697 | .ifnum = 2, |
@@ -1972,38 +1702,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1972 | } | 1702 | } |
1973 | }, | 1703 | }, |
1974 | { | 1704 | { |
1975 | .ifnum = -1 | 1705 | .ifnum = 3, |
1976 | } | ||
1977 | } | ||
1978 | } | ||
1979 | }, | ||
1980 | { | ||
1981 | USB_DEVICE(0x0582, 0x0130), | ||
1982 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1983 | /* .vendor_name = "BOSS", */ | ||
1984 | /* .product_name = "MICRO BR-80", */ | ||
1985 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1986 | .type = QUIRK_COMPOSITE, | ||
1987 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1988 | { | ||
1989 | .ifnum = 0, | ||
1990 | .type = QUIRK_IGNORE_INTERFACE | 1706 | .type = QUIRK_IGNORE_INTERFACE |
1991 | }, | 1707 | }, |
1992 | { | 1708 | { |
1993 | .ifnum = 1, | 1709 | .ifnum = 4, |
1994 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | 1710 | .type = QUIRK_IGNORE_INTERFACE |
1995 | }, | ||
1996 | { | ||
1997 | .ifnum = 2, | ||
1998 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1999 | }, | ||
2000 | { | ||
2001 | .ifnum = 3, | ||
2002 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
2003 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
2004 | .out_cables = 0x0001, | ||
2005 | .in_cables = 0x0001 | ||
2006 | } | ||
2007 | }, | 1711 | }, |
2008 | { | 1712 | { |
2009 | .ifnum = -1 | 1713 | .ifnum = -1 |
@@ -2011,34 +1715,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2011 | } | 1715 | } |
2012 | } | 1716 | } |
2013 | }, | 1717 | }, |
1718 | /* this catches most recent vendor-specific Roland devices */ | ||
2014 | { | 1719 | { |
2015 | USB_DEVICE(0x0582, 0x014d), | 1720 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | |
2016 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1721 | USB_DEVICE_ID_MATCH_INT_CLASS, |
2017 | /* .vendor_name = "BOSS", */ | 1722 | .idVendor = 0x0582, |
2018 | /* .product_name = "GT-100", */ | 1723 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, |
1724 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
2019 | .ifnum = QUIRK_ANY_INTERFACE, | 1725 | .ifnum = QUIRK_ANY_INTERFACE, |
2020 | .type = QUIRK_COMPOSITE, | 1726 | .type = QUIRK_AUTODETECT |
2021 | .data = (const struct snd_usb_audio_quirk[]) { | ||
2022 | { | ||
2023 | .ifnum = 1, | ||
2024 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2025 | }, | ||
2026 | { | ||
2027 | .ifnum = 2, | ||
2028 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
2029 | }, | ||
2030 | { | ||
2031 | .ifnum = 3, | ||
2032 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
2033 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
2034 | .out_cables = 0x0001, | ||
2035 | .in_cables = 0x0001 | ||
2036 | } | ||
2037 | }, | ||
2038 | { | ||
2039 | .ifnum = -1 | ||
2040 | } | ||
2041 | } | ||
2042 | } | 1727 | } |
2043 | }, | 1728 | }, |
2044 | 1729 | ||
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 3879eae7e874..5b01330b8452 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
20 | #include <linux/usb/audio.h> | 20 | #include <linux/usb/audio.h> |
21 | #include <linux/usb/midi.h> | ||
21 | 22 | ||
22 | #include <sound/control.h> | 23 | #include <sound/control.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
@@ -175,6 +176,212 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, | |||
175 | return 0; | 176 | return 0; |
176 | } | 177 | } |
177 | 178 | ||
179 | static int create_auto_pcm_quirk(struct snd_usb_audio *chip, | ||
180 | struct usb_interface *iface, | ||
181 | struct usb_driver *driver) | ||
182 | { | ||
183 | struct usb_host_interface *alts; | ||
184 | struct usb_interface_descriptor *altsd; | ||
185 | struct usb_endpoint_descriptor *epd; | ||
186 | struct uac1_as_header_descriptor *ashd; | ||
187 | struct uac_format_type_i_discrete_descriptor *fmtd; | ||
188 | |||
189 | /* | ||
190 | * Most Roland/Yamaha audio streaming interfaces have more or less | ||
191 | * standard descriptors, but older devices might lack descriptors, and | ||
192 | * future ones might change, so ensure that we fail silently if the | ||
193 | * interface doesn't look exactly right. | ||
194 | */ | ||
195 | |||
196 | /* must have a non-zero altsetting for streaming */ | ||
197 | if (iface->num_altsetting < 2) | ||
198 | return -ENODEV; | ||
199 | alts = &iface->altsetting[1]; | ||
200 | altsd = get_iface_desc(alts); | ||
201 | |||
202 | /* must have an isochronous endpoint for streaming */ | ||
203 | if (altsd->bNumEndpoints < 1) | ||
204 | return -ENODEV; | ||
205 | epd = get_endpoint(alts, 0); | ||
206 | if (!usb_endpoint_xfer_isoc(epd)) | ||
207 | return -ENODEV; | ||
208 | |||
209 | /* must have format descriptors */ | ||
210 | ashd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, | ||
211 | UAC_AS_GENERAL); | ||
212 | fmtd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, | ||
213 | UAC_FORMAT_TYPE); | ||
214 | if (!ashd || ashd->bLength < 7 || | ||
215 | !fmtd || fmtd->bLength < 8) | ||
216 | return -ENODEV; | ||
217 | |||
218 | return create_standard_audio_quirk(chip, iface, driver, NULL); | ||
219 | } | ||
220 | |||
221 | static int create_yamaha_midi_quirk(struct snd_usb_audio *chip, | ||
222 | struct usb_interface *iface, | ||
223 | struct usb_driver *driver, | ||
224 | struct usb_host_interface *alts) | ||
225 | { | ||
226 | static const struct snd_usb_audio_quirk yamaha_midi_quirk = { | ||
227 | .type = QUIRK_MIDI_YAMAHA | ||
228 | }; | ||
229 | struct usb_midi_in_jack_descriptor *injd; | ||
230 | struct usb_midi_out_jack_descriptor *outjd; | ||
231 | |||
232 | /* must have some valid jack descriptors */ | ||
233 | injd = snd_usb_find_csint_desc(alts->extra, alts->extralen, | ||
234 | NULL, USB_MS_MIDI_IN_JACK); | ||
235 | outjd = snd_usb_find_csint_desc(alts->extra, alts->extralen, | ||
236 | NULL, USB_MS_MIDI_OUT_JACK); | ||
237 | if (!injd && !outjd) | ||
238 | return -ENODEV; | ||
239 | if (injd && (injd->bLength < 5 || | ||
240 | (injd->bJackType != USB_MS_EMBEDDED && | ||
241 | injd->bJackType != USB_MS_EXTERNAL))) | ||
242 | return -ENODEV; | ||
243 | if (outjd && (outjd->bLength < 6 || | ||
244 | (outjd->bJackType != USB_MS_EMBEDDED && | ||
245 | outjd->bJackType != USB_MS_EXTERNAL))) | ||
246 | return -ENODEV; | ||
247 | return create_any_midi_quirk(chip, iface, driver, &yamaha_midi_quirk); | ||
248 | } | ||
249 | |||
250 | static int create_roland_midi_quirk(struct snd_usb_audio *chip, | ||
251 | struct usb_interface *iface, | ||
252 | struct usb_driver *driver, | ||
253 | struct usb_host_interface *alts) | ||
254 | { | ||
255 | static const struct snd_usb_audio_quirk roland_midi_quirk = { | ||
256 | .type = QUIRK_MIDI_ROLAND | ||
257 | }; | ||
258 | u8 *roland_desc = NULL; | ||
259 | |||
260 | /* might have a vendor-specific descriptor <06 24 F1 02 ...> */ | ||
261 | for (;;) { | ||
262 | roland_desc = snd_usb_find_csint_desc(alts->extra, | ||
263 | alts->extralen, | ||
264 | roland_desc, 0xf1); | ||
265 | if (!roland_desc) | ||
266 | return -ENODEV; | ||
267 | if (roland_desc[0] < 6 || roland_desc[3] != 2) | ||
268 | continue; | ||
269 | return create_any_midi_quirk(chip, iface, driver, | ||
270 | &roland_midi_quirk); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static int create_std_midi_quirk(struct snd_usb_audio *chip, | ||
275 | struct usb_interface *iface, | ||
276 | struct usb_driver *driver, | ||
277 | struct usb_host_interface *alts) | ||
278 | { | ||
279 | struct usb_ms_header_descriptor *mshd; | ||
280 | struct usb_ms_endpoint_descriptor *msepd; | ||
281 | |||
282 | /* must have the MIDIStreaming interface header descriptor*/ | ||
283 | mshd = (struct usb_ms_header_descriptor *)alts->extra; | ||
284 | if (alts->extralen < 7 || | ||
285 | mshd->bLength < 7 || | ||
286 | mshd->bDescriptorType != USB_DT_CS_INTERFACE || | ||
287 | mshd->bDescriptorSubtype != USB_MS_HEADER) | ||
288 | return -ENODEV; | ||
289 | /* must have the MIDIStreaming endpoint descriptor*/ | ||
290 | msepd = (struct usb_ms_endpoint_descriptor *)alts->endpoint[0].extra; | ||
291 | if (alts->endpoint[0].extralen < 4 || | ||
292 | msepd->bLength < 4 || | ||
293 | msepd->bDescriptorType != USB_DT_CS_ENDPOINT || | ||
294 | msepd->bDescriptorSubtype != UAC_MS_GENERAL || | ||
295 | msepd->bNumEmbMIDIJack < 1 || | ||
296 | msepd->bNumEmbMIDIJack > 16) | ||
297 | return -ENODEV; | ||
298 | |||
299 | return create_any_midi_quirk(chip, iface, driver, NULL); | ||
300 | } | ||
301 | |||
302 | static int create_auto_midi_quirk(struct snd_usb_audio *chip, | ||
303 | struct usb_interface *iface, | ||
304 | struct usb_driver *driver) | ||
305 | { | ||
306 | struct usb_host_interface *alts; | ||
307 | struct usb_interface_descriptor *altsd; | ||
308 | struct usb_endpoint_descriptor *epd; | ||
309 | int err; | ||
310 | |||
311 | alts = &iface->altsetting[0]; | ||
312 | altsd = get_iface_desc(alts); | ||
313 | |||
314 | /* must have at least one bulk/interrupt endpoint for streaming */ | ||
315 | if (altsd->bNumEndpoints < 1) | ||
316 | return -ENODEV; | ||
317 | epd = get_endpoint(alts, 0); | ||
318 | if (!usb_endpoint_xfer_bulk(epd) || | ||
319 | !usb_endpoint_xfer_int(epd)) | ||
320 | return -ENODEV; | ||
321 | |||
322 | switch (USB_ID_VENDOR(chip->usb_id)) { | ||
323 | case 0x0499: /* Yamaha */ | ||
324 | err = create_yamaha_midi_quirk(chip, iface, driver, alts); | ||
325 | if (err < 0 && err != -ENODEV) | ||
326 | return err; | ||
327 | break; | ||
328 | case 0x0582: /* Roland */ | ||
329 | err = create_roland_midi_quirk(chip, iface, driver, alts); | ||
330 | if (err < 0 && err != -ENODEV) | ||
331 | return err; | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | return create_std_midi_quirk(chip, iface, driver, alts); | ||
336 | } | ||
337 | |||
338 | static int create_autodetect_quirk(struct snd_usb_audio *chip, | ||
339 | struct usb_interface *iface, | ||
340 | struct usb_driver *driver) | ||
341 | { | ||
342 | int err; | ||
343 | |||
344 | err = create_auto_pcm_quirk(chip, iface, driver); | ||
345 | if (err == -ENODEV) | ||
346 | err = create_auto_midi_quirk(chip, iface, driver); | ||
347 | return err; | ||
348 | } | ||
349 | |||
350 | static int create_autodetect_quirks(struct snd_usb_audio *chip, | ||
351 | struct usb_interface *iface, | ||
352 | struct usb_driver *driver, | ||
353 | const struct snd_usb_audio_quirk *quirk) | ||
354 | { | ||
355 | int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber; | ||
356 | int ifcount, ifnum, err; | ||
357 | |||
358 | err = create_autodetect_quirk(chip, iface, driver); | ||
359 | if (err < 0) | ||
360 | return err; | ||
361 | |||
362 | /* | ||
363 | * ALSA PCM playback/capture devices cannot be registered in two steps, | ||
364 | * so we have to claim the other corresponding interface here. | ||
365 | */ | ||
366 | ifcount = chip->dev->actconfig->desc.bNumInterfaces; | ||
367 | for (ifnum = 0; ifnum < ifcount; ifnum++) { | ||
368 | if (ifnum == probed_ifnum || quirk->ifnum >= 0) | ||
369 | continue; | ||
370 | iface = usb_ifnum_to_if(chip->dev, ifnum); | ||
371 | if (!iface || | ||
372 | usb_interface_claimed(iface) || | ||
373 | get_iface_desc(iface->altsetting)->bInterfaceClass != | ||
374 | USB_CLASS_VENDOR_SPEC) | ||
375 | continue; | ||
376 | |||
377 | err = create_autodetect_quirk(chip, iface, driver); | ||
378 | if (err >= 0) | ||
379 | usb_driver_claim_interface(driver, iface, (void *)-1L); | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
178 | /* | 385 | /* |
179 | * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. | 386 | * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. |
180 | * The only way to detect the sample rate is by looking at wMaxPacketSize. | 387 | * The only way to detect the sample rate is by looking at wMaxPacketSize. |
@@ -303,9 +510,11 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
303 | static const quirk_func_t quirk_funcs[] = { | 510 | static const quirk_func_t quirk_funcs[] = { |
304 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, | 511 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, |
305 | [QUIRK_COMPOSITE] = create_composite_quirk, | 512 | [QUIRK_COMPOSITE] = create_composite_quirk, |
513 | [QUIRK_AUTODETECT] = create_autodetect_quirks, | ||
306 | [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, | 514 | [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, |
307 | [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, | 515 | [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, |
308 | [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, | 516 | [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, |
517 | [QUIRK_MIDI_ROLAND] = create_any_midi_quirk, | ||
309 | [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, | 518 | [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, |
310 | [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, | 519 | [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, |
311 | [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, | 520 | [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 7db2f8958e79..c4339f97226b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -493,10 +493,10 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
493 | altsd = get_iface_desc(alts); | 493 | altsd = get_iface_desc(alts); |
494 | protocol = altsd->bInterfaceProtocol; | 494 | protocol = altsd->bInterfaceProtocol; |
495 | /* skip invalid one */ | 495 | /* skip invalid one */ |
496 | if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && | 496 | if (((altsd->bInterfaceClass != USB_CLASS_AUDIO || |
497 | (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && | ||
498 | altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) && | ||
497 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || | 499 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || |
498 | (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && | ||
499 | altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || | ||
500 | altsd->bNumEndpoints < 1 || | 500 | altsd->bNumEndpoints < 1 || |
501 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) | 501 | le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) |
502 | continue; | 502 | continue; |
@@ -512,6 +512,15 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
512 | if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) | 512 | if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) |
513 | continue; | 513 | continue; |
514 | 514 | ||
515 | /* | ||
516 | * Roland audio streaming interfaces are marked with protocols | ||
517 | * 0/1/2, but are UAC 1 compatible. | ||
518 | */ | ||
519 | if (USB_ID_VENDOR(chip->usb_id) == 0x0582 && | ||
520 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && | ||
521 | protocol <= 2) | ||
522 | protocol = UAC_VERSION_1; | ||
523 | |||
515 | chconfig = 0; | 524 | chconfig = 0; |
516 | /* get audio formats */ | 525 | /* get audio formats */ |
517 | switch (protocol) { | 526 | switch (protocol) { |
@@ -635,6 +644,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
635 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | 644 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; |
636 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | 645 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; |
637 | fp->datainterval = snd_usb_parse_datainterval(chip, alts); | 646 | fp->datainterval = snd_usb_parse_datainterval(chip, alts); |
647 | fp->protocol = protocol; | ||
638 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | 648 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
639 | fp->channels = num_channels; | 649 | fp->channels = num_channels; |
640 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) | 650 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) |
@@ -676,7 +686,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
676 | } | 686 | } |
677 | 687 | ||
678 | /* ok, let's parse further... */ | 688 | /* ok, let's parse further... */ |
679 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { | 689 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) { |
680 | kfree(fp->rate_table); | 690 | kfree(fp->rate_table); |
681 | kfree(fp->chmap); | 691 | kfree(fp->chmap); |
682 | kfree(fp); | 692 | kfree(fp); |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index bc43bcaddf4d..caabe9b3af49 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -72,9 +72,11 @@ struct snd_usb_audio { | |||
72 | enum quirk_type { | 72 | enum quirk_type { |
73 | QUIRK_IGNORE_INTERFACE, | 73 | QUIRK_IGNORE_INTERFACE, |
74 | QUIRK_COMPOSITE, | 74 | QUIRK_COMPOSITE, |
75 | QUIRK_AUTODETECT, | ||
75 | QUIRK_MIDI_STANDARD_INTERFACE, | 76 | QUIRK_MIDI_STANDARD_INTERFACE, |
76 | QUIRK_MIDI_FIXED_ENDPOINT, | 77 | QUIRK_MIDI_FIXED_ENDPOINT, |
77 | QUIRK_MIDI_YAMAHA, | 78 | QUIRK_MIDI_YAMAHA, |
79 | QUIRK_MIDI_ROLAND, | ||
78 | QUIRK_MIDI_MIDIMAN, | 80 | QUIRK_MIDI_MIDIMAN, |
79 | QUIRK_MIDI_NOVATION, | 81 | QUIRK_MIDI_NOVATION, |
80 | QUIRK_MIDI_RAW_BYTES, | 82 | QUIRK_MIDI_RAW_BYTES, |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 9af7c1f17413..1f9bbd55553f 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -150,7 +150,7 @@ | |||
150 | MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); | 150 | MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); |
151 | MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); | 151 | MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); |
152 | MODULE_LICENSE("GPL"); | 152 | MODULE_LICENSE("GPL"); |
153 | MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}"); | 153 | MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604),"NAME_ALLCAPS"(0x8001)(0x8005)(0x8007)}}"); |
154 | 154 | ||
155 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | 155 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ |
156 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ | 156 | static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ |
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index b37653247ef4..4967fe9c938d 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c | |||
@@ -695,9 +695,6 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) | |||
695 | ((char*)(usbdata + i))[1] = ra[i].c2; | 695 | ((char*)(usbdata + i))[1] = ra[i].c2; |
696 | usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), | 696 | usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), |
697 | usbdata + i, 2, i_usX2Y_04Int, usX2Y); | 697 | usbdata + i, 2, i_usX2Y_04Int, usX2Y); |
698 | #ifdef OLD_USB | ||
699 | us->urb[i]->transfer_flags = USB_QUEUE_BULK; | ||
700 | #endif | ||
701 | } | 698 | } |
702 | us->submitted = 0; | 699 | us->submitted = 0; |
703 | us->len = NOOF_SETRATE_URBS; | 700 | us->len = NOOF_SETRATE_URBS; |