diff options
489 files changed, 13243 insertions, 4950 deletions
diff --git a/Documentation/DocBook/media/v4l/dev-codec.xml b/Documentation/DocBook/media/v4l/dev-codec.xml index dca0ecd54dc6..ff44c16fc080 100644 --- a/Documentation/DocBook/media/v4l/dev-codec.xml +++ b/Documentation/DocBook/media/v4l/dev-codec.xml | |||
| @@ -1,18 +1,27 @@ | |||
| 1 | <title>Codec Interface</title> | 1 | <title>Codec Interface</title> |
| 2 | 2 | ||
| 3 | <note> | 3 | <para>A V4L2 codec can compress, decompress, transform, or otherwise |
| 4 | <title>Suspended</title> | 4 | convert video data from one format into another format, in memory. Typically |
| 5 | such devices are memory-to-memory devices (i.e. devices with the | ||
| 6 | <constant>V4L2_CAP_VIDEO_M2M</constant> or <constant>V4L2_CAP_VIDEO_M2M_MPLANE</constant> | ||
| 7 | capability set). | ||
| 8 | </para> | ||
| 5 | 9 | ||
| 6 | <para>This interface has been be suspended from the V4L2 API | 10 | <para>A memory-to-memory video node acts just like a normal video node, but it |
| 7 | implemented in Linux 2.6 until we have more experience with codec | 11 | supports both output (sending frames from memory to the codec hardware) and |
| 8 | device interfaces.</para> | 12 | capture (receiving the processed frames from the codec hardware into memory) |
| 9 | </note> | 13 | stream I/O. An application will have to setup the stream |
| 14 | I/O for both sides and finally call &VIDIOC-STREAMON; for both capture and output | ||
| 15 | to start the codec.</para> | ||
| 10 | 16 | ||
| 11 | <para>A V4L2 codec can compress, decompress, transform, or otherwise | 17 | <para>Video compression codecs use the MPEG controls to setup their codec parameters |
| 12 | convert video data from one format into another format, in memory. | 18 | (note that the MPEG controls actually support many more codecs than just MPEG). |
| 13 | Applications send data to be converted to the driver through a | 19 | See <xref linkend="mpeg-controls"></xref>.</para> |
| 14 | &func-write; call, and receive the converted data through a | ||
| 15 | &func-read; call. For efficiency a driver may also support streaming | ||
| 16 | I/O.</para> | ||
| 17 | 20 | ||
| 18 | <para>[to do]</para> | 21 | <para>Memory-to-memory devices can often be used as a shared resource: you can |
| 22 | open the video node multiple times, each application setting up their own codec properties | ||
| 23 | that are local to the file handle, and each can use it independently from the others. | ||
| 24 | The driver will arbitrate access to the codec and reprogram it whenever another file | ||
| 25 | handler gets access. This is different from the usual video node behavior where the video properties | ||
| 26 | are global to the device (i.e. changing something through one file handle is visible | ||
| 27 | through another file handle).</para> | ||
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index bfc93cdcf696..bfe823dd0f31 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml | |||
| @@ -493,7 +493,7 @@ and discussions on the V4L mailing list.</revremark> | |||
| 493 | </partinfo> | 493 | </partinfo> |
| 494 | 494 | ||
| 495 | <title>Video for Linux Two API Specification</title> | 495 | <title>Video for Linux Two API Specification</title> |
| 496 | <subtitle>Revision 3.9</subtitle> | 496 | <subtitle>Revision 3.10</subtitle> |
| 497 | 497 | ||
| 498 | <chapter id="common"> | 498 | <chapter id="common"> |
| 499 | &sub-common; | 499 | &sub-common; |
diff --git a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt index 3f62adfb3e0b..de9f6b78ee51 100644 --- a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt +++ b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt | |||
| @@ -2,7 +2,7 @@ Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE) | |||
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | 4 | ||
| 5 | - compatible : should be "samsung,exynos4212-fimc" for Exynos4212 and | 5 | - compatible : should be "samsung,exynos4212-fimc-lite" for Exynos4212 and |
| 6 | Exynos4412 SoCs; | 6 | Exynos4412 SoCs; |
| 7 | - reg : physical base address and size of the device memory mapped | 7 | - reg : physical base address and size of the device memory mapped |
| 8 | registers; | 8 | registers; |
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/adi,adau1701.txt b/Documentation/devicetree/bindings/sound/adi,adau1701.txt new file mode 100644 index 000000000000..547a49b56a62 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,adau1701.txt | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | Analog Devices ADAU1701 | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Should contain "adi,adau1701" | ||
| 6 | - reg: The i2c address. Value depends on the state of ADDR0 | ||
| 7 | and ADDR1, as wired in hardware. | ||
| 8 | |||
| 9 | Optional properties: | ||
| 10 | |||
| 11 | - reset-gpio: A GPIO spec to define which pin is connected to the | ||
| 12 | chip's !RESET pin. If specified, the driver will | ||
| 13 | assert a hardware reset at probe time. | ||
| 14 | - adi,pll-mode-gpios: An array of two GPIO specs to describe the GPIOs | ||
| 15 | the ADAU's PLL config pins are connected to. | ||
| 16 | The state of the pins are set according to the | ||
| 17 | configured clock divider on ASoC side before the | ||
| 18 | firmware is loaded. | ||
| 19 | - adi,pin-config: An array of 12 numerical values selecting one of the | ||
| 20 | pin configurations as described in the datasheet, | ||
| 21 | table 53. Note that the value of this property has | ||
| 22 | to be prefixed with '/bits/ 8'. | ||
| 23 | |||
| 24 | Examples: | ||
| 25 | |||
| 26 | i2c_bus { | ||
| 27 | adau1701@34 { | ||
| 28 | compatible = "adi,adau1701"; | ||
| 29 | reg = <0x34>; | ||
| 30 | reset-gpio = <&gpio 23 0>; | ||
| 31 | adi,pll-mode-gpios = <&gpio 24 0 &gpio 25 0>; | ||
| 32 | adi,pin-config = /bits/ 8 <0x4 0x7 0x5 0x5 0x4 0x4 | ||
| 33 | 0x4 0x4 0x4 0x4 0x4 0x4>; | ||
| 34 | }; | ||
| 35 | }; | ||
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/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt index 8ea4f5b4818d..d2866a0d6a26 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas5086.txt +++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt | |||
| @@ -20,6 +20,17 @@ Optional properties: | |||
| 20 | When not specified, the hardware default of 1300ms | 20 | When not specified, the hardware default of 1300ms |
| 21 | is retained. | 21 | is retained. |
| 22 | 22 | ||
| 23 | - ti,mid-z-channel-X: Boolean properties, X being a number from 1 to 6. | ||
| 24 | If given, channel X will start with the Mid-Z start | ||
| 25 | sequence, otherwise the default Low-Z scheme is used. | ||
| 26 | |||
| 27 | The correct configuration depends on how the power | ||
| 28 | stages connected to the PWM output pins work. Not all | ||
| 29 | power stages are compatible to Mid-Z - please refer | ||
| 30 | to the datasheets for more details. | ||
| 31 | |||
| 32 | Most systems should not set any of these properties. | ||
| 33 | |||
| 23 | Examples: | 34 | Examples: |
| 24 | 35 | ||
| 25 | i2c_bus { | 36 | i2c_bus { |
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 |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 10 | 2 | PATCHLEVEL = 10 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc6 | 4 | EXTRAVERSION = -rc7 |
| 5 | NAME = Unicycling Gorilla | 5 | NAME = Unicycling Gorilla |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 49d993cee512..2651b1da1c56 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -1189,6 +1189,16 @@ config PL310_ERRATA_588369 | |||
| 1189 | is not correctly implemented in PL310 as clean lines are not | 1189 | is not correctly implemented in PL310 as clean lines are not |
| 1190 | invalidated as a result of these operations. | 1190 | invalidated as a result of these operations. |
| 1191 | 1191 | ||
| 1192 | config ARM_ERRATA_643719 | ||
| 1193 | bool "ARM errata: LoUIS bit field in CLIDR register is incorrect" | ||
| 1194 | depends on CPU_V7 && SMP | ||
| 1195 | help | ||
| 1196 | This option enables the workaround for the 643719 Cortex-A9 (prior to | ||
| 1197 | r1p0) erratum. On affected cores the LoUIS bit field of the CLIDR | ||
| 1198 | register returns zero when it should return one. The workaround | ||
| 1199 | corrects this value, ensuring cache maintenance operations which use | ||
| 1200 | it behave as intended and avoiding data corruption. | ||
| 1201 | |||
| 1192 | config ARM_ERRATA_720789 | 1202 | config ARM_ERRATA_720789 |
| 1193 | bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" | 1203 | bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" |
| 1194 | depends on CPU_V7 | 1204 | depends on CPU_V7 |
| @@ -2006,7 +2016,7 @@ config XIP_PHYS_ADDR | |||
| 2006 | 2016 | ||
| 2007 | config KEXEC | 2017 | config KEXEC |
| 2008 | bool "Kexec system call (EXPERIMENTAL)" | 2018 | bool "Kexec system call (EXPERIMENTAL)" |
| 2009 | depends on (!SMP || HOTPLUG_CPU) | 2019 | depends on (!SMP || PM_SLEEP_SMP) |
| 2010 | help | 2020 | help |
| 2011 | kexec is a system call that implements the ability to shutdown your | 2021 | kexec is a system call that implements the ability to shutdown your |
| 2012 | current kernel, and to start another kernel. It is like a reboot | 2022 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 79e9bdbfc491..120b83bfde20 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
| @@ -116,7 +116,8 @@ targets := vmlinux vmlinux.lds \ | |||
| 116 | 116 | ||
| 117 | # Make sure files are removed during clean | 117 | # Make sure files are removed during clean |
| 118 | extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \ | 118 | extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \ |
| 119 | lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) | 119 | lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) \ |
| 120 | hyp-stub.S | ||
| 120 | 121 | ||
| 121 | ifeq ($(CONFIG_FUNCTION_TRACER),y) | 122 | ifeq ($(CONFIG_FUNCTION_TRACER),y) |
| 122 | ORIG_CFLAGS := $(KBUILD_CFLAGS) | 123 | ORIG_CFLAGS := $(KBUILD_CFLAGS) |
diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi index d1650fb34c0a..ded558bb0f3b 100644 --- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi | |||
| @@ -763,7 +763,7 @@ | |||
| 763 | }; | 763 | }; |
| 764 | }; | 764 | }; |
| 765 | 765 | ||
| 766 | pinctrl@03680000 { | 766 | pinctrl@03860000 { |
| 767 | gpz: gpz { | 767 | gpz: gpz { |
| 768 | gpio-controller; | 768 | gpio-controller; |
| 769 | #gpio-cells = <2>; | 769 | #gpio-cells = <2>; |
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 0673524238a6..fc9fb3d526e2 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi | |||
| @@ -161,9 +161,9 @@ | |||
| 161 | interrupts = <0 50 0>; | 161 | interrupts = <0 50 0>; |
| 162 | }; | 162 | }; |
| 163 | 163 | ||
| 164 | pinctrl_3: pinctrl@03680000 { | 164 | pinctrl_3: pinctrl@03860000 { |
| 165 | compatible = "samsung,exynos5250-pinctrl"; | 165 | compatible = "samsung,exynos5250-pinctrl"; |
| 166 | reg = <0x0368000 0x1000>; | 166 | reg = <0x03860000 0x1000>; |
| 167 | interrupts = <0 47 0>; | 167 | interrupts = <0 47 0>; |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index bff71388e72a..17d0ae8672fa 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
| @@ -320,9 +320,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, | |||
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE | 322 | #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE |
| 323 | static inline void flush_kernel_dcache_page(struct page *page) | 323 | extern void flush_kernel_dcache_page(struct page *); |
| 324 | { | ||
| 325 | } | ||
| 326 | 324 | ||
| 327 | #define flush_dcache_mmap_lock(mapping) \ | 325 | #define flush_dcache_mmap_lock(mapping) \ |
| 328 | spin_lock_irq(&(mapping)->tree_lock) | 326 | spin_lock_irq(&(mapping)->tree_lock) |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8ef8c9337809..4fb074c446bf 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
| @@ -134,6 +134,10 @@ void machine_kexec(struct kimage *image) | |||
| 134 | unsigned long reboot_code_buffer_phys; | 134 | unsigned long reboot_code_buffer_phys; |
| 135 | void *reboot_code_buffer; | 135 | void *reboot_code_buffer; |
| 136 | 136 | ||
| 137 | if (num_online_cpus() > 1) { | ||
| 138 | pr_err("kexec: error: multiple CPUs still online\n"); | ||
| 139 | return; | ||
| 140 | } | ||
| 137 | 141 | ||
| 138 | page_list = image->head & PAGE_MASK; | 142 | page_list = image->head & PAGE_MASK; |
| 139 | 143 | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 282de4826abb..6e8931ccf13e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -184,30 +184,61 @@ int __init reboot_setup(char *str) | |||
| 184 | 184 | ||
| 185 | __setup("reboot=", reboot_setup); | 185 | __setup("reboot=", reboot_setup); |
| 186 | 186 | ||
| 187 | /* | ||
| 188 | * Called by kexec, immediately prior to machine_kexec(). | ||
| 189 | * | ||
| 190 | * This must completely disable all secondary CPUs; simply causing those CPUs | ||
| 191 | * to execute e.g. a RAM-based pin loop is not sufficient. This allows the | ||
| 192 | * kexec'd kernel to use any and all RAM as it sees fit, without having to | ||
| 193 | * avoid any code or data used by any SW CPU pin loop. The CPU hotplug | ||
| 194 | * functionality embodied in disable_nonboot_cpus() to achieve this. | ||
| 195 | */ | ||
| 187 | void machine_shutdown(void) | 196 | void machine_shutdown(void) |
| 188 | { | 197 | { |
| 189 | #ifdef CONFIG_SMP | 198 | disable_nonboot_cpus(); |
| 190 | smp_send_stop(); | ||
| 191 | #endif | ||
| 192 | } | 199 | } |
| 193 | 200 | ||
| 201 | /* | ||
| 202 | * Halting simply requires that the secondary CPUs stop performing any | ||
| 203 | * activity (executing tasks, handling interrupts). smp_send_stop() | ||
| 204 | * achieves this. | ||
| 205 | */ | ||
| 194 | void machine_halt(void) | 206 | void machine_halt(void) |
| 195 | { | 207 | { |
| 196 | machine_shutdown(); | 208 | smp_send_stop(); |
| 209 | |||
| 197 | local_irq_disable(); | 210 | local_irq_disable(); |
| 198 | while (1); | 211 | while (1); |
| 199 | } | 212 | } |
| 200 | 213 | ||
| 214 | /* | ||
| 215 | * Power-off simply requires that the secondary CPUs stop performing any | ||
| 216 | * activity (executing tasks, handling interrupts). smp_send_stop() | ||
| 217 | * achieves this. When the system power is turned off, it will take all CPUs | ||
| 218 | * with it. | ||
| 219 | */ | ||
| 201 | void machine_power_off(void) | 220 | void machine_power_off(void) |
| 202 | { | 221 | { |
| 203 | machine_shutdown(); | 222 | smp_send_stop(); |
| 223 | |||
| 204 | if (pm_power_off) | 224 | if (pm_power_off) |
| 205 | pm_power_off(); | 225 | pm_power_off(); |
| 206 | } | 226 | } |
| 207 | 227 | ||
| 228 | /* | ||
| 229 | * Restart requires that the secondary CPUs stop performing any activity | ||
| 230 | * while the primary CPU resets the system. Systems with a single CPU can | ||
| 231 | * use soft_restart() as their machine descriptor's .restart hook, since that | ||
| 232 | * will cause the only available CPU to reset. Systems with multiple CPUs must | ||
| 233 | * provide a HW restart implementation, to ensure that all CPUs reset at once. | ||
| 234 | * This is required so that any code running after reset on the primary CPU | ||
| 235 | * doesn't have to co-ordinate with other CPUs to ensure they aren't still | ||
| 236 | * executing pre-reset code, and using RAM that the primary CPU's code wishes | ||
| 237 | * to use. Implementing such co-ordination would be essentially impossible. | ||
| 238 | */ | ||
| 208 | void machine_restart(char *cmd) | 239 | void machine_restart(char *cmd) |
| 209 | { | 240 | { |
| 210 | machine_shutdown(); | 241 | smp_send_stop(); |
| 211 | 242 | ||
| 212 | arm_pm_restart(reboot_mode, cmd); | 243 | arm_pm_restart(reboot_mode, cmd); |
| 213 | 244 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 550d63cef68e..5919eb451bb9 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
| @@ -651,17 +651,6 @@ void smp_send_reschedule(int cpu) | |||
| 651 | smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); | 651 | smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); |
| 652 | } | 652 | } |
| 653 | 653 | ||
| 654 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 655 | static void smp_kill_cpus(cpumask_t *mask) | ||
| 656 | { | ||
| 657 | unsigned int cpu; | ||
| 658 | for_each_cpu(cpu, mask) | ||
| 659 | platform_cpu_kill(cpu); | ||
| 660 | } | ||
| 661 | #else | ||
| 662 | static void smp_kill_cpus(cpumask_t *mask) { } | ||
| 663 | #endif | ||
| 664 | |||
| 665 | void smp_send_stop(void) | 654 | void smp_send_stop(void) |
| 666 | { | 655 | { |
| 667 | unsigned long timeout; | 656 | unsigned long timeout; |
| @@ -679,8 +668,6 @@ void smp_send_stop(void) | |||
| 679 | 668 | ||
| 680 | if (num_online_cpus() > 1) | 669 | if (num_online_cpus() > 1) |
| 681 | pr_warning("SMP: failed to stop secondary CPUs\n"); | 670 | pr_warning("SMP: failed to stop secondary CPUs\n"); |
| 682 | |||
| 683 | smp_kill_cpus(&mask); | ||
| 684 | } | 671 | } |
| 685 | 672 | ||
| 686 | /* | 673 | /* |
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 15451ee4acc8..515b00064da8 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
| @@ -92,6 +92,14 @@ ENTRY(v7_flush_dcache_louis) | |||
| 92 | mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr | 92 | mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr |
| 93 | ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr | 93 | ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr |
| 94 | ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr | 94 | ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr |
| 95 | #ifdef CONFIG_ARM_ERRATA_643719 | ||
| 96 | ALT_SMP(mrceq p15, 0, r2, c0, c0, 0) @ read main ID register | ||
| 97 | ALT_UP(moveq pc, lr) @ LoUU is zero, so nothing to do | ||
| 98 | ldreq r1, =0x410fc090 @ ID of ARM Cortex A9 r0p? | ||
| 99 | biceq r2, r2, #0x0000000f @ clear minor revision number | ||
| 100 | teqeq r2, r1 @ test for errata affected core and if so... | ||
| 101 | orreqs r3, #(1 << 21) @ fix LoUIS value (and set flags state to 'ne') | ||
| 102 | #endif | ||
| 95 | ALT_SMP(mov r3, r3, lsr #20) @ r3 = LoUIS * 2 | 103 | ALT_SMP(mov r3, r3, lsr #20) @ r3 = LoUIS * 2 |
| 96 | ALT_UP(mov r3, r3, lsr #26) @ r3 = LoUU * 2 | 104 | ALT_UP(mov r3, r3, lsr #26) @ r3 = LoUU * 2 |
| 97 | moveq pc, lr @ return if level == 0 | 105 | moveq pc, lr @ return if level == 0 |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 0d473cce501c..32aa5861119f 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
| @@ -301,6 +301,39 @@ void flush_dcache_page(struct page *page) | |||
| 301 | EXPORT_SYMBOL(flush_dcache_page); | 301 | EXPORT_SYMBOL(flush_dcache_page); |
| 302 | 302 | ||
| 303 | /* | 303 | /* |
| 304 | * Ensure cache coherency for the kernel mapping of this page. We can | ||
| 305 | * assume that the page is pinned via kmap. | ||
| 306 | * | ||
| 307 | * If the page only exists in the page cache and there are no user | ||
| 308 | * space mappings, this is a no-op since the page was already marked | ||
| 309 | * dirty at creation. Otherwise, we need to flush the dirty kernel | ||
| 310 | * cache lines directly. | ||
| 311 | */ | ||
| 312 | void flush_kernel_dcache_page(struct page *page) | ||
| 313 | { | ||
| 314 | if (cache_is_vivt() || cache_is_vipt_aliasing()) { | ||
| 315 | struct address_space *mapping; | ||
| 316 | |||
| 317 | mapping = page_mapping(page); | ||
| 318 | |||
| 319 | if (!mapping || mapping_mapped(mapping)) { | ||
| 320 | void *addr; | ||
| 321 | |||
| 322 | addr = page_address(page); | ||
| 323 | /* | ||
| 324 | * kmap_atomic() doesn't set the page virtual | ||
| 325 | * address for highmem pages, and | ||
| 326 | * kunmap_atomic() takes care of cache | ||
| 327 | * flushing already. | ||
| 328 | */ | ||
| 329 | if (!IS_ENABLED(CONFIG_HIGHMEM) || addr) | ||
| 330 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | ||
| 331 | } | ||
| 332 | } | ||
| 333 | } | ||
| 334 | EXPORT_SYMBOL(flush_kernel_dcache_page); | ||
| 335 | |||
| 336 | /* | ||
| 304 | * Flush an anonymous page so that users of get_user_pages() | 337 | * Flush an anonymous page so that users of get_user_pages() |
| 305 | * can safely access the data. The expected sequence is: | 338 | * can safely access the data. The expected sequence is: |
| 306 | * | 339 | * |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e0d8565671a6..4d409e6a552d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -616,10 +616,12 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
| 616 | } while (pte++, addr += PAGE_SIZE, addr != end); | 616 | } while (pte++, addr += PAGE_SIZE, addr != end); |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | static void __init map_init_section(pmd_t *pmd, unsigned long addr, | 619 | static void __init __map_init_section(pmd_t *pmd, unsigned long addr, |
| 620 | unsigned long end, phys_addr_t phys, | 620 | unsigned long end, phys_addr_t phys, |
| 621 | const struct mem_type *type) | 621 | const struct mem_type *type) |
| 622 | { | 622 | { |
| 623 | pmd_t *p = pmd; | ||
| 624 | |||
| 623 | #ifndef CONFIG_ARM_LPAE | 625 | #ifndef CONFIG_ARM_LPAE |
| 624 | /* | 626 | /* |
| 625 | * In classic MMU format, puds and pmds are folded in to | 627 | * In classic MMU format, puds and pmds are folded in to |
| @@ -638,7 +640,7 @@ static void __init map_init_section(pmd_t *pmd, unsigned long addr, | |||
| 638 | phys += SECTION_SIZE; | 640 | phys += SECTION_SIZE; |
| 639 | } while (pmd++, addr += SECTION_SIZE, addr != end); | 641 | } while (pmd++, addr += SECTION_SIZE, addr != end); |
| 640 | 642 | ||
| 641 | flush_pmd_entry(pmd); | 643 | flush_pmd_entry(p); |
| 642 | } | 644 | } |
| 643 | 645 | ||
| 644 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | 646 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, |
| @@ -661,7 +663,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
| 661 | */ | 663 | */ |
| 662 | if (type->prot_sect && | 664 | if (type->prot_sect && |
| 663 | ((addr | next | phys) & ~SECTION_MASK) == 0) { | 665 | ((addr | next | phys) & ~SECTION_MASK) == 0) { |
| 664 | map_init_section(pmd, addr, next, phys, type); | 666 | __map_init_section(pmd, addr, next, phys, type); |
| 665 | } else { | 667 | } else { |
| 666 | alloc_init_pte(pmd, addr, next, | 668 | alloc_init_pte(pmd, addr, next, |
| 667 | __phys_to_pfn(phys), type); | 669 | __phys_to_pfn(phys), type); |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 2c73a7301ff7..4c8c9c10a388 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
| @@ -409,8 +409,8 @@ __v7_ca9mp_proc_info: | |||
| 409 | */ | 409 | */ |
| 410 | .type __v7_pj4b_proc_info, #object | 410 | .type __v7_pj4b_proc_info, #object |
| 411 | __v7_pj4b_proc_info: | 411 | __v7_pj4b_proc_info: |
| 412 | .long 0x562f5840 | 412 | .long 0x560f5800 |
| 413 | .long 0xfffffff0 | 413 | .long 0xff0fff00 |
| 414 | __v7_proc __v7_pj4b_setup | 414 | __v7_proc __v7_pj4b_setup |
| 415 | .size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info | 415 | .size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info |
| 416 | 416 | ||
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 1e49e5eb81e9..9ba33c40cdf8 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c | |||
| @@ -1336,6 +1336,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, | |||
| 1336 | return; | 1336 | return; |
| 1337 | } | 1337 | } |
| 1338 | 1338 | ||
| 1339 | perf_callchain_store(entry, regs->pc); | ||
| 1339 | tail = (struct frame_tail __user *)regs->regs[29]; | 1340 | tail = (struct frame_tail __user *)regs->regs[29]; |
| 1340 | 1341 | ||
| 1341 | while (entry->nr < PERF_MAX_STACK_DEPTH && | 1342 | while (entry->nr < PERF_MAX_STACK_DEPTH && |
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/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h index 1bf2cf2f4ab4..cec6c06b52c0 100644 --- a/arch/ia64/include/asm/irqflags.h +++ b/arch/ia64/include/asm/irqflags.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #define _ASM_IA64_IRQFLAGS_H | 11 | #define _ASM_IA64_IRQFLAGS_H |
| 12 | 12 | ||
| 13 | #include <asm/pal.h> | 13 | #include <asm/pal.h> |
| 14 | #include <asm/kregs.h> | ||
| 14 | 15 | ||
| 15 | #ifdef CONFIG_IA64_DEBUG_IRQ | 16 | #ifdef CONFIG_IA64_DEBUG_IRQ |
| 16 | extern unsigned long last_cli_ip; | 17 | extern unsigned long last_cli_ip; |
diff --git a/arch/metag/include/asm/hugetlb.h b/arch/metag/include/asm/hugetlb.h index f545477e61f3..471f481e67f3 100644 --- a/arch/metag/include/asm/hugetlb.h +++ b/arch/metag/include/asm/hugetlb.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _ASM_METAG_HUGETLB_H | 2 | #define _ASM_METAG_HUGETLB_H |
| 3 | 3 | ||
| 4 | #include <asm/page.h> | 4 | #include <asm/page.h> |
| 5 | #include <asm-generic/hugetlb.h> | ||
| 5 | 6 | ||
| 6 | 7 | ||
| 7 | static inline int is_hugepage_only_range(struct mm_struct *mm, | 8 | static inline int is_hugepage_only_range(struct mm_struct *mm, |
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h index 678f68d5f37b..8730c0a3c37d 100644 --- a/arch/mn10300/include/asm/irqflags.h +++ b/arch/mn10300/include/asm/irqflags.h | |||
| @@ -13,9 +13,8 @@ | |||
| 13 | #define _ASM_IRQFLAGS_H | 13 | #define _ASM_IRQFLAGS_H |
| 14 | 14 | ||
| 15 | #include <asm/cpu-regs.h> | 15 | #include <asm/cpu-regs.h> |
| 16 | #ifndef __ASSEMBLY__ | 16 | /* linux/smp.h <- linux/irqflags.h needs asm/smp.h first */ |
| 17 | #include <linux/smp.h> | 17 | #include <asm/smp.h> |
| 18 | #endif | ||
| 19 | 18 | ||
| 20 | /* | 19 | /* |
| 21 | * interrupt control | 20 | * interrupt control |
diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h index 6745dbe64944..56c42417d428 100644 --- a/arch/mn10300/include/asm/smp.h +++ b/arch/mn10300/include/asm/smp.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #ifndef __ASSEMBLY__ | 24 | #ifndef __ASSEMBLY__ |
| 25 | #include <linux/threads.h> | 25 | #include <linux/threads.h> |
| 26 | #include <linux/cpumask.h> | 26 | #include <linux/cpumask.h> |
| 27 | #include <linux/thread_info.h> | ||
| 27 | #endif | 28 | #endif |
| 28 | 29 | ||
| 29 | #ifdef CONFIG_SMP | 30 | #ifdef CONFIG_SMP |
| @@ -85,7 +86,7 @@ extern cpumask_t cpu_boot_map; | |||
| 85 | extern void smp_init_cpus(void); | 86 | extern void smp_init_cpus(void); |
| 86 | extern void smp_cache_interrupt(void); | 87 | extern void smp_cache_interrupt(void); |
| 87 | extern void send_IPI_allbutself(int irq); | 88 | extern void send_IPI_allbutself(int irq); |
| 88 | extern int smp_nmi_call_function(smp_call_func_t func, void *info, int wait); | 89 | extern int smp_nmi_call_function(void (*func)(void *), void *info, int wait); |
| 89 | 90 | ||
| 90 | extern void arch_send_call_function_single_ipi(int cpu); | 91 | extern void arch_send_call_function_single_ipi(int cpu); |
| 91 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | 92 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
| @@ -100,6 +101,7 @@ extern void __cpu_die(unsigned int cpu); | |||
| 100 | #ifndef __ASSEMBLY__ | 101 | #ifndef __ASSEMBLY__ |
| 101 | 102 | ||
| 102 | static inline void smp_init_cpus(void) {} | 103 | static inline void smp_init_cpus(void) {} |
| 104 | #define raw_smp_processor_id() 0 | ||
| 103 | 105 | ||
| 104 | #endif /* __ASSEMBLY__ */ | 106 | #endif /* __ASSEMBLY__ */ |
| 105 | #endif /* CONFIG_SMP */ | 107 | #endif /* CONFIG_SMP */ |
diff --git a/arch/parisc/include/asm/mmzone.h b/arch/parisc/include/asm/mmzone.h index cc50d33b7b88..b6b34a0987e7 100644 --- a/arch/parisc/include/asm/mmzone.h +++ b/arch/parisc/include/asm/mmzone.h | |||
| @@ -27,7 +27,7 @@ extern struct node_map_data node_data[]; | |||
| 27 | 27 | ||
| 28 | #define PFNNID_SHIFT (30 - PAGE_SHIFT) | 28 | #define PFNNID_SHIFT (30 - PAGE_SHIFT) |
| 29 | #define PFNNID_MAP_MAX 512 /* support 512GB */ | 29 | #define PFNNID_MAP_MAX 512 /* support 512GB */ |
| 30 | extern unsigned char pfnnid_map[PFNNID_MAP_MAX]; | 30 | extern signed char pfnnid_map[PFNNID_MAP_MAX]; |
| 31 | 31 | ||
| 32 | #ifndef CONFIG_64BIT | 32 | #ifndef CONFIG_64BIT |
| 33 | #define pfn_is_io(pfn) ((pfn & (0xf0000000UL >> PAGE_SHIFT)) == (0xf0000000UL >> PAGE_SHIFT)) | 33 | #define pfn_is_io(pfn) ((pfn & (0xf0000000UL >> PAGE_SHIFT)) == (0xf0000000UL >> PAGE_SHIFT)) |
| @@ -46,7 +46,7 @@ static inline int pfn_to_nid(unsigned long pfn) | |||
| 46 | i = pfn >> PFNNID_SHIFT; | 46 | i = pfn >> PFNNID_SHIFT; |
| 47 | BUG_ON(i >= ARRAY_SIZE(pfnnid_map)); | 47 | BUG_ON(i >= ARRAY_SIZE(pfnnid_map)); |
| 48 | 48 | ||
| 49 | return (int)pfnnid_map[i]; | 49 | return pfnnid_map[i]; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static inline int pfn_valid(int pfn) | 52 | static inline int pfn_valid(int pfn) |
diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index 3234f492d575..465154076d23 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h | |||
| @@ -225,4 +225,9 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) | |||
| 225 | return channel ? 15 : 14; | 225 | return channel ? 15 : 14; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | #define HAVE_PCI_MMAP | ||
| 229 | |||
| 230 | extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 231 | enum pci_mmap_state mmap_state, int write_combine); | ||
| 232 | |||
| 228 | #endif /* __ASM_PARISC_PCI_H */ | 233 | #endif /* __ASM_PARISC_PCI_H */ |
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index 9e2d2e408529..872275659d98 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c | |||
| @@ -1205,6 +1205,7 @@ static struct hp_hardware hp_hardware_list[] = { | |||
| 1205 | {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"}, | 1205 | {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"}, |
| 1206 | {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"}, | 1206 | {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"}, |
| 1207 | {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"}, | 1207 | {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"}, |
| 1208 | {HPHW_FIO, 0x076, 0x000AD, 0x00, "Crestone Peak RS-232"}, | ||
| 1208 | {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, | 1209 | {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, |
| 1209 | {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, | 1210 | {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, |
| 1210 | {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, | 1211 | {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, |
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 36d7f402e48e..b743a80eaba0 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
| @@ -860,7 +860,7 @@ ENTRY(flush_dcache_page_asm) | |||
| 860 | #endif | 860 | #endif |
| 861 | 861 | ||
| 862 | ldil L%dcache_stride, %r1 | 862 | ldil L%dcache_stride, %r1 |
| 863 | ldw R%dcache_stride(%r1), %r1 | 863 | ldw R%dcache_stride(%r1), r31 |
| 864 | 864 | ||
| 865 | #ifdef CONFIG_64BIT | 865 | #ifdef CONFIG_64BIT |
| 866 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | 866 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 |
| @@ -868,26 +868,26 @@ ENTRY(flush_dcache_page_asm) | |||
| 868 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | 868 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 |
| 869 | #endif | 869 | #endif |
| 870 | add %r28, %r25, %r25 | 870 | add %r28, %r25, %r25 |
| 871 | sub %r25, %r1, %r25 | 871 | sub %r25, r31, %r25 |
| 872 | 872 | ||
| 873 | 873 | ||
| 874 | 1: fdc,m %r1(%r28) | 874 | 1: fdc,m r31(%r28) |
| 875 | fdc,m %r1(%r28) | 875 | fdc,m r31(%r28) |
| 876 | fdc,m %r1(%r28) | 876 | fdc,m r31(%r28) |
| 877 | fdc,m %r1(%r28) | 877 | fdc,m r31(%r28) |
| 878 | fdc,m %r1(%r28) | 878 | fdc,m r31(%r28) |
| 879 | fdc,m %r1(%r28) | 879 | fdc,m r31(%r28) |
| 880 | fdc,m %r1(%r28) | 880 | fdc,m r31(%r28) |
| 881 | fdc,m %r1(%r28) | 881 | fdc,m r31(%r28) |
| 882 | fdc,m %r1(%r28) | 882 | fdc,m r31(%r28) |
| 883 | fdc,m %r1(%r28) | 883 | fdc,m r31(%r28) |
| 884 | fdc,m %r1(%r28) | 884 | fdc,m r31(%r28) |
| 885 | fdc,m %r1(%r28) | 885 | fdc,m r31(%r28) |
| 886 | fdc,m %r1(%r28) | 886 | fdc,m r31(%r28) |
| 887 | fdc,m %r1(%r28) | 887 | fdc,m r31(%r28) |
| 888 | fdc,m %r1(%r28) | 888 | fdc,m r31(%r28) |
| 889 | cmpb,COND(<<) %r28, %r25,1b | 889 | cmpb,COND(<<) %r28, %r25,1b |
| 890 | fdc,m %r1(%r28) | 890 | fdc,m r31(%r28) |
| 891 | 891 | ||
| 892 | sync | 892 | sync |
| 893 | 893 | ||
| @@ -936,7 +936,7 @@ ENTRY(flush_icache_page_asm) | |||
| 936 | #endif | 936 | #endif |
| 937 | 937 | ||
| 938 | ldil L%icache_stride, %r1 | 938 | ldil L%icache_stride, %r1 |
| 939 | ldw R%icache_stride(%r1), %r1 | 939 | ldw R%icache_stride(%r1), %r31 |
| 940 | 940 | ||
| 941 | #ifdef CONFIG_64BIT | 941 | #ifdef CONFIG_64BIT |
| 942 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | 942 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 |
| @@ -944,28 +944,28 @@ ENTRY(flush_icache_page_asm) | |||
| 944 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | 944 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 |
| 945 | #endif | 945 | #endif |
| 946 | add %r28, %r25, %r25 | 946 | add %r28, %r25, %r25 |
| 947 | sub %r25, %r1, %r25 | 947 | sub %r25, %r31, %r25 |
| 948 | 948 | ||
| 949 | 949 | ||
| 950 | /* fic only has the type 26 form on PA1.1, requiring an | 950 | /* fic only has the type 26 form on PA1.1, requiring an |
| 951 | * explicit space specification, so use %sr4 */ | 951 | * explicit space specification, so use %sr4 */ |
| 952 | 1: fic,m %r1(%sr4,%r28) | 952 | 1: fic,m %r31(%sr4,%r28) |
| 953 | fic,m %r1(%sr4,%r28) | 953 | fic,m %r31(%sr4,%r28) |
| 954 | fic,m %r1(%sr4,%r28) | 954 | fic,m %r31(%sr4,%r28) |
| 955 | fic,m %r1(%sr4,%r28) | 955 | fic,m %r31(%sr4,%r28) |
| 956 | fic,m %r1(%sr4,%r28) | 956 | fic,m %r31(%sr4,%r28) |
| 957 | fic,m %r1(%sr4,%r28) | 957 | fic,m %r31(%sr4,%r28) |
| 958 | fic,m %r1(%sr4,%r28) | 958 | fic,m %r31(%sr4,%r28) |
| 959 | fic,m %r1(%sr4,%r28) | 959 | fic,m %r31(%sr4,%r28) |
| 960 | fic,m %r1(%sr4,%r28) | 960 | fic,m %r31(%sr4,%r28) |
| 961 | fic,m %r1(%sr4,%r28) | 961 | fic,m %r31(%sr4,%r28) |
| 962 | fic,m %r1(%sr4,%r28) | 962 | fic,m %r31(%sr4,%r28) |
| 963 | fic,m %r1(%sr4,%r28) | 963 | fic,m %r31(%sr4,%r28) |
| 964 | fic,m %r1(%sr4,%r28) | 964 | fic,m %r31(%sr4,%r28) |
| 965 | fic,m %r1(%sr4,%r28) | 965 | fic,m %r31(%sr4,%r28) |
| 966 | fic,m %r1(%sr4,%r28) | 966 | fic,m %r31(%sr4,%r28) |
| 967 | cmpb,COND(<<) %r28, %r25,1b | 967 | cmpb,COND(<<) %r28, %r25,1b |
| 968 | fic,m %r1(%sr4,%r28) | 968 | fic,m %r31(%sr4,%r28) |
| 969 | 969 | ||
| 970 | sync | 970 | sync |
| 971 | 971 | ||
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 60309051875e..64f2764a8cef 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c | |||
| @@ -220,6 +220,33 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, | |||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | 222 | ||
| 223 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 224 | enum pci_mmap_state mmap_state, int write_combine) | ||
| 225 | { | ||
| 226 | unsigned long prot; | ||
| 227 | |||
| 228 | /* | ||
| 229 | * I/O space can be accessed via normal processor loads and stores on | ||
| 230 | * this platform but for now we elect not to do this and portable | ||
| 231 | * drivers should not do this anyway. | ||
| 232 | */ | ||
| 233 | if (mmap_state == pci_mmap_io) | ||
| 234 | return -EINVAL; | ||
| 235 | |||
| 236 | if (write_combine) | ||
| 237 | return -EINVAL; | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Ignore write-combine; for now only return uncached mappings. | ||
| 241 | */ | ||
| 242 | prot = pgprot_val(vma->vm_page_prot); | ||
| 243 | prot |= _PAGE_NO_CACHE; | ||
| 244 | vma->vm_page_prot = __pgprot(prot); | ||
| 245 | |||
| 246 | return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
| 247 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
| 248 | } | ||
| 249 | |||
| 223 | /* | 250 | /* |
| 224 | * A driver is enabling the device. We make sure that all the appropriate | 251 | * A driver is enabling the device. We make sure that all the appropriate |
| 225 | * bits are set to allow the device to operate as the driver is expecting. | 252 | * bits are set to allow the device to operate as the driver is expecting. |
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1c965642068b..505b56c6b9b9 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
| @@ -47,7 +47,7 @@ pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pt | |||
| 47 | 47 | ||
| 48 | #ifdef CONFIG_DISCONTIGMEM | 48 | #ifdef CONFIG_DISCONTIGMEM |
| 49 | struct node_map_data node_data[MAX_NUMNODES] __read_mostly; | 49 | struct node_map_data node_data[MAX_NUMNODES] __read_mostly; |
| 50 | unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; | 50 | signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; |
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | static struct resource data_resource = { | 53 | static struct resource data_resource = { |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 5cd7ad0c1176..1a1b51189773 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
| @@ -673,7 +673,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
| 673 | ret = s; | 673 | ret = s; |
| 674 | goto out; | 674 | goto out; |
| 675 | } | 675 | } |
| 676 | kvmppc_lazy_ee_enable(); | ||
| 677 | 676 | ||
| 678 | kvm_guest_enter(); | 677 | kvm_guest_enter(); |
| 679 | 678 | ||
| @@ -699,6 +698,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
| 699 | kvmppc_load_guest_fp(vcpu); | 698 | kvmppc_load_guest_fp(vcpu); |
| 700 | #endif | 699 | #endif |
| 701 | 700 | ||
| 701 | kvmppc_lazy_ee_enable(); | ||
| 702 | |||
| 702 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); | 703 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); |
| 703 | 704 | ||
| 704 | /* No need for kvm_guest_exit. It's done in handle_exit. | 705 | /* No need for kvm_guest_exit. It's done in handle_exit. |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 237c8e5f2640..77fdd2cef33b 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
| @@ -592,8 +592,14 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
| 592 | do { | 592 | do { |
| 593 | pmd = pmd_offset(pud, addr); | 593 | pmd = pmd_offset(pud, addr); |
| 594 | next = pmd_addr_end(addr, end); | 594 | next = pmd_addr_end(addr, end); |
| 595 | if (pmd_none_or_clear_bad(pmd)) | 595 | if (!is_hugepd(pmd)) { |
| 596 | /* | ||
| 597 | * if it is not hugepd pointer, we should already find | ||
| 598 | * it cleared. | ||
| 599 | */ | ||
| 600 | WARN_ON(!pmd_none_or_clear_bad(pmd)); | ||
| 596 | continue; | 601 | continue; |
| 602 | } | ||
| 597 | #ifdef CONFIG_PPC_FSL_BOOK3E | 603 | #ifdef CONFIG_PPC_FSL_BOOK3E |
| 598 | /* | 604 | /* |
| 599 | * Increment next by the size of the huge mapping since | 605 | * Increment next by the size of the huge mapping since |
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index ff18e3cfb6b1..7e4a97fbded4 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
| @@ -6,6 +6,7 @@ generic-y += cputime.h | |||
| 6 | generic-y += div64.h | 6 | generic-y += div64.h |
| 7 | generic-y += emergency-restart.h | 7 | generic-y += emergency-restart.h |
| 8 | generic-y += exec.h | 8 | generic-y += exec.h |
| 9 | generic-y += linkage.h | ||
| 9 | generic-y += local64.h | 10 | generic-y += local64.h |
| 10 | generic-y += mutex.h | 11 | generic-y += mutex.h |
| 11 | generic-y += irq_regs.h | 12 | generic-y += irq_regs.h |
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 15a716934e4d..b836e9297f2a 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h | |||
| @@ -135,7 +135,7 @@ static inline int sparc_leon3_cpuid(void) | |||
| 135 | 135 | ||
| 136 | #ifdef CONFIG_SMP | 136 | #ifdef CONFIG_SMP |
| 137 | # define LEON3_IRQ_IPI_DEFAULT 13 | 137 | # define LEON3_IRQ_IPI_DEFAULT 13 |
| 138 | # define LEON3_IRQ_TICKER (leon3_ticker_irq) | 138 | # define LEON3_IRQ_TICKER (leon3_gptimer_irq) |
| 139 | # define LEON3_IRQ_CROSS_CALL 15 | 139 | # define LEON3_IRQ_CROSS_CALL 15 |
| 140 | #endif | 140 | #endif |
| 141 | 141 | ||
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h index f3034eddf468..24ec48c3ff90 100644 --- a/arch/sparc/include/asm/leon_amba.h +++ b/arch/sparc/include/asm/leon_amba.h | |||
| @@ -47,6 +47,7 @@ struct amba_prom_registers { | |||
| 47 | #define LEON3_GPTIMER_LD 4 | 47 | #define LEON3_GPTIMER_LD 4 |
| 48 | #define LEON3_GPTIMER_IRQEN 8 | 48 | #define LEON3_GPTIMER_IRQEN 8 |
| 49 | #define LEON3_GPTIMER_SEPIRQ 8 | 49 | #define LEON3_GPTIMER_SEPIRQ 8 |
| 50 | #define LEON3_GPTIMER_TIMERS 0x7 | ||
| 50 | 51 | ||
| 51 | #define LEON23_REG_TIMER_CONTROL_EN 0x00000001 /* 1 = enable counting */ | 52 | #define LEON23_REG_TIMER_CONTROL_EN 0x00000001 /* 1 = enable counting */ |
| 52 | /* 0 = hold scalar and counter */ | 53 | /* 0 = hold scalar and counter */ |
diff --git a/arch/sparc/include/asm/linkage.h b/arch/sparc/include/asm/linkage.h deleted file mode 100644 index 291c2d01c44f..000000000000 --- a/arch/sparc/include/asm/linkage.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __ASM_LINKAGE_H | ||
| 2 | #define __ASM_LINKAGE_H | ||
| 3 | |||
| 4 | /* Nothing to see here... */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 75bb608c423e..5ef48dab5636 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c | |||
| @@ -843,7 +843,8 @@ void ldom_reboot(const char *boot_command) | |||
| 843 | unsigned long len; | 843 | unsigned long len; |
| 844 | 844 | ||
| 845 | strcpy(full_boot_str, "boot "); | 845 | strcpy(full_boot_str, "boot "); |
| 846 | strcpy(full_boot_str + strlen("boot "), boot_command); | 846 | strlcpy(full_boot_str + strlen("boot "), boot_command, |
| 847 | sizeof(full_boot_str + strlen("boot "))); | ||
| 847 | len = strlen(full_boot_str); | 848 | len = strlen(full_boot_str); |
| 848 | 849 | ||
| 849 | if (reboot_data_supported) { | 850 | if (reboot_data_supported) { |
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 7c0231dabe44..b7c68976cbc7 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
| @@ -38,7 +38,6 @@ static DEFINE_SPINLOCK(leon_irq_lock); | |||
| 38 | 38 | ||
| 39 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | 39 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
| 40 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | 40 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ |
| 41 | int leon3_ticker_irq; /* Timer ticker IRQ */ | ||
| 42 | unsigned int sparc_leon_eirq; | 41 | unsigned int sparc_leon_eirq; |
| 43 | #define LEON_IMASK(cpu) (&leon3_irqctrl_regs->mask[cpu]) | 42 | #define LEON_IMASK(cpu) (&leon3_irqctrl_regs->mask[cpu]) |
| 44 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) | 43 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) |
| @@ -278,6 +277,9 @@ irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused) | |||
| 278 | 277 | ||
| 279 | leon_clear_profile_irq(cpu); | 278 | leon_clear_profile_irq(cpu); |
| 280 | 279 | ||
| 280 | if (cpu == boot_cpu_id) | ||
| 281 | timer_interrupt(irq, NULL); | ||
| 282 | |||
| 281 | ce = &per_cpu(sparc32_clockevent, cpu); | 283 | ce = &per_cpu(sparc32_clockevent, cpu); |
| 282 | 284 | ||
| 283 | irq_enter(); | 285 | irq_enter(); |
| @@ -299,6 +301,7 @@ void __init leon_init_timers(void) | |||
| 299 | int icsel; | 301 | int icsel; |
| 300 | int ampopts; | 302 | int ampopts; |
| 301 | int err; | 303 | int err; |
| 304 | u32 config; | ||
| 302 | 305 | ||
| 303 | sparc_config.get_cycles_offset = leon_cycles_offset; | 306 | sparc_config.get_cycles_offset = leon_cycles_offset; |
| 304 | sparc_config.cs_period = 1000000 / HZ; | 307 | sparc_config.cs_period = 1000000 / HZ; |
| @@ -377,23 +380,6 @@ void __init leon_init_timers(void) | |||
| 377 | LEON3_BYPASS_STORE_PA( | 380 | LEON3_BYPASS_STORE_PA( |
| 378 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); | 381 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); |
| 379 | 382 | ||
| 380 | #ifdef CONFIG_SMP | ||
| 381 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; | ||
| 382 | |||
| 383 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | ||
| 384 | (1<<LEON3_GPTIMER_SEPIRQ))) { | ||
| 385 | printk(KERN_ERR "timer not configured with separate irqs\n"); | ||
| 386 | BUG(); | ||
| 387 | } | ||
| 388 | |||
| 389 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, | ||
| 390 | 0); | ||
| 391 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, | ||
| 392 | (((1000000/HZ) - 1))); | ||
| 393 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | ||
| 394 | 0); | ||
| 395 | #endif | ||
| 396 | |||
| 397 | /* | 383 | /* |
| 398 | * The IRQ controller may (if implemented) consist of multiple | 384 | * The IRQ controller may (if implemented) consist of multiple |
| 399 | * IRQ controllers, each mapped on a 4Kb boundary. | 385 | * IRQ controllers, each mapped on a 4Kb boundary. |
| @@ -416,13 +402,6 @@ void __init leon_init_timers(void) | |||
| 416 | if (eirq != 0) | 402 | if (eirq != 0) |
| 417 | leon_eirq_setup(eirq); | 403 | leon_eirq_setup(eirq); |
| 418 | 404 | ||
| 419 | irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); | ||
| 420 | err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); | ||
| 421 | if (err) { | ||
| 422 | printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); | ||
| 423 | prom_halt(); | ||
| 424 | } | ||
| 425 | |||
| 426 | #ifdef CONFIG_SMP | 405 | #ifdef CONFIG_SMP |
| 427 | { | 406 | { |
| 428 | unsigned long flags; | 407 | unsigned long flags; |
| @@ -439,30 +418,31 @@ void __init leon_init_timers(void) | |||
| 439 | } | 418 | } |
| 440 | #endif | 419 | #endif |
| 441 | 420 | ||
| 442 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, | 421 | config = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config); |
| 443 | LEON3_GPTIMER_EN | | 422 | if (config & (1 << LEON3_GPTIMER_SEPIRQ)) |
| 444 | LEON3_GPTIMER_RL | | 423 | leon3_gptimer_irq += leon3_gptimer_idx; |
| 445 | LEON3_GPTIMER_LD | | 424 | else if ((config & LEON3_GPTIMER_TIMERS) > 1) |
| 446 | LEON3_GPTIMER_IRQEN); | 425 | pr_warn("GPTIMER uses shared irqs, using other timers of the same core will fail.\n"); |
| 447 | 426 | ||
| 448 | #ifdef CONFIG_SMP | 427 | #ifdef CONFIG_SMP |
| 449 | /* Install per-cpu IRQ handler for broadcasted ticker */ | 428 | /* Install per-cpu IRQ handler for broadcasted ticker */ |
| 450 | irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, | 429 | irq = leon_build_device_irq(leon3_gptimer_irq, handle_percpu_irq, |
| 451 | "per-cpu", 0); | 430 | "per-cpu", 0); |
| 452 | err = request_irq(irq, leon_percpu_timer_ce_interrupt, | 431 | err = request_irq(irq, leon_percpu_timer_ce_interrupt, |
| 453 | IRQF_PERCPU | IRQF_TIMER, "ticker", | 432 | IRQF_PERCPU | IRQF_TIMER, "timer", NULL); |
| 454 | NULL); | 433 | #else |
| 434 | irq = _leon_build_device_irq(NULL, leon3_gptimer_irq); | ||
| 435 | err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); | ||
| 436 | #endif | ||
| 455 | if (err) { | 437 | if (err) { |
| 456 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); | 438 | pr_err("Unable to attach timer IRQ%d\n", irq); |
| 457 | prom_halt(); | 439 | prom_halt(); |
| 458 | } | 440 | } |
| 459 | 441 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, | |
| 460 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | ||
| 461 | LEON3_GPTIMER_EN | | 442 | LEON3_GPTIMER_EN | |
| 462 | LEON3_GPTIMER_RL | | 443 | LEON3_GPTIMER_RL | |
| 463 | LEON3_GPTIMER_LD | | 444 | LEON3_GPTIMER_LD | |
| 464 | LEON3_GPTIMER_IRQEN); | 445 | LEON3_GPTIMER_IRQEN); |
| 465 | #endif | ||
| 466 | return; | 446 | return; |
| 467 | bad: | 447 | bad: |
| 468 | printk(KERN_ERR "No Timer/irqctrl found\n"); | 448 | printk(KERN_ERR "No Timer/irqctrl found\n"); |
diff --git a/arch/sparc/kernel/leon_pci_grpci1.c b/arch/sparc/kernel/leon_pci_grpci1.c index 7739a54315e2..6df26e37f879 100644 --- a/arch/sparc/kernel/leon_pci_grpci1.c +++ b/arch/sparc/kernel/leon_pci_grpci1.c | |||
| @@ -536,11 +536,9 @@ static int grpci1_of_probe(struct platform_device *ofdev) | |||
| 536 | 536 | ||
| 537 | /* find device register base address */ | 537 | /* find device register base address */ |
| 538 | res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); | 538 | res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); |
| 539 | regs = devm_request_and_ioremap(&ofdev->dev, res); | 539 | regs = devm_ioremap_resource(&ofdev->dev, res); |
| 540 | if (!regs) { | 540 | if (IS_ERR(regs)) |
| 541 | dev_err(&ofdev->dev, "io-regs mapping failed\n"); | 541 | return PTR_ERR(regs); |
| 542 | return -EADDRNOTAVAIL; | ||
| 543 | } | ||
| 544 | 542 | ||
| 545 | /* | 543 | /* |
| 546 | * check that we're in Host Slot and that we can act as a Host Bridge | 544 | * check that we're in Host Slot and that we can act as a Host Bridge |
diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c index bdf53d9a8d46..b0b3967a2dd2 100644 --- a/arch/sparc/kernel/leon_pmc.c +++ b/arch/sparc/kernel/leon_pmc.c | |||
| @@ -47,6 +47,10 @@ void pmc_leon_idle_fixup(void) | |||
| 47 | * MMU does not get a TLB miss here by using the MMU BYPASS ASI. | 47 | * MMU does not get a TLB miss here by using the MMU BYPASS ASI. |
| 48 | */ | 48 | */ |
| 49 | register unsigned int address = (unsigned int)leon3_irqctrl_regs; | 49 | register unsigned int address = (unsigned int)leon3_irqctrl_regs; |
| 50 | |||
| 51 | /* Interrupts need to be enabled to not hang the CPU */ | ||
| 52 | local_irq_enable(); | ||
| 53 | |||
| 50 | __asm__ __volatile__ ( | 54 | __asm__ __volatile__ ( |
| 51 | "wr %%g0, %%asr19\n" | 55 | "wr %%g0, %%asr19\n" |
| 52 | "lda [%0] %1, %%g0\n" | 56 | "lda [%0] %1, %%g0\n" |
| @@ -60,6 +64,9 @@ void pmc_leon_idle_fixup(void) | |||
| 60 | */ | 64 | */ |
| 61 | void pmc_leon_idle(void) | 65 | void pmc_leon_idle(void) |
| 62 | { | 66 | { |
| 67 | /* Interrupts need to be enabled to not hang the CPU */ | ||
| 68 | local_irq_enable(); | ||
| 69 | |||
| 63 | /* For systems without power-down, this will be no-op */ | 70 | /* For systems without power-down, this will be no-op */ |
| 64 | __asm__ __volatile__ ("wr %g0, %asr19\n\t"); | 71 | __asm__ __volatile__ ("wr %g0, %asr19\n\t"); |
| 65 | } | 72 | } |
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 38bf80a22f02..1434526970a6 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c | |||
| @@ -304,7 +304,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 304 | 304 | ||
| 305 | /* Initialize PROM console and command line. */ | 305 | /* Initialize PROM console and command line. */ |
| 306 | *cmdline_p = prom_getbootargs(); | 306 | *cmdline_p = prom_getbootargs(); |
| 307 | strcpy(boot_command_line, *cmdline_p); | 307 | strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); |
| 308 | parse_early_param(); | 308 | parse_early_param(); |
| 309 | 309 | ||
| 310 | boot_flags_init(*cmdline_p); | 310 | boot_flags_init(*cmdline_p); |
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 88a127b9c69e..13785547e435 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c | |||
| @@ -555,7 +555,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 555 | { | 555 | { |
| 556 | /* Initialize PROM console and command line. */ | 556 | /* Initialize PROM console and command line. */ |
| 557 | *cmdline_p = prom_getbootargs(); | 557 | *cmdline_p = prom_getbootargs(); |
| 558 | strcpy(boot_command_line, *cmdline_p); | 558 | strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); |
| 559 | parse_early_param(); | 559 | parse_early_param(); |
| 560 | 560 | ||
| 561 | boot_flags_init(*cmdline_p); | 561 | boot_flags_init(*cmdline_p); |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index a7171997adfd..04fd55a6e461 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
| @@ -1098,7 +1098,14 @@ static int __init grab_mblocks(struct mdesc_handle *md) | |||
| 1098 | m->size = *val; | 1098 | m->size = *val; |
| 1099 | val = mdesc_get_property(md, node, | 1099 | val = mdesc_get_property(md, node, |
| 1100 | "address-congruence-offset", NULL); | 1100 | "address-congruence-offset", NULL); |
| 1101 | m->offset = *val; | 1101 | |
| 1102 | /* The address-congruence-offset property is optional. | ||
| 1103 | * Explicity zero it be identifty this. | ||
| 1104 | */ | ||
| 1105 | if (val) | ||
| 1106 | m->offset = *val; | ||
| 1107 | else | ||
| 1108 | m->offset = 0UL; | ||
| 1102 | 1109 | ||
| 1103 | numadbg("MBLOCK[%d]: base[%llx] size[%llx] offset[%llx]\n", | 1110 | numadbg("MBLOCK[%d]: base[%llx] size[%llx] offset[%llx]\n", |
| 1104 | count - 1, m->base, m->size, m->offset); | 1111 | count - 1, m->base, m->size, m->offset); |
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 83d89bcb44af..37e7bc4c95b3 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
| @@ -85,8 +85,8 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | if (!tb->active) { | 87 | if (!tb->active) { |
| 88 | global_flush_tlb_page(mm, vaddr); | ||
| 89 | flush_tsb_user_page(mm, vaddr); | 88 | flush_tsb_user_page(mm, vaddr); |
| 89 | global_flush_tlb_page(mm, vaddr); | ||
| 90 | goto out; | 90 | goto out; |
| 91 | } | 91 | } |
| 92 | 92 | ||
diff --git a/arch/sparc/prom/bootstr_32.c b/arch/sparc/prom/bootstr_32.c index f5ec32e0d419..d2b49d2365e7 100644 --- a/arch/sparc/prom/bootstr_32.c +++ b/arch/sparc/prom/bootstr_32.c | |||
| @@ -23,23 +23,25 @@ prom_getbootargs(void) | |||
| 23 | return barg_buf; | 23 | return barg_buf; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | switch(prom_vers) { | 26 | switch (prom_vers) { |
| 27 | case PROM_V0: | 27 | case PROM_V0: |
| 28 | cp = barg_buf; | 28 | cp = barg_buf; |
| 29 | /* Start from 1 and go over fd(0,0,0)kernel */ | 29 | /* Start from 1 and go over fd(0,0,0)kernel */ |
| 30 | for(iter = 1; iter < 8; iter++) { | 30 | for (iter = 1; iter < 8; iter++) { |
| 31 | arg = (*(romvec->pv_v0bootargs))->argv[iter]; | 31 | arg = (*(romvec->pv_v0bootargs))->argv[iter]; |
| 32 | if (arg == NULL) | 32 | if (arg == NULL) |
| 33 | break; | 33 | break; |
| 34 | while(*arg != 0) { | 34 | while (*arg != 0) { |
| 35 | /* Leave place for space and null. */ | 35 | /* Leave place for space and null. */ |
| 36 | if(cp >= barg_buf + BARG_LEN-2){ | 36 | if (cp >= barg_buf + BARG_LEN - 2) |
| 37 | /* We might issue a warning here. */ | 37 | /* We might issue a warning here. */ |
| 38 | break; | 38 | break; |
| 39 | } | ||
| 40 | *cp++ = *arg++; | 39 | *cp++ = *arg++; |
| 41 | } | 40 | } |
| 42 | *cp++ = ' '; | 41 | *cp++ = ' '; |
| 42 | if (cp >= barg_buf + BARG_LEN - 1) | ||
| 43 | /* We might issue a warning here. */ | ||
| 44 | break; | ||
| 43 | } | 45 | } |
| 44 | *cp = 0; | 46 | *cp = 0; |
| 45 | break; | 47 | break; |
diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c index 92204c3800b5..bd1b2a3ac34e 100644 --- a/arch/sparc/prom/tree_64.c +++ b/arch/sparc/prom/tree_64.c | |||
| @@ -39,7 +39,7 @@ inline phandle __prom_getchild(phandle node) | |||
| 39 | return prom_node_to_node("child", node); | 39 | return prom_node_to_node("child", node); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | inline phandle prom_getchild(phandle node) | 42 | phandle prom_getchild(phandle node) |
| 43 | { | 43 | { |
| 44 | phandle cnode; | 44 | phandle cnode; |
| 45 | 45 | ||
| @@ -72,7 +72,7 @@ inline phandle __prom_getsibling(phandle node) | |||
| 72 | return prom_node_to_node(prom_peer_name, node); | 72 | return prom_node_to_node(prom_peer_name, node); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | inline phandle prom_getsibling(phandle node) | 75 | phandle prom_getsibling(phandle node) |
| 76 | { | 76 | { |
| 77 | phandle sibnode; | 77 | phandle sibnode; |
| 78 | 78 | ||
| @@ -89,7 +89,7 @@ EXPORT_SYMBOL(prom_getsibling); | |||
| 89 | /* Return the length in bytes of property 'prop' at node 'node'. | 89 | /* Return the length in bytes of property 'prop' at node 'node'. |
| 90 | * Return -1 on error. | 90 | * Return -1 on error. |
| 91 | */ | 91 | */ |
| 92 | inline int prom_getproplen(phandle node, const char *prop) | 92 | int prom_getproplen(phandle node, const char *prop) |
| 93 | { | 93 | { |
| 94 | unsigned long args[6]; | 94 | unsigned long args[6]; |
| 95 | 95 | ||
| @@ -113,8 +113,8 @@ EXPORT_SYMBOL(prom_getproplen); | |||
| 113 | * 'buffer' which has a size of 'bufsize'. If the acquisition | 113 | * 'buffer' which has a size of 'bufsize'. If the acquisition |
| 114 | * was successful the length will be returned, else -1 is returned. | 114 | * was successful the length will be returned, else -1 is returned. |
| 115 | */ | 115 | */ |
| 116 | inline int prom_getproperty(phandle node, const char *prop, | 116 | int prom_getproperty(phandle node, const char *prop, |
| 117 | char *buffer, int bufsize) | 117 | char *buffer, int bufsize) |
| 118 | { | 118 | { |
| 119 | unsigned long args[8]; | 119 | unsigned long args[8]; |
| 120 | int plen; | 120 | int plen; |
| @@ -141,7 +141,7 @@ EXPORT_SYMBOL(prom_getproperty); | |||
| 141 | /* Acquire an integer property and return its value. Returns -1 | 141 | /* Acquire an integer property and return its value. Returns -1 |
| 142 | * on failure. | 142 | * on failure. |
| 143 | */ | 143 | */ |
| 144 | inline int prom_getint(phandle node, const char *prop) | 144 | int prom_getint(phandle node, const char *prop) |
| 145 | { | 145 | { |
| 146 | int intprop; | 146 | int intprop; |
| 147 | 147 | ||
| @@ -235,7 +235,7 @@ static const char *prom_nextprop_name = "nextprop"; | |||
| 235 | /* Return the first property type for node 'node'. | 235 | /* Return the first property type for node 'node'. |
| 236 | * buffer should be at least 32B in length | 236 | * buffer should be at least 32B in length |
| 237 | */ | 237 | */ |
| 238 | inline char *prom_firstprop(phandle node, char *buffer) | 238 | char *prom_firstprop(phandle node, char *buffer) |
| 239 | { | 239 | { |
| 240 | unsigned long args[7]; | 240 | unsigned long args[7]; |
| 241 | 241 | ||
| @@ -261,7 +261,7 @@ EXPORT_SYMBOL(prom_firstprop); | |||
| 261 | * at node 'node' . Returns NULL string if no more | 261 | * at node 'node' . Returns NULL string if no more |
| 262 | * property types for this node. | 262 | * property types for this node. |
| 263 | */ | 263 | */ |
| 264 | inline char *prom_nextprop(phandle node, const char *oprop, char *buffer) | 264 | char *prom_nextprop(phandle node, const char *oprop, char *buffer) |
| 265 | { | 265 | { |
| 266 | unsigned long args[7]; | 266 | unsigned long args[7]; |
| 267 | char buf[32]; | 267 | char buf[32]; |
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c index 4385cb6fa00a..a93b02a25222 100644 --- a/arch/tile/lib/exports.c +++ b/arch/tile/lib/exports.c | |||
| @@ -84,4 +84,6 @@ uint64_t __ashrdi3(uint64_t, unsigned int); | |||
| 84 | EXPORT_SYMBOL(__ashrdi3); | 84 | EXPORT_SYMBOL(__ashrdi3); |
| 85 | uint64_t __ashldi3(uint64_t, unsigned int); | 85 | uint64_t __ashldi3(uint64_t, unsigned int); |
| 86 | EXPORT_SYMBOL(__ashldi3); | 86 | EXPORT_SYMBOL(__ashldi3); |
| 87 | int __ffsdi2(uint64_t); | ||
| 88 | EXPORT_SYMBOL(__ffsdi2); | ||
| 87 | #endif | 89 | #endif |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d7d21851e60c..3df3bd544492 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -147,7 +147,7 @@ void mconsole_proc(struct mc_request *req) | |||
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | do { | 149 | do { |
| 150 | loff_t pos; | 150 | loff_t pos = file->f_pos; |
| 151 | mm_segment_t old_fs = get_fs(); | 151 | mm_segment_t old_fs = get_fs(); |
| 152 | set_fs(KERNEL_DS); | 152 | set_fs(KERNEL_DS); |
| 153 | len = vfs_read(file, buf, PAGE_SIZE - 1, &pos); | 153 | len = vfs_read(file, buf, PAGE_SIZE - 1, &pos); |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 685692c94f05..fe120da25625 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -2265,6 +2265,7 @@ source "fs/Kconfig.binfmt" | |||
| 2265 | config IA32_EMULATION | 2265 | config IA32_EMULATION |
| 2266 | bool "IA32 Emulation" | 2266 | bool "IA32 Emulation" |
| 2267 | depends on X86_64 | 2267 | depends on X86_64 |
| 2268 | select BINFMT_ELF | ||
| 2268 | select COMPAT_BINFMT_ELF | 2269 | select COMPAT_BINFMT_ELF |
| 2269 | select HAVE_UID16 | 2270 | select HAVE_UID16 |
| 2270 | ---help--- | 2271 | ---help--- |
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index 62fe22cd4cba..477e9d75149b 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S | |||
| @@ -2681,56 +2681,68 @@ ENTRY(aesni_xts_crypt8) | |||
| 2681 | addq %rcx, KEYP | 2681 | addq %rcx, KEYP |
| 2682 | 2682 | ||
| 2683 | movdqa IV, STATE1 | 2683 | movdqa IV, STATE1 |
| 2684 | pxor 0x00(INP), STATE1 | 2684 | movdqu 0x00(INP), INC |
| 2685 | pxor INC, STATE1 | ||
| 2685 | movdqu IV, 0x00(OUTP) | 2686 | movdqu IV, 0x00(OUTP) |
| 2686 | 2687 | ||
| 2687 | _aesni_gf128mul_x_ble() | 2688 | _aesni_gf128mul_x_ble() |
| 2688 | movdqa IV, STATE2 | 2689 | movdqa IV, STATE2 |
| 2689 | pxor 0x10(INP), STATE2 | 2690 | movdqu 0x10(INP), INC |
| 2691 | pxor INC, STATE2 | ||
| 2690 | movdqu IV, 0x10(OUTP) | 2692 | movdqu IV, 0x10(OUTP) |
| 2691 | 2693 | ||
| 2692 | _aesni_gf128mul_x_ble() | 2694 | _aesni_gf128mul_x_ble() |
| 2693 | movdqa IV, STATE3 | 2695 | movdqa IV, STATE3 |
| 2694 | pxor 0x20(INP), STATE3 | 2696 | movdqu 0x20(INP), INC |
| 2697 | pxor INC, STATE3 | ||
| 2695 | movdqu IV, 0x20(OUTP) | 2698 | movdqu IV, 0x20(OUTP) |
| 2696 | 2699 | ||
| 2697 | _aesni_gf128mul_x_ble() | 2700 | _aesni_gf128mul_x_ble() |
| 2698 | movdqa IV, STATE4 | 2701 | movdqa IV, STATE4 |
| 2699 | pxor 0x30(INP), STATE4 | 2702 | movdqu 0x30(INP), INC |
| 2703 | pxor INC, STATE4 | ||
| 2700 | movdqu IV, 0x30(OUTP) | 2704 | movdqu IV, 0x30(OUTP) |
| 2701 | 2705 | ||
| 2702 | call *%r11 | 2706 | call *%r11 |
| 2703 | 2707 | ||
| 2704 | pxor 0x00(OUTP), STATE1 | 2708 | movdqu 0x00(OUTP), INC |
| 2709 | pxor INC, STATE1 | ||
| 2705 | movdqu STATE1, 0x00(OUTP) | 2710 | movdqu STATE1, 0x00(OUTP) |
| 2706 | 2711 | ||
| 2707 | _aesni_gf128mul_x_ble() | 2712 | _aesni_gf128mul_x_ble() |
| 2708 | movdqa IV, STATE1 | 2713 | movdqa IV, STATE1 |
| 2709 | pxor 0x40(INP), STATE1 | 2714 | movdqu 0x40(INP), INC |
| 2715 | pxor INC, STATE1 | ||
| 2710 | movdqu IV, 0x40(OUTP) | 2716 | movdqu IV, 0x40(OUTP) |
| 2711 | 2717 | ||
| 2712 | pxor 0x10(OUTP), STATE2 | 2718 | movdqu 0x10(OUTP), INC |
| 2719 | pxor INC, STATE2 | ||
| 2713 | movdqu STATE2, 0x10(OUTP) | 2720 | movdqu STATE2, 0x10(OUTP) |
| 2714 | 2721 | ||
| 2715 | _aesni_gf128mul_x_ble() | 2722 | _aesni_gf128mul_x_ble() |
| 2716 | movdqa IV, STATE2 | 2723 | movdqa IV, STATE2 |
| 2717 | pxor 0x50(INP), STATE2 | 2724 | movdqu 0x50(INP), INC |
| 2725 | pxor INC, STATE2 | ||
| 2718 | movdqu IV, 0x50(OUTP) | 2726 | movdqu IV, 0x50(OUTP) |
| 2719 | 2727 | ||
| 2720 | pxor 0x20(OUTP), STATE3 | 2728 | movdqu 0x20(OUTP), INC |
| 2729 | pxor INC, STATE3 | ||
| 2721 | movdqu STATE3, 0x20(OUTP) | 2730 | movdqu STATE3, 0x20(OUTP) |
| 2722 | 2731 | ||
| 2723 | _aesni_gf128mul_x_ble() | 2732 | _aesni_gf128mul_x_ble() |
| 2724 | movdqa IV, STATE3 | 2733 | movdqa IV, STATE3 |
| 2725 | pxor 0x60(INP), STATE3 | 2734 | movdqu 0x60(INP), INC |
| 2735 | pxor INC, STATE3 | ||
| 2726 | movdqu IV, 0x60(OUTP) | 2736 | movdqu IV, 0x60(OUTP) |
| 2727 | 2737 | ||
| 2728 | pxor 0x30(OUTP), STATE4 | 2738 | movdqu 0x30(OUTP), INC |
| 2739 | pxor INC, STATE4 | ||
| 2729 | movdqu STATE4, 0x30(OUTP) | 2740 | movdqu STATE4, 0x30(OUTP) |
| 2730 | 2741 | ||
| 2731 | _aesni_gf128mul_x_ble() | 2742 | _aesni_gf128mul_x_ble() |
| 2732 | movdqa IV, STATE4 | 2743 | movdqa IV, STATE4 |
| 2733 | pxor 0x70(INP), STATE4 | 2744 | movdqu 0x70(INP), INC |
| 2745 | pxor INC, STATE4 | ||
| 2734 | movdqu IV, 0x70(OUTP) | 2746 | movdqu IV, 0x70(OUTP) |
| 2735 | 2747 | ||
| 2736 | _aesni_gf128mul_x_ble() | 2748 | _aesni_gf128mul_x_ble() |
| @@ -2738,16 +2750,20 @@ ENTRY(aesni_xts_crypt8) | |||
| 2738 | 2750 | ||
| 2739 | call *%r11 | 2751 | call *%r11 |
| 2740 | 2752 | ||
| 2741 | pxor 0x40(OUTP), STATE1 | 2753 | movdqu 0x40(OUTP), INC |
| 2754 | pxor INC, STATE1 | ||
| 2742 | movdqu STATE1, 0x40(OUTP) | 2755 | movdqu STATE1, 0x40(OUTP) |
| 2743 | 2756 | ||
| 2744 | pxor 0x50(OUTP), STATE2 | 2757 | movdqu 0x50(OUTP), INC |
| 2758 | pxor INC, STATE2 | ||
| 2745 | movdqu STATE2, 0x50(OUTP) | 2759 | movdqu STATE2, 0x50(OUTP) |
| 2746 | 2760 | ||
| 2747 | pxor 0x60(OUTP), STATE3 | 2761 | movdqu 0x60(OUTP), INC |
| 2762 | pxor INC, STATE3 | ||
| 2748 | movdqu STATE3, 0x60(OUTP) | 2763 | movdqu STATE3, 0x60(OUTP) |
| 2749 | 2764 | ||
| 2750 | pxor 0x70(OUTP), STATE4 | 2765 | movdqu 0x70(OUTP), INC |
| 2766 | pxor INC, STATE4 | ||
| 2751 | movdqu STATE4, 0x70(OUTP) | 2767 | movdqu STATE4, 0x70(OUTP) |
| 2752 | 2768 | ||
| 2753 | ret | 2769 | ret |
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 805078e08013..52ff81cce008 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
| @@ -192,7 +192,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | |||
| 192 | /* struct user */ | 192 | /* struct user */ |
| 193 | DUMP_WRITE(&dump, sizeof(dump)); | 193 | DUMP_WRITE(&dump, sizeof(dump)); |
| 194 | /* Now dump all of the user data. Include malloced stuff as well */ | 194 | /* Now dump all of the user data. Include malloced stuff as well */ |
| 195 | DUMP_SEEK(PAGE_SIZE); | 195 | DUMP_SEEK(PAGE_SIZE - sizeof(dump)); |
| 196 | /* now we start writing out the user space info */ | 196 | /* now we start writing out the user space info */ |
| 197 | set_fs(USER_DS); | 197 | set_fs(USER_DS); |
| 198 | /* Dump the data area */ | 198 | /* Dump the data area */ |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index ba870bb6dd8e..57873beb3292 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
| @@ -41,4 +41,9 @@ extern int vector_used_by_percpu_irq(unsigned int vector); | |||
| 41 | 41 | ||
| 42 | extern void init_ISA_irqs(void); | 42 | extern void init_ISA_irqs(void); |
| 43 | 43 | ||
| 44 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 45 | void arch_trigger_all_cpu_backtrace(void); | ||
| 46 | #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace | ||
| 47 | #endif | ||
| 48 | |||
| 44 | #endif /* _ASM_X86_IRQ_H */ | 49 | #endif /* _ASM_X86_IRQ_H */ |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 6825e2efd1b4..6bc3985ee473 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
| @@ -60,11 +60,11 @@ static inline void __exit exit_amd_microcode(void) {} | |||
| 60 | #ifdef CONFIG_MICROCODE_EARLY | 60 | #ifdef CONFIG_MICROCODE_EARLY |
| 61 | #define MAX_UCODE_COUNT 128 | 61 | #define MAX_UCODE_COUNT 128 |
| 62 | extern void __init load_ucode_bsp(void); | 62 | extern void __init load_ucode_bsp(void); |
| 63 | extern __init void load_ucode_ap(void); | 63 | extern void __cpuinit load_ucode_ap(void); |
| 64 | extern int __init save_microcode_in_initrd(void); | 64 | extern int __init save_microcode_in_initrd(void); |
| 65 | #else | 65 | #else |
| 66 | static inline void __init load_ucode_bsp(void) {} | 66 | static inline void __init load_ucode_bsp(void) {} |
| 67 | static inline __init void load_ucode_ap(void) {} | 67 | static inline void __cpuinit load_ucode_ap(void) {} |
| 68 | static inline int __init save_microcode_in_initrd(void) | 68 | static inline int __init save_microcode_in_initrd(void) |
| 69 | { | 69 | { |
| 70 | return 0; | 70 | return 0; |
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index c0fa356e90de..86f9301903c8 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h | |||
| @@ -18,9 +18,7 @@ extern int proc_nmi_enabled(struct ctl_table *, int , | |||
| 18 | void __user *, size_t *, loff_t *); | 18 | void __user *, size_t *, loff_t *); |
| 19 | extern int unknown_nmi_panic; | 19 | extern int unknown_nmi_panic; |
| 20 | 20 | ||
| 21 | void arch_trigger_all_cpu_backtrace(void); | 21 | #endif /* CONFIG_X86_LOCAL_APIC */ |
| 22 | #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace | ||
| 23 | #endif | ||
| 24 | 22 | ||
| 25 | #define NMI_FLAG_FIRST 1 | 23 | #define NMI_FLAG_FIRST 1 |
| 26 | 24 | ||
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index 31cb9ae992b7..a698d7165c96 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * | 9 | * |
| 10 | */ | 10 | */ |
| 11 | #include <asm/apic.h> | 11 | #include <asm/apic.h> |
| 12 | #include <asm/nmi.h> | ||
| 12 | 13 | ||
| 13 | #include <linux/cpumask.h> | 14 | #include <linux/cpumask.h> |
| 14 | #include <linux/kdebug.h> | 15 | #include <linux/kdebug.h> |
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 35ffda5d0727..5f90b85ff22e 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c | |||
| @@ -714,15 +714,15 @@ int __init mtrr_cleanup(unsigned address_bits) | |||
| 714 | if (mtrr_tom2) | 714 | if (mtrr_tom2) |
| 715 | x_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - x_remove_base; | 715 | x_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - x_remove_base; |
| 716 | 716 | ||
| 717 | nr_range = x86_get_mtrr_mem_range(range, 0, x_remove_base, x_remove_size); | ||
| 718 | /* | 717 | /* |
| 719 | * [0, 1M) should always be covered by var mtrr with WB | 718 | * [0, 1M) should always be covered by var mtrr with WB |
| 720 | * and fixed mtrrs should take effect before var mtrr for it: | 719 | * and fixed mtrrs should take effect before var mtrr for it: |
| 721 | */ | 720 | */ |
| 722 | nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0, | 721 | nr_range = add_range_with_merge(range, RANGE_NUM, 0, 0, |
| 723 | 1ULL<<(20 - PAGE_SHIFT)); | 722 | 1ULL<<(20 - PAGE_SHIFT)); |
| 724 | /* Sort the ranges: */ | 723 | /* add from var mtrr at last */ |
| 725 | sort_range(range, nr_range); | 724 | nr_range = x86_get_mtrr_mem_range(range, nr_range, |
| 725 | x_remove_base, x_remove_size); | ||
| 726 | 726 | ||
| 727 | range_sums = sum_ranges(range, nr_range); | 727 | range_sums = sum_ranges(range, nr_range); |
| 728 | printk(KERN_INFO "total RAM covered: %ldM\n", | 728 | printk(KERN_INFO "total RAM covered: %ldM\n", |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index f60d41ff9a97..a9e22073bd56 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
| @@ -165,13 +165,13 @@ static struct extra_reg intel_snb_extra_regs[] __read_mostly = { | |||
| 165 | INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0), | 165 | INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0), |
| 166 | INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1), | 166 | INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1), |
| 167 | INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd), | 167 | INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd), |
| 168 | INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd), | ||
| 169 | EVENT_EXTRA_END | 168 | EVENT_EXTRA_END |
| 170 | }; | 169 | }; |
| 171 | 170 | ||
| 172 | static struct extra_reg intel_snbep_extra_regs[] __read_mostly = { | 171 | static struct extra_reg intel_snbep_extra_regs[] __read_mostly = { |
| 173 | INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0), | 172 | INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0), |
| 174 | INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1), | 173 | INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1), |
| 174 | INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd), | ||
| 175 | EVENT_EXTRA_END | 175 | EVENT_EXTRA_END |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index d2c381280e3c..3dd37ebd591b 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
| @@ -242,6 +242,7 @@ void __init kvmclock_init(void) | |||
| 242 | if (!mem) | 242 | if (!mem) |
| 243 | return; | 243 | return; |
| 244 | hv_clock = __va(mem); | 244 | hv_clock = __va(mem); |
| 245 | memset(hv_clock, 0, size); | ||
| 245 | 246 | ||
| 246 | if (kvm_register_clock("boot clock")) { | 247 | if (kvm_register_clock("boot clock")) { |
| 247 | hv_clock = NULL; | 248 | hv_clock = NULL; |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 4e7a37ff03ab..81a5f5e8f142 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -277,18 +277,6 @@ void exit_idle(void) | |||
| 277 | } | 277 | } |
| 278 | #endif | 278 | #endif |
| 279 | 279 | ||
| 280 | void arch_cpu_idle_prepare(void) | ||
| 281 | { | ||
| 282 | /* | ||
| 283 | * If we're the non-boot CPU, nothing set the stack canary up | ||
| 284 | * for us. CPU0 already has it initialized but no harm in | ||
| 285 | * doing it again. This is a good place for updating it, as | ||
| 286 | * we wont ever return from this function (so the invalid | ||
| 287 | * canaries already on the stack wont ever trigger). | ||
| 288 | */ | ||
| 289 | boot_init_stack_canary(); | ||
| 290 | } | ||
| 291 | |||
| 292 | void arch_cpu_idle_enter(void) | 280 | void arch_cpu_idle_enter(void) |
| 293 | { | 281 | { |
| 294 | local_touch_nmi(); | 282 | local_touch_nmi(); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 9c73b51817e4..bfd348e99369 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -372,15 +372,15 @@ static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) | |||
| 372 | 372 | ||
| 373 | void __cpuinit set_cpu_sibling_map(int cpu) | 373 | void __cpuinit set_cpu_sibling_map(int cpu) |
| 374 | { | 374 | { |
| 375 | bool has_mc = boot_cpu_data.x86_max_cores > 1; | ||
| 376 | bool has_smt = smp_num_siblings > 1; | 375 | bool has_smt = smp_num_siblings > 1; |
| 376 | bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1; | ||
| 377 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 377 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 378 | struct cpuinfo_x86 *o; | 378 | struct cpuinfo_x86 *o; |
| 379 | int i; | 379 | int i; |
| 380 | 380 | ||
| 381 | cpumask_set_cpu(cpu, cpu_sibling_setup_mask); | 381 | cpumask_set_cpu(cpu, cpu_sibling_setup_mask); |
| 382 | 382 | ||
| 383 | if (!has_smt && !has_mc) { | 383 | if (!has_mp) { |
| 384 | cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); | 384 | cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); |
| 385 | cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu)); | 385 | cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu)); |
| 386 | cpumask_set_cpu(cpu, cpu_core_mask(cpu)); | 386 | cpumask_set_cpu(cpu, cpu_core_mask(cpu)); |
| @@ -394,7 +394,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) | |||
| 394 | if ((i == cpu) || (has_smt && match_smt(c, o))) | 394 | if ((i == cpu) || (has_smt && match_smt(c, o))) |
| 395 | link_mask(sibling, cpu, i); | 395 | link_mask(sibling, cpu, i); |
| 396 | 396 | ||
| 397 | if ((i == cpu) || (has_mc && match_llc(c, o))) | 397 | if ((i == cpu) || (has_mp && match_llc(c, o))) |
| 398 | link_mask(llc_shared, cpu, i); | 398 | link_mask(llc_shared, cpu, i); |
| 399 | 399 | ||
| 400 | } | 400 | } |
| @@ -406,7 +406,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) | |||
| 406 | for_each_cpu(i, cpu_sibling_setup_mask) { | 406 | for_each_cpu(i, cpu_sibling_setup_mask) { |
| 407 | o = &cpu_data(i); | 407 | o = &cpu_data(i); |
| 408 | 408 | ||
| 409 | if ((i == cpu) || (has_mc && match_mc(c, o))) { | 409 | if ((i == cpu) || (has_mp && match_mc(c, o))) { |
| 410 | link_mask(core, cpu, i); | 410 | link_mask(core, cpu, i); |
| 411 | 411 | ||
| 412 | /* | 412 | /* |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 094b5d96ab14..e8ba99c34180 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -582,8 +582,6 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) | |||
| 582 | if (index != XCR_XFEATURE_ENABLED_MASK) | 582 | if (index != XCR_XFEATURE_ENABLED_MASK) |
| 583 | return 1; | 583 | return 1; |
| 584 | xcr0 = xcr; | 584 | xcr0 = xcr; |
| 585 | if (kvm_x86_ops->get_cpl(vcpu) != 0) | ||
| 586 | return 1; | ||
| 587 | if (!(xcr0 & XSTATE_FP)) | 585 | if (!(xcr0 & XSTATE_FP)) |
| 588 | return 1; | 586 | return 1; |
| 589 | if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE)) | 587 | if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE)) |
| @@ -597,7 +595,8 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) | |||
| 597 | 595 | ||
| 598 | int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) | 596 | int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) |
| 599 | { | 597 | { |
| 600 | if (__kvm_set_xcr(vcpu, index, xcr)) { | 598 | if (kvm_x86_ops->get_cpl(vcpu) != 0 || |
| 599 | __kvm_set_xcr(vcpu, index, xcr)) { | ||
| 601 | kvm_inject_gp(vcpu, 0); | 600 | kvm_inject_gp(vcpu, 0); |
| 602 | return 1; | 601 | return 1; |
| 603 | } | 602 | } |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 5ae2eb09419e..d2fbcedcf6ea 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
| @@ -1069,7 +1069,10 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | |||
| 1069 | * that by attempting to use more space than is available. | 1069 | * that by attempting to use more space than is available. |
| 1070 | */ | 1070 | */ |
| 1071 | unsigned long dummy_size = remaining_size + 1024; | 1071 | unsigned long dummy_size = remaining_size + 1024; |
| 1072 | void *dummy = kmalloc(dummy_size, GFP_ATOMIC); | 1072 | void *dummy = kzalloc(dummy_size, GFP_ATOMIC); |
| 1073 | |||
| 1074 | if (!dummy) | ||
| 1075 | return EFI_OUT_OF_RESOURCES; | ||
| 1073 | 1076 | ||
| 1074 | status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | 1077 | status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, |
| 1075 | EFI_VARIABLE_NON_VOLATILE | | 1078 | EFI_VARIABLE_NON_VOLATILE | |
| @@ -1089,6 +1092,8 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | |||
| 1089 | 0, dummy); | 1092 | 0, dummy); |
| 1090 | } | 1093 | } |
| 1091 | 1094 | ||
| 1095 | kfree(dummy); | ||
| 1096 | |||
| 1092 | /* | 1097 | /* |
| 1093 | * The runtime code may now have triggered a garbage collection | 1098 | * The runtime code may now have triggered a garbage collection |
| 1094 | * run, so check the variable info again | 1099 | * run, so check the variable info again |
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 652fd5ce303c..cab13f2fc28e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
| @@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
| 164 | if (dev_desc->clk_required) { | 164 | if (dev_desc->clk_required) { |
| 165 | ret = register_device_clock(adev, pdata); | 165 | ret = register_device_clock(adev, pdata); |
| 166 | if (ret) { | 166 | if (ret) { |
| 167 | /* | 167 | /* Skip the device, but continue the namespace scan. */ |
| 168 | * Skip the device, but don't terminate the namespace | 168 | ret = 0; |
| 169 | * scan. | 169 | goto err_out; |
| 170 | */ | ||
| 171 | kfree(pdata); | ||
| 172 | return 0; | ||
| 173 | } | 170 | } |
| 174 | } | 171 | } |
| 175 | 172 | ||
| 173 | /* | ||
| 174 | * This works around a known issue in ACPI tables where LPSS devices | ||
| 175 | * have _PS0 and _PS3 without _PSC (and no power resources), so | ||
| 176 | * acpi_bus_init_power() will assume that the BIOS has put them into D0. | ||
| 177 | */ | ||
| 178 | ret = acpi_device_fix_up_power(adev); | ||
| 179 | if (ret) { | ||
| 180 | /* Skip the device, but continue the namespace scan. */ | ||
| 181 | ret = 0; | ||
| 182 | goto err_out; | ||
| 183 | } | ||
| 184 | |||
| 176 | adev->driver_data = pdata; | 185 | adev->driver_data = pdata; |
| 177 | ret = acpi_create_platform_device(adev, id); | 186 | ret = acpi_create_platform_device(adev, id); |
| 178 | if (ret > 0) | 187 | if (ret > 0) |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 318fa32a141e..31c217a42839 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
| @@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device) | |||
| 290 | return 0; | 290 | return 0; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | /** | ||
| 294 | * acpi_device_fix_up_power - Force device with missing _PSC into D0. | ||
| 295 | * @device: Device object whose power state is to be fixed up. | ||
| 296 | * | ||
| 297 | * Devices without power resources and _PSC, but having _PS0 and _PS3 defined, | ||
| 298 | * are assumed to be put into D0 by the BIOS. However, in some cases that may | ||
| 299 | * not be the case and this function should be used then. | ||
| 300 | */ | ||
| 301 | int acpi_device_fix_up_power(struct acpi_device *device) | ||
| 302 | { | ||
| 303 | int ret = 0; | ||
| 304 | |||
| 305 | if (!device->power.flags.power_resources | ||
| 306 | && !device->power.flags.explicit_get | ||
| 307 | && device->power.state == ACPI_STATE_D0) | ||
| 308 | ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0); | ||
| 309 | |||
| 310 | return ret; | ||
| 311 | } | ||
| 312 | |||
| 293 | int acpi_bus_update_power(acpi_handle handle, int *state_p) | 313 | int acpi_bus_update_power(acpi_handle handle, int *state_p) |
| 294 | { | 314 | { |
| 295 | struct acpi_device *device; | 315 | struct acpi_device *device; |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4fdea381ef21..ec117c6c996c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -868,8 +868,10 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | |||
| 868 | if (!count) | 868 | if (!count) |
| 869 | return -EINVAL; | 869 | return -EINVAL; |
| 870 | 870 | ||
| 871 | acpi_scan_lock_acquire(); | ||
| 871 | begin_undock(dock_station); | 872 | begin_undock(dock_station); |
| 872 | ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); | 873 | ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); |
| 874 | acpi_scan_lock_release(); | ||
| 873 | return ret ? ret: count; | 875 | return ret ? ret: count; |
| 874 | } | 876 | } |
| 875 | static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); | 877 | static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index f962047c6c85..288bb270f8ed 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -885,6 +885,7 @@ int acpi_add_power_resource(acpi_handle handle) | |||
| 885 | ACPI_STA_DEFAULT); | 885 | ACPI_STA_DEFAULT); |
| 886 | mutex_init(&resource->resource_lock); | 886 | mutex_init(&resource->resource_lock); |
| 887 | INIT_LIST_HEAD(&resource->dependent); | 887 | INIT_LIST_HEAD(&resource->dependent); |
| 888 | INIT_LIST_HEAD(&resource->list_node); | ||
| 888 | resource->name = device->pnp.bus_id; | 889 | resource->name = device->pnp.bus_id; |
| 889 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 890 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
| 890 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 891 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index a3868f6c222a..3322b47ab7ca 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
| @@ -304,7 +304,8 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) | |||
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | 306 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, |
| 307 | u8 triggering, u8 polarity, u8 shareable) | 307 | u8 triggering, u8 polarity, u8 shareable, |
| 308 | bool legacy) | ||
| 308 | { | 309 | { |
| 309 | int irq, p, t; | 310 | int irq, p, t; |
| 310 | 311 | ||
| @@ -317,14 +318,19 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | |||
| 317 | * In IO-APIC mode, use overrided attribute. Two reasons: | 318 | * In IO-APIC mode, use overrided attribute. Two reasons: |
| 318 | * 1. BIOS bug in DSDT | 319 | * 1. BIOS bug in DSDT |
| 319 | * 2. BIOS uses IO-APIC mode Interrupt Source Override | 320 | * 2. BIOS uses IO-APIC mode Interrupt Source Override |
| 321 | * | ||
| 322 | * We do this only if we are dealing with IRQ() or IRQNoFlags() | ||
| 323 | * resource (the legacy ISA resources). With modern ACPI 5 devices | ||
| 324 | * using extended IRQ descriptors we take the IRQ configuration | ||
| 325 | * from _CRS directly. | ||
| 320 | */ | 326 | */ |
| 321 | if (!acpi_get_override_irq(gsi, &t, &p)) { | 327 | if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { |
| 322 | u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | 328 | u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; |
| 323 | u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | 329 | u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; |
| 324 | 330 | ||
| 325 | if (triggering != trig || polarity != pol) { | 331 | if (triggering != trig || polarity != pol) { |
| 326 | pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, | 332 | pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, |
| 327 | t ? "edge" : "level", p ? "low" : "high"); | 333 | t ? "level" : "edge", p ? "low" : "high"); |
| 328 | triggering = trig; | 334 | triggering = trig; |
| 329 | polarity = pol; | 335 | polarity = pol; |
| 330 | } | 336 | } |
| @@ -373,7 +379,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | |||
| 373 | } | 379 | } |
| 374 | acpi_dev_get_irqresource(res, irq->interrupts[index], | 380 | acpi_dev_get_irqresource(res, irq->interrupts[index], |
| 375 | irq->triggering, irq->polarity, | 381 | irq->triggering, irq->polarity, |
| 376 | irq->sharable); | 382 | irq->sharable, true); |
| 377 | break; | 383 | break; |
| 378 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 384 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| 379 | ext_irq = &ares->data.extended_irq; | 385 | ext_irq = &ares->data.extended_irq; |
| @@ -383,7 +389,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | |||
| 383 | } | 389 | } |
| 384 | acpi_dev_get_irqresource(res, ext_irq->interrupts[index], | 390 | acpi_dev_get_irqresource(res, ext_irq->interrupts[index], |
| 385 | ext_irq->triggering, ext_irq->polarity, | 391 | ext_irq->triggering, ext_irq->polarity, |
| 386 | ext_irq->sharable); | 392 | ext_irq->sharable, false); |
| 387 | break; | 393 | break; |
| 388 | default: | 394 | default: |
| 389 | return false; | 395 | return false; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 4b1f9265887f..01e21037d8fe 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -450,8 +450,18 @@ static void fw_load_abort(struct firmware_priv *fw_priv) | |||
| 450 | { | 450 | { |
| 451 | struct firmware_buf *buf = fw_priv->buf; | 451 | struct firmware_buf *buf = fw_priv->buf; |
| 452 | 452 | ||
| 453 | /* | ||
| 454 | * There is a small window in which user can write to 'loading' | ||
| 455 | * between loading done and disappearance of 'loading' | ||
| 456 | */ | ||
| 457 | if (test_bit(FW_STATUS_DONE, &buf->status)) | ||
| 458 | return; | ||
| 459 | |||
| 453 | set_bit(FW_STATUS_ABORT, &buf->status); | 460 | set_bit(FW_STATUS_ABORT, &buf->status); |
| 454 | complete_all(&buf->completion); | 461 | complete_all(&buf->completion); |
| 462 | |||
| 463 | /* avoid user action after loading abort */ | ||
| 464 | fw_priv->buf = NULL; | ||
| 455 | } | 465 | } |
| 456 | 466 | ||
| 457 | #define is_fw_load_aborted(buf) \ | 467 | #define is_fw_load_aborted(buf) \ |
| @@ -528,7 +538,12 @@ static ssize_t firmware_loading_show(struct device *dev, | |||
| 528 | struct device_attribute *attr, char *buf) | 538 | struct device_attribute *attr, char *buf) |
| 529 | { | 539 | { |
| 530 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 540 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
| 531 | int loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status); | 541 | int loading = 0; |
| 542 | |||
| 543 | mutex_lock(&fw_lock); | ||
| 544 | if (fw_priv->buf) | ||
| 545 | loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status); | ||
| 546 | mutex_unlock(&fw_lock); | ||
| 532 | 547 | ||
| 533 | return sprintf(buf, "%d\n", loading); | 548 | return sprintf(buf, "%d\n", loading); |
| 534 | } | 549 | } |
| @@ -570,12 +585,12 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
| 570 | const char *buf, size_t count) | 585 | const char *buf, size_t count) |
| 571 | { | 586 | { |
| 572 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 587 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
| 573 | struct firmware_buf *fw_buf = fw_priv->buf; | 588 | struct firmware_buf *fw_buf; |
| 574 | int loading = simple_strtol(buf, NULL, 10); | 589 | int loading = simple_strtol(buf, NULL, 10); |
| 575 | int i; | 590 | int i; |
| 576 | 591 | ||
| 577 | mutex_lock(&fw_lock); | 592 | mutex_lock(&fw_lock); |
| 578 | 593 | fw_buf = fw_priv->buf; | |
| 579 | if (!fw_buf) | 594 | if (!fw_buf) |
| 580 | goto out; | 595 | goto out; |
| 581 | 596 | ||
| @@ -777,10 +792,6 @@ static void firmware_class_timeout_work(struct work_struct *work) | |||
| 777 | struct firmware_priv, timeout_work.work); | 792 | struct firmware_priv, timeout_work.work); |
| 778 | 793 | ||
| 779 | mutex_lock(&fw_lock); | 794 | mutex_lock(&fw_lock); |
| 780 | if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) { | ||
| 781 | mutex_unlock(&fw_lock); | ||
| 782 | return; | ||
| 783 | } | ||
| 784 | fw_load_abort(fw_priv); | 795 | fw_load_abort(fw_priv); |
| 785 | mutex_unlock(&fw_lock); | 796 | mutex_unlock(&fw_lock); |
| 786 | } | 797 | } |
| @@ -861,8 +872,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
| 861 | 872 | ||
| 862 | cancel_delayed_work_sync(&fw_priv->timeout_work); | 873 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
| 863 | 874 | ||
| 864 | fw_priv->buf = NULL; | ||
| 865 | |||
| 866 | device_remove_file(f_dev, &dev_attr_loading); | 875 | device_remove_file(f_dev, &dev_attr_loading); |
| 867 | err_del_bin_attr: | 876 | err_del_bin_attr: |
| 868 | device_remove_bin_file(f_dev, &firmware_attr_data); | 877 | device_remove_bin_file(f_dev, &firmware_attr_data); |
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 3063452e55da..49394e3f31bc 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -1036,12 +1036,16 @@ static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset) | |||
| 1036 | char *name; | 1036 | char *name; |
| 1037 | u64 segment; | 1037 | u64 segment; |
| 1038 | int ret; | 1038 | int ret; |
| 1039 | char *name_format; | ||
| 1039 | 1040 | ||
| 1040 | name = kmem_cache_alloc(rbd_segment_name_cache, GFP_NOIO); | 1041 | name = kmem_cache_alloc(rbd_segment_name_cache, GFP_NOIO); |
| 1041 | if (!name) | 1042 | if (!name) |
| 1042 | return NULL; | 1043 | return NULL; |
| 1043 | segment = offset >> rbd_dev->header.obj_order; | 1044 | segment = offset >> rbd_dev->header.obj_order; |
| 1044 | ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx", | 1045 | name_format = "%s.%012llx"; |
| 1046 | if (rbd_dev->image_format == 2) | ||
| 1047 | name_format = "%s.%016llx"; | ||
| 1048 | ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, name_format, | ||
| 1045 | rbd_dev->header.object_prefix, segment); | 1049 | rbd_dev->header.object_prefix, segment); |
| 1046 | if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { | 1050 | if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { |
| 1047 | pr_err("error formatting segment name for #%llu (%d)\n", | 1051 | pr_err("error formatting segment name for #%llu (%d)\n", |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 934cfd18f72d..1144e8c7579d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -1955,6 +1955,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
| 1955 | /* XXX the notifier code should handle this better */ | 1955 | /* XXX the notifier code should handle this better */ |
| 1956 | if (!cn->notifier_head.head) { | 1956 | if (!cn->notifier_head.head) { |
| 1957 | srcu_cleanup_notifier_head(&cn->notifier_head); | 1957 | srcu_cleanup_notifier_head(&cn->notifier_head); |
| 1958 | list_del(&cn->node); | ||
| 1958 | kfree(cn); | 1959 | kfree(cn); |
| 1959 | } | 1960 | } |
| 1960 | 1961 | ||
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 5c97e75924a8..22d7699e7ced 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c | |||
| @@ -155,7 +155,7 @@ static __initdata unsigned long exynos5250_clk_regs[] = { | |||
| 155 | 155 | ||
| 156 | /* list of all parent clock list */ | 156 | /* list of all parent clock list */ |
| 157 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; | 157 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; |
| 158 | PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", }; | 158 | PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", }; |
| 159 | PNAME(mout_mpll_fout_p) = { "fout_mplldiv2", "fout_mpll" }; | 159 | PNAME(mout_mpll_fout_p) = { "fout_mplldiv2", "fout_mpll" }; |
| 160 | PNAME(mout_mpll_p) = { "fin_pll", "mout_mpll_fout" }; | 160 | PNAME(mout_mpll_p) = { "fin_pll", "mout_mpll_fout" }; |
| 161 | PNAME(mout_bpll_fout_p) = { "fout_bplldiv2", "fout_bpll" }; | 161 | PNAME(mout_bpll_fout_p) = { "fout_bplldiv2", "fout_bpll" }; |
| @@ -208,10 +208,10 @@ struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = { | |||
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { | 210 | struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { |
| 211 | MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1), | 211 | MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"), |
| 212 | MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), | 212 | MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"), |
| 213 | MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1), | 213 | MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1), |
| 214 | MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1), | 214 | MUX_A(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"), |
| 215 | MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1), | 215 | MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1), |
| 216 | MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1), | 216 | MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1), |
| 217 | MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1), | 217 | MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1), |
| @@ -378,7 +378,7 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { | |||
| 378 | GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0), | 378 | GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0), |
| 379 | GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0), | 379 | GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0), |
| 380 | GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0), | 380 | GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0), |
| 381 | GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, 0, 0), | 381 | GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0), |
| 382 | GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0), | 382 | GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0), |
| 383 | GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0), | 383 | GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0), |
| 384 | GATE(tzpc2, "tzpc2", "aclk66", GATE_IP_PERIS, 8, 0, 0), | 384 | GATE(tzpc2, "tzpc2", "aclk66", GATE_IP_PERIS, 8, 0, 0), |
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 89135f6be116..362f12dcd944 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c | |||
| @@ -111,7 +111,8 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, | |||
| 111 | unsigned long parent_rate) | 111 | unsigned long parent_rate) |
| 112 | { | 112 | { |
| 113 | struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw); | 113 | struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw); |
| 114 | u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; | 114 | u32 mdiv, pdiv, sdiv, pll_con0, pll_con1; |
| 115 | s16 kdiv; | ||
| 115 | u64 fvco = parent_rate; | 116 | u64 fvco = parent_rate; |
| 116 | 117 | ||
| 117 | pll_con0 = __raw_readl(pll->con_reg); | 118 | pll_con0 = __raw_readl(pll->con_reg); |
| @@ -119,7 +120,7 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, | |||
| 119 | mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; | 120 | mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; |
| 120 | pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; | 121 | pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; |
| 121 | sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK; | 122 | sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK; |
| 122 | kdiv = pll_con1 & PLL36XX_KDIV_MASK; | 123 | kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK); |
| 123 | 124 | ||
| 124 | fvco *= (mdiv << 16) + kdiv; | 125 | fvco *= (mdiv << 16) + kdiv; |
| 125 | do_div(fvco, (pdiv << sdiv)); | 126 | do_div(fvco, (pdiv << sdiv)); |
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c index f9ec43fd1320..080c3c5e33f6 100644 --- a/drivers/clk/spear/spear3xx_clock.c +++ b/drivers/clk/spear/spear3xx_clock.c | |||
| @@ -369,7 +369,7 @@ static void __init spear320_clk_init(void __iomem *soc_config_base) | |||
| 369 | clk_register_clkdev(clk, NULL, "60100000.serial"); | 369 | clk_register_clkdev(clk, NULL, "60100000.serial"); |
| 370 | } | 370 | } |
| 371 | #else | 371 | #else |
| 372 | static inline void spear320_clk_init(void) { } | 372 | static inline void spear320_clk_init(void __iomem *soc_config_base) { } |
| 373 | #endif | 373 | #endif |
| 374 | 374 | ||
| 375 | void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_base) | 375 | void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_base) |
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index c6921f538e28..ba99e3844106 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c | |||
| @@ -1598,6 +1598,12 @@ static void __init tegra30_periph_clk_init(void) | |||
| 1598 | clk_register_clkdev(clk, "afi", "tegra-pcie"); | 1598 | clk_register_clkdev(clk, "afi", "tegra-pcie"); |
| 1599 | clks[afi] = clk; | 1599 | clks[afi] = clk; |
| 1600 | 1600 | ||
| 1601 | /* pciex */ | ||
| 1602 | clk = tegra_clk_register_periph_gate("pciex", "pll_e", 0, clk_base, 0, | ||
| 1603 | 74, &periph_u_regs, periph_clk_enb_refcnt); | ||
| 1604 | clk_register_clkdev(clk, "pciex", "tegra-pcie"); | ||
| 1605 | clks[pciex] = clk; | ||
| 1606 | |||
| 1601 | /* kfuse */ | 1607 | /* kfuse */ |
| 1602 | clk = tegra_clk_register_periph_gate("kfuse", "clk_m", | 1608 | clk = tegra_clk_register_periph_gate("kfuse", "clk_m", |
| 1603 | TEGRA_PERIPH_ON_APB, | 1609 | TEGRA_PERIPH_ON_APB, |
| @@ -1716,11 +1722,6 @@ static void __init tegra30_fixed_clk_init(void) | |||
| 1716 | 1, 0, &cml_lock); | 1722 | 1, 0, &cml_lock); |
| 1717 | clk_register_clkdev(clk, "cml1", NULL); | 1723 | clk_register_clkdev(clk, "cml1", NULL); |
| 1718 | clks[cml1] = clk; | 1724 | clks[cml1] = clk; |
| 1719 | |||
| 1720 | /* pciex */ | ||
| 1721 | clk = clk_register_fixed_rate(NULL, "pciex", "pll_e", 0, 100000000); | ||
| 1722 | clk_register_clkdev(clk, "pciex", NULL); | ||
| 1723 | clks[pciex] = clk; | ||
| 1724 | } | 1725 | } |
| 1725 | 1726 | ||
| 1726 | static void __init tegra30_osc_clk_init(void) | 1727 | static void __init tegra30_osc_clk_init(void) |
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index dcde35231e25..5b7b9110254b 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
| @@ -190,8 +190,7 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev, | |||
| 190 | if (ret) | 190 | if (ret) |
| 191 | return ERR_PTR(ret); | 191 | return ERR_PTR(ret); |
| 192 | } | 192 | } |
| 193 | return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, | 193 | return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags); |
| 194 | 0600); | ||
| 195 | } | 194 | } |
| 196 | EXPORT_SYMBOL(drm_gem_prime_export); | 195 | EXPORT_SYMBOL(drm_gem_prime_export); |
| 197 | 196 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0e5341695922..6948eb88c2b7 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -2687,6 +2687,9 @@ void r600_uvd_rbc_stop(struct radeon_device *rdev) | |||
| 2687 | int r600_uvd_init(struct radeon_device *rdev) | 2687 | int r600_uvd_init(struct radeon_device *rdev) |
| 2688 | { | 2688 | { |
| 2689 | int i, j, r; | 2689 | int i, j, r; |
| 2690 | /* disable byte swapping */ | ||
| 2691 | u32 lmi_swap_cntl = 0; | ||
| 2692 | u32 mp_swap_cntl = 0; | ||
| 2690 | 2693 | ||
| 2691 | /* raise clocks while booting up the VCPU */ | 2694 | /* raise clocks while booting up the VCPU */ |
| 2692 | radeon_set_uvd_clocks(rdev, 53300, 40000); | 2695 | radeon_set_uvd_clocks(rdev, 53300, 40000); |
| @@ -2711,9 +2714,13 @@ int r600_uvd_init(struct radeon_device *rdev) | |||
| 2711 | WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) | | 2714 | WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) | |
| 2712 | (1 << 21) | (1 << 9) | (1 << 20)); | 2715 | (1 << 21) | (1 << 9) | (1 << 20)); |
| 2713 | 2716 | ||
| 2714 | /* disable byte swapping */ | 2717 | #ifdef __BIG_ENDIAN |
| 2715 | WREG32(UVD_LMI_SWAP_CNTL, 0); | 2718 | /* swap (8 in 32) RB and IB */ |
| 2716 | WREG32(UVD_MP_SWAP_CNTL, 0); | 2719 | lmi_swap_cntl = 0xa; |
| 2720 | mp_swap_cntl = 0; | ||
| 2721 | #endif | ||
| 2722 | WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl); | ||
| 2723 | WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl); | ||
| 2717 | 2724 | ||
| 2718 | WREG32(UVD_MPC_SET_MUXA0, 0x40c2040); | 2725 | WREG32(UVD_MPC_SET_MUXA0, 0x40c2040); |
| 2719 | WREG32(UVD_MPC_SET_MUXA1, 0x0); | 2726 | WREG32(UVD_MPC_SET_MUXA1, 0x0); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 189973836cff..b0dc0b6cb4e0 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -244,16 +244,6 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
| 244 | */ | 244 | */ |
| 245 | void radeon_wb_disable(struct radeon_device *rdev) | 245 | void radeon_wb_disable(struct radeon_device *rdev) |
| 246 | { | 246 | { |
| 247 | int r; | ||
| 248 | |||
| 249 | if (rdev->wb.wb_obj) { | ||
| 250 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
| 251 | if (unlikely(r != 0)) | ||
| 252 | return; | ||
| 253 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
| 254 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
| 255 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
| 256 | } | ||
| 257 | rdev->wb.enabled = false; | 247 | rdev->wb.enabled = false; |
| 258 | } | 248 | } |
| 259 | 249 | ||
| @@ -269,6 +259,11 @@ void radeon_wb_fini(struct radeon_device *rdev) | |||
| 269 | { | 259 | { |
| 270 | radeon_wb_disable(rdev); | 260 | radeon_wb_disable(rdev); |
| 271 | if (rdev->wb.wb_obj) { | 261 | if (rdev->wb.wb_obj) { |
| 262 | if (!radeon_bo_reserve(rdev->wb.wb_obj, false)) { | ||
| 263 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
| 264 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
| 265 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
| 266 | } | ||
| 272 | radeon_bo_unref(&rdev->wb.wb_obj); | 267 | radeon_bo_unref(&rdev->wb.wb_obj); |
| 273 | rdev->wb.wb = NULL; | 268 | rdev->wb.wb = NULL; |
| 274 | rdev->wb.wb_obj = NULL; | 269 | rdev->wb.wb_obj = NULL; |
| @@ -295,26 +290,26 @@ int radeon_wb_init(struct radeon_device *rdev) | |||
| 295 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); | 290 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); |
| 296 | return r; | 291 | return r; |
| 297 | } | 292 | } |
| 298 | } | 293 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); |
| 299 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | 294 | if (unlikely(r != 0)) { |
| 300 | if (unlikely(r != 0)) { | 295 | radeon_wb_fini(rdev); |
| 301 | radeon_wb_fini(rdev); | 296 | return r; |
| 302 | return r; | 297 | } |
| 303 | } | 298 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, |
| 304 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, | 299 | &rdev->wb.gpu_addr); |
| 305 | &rdev->wb.gpu_addr); | 300 | if (r) { |
| 306 | if (r) { | 301 | radeon_bo_unreserve(rdev->wb.wb_obj); |
| 302 | dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); | ||
| 303 | radeon_wb_fini(rdev); | ||
| 304 | return r; | ||
| 305 | } | ||
| 306 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
| 307 | radeon_bo_unreserve(rdev->wb.wb_obj); | 307 | radeon_bo_unreserve(rdev->wb.wb_obj); |
| 308 | dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); | 308 | if (r) { |
| 309 | radeon_wb_fini(rdev); | 309 | dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); |
| 310 | return r; | 310 | radeon_wb_fini(rdev); |
| 311 | } | 311 | return r; |
| 312 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | 312 | } |
| 313 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
| 314 | if (r) { | ||
| 315 | dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); | ||
| 316 | radeon_wb_fini(rdev); | ||
| 317 | return r; | ||
| 318 | } | 313 | } |
| 319 | 314 | ||
| 320 | /* clear wb memory */ | 315 | /* clear wb memory */ |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 5b937dfe6f65..ddb8f8e04eb5 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -63,7 +63,9 @@ static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) | |||
| 63 | { | 63 | { |
| 64 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; | 64 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; |
| 65 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { | 65 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 66 | *drv->cpu_addr = cpu_to_le32(seq); | 66 | if (drv->cpu_addr) { |
| 67 | *drv->cpu_addr = cpu_to_le32(seq); | ||
| 68 | } | ||
| 67 | } else { | 69 | } else { |
| 68 | WREG32(drv->scratch_reg, seq); | 70 | WREG32(drv->scratch_reg, seq); |
| 69 | } | 71 | } |
| @@ -84,7 +86,11 @@ static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | |||
| 84 | u32 seq = 0; | 86 | u32 seq = 0; |
| 85 | 87 | ||
| 86 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { | 88 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 87 | seq = le32_to_cpu(*drv->cpu_addr); | 89 | if (drv->cpu_addr) { |
| 90 | seq = le32_to_cpu(*drv->cpu_addr); | ||
| 91 | } else { | ||
| 92 | seq = lower_32_bits(atomic64_read(&drv->last_seq)); | ||
| 93 | } | ||
| 88 | } else { | 94 | } else { |
| 89 | seq = RREG32(drv->scratch_reg); | 95 | seq = RREG32(drv->scratch_reg); |
| 90 | } | 96 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 2c1341f63dc5..43ec4a401f07 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -1197,11 +1197,13 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, | |||
| 1197 | int radeon_vm_bo_rmv(struct radeon_device *rdev, | 1197 | int radeon_vm_bo_rmv(struct radeon_device *rdev, |
| 1198 | struct radeon_bo_va *bo_va) | 1198 | struct radeon_bo_va *bo_va) |
| 1199 | { | 1199 | { |
| 1200 | int r; | 1200 | int r = 0; |
| 1201 | 1201 | ||
| 1202 | mutex_lock(&rdev->vm_manager.lock); | 1202 | mutex_lock(&rdev->vm_manager.lock); |
| 1203 | mutex_lock(&bo_va->vm->mutex); | 1203 | mutex_lock(&bo_va->vm->mutex); |
| 1204 | r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL); | 1204 | if (bo_va->soffset) { |
| 1205 | r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL); | ||
| 1206 | } | ||
| 1205 | mutex_unlock(&rdev->vm_manager.lock); | 1207 | mutex_unlock(&rdev->vm_manager.lock); |
| 1206 | list_del(&bo_va->vm_list); | 1208 | list_del(&bo_va->vm_list); |
| 1207 | mutex_unlock(&bo_va->vm->mutex); | 1209 | mutex_unlock(&bo_va->vm->mutex); |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index e17faa7cf732..82434018cbe8 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -402,6 +402,13 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
| 402 | return -ENOMEM; | 402 | return -ENOMEM; |
| 403 | /* Align requested size with padding so unlock_commit can | 403 | /* Align requested size with padding so unlock_commit can |
| 404 | * pad safely */ | 404 | * pad safely */ |
| 405 | radeon_ring_free_size(rdev, ring); | ||
| 406 | if (ring->ring_free_dw == (ring->ring_size / 4)) { | ||
| 407 | /* This is an empty ring update lockup info to avoid | ||
| 408 | * false positive. | ||
| 409 | */ | ||
| 410 | radeon_ring_lockup_update(ring); | ||
| 411 | } | ||
| 405 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; | 412 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; |
| 406 | while (ndw > (ring->ring_free_dw - 1)) { | 413 | while (ndw > (ring->ring_free_dw - 1)) { |
| 407 | radeon_ring_free_size(rdev, ring); | 414 | radeon_ring_free_size(rdev, ring); |
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 906e5c0ca3b9..cad735dd02c6 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c | |||
| @@ -159,7 +159,17 @@ int radeon_uvd_suspend(struct radeon_device *rdev) | |||
| 159 | if (!r) { | 159 | if (!r) { |
| 160 | radeon_bo_kunmap(rdev->uvd.vcpu_bo); | 160 | radeon_bo_kunmap(rdev->uvd.vcpu_bo); |
| 161 | radeon_bo_unpin(rdev->uvd.vcpu_bo); | 161 | radeon_bo_unpin(rdev->uvd.vcpu_bo); |
| 162 | rdev->uvd.cpu_addr = NULL; | ||
| 163 | if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) { | ||
| 164 | radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); | ||
| 165 | } | ||
| 162 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); | 166 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); |
| 167 | |||
| 168 | if (rdev->uvd.cpu_addr) { | ||
| 169 | radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); | ||
| 170 | } else { | ||
| 171 | rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL; | ||
| 172 | } | ||
| 163 | } | 173 | } |
| 164 | return r; | 174 | return r; |
| 165 | } | 175 | } |
| @@ -178,6 +188,10 @@ int radeon_uvd_resume(struct radeon_device *rdev) | |||
| 178 | return r; | 188 | return r; |
| 179 | } | 189 | } |
| 180 | 190 | ||
| 191 | /* Have been pin in cpu unmap unpin */ | ||
| 192 | radeon_bo_kunmap(rdev->uvd.vcpu_bo); | ||
| 193 | radeon_bo_unpin(rdev->uvd.vcpu_bo); | ||
| 194 | |||
| 181 | r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, | 195 | r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, |
| 182 | &rdev->uvd.gpu_addr); | 196 | &rdev->uvd.gpu_addr); |
| 183 | if (r) { | 197 | if (r) { |
| @@ -613,19 +627,19 @@ int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring, | |||
| 613 | } | 627 | } |
| 614 | 628 | ||
| 615 | /* stitch together an UVD create msg */ | 629 | /* stitch together an UVD create msg */ |
| 616 | msg[0] = 0x00000de4; | 630 | msg[0] = cpu_to_le32(0x00000de4); |
| 617 | msg[1] = 0x00000000; | 631 | msg[1] = cpu_to_le32(0x00000000); |
| 618 | msg[2] = handle; | 632 | msg[2] = cpu_to_le32(handle); |
| 619 | msg[3] = 0x00000000; | 633 | msg[3] = cpu_to_le32(0x00000000); |
| 620 | msg[4] = 0x00000000; | 634 | msg[4] = cpu_to_le32(0x00000000); |
| 621 | msg[5] = 0x00000000; | 635 | msg[5] = cpu_to_le32(0x00000000); |
| 622 | msg[6] = 0x00000000; | 636 | msg[6] = cpu_to_le32(0x00000000); |
| 623 | msg[7] = 0x00000780; | 637 | msg[7] = cpu_to_le32(0x00000780); |
| 624 | msg[8] = 0x00000440; | 638 | msg[8] = cpu_to_le32(0x00000440); |
| 625 | msg[9] = 0x00000000; | 639 | msg[9] = cpu_to_le32(0x00000000); |
| 626 | msg[10] = 0x01b37000; | 640 | msg[10] = cpu_to_le32(0x01b37000); |
| 627 | for (i = 11; i < 1024; ++i) | 641 | for (i = 11; i < 1024; ++i) |
| 628 | msg[i] = 0x0; | 642 | msg[i] = cpu_to_le32(0x0); |
| 629 | 643 | ||
| 630 | radeon_bo_kunmap(bo); | 644 | radeon_bo_kunmap(bo); |
| 631 | radeon_bo_unreserve(bo); | 645 | radeon_bo_unreserve(bo); |
| @@ -659,12 +673,12 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring, | |||
| 659 | } | 673 | } |
| 660 | 674 | ||
| 661 | /* stitch together an UVD destroy msg */ | 675 | /* stitch together an UVD destroy msg */ |
| 662 | msg[0] = 0x00000de4; | 676 | msg[0] = cpu_to_le32(0x00000de4); |
| 663 | msg[1] = 0x00000002; | 677 | msg[1] = cpu_to_le32(0x00000002); |
| 664 | msg[2] = handle; | 678 | msg[2] = cpu_to_le32(handle); |
| 665 | msg[3] = 0x00000000; | 679 | msg[3] = cpu_to_le32(0x00000000); |
| 666 | for (i = 4; i < 1024; ++i) | 680 | for (i = 4; i < 1024; ++i) |
| 667 | msg[i] = 0x0; | 681 | msg[i] = cpu_to_le32(0x0); |
| 668 | 682 | ||
| 669 | radeon_bo_kunmap(bo); | 683 | radeon_bo_kunmap(bo); |
| 670 | radeon_bo_unreserve(bo); | 684 | radeon_bo_unreserve(bo); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 1760ceb68b7b..19ceaa60e0f4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
| @@ -705,7 +705,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
| 705 | static int __cpuinit gic_secondary_init(struct notifier_block *nfb, | 705 | static int __cpuinit gic_secondary_init(struct notifier_block *nfb, |
| 706 | unsigned long action, void *hcpu) | 706 | unsigned long action, void *hcpu) |
| 707 | { | 707 | { |
| 708 | if (action == CPU_STARTING) | 708 | if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) |
| 709 | gic_cpu_init(&gic_data[0]); | 709 | gic_cpu_init(&gic_data[0]); |
| 710 | return NOTIFY_OK; | 710 | return NOTIFY_OK; |
| 711 | } | 711 | } |
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 7f5a7cac6dc7..8270388e2a0d 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
| @@ -136,9 +136,9 @@ config DVB_NET | |||
| 136 | 136 | ||
| 137 | # This Kconfig option is used by both PCI and USB drivers | 137 | # This Kconfig option is used by both PCI and USB drivers |
| 138 | config TTPCI_EEPROM | 138 | config TTPCI_EEPROM |
| 139 | tristate | 139 | tristate |
| 140 | depends on I2C | 140 | depends on I2C |
| 141 | default n | 141 | default n |
| 142 | 142 | ||
| 143 | source "drivers/media/dvb-core/Kconfig" | 143 | source "drivers/media/dvb-core/Kconfig" |
| 144 | 144 | ||
| @@ -189,6 +189,12 @@ config MEDIA_SUBDRV_AUTOSELECT | |||
| 189 | 189 | ||
| 190 | If unsure say Y. | 190 | If unsure say Y. |
| 191 | 191 | ||
| 192 | config MEDIA_ATTACH | ||
| 193 | bool | ||
| 194 | depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT | ||
| 195 | depends on MODULES | ||
| 196 | default MODULES | ||
| 197 | |||
| 192 | source "drivers/media/i2c/Kconfig" | 198 | source "drivers/media/i2c/Kconfig" |
| 193 | source "drivers/media/tuners/Kconfig" | 199 | source "drivers/media/tuners/Kconfig" |
| 194 | source "drivers/media/dvb-frontends/Kconfig" | 200 | source "drivers/media/dvb-frontends/Kconfig" |
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index cb52438e53ac..9eac5310942f 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c | |||
| @@ -956,7 +956,7 @@ static int s5c73m3_oif_enum_frame_interval(struct v4l2_subdev *sd, | |||
| 956 | 956 | ||
| 957 | if (fie->pad != OIF_SOURCE_PAD) | 957 | if (fie->pad != OIF_SOURCE_PAD) |
| 958 | return -EINVAL; | 958 | return -EINVAL; |
| 959 | if (fie->index > ARRAY_SIZE(s5c73m3_intervals)) | 959 | if (fie->index >= ARRAY_SIZE(s5c73m3_intervals)) |
| 960 | return -EINVAL; | 960 | return -EINVAL; |
| 961 | 961 | ||
| 962 | mutex_lock(&state->lock); | 962 | mutex_lock(&state->lock); |
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 27d62623274b..aba5b1c649e6 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c | |||
| @@ -615,7 +615,7 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, | |||
| 615 | int changed = 0; | 615 | int changed = 0; |
| 616 | u32 old; | 616 | u32 old; |
| 617 | 617 | ||
| 618 | if (core->board.audio_chip == V4L2_IDENT_WM8775) | 618 | if (core->sd_wm8775) |
| 619 | snd_cx88_wm8775_volume_put(kcontrol, value); | 619 | snd_cx88_wm8775_volume_put(kcontrol, value); |
| 620 | 620 | ||
| 621 | left = value->value.integer.value[0] & 0x3f; | 621 | left = value->value.integer.value[0] & 0x3f; |
| @@ -682,8 +682,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, | |||
| 682 | vol ^= bit; | 682 | vol ^= bit; |
| 683 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); | 683 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); |
| 684 | /* Pass mute onto any WM8775 */ | 684 | /* Pass mute onto any WM8775 */ |
| 685 | if ((core->board.audio_chip == V4L2_IDENT_WM8775) && | 685 | if (core->sd_wm8775 && ((1<<6) == bit)) |
| 686 | ((1<<6) == bit)) | ||
| 687 | wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); | 686 | wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); |
| 688 | ret = 1; | 687 | ret = 1; |
| 689 | } | 688 | } |
| @@ -903,7 +902,7 @@ static int cx88_audio_initdev(struct pci_dev *pci, | |||
| 903 | goto error; | 902 | goto error; |
| 904 | 903 | ||
| 905 | /* If there's a wm8775 then add a Line-In ALC switch */ | 904 | /* If there's a wm8775 then add a Line-In ALC switch */ |
| 906 | if (core->board.audio_chip == V4L2_IDENT_WM8775) | 905 | if (core->sd_wm8775) |
| 907 | snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); | 906 | snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); |
| 908 | 907 | ||
| 909 | strcpy (card->driver, "CX88x"); | 908 | strcpy (card->driver, "CX88x"); |
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index 1b00615fd395..c7a9be1065c0 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c | |||
| @@ -385,8 +385,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
| 385 | /* The wm8775 module has the "2" route hardwired into | 385 | /* The wm8775 module has the "2" route hardwired into |
| 386 | the initialization. Some boards may use different | 386 | the initialization. Some boards may use different |
| 387 | routes for different inputs. HVR-1300 surely does */ | 387 | routes for different inputs. HVR-1300 surely does */ |
| 388 | if (core->board.audio_chip && | 388 | if (core->sd_wm8775) { |
| 389 | core->board.audio_chip == V4L2_IDENT_WM8775) { | ||
| 390 | call_all(core, audio, s_routing, | 389 | call_all(core, audio, s_routing, |
| 391 | INPUT(input).audioroute, 0, 0); | 390 | INPUT(input).audioroute, 0, 0); |
| 392 | } | 391 | } |
| @@ -771,8 +770,7 @@ static int video_open(struct file *file) | |||
| 771 | cx_write(MO_GP1_IO, core->board.radio.gpio1); | 770 | cx_write(MO_GP1_IO, core->board.radio.gpio1); |
| 772 | cx_write(MO_GP2_IO, core->board.radio.gpio2); | 771 | cx_write(MO_GP2_IO, core->board.radio.gpio2); |
| 773 | if (core->board.radio.audioroute) { | 772 | if (core->board.radio.audioroute) { |
| 774 | if(core->board.audio_chip && | 773 | if (core->sd_wm8775) { |
| 775 | core->board.audio_chip == V4L2_IDENT_WM8775) { | ||
| 776 | call_all(core, audio, s_routing, | 774 | call_all(core, audio, s_routing, |
| 777 | core->board.radio.audioroute, 0, 0); | 775 | core->board.radio.audioroute, 0, 0); |
| 778 | } | 776 | } |
| @@ -959,7 +957,7 @@ static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl) | |||
| 959 | u32 value,mask; | 957 | u32 value,mask; |
| 960 | 958 | ||
| 961 | /* Pass changes onto any WM8775 */ | 959 | /* Pass changes onto any WM8775 */ |
| 962 | if (core->board.audio_chip == V4L2_IDENT_WM8775) { | 960 | if (core->sd_wm8775) { |
| 963 | switch (ctrl->id) { | 961 | switch (ctrl->id) { |
| 964 | case V4L2_CID_AUDIO_MUTE: | 962 | case V4L2_CID_AUDIO_MUTE: |
| 965 | wm8775_s_ctrl(core, ctrl->id, ctrl->val); | 963 | wm8775_s_ctrl(core, ctrl->id, ctrl->val); |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 48b8d7af386d..9d1481a60bd9 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
| @@ -576,6 +576,14 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
| 576 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 576 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); |
| 577 | } | 577 | } |
| 578 | 578 | ||
| 579 | static int vidioc_create_bufs(struct file *file, void *priv, | ||
| 580 | struct v4l2_create_buffers *create) | ||
| 581 | { | ||
| 582 | struct coda_ctx *ctx = fh_to_ctx(priv); | ||
| 583 | |||
| 584 | return v4l2_m2m_create_bufs(file, ctx->m2m_ctx, create); | ||
| 585 | } | ||
| 586 | |||
| 579 | static int vidioc_streamon(struct file *file, void *priv, | 587 | static int vidioc_streamon(struct file *file, void *priv, |
| 580 | enum v4l2_buf_type type) | 588 | enum v4l2_buf_type type) |
| 581 | { | 589 | { |
| @@ -610,6 +618,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { | |||
| 610 | 618 | ||
| 611 | .vidioc_qbuf = vidioc_qbuf, | 619 | .vidioc_qbuf = vidioc_qbuf, |
| 612 | .vidioc_dqbuf = vidioc_dqbuf, | 620 | .vidioc_dqbuf = vidioc_dqbuf, |
| 621 | .vidioc_create_bufs = vidioc_create_bufs, | ||
| 613 | 622 | ||
| 614 | .vidioc_streamon = vidioc_streamon, | 623 | .vidioc_streamon = vidioc_streamon, |
| 615 | .vidioc_streamoff = vidioc_streamoff, | 624 | .vidioc_streamoff = vidioc_streamoff, |
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 1802f11e939f..d0b375cf565f 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
| @@ -916,6 +916,21 @@ static int vpbe_display_s_fmt(struct file *file, void *priv, | |||
| 916 | other video window */ | 916 | other video window */ |
| 917 | 917 | ||
| 918 | layer->pix_fmt = *pixfmt; | 918 | layer->pix_fmt = *pixfmt; |
| 919 | if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12) { | ||
| 920 | struct vpbe_layer *otherlayer; | ||
| 921 | |||
| 922 | otherlayer = _vpbe_display_get_other_win_layer(disp_dev, layer); | ||
| 923 | /* if other layer is available, only | ||
| 924 | * claim it, do not configure it | ||
| 925 | */ | ||
| 926 | ret = osd_device->ops.request_layer(osd_device, | ||
| 927 | otherlayer->layer_info.id); | ||
| 928 | if (ret < 0) { | ||
| 929 | v4l2_err(&vpbe_dev->v4l2_dev, | ||
| 930 | "Display Manager failed to allocate layer\n"); | ||
| 931 | return -EBUSY; | ||
| 932 | } | ||
| 933 | } | ||
| 919 | 934 | ||
| 920 | /* Get osd layer config */ | 935 | /* Get osd layer config */ |
| 921 | osd_device->ops.get_layer_config(osd_device, | 936 | osd_device->ops.get_layer_config(osd_device, |
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 8c50d3074866..93609091cb23 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c | |||
| @@ -1837,7 +1837,7 @@ static int vpfe_probe(struct platform_device *pdev) | |||
| 1837 | if (NULL == ccdc_cfg) { | 1837 | if (NULL == ccdc_cfg) { |
| 1838 | v4l2_err(pdev->dev.driver, | 1838 | v4l2_err(pdev->dev.driver, |
| 1839 | "Memory allocation failed for ccdc_cfg\n"); | 1839 | "Memory allocation failed for ccdc_cfg\n"); |
| 1840 | goto probe_free_lock; | 1840 | goto probe_free_dev_mem; |
| 1841 | } | 1841 | } |
| 1842 | 1842 | ||
| 1843 | mutex_lock(&ccdc_lock); | 1843 | mutex_lock(&ccdc_lock); |
| @@ -1991,7 +1991,6 @@ probe_out_release_irq: | |||
| 1991 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); | 1991 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); |
| 1992 | probe_free_ccdc_cfg_mem: | 1992 | probe_free_ccdc_cfg_mem: |
| 1993 | kfree(ccdc_cfg); | 1993 | kfree(ccdc_cfg); |
| 1994 | probe_free_lock: | ||
| 1995 | mutex_unlock(&ccdc_lock); | 1994 | mutex_unlock(&ccdc_lock); |
| 1996 | probe_free_dev_mem: | 1995 | probe_free_dev_mem: |
| 1997 | kfree(vpfe_dev); | 1996 | kfree(vpfe_dev); |
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index b0ff67bc1b05..d05eaa2c8490 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c | |||
| @@ -174,7 +174,7 @@ int fimc_is_hw_change_mode(struct fimc_is *is) | |||
| 174 | HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO, | 174 | HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO, |
| 175 | }; | 175 | }; |
| 176 | 176 | ||
| 177 | if (WARN_ON(is->config_index > ARRAY_SIZE(cmd))) | 177 | if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd))) |
| 178 | return -EINVAL; | 178 | return -EINVAL; |
| 179 | 179 | ||
| 180 | mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0)); | 180 | mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0)); |
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 47c6363d04e2..0741945b79ed 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c | |||
| @@ -48,7 +48,6 @@ static char *fimc_is_clocks[ISS_CLKS_MAX] = { | |||
| 48 | [ISS_CLK_LITE0] = "lite0", | 48 | [ISS_CLK_LITE0] = "lite0", |
| 49 | [ISS_CLK_LITE1] = "lite1", | 49 | [ISS_CLK_LITE1] = "lite1", |
| 50 | [ISS_CLK_MPLL] = "mpll", | 50 | [ISS_CLK_MPLL] = "mpll", |
| 51 | [ISS_CLK_SYSREG] = "sysreg", | ||
| 52 | [ISS_CLK_ISP] = "isp", | 51 | [ISS_CLK_ISP] = "isp", |
| 53 | [ISS_CLK_DRC] = "drc", | 52 | [ISS_CLK_DRC] = "drc", |
| 54 | [ISS_CLK_FD] = "fd", | 53 | [ISS_CLK_FD] = "fd", |
| @@ -71,7 +70,6 @@ static void fimc_is_put_clocks(struct fimc_is *is) | |||
| 71 | for (i = 0; i < ISS_CLKS_MAX; i++) { | 70 | for (i = 0; i < ISS_CLKS_MAX; i++) { |
| 72 | if (IS_ERR(is->clocks[i])) | 71 | if (IS_ERR(is->clocks[i])) |
| 73 | continue; | 72 | continue; |
| 74 | clk_unprepare(is->clocks[i]); | ||
| 75 | clk_put(is->clocks[i]); | 73 | clk_put(is->clocks[i]); |
| 76 | is->clocks[i] = ERR_PTR(-EINVAL); | 74 | is->clocks[i] = ERR_PTR(-EINVAL); |
| 77 | } | 75 | } |
| @@ -90,12 +88,6 @@ static int fimc_is_get_clocks(struct fimc_is *is) | |||
| 90 | ret = PTR_ERR(is->clocks[i]); | 88 | ret = PTR_ERR(is->clocks[i]); |
| 91 | goto err; | 89 | goto err; |
| 92 | } | 90 | } |
| 93 | ret = clk_prepare(is->clocks[i]); | ||
| 94 | if (ret < 0) { | ||
| 95 | clk_put(is->clocks[i]); | ||
| 96 | is->clocks[i] = ERR_PTR(-EINVAL); | ||
| 97 | goto err; | ||
| 98 | } | ||
| 99 | } | 91 | } |
| 100 | 92 | ||
| 101 | return 0; | 93 | return 0; |
| @@ -103,7 +95,7 @@ err: | |||
| 103 | fimc_is_put_clocks(is); | 95 | fimc_is_put_clocks(is); |
| 104 | dev_err(&is->pdev->dev, "failed to get clock: %s\n", | 96 | dev_err(&is->pdev->dev, "failed to get clock: %s\n", |
| 105 | fimc_is_clocks[i]); | 97 | fimc_is_clocks[i]); |
| 106 | return -ENXIO; | 98 | return ret; |
| 107 | } | 99 | } |
| 108 | 100 | ||
| 109 | static int fimc_is_setup_clocks(struct fimc_is *is) | 101 | static int fimc_is_setup_clocks(struct fimc_is *is) |
| @@ -144,7 +136,7 @@ int fimc_is_enable_clocks(struct fimc_is *is) | |||
| 144 | for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { | 136 | for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { |
| 145 | if (IS_ERR(is->clocks[i])) | 137 | if (IS_ERR(is->clocks[i])) |
| 146 | continue; | 138 | continue; |
| 147 | ret = clk_enable(is->clocks[i]); | 139 | ret = clk_prepare_enable(is->clocks[i]); |
| 148 | if (ret < 0) { | 140 | if (ret < 0) { |
| 149 | dev_err(&is->pdev->dev, "clock %s enable failed\n", | 141 | dev_err(&is->pdev->dev, "clock %s enable failed\n", |
| 150 | fimc_is_clocks[i]); | 142 | fimc_is_clocks[i]); |
| @@ -163,7 +155,7 @@ void fimc_is_disable_clocks(struct fimc_is *is) | |||
| 163 | 155 | ||
| 164 | for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { | 156 | for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { |
| 165 | if (!IS_ERR(is->clocks[i])) { | 157 | if (!IS_ERR(is->clocks[i])) { |
| 166 | clk_disable(is->clocks[i]); | 158 | clk_disable_unprepare(is->clocks[i]); |
| 167 | pr_debug("disabled clock: %s\n", fimc_is_clocks[i]); | 159 | pr_debug("disabled clock: %s\n", fimc_is_clocks[i]); |
| 168 | } | 160 | } |
| 169 | } | 161 | } |
| @@ -326,6 +318,11 @@ int fimc_is_start_firmware(struct fimc_is *is) | |||
| 326 | struct device *dev = &is->pdev->dev; | 318 | struct device *dev = &is->pdev->dev; |
| 327 | int ret; | 319 | int ret; |
| 328 | 320 | ||
| 321 | if (is->fw.f_w == NULL) { | ||
| 322 | dev_err(dev, "firmware is not loaded\n"); | ||
| 323 | return -EINVAL; | ||
| 324 | } | ||
| 325 | |||
| 329 | memcpy(is->memory.vaddr, is->fw.f_w->data, is->fw.f_w->size); | 326 | memcpy(is->memory.vaddr, is->fw.f_w->data, is->fw.f_w->size); |
| 330 | wmb(); | 327 | wmb(); |
| 331 | 328 | ||
| @@ -837,23 +834,11 @@ static int fimc_is_probe(struct platform_device *pdev) | |||
| 837 | goto err_clk; | 834 | goto err_clk; |
| 838 | } | 835 | } |
| 839 | pm_runtime_enable(dev); | 836 | pm_runtime_enable(dev); |
| 840 | /* | ||
| 841 | * Enable only the ISP power domain, keep FIMC-IS clocks off until | ||
| 842 | * the whole clock tree is configured. The ISP power domain needs | ||
| 843 | * be active in order to acces any CMU_ISP clock registers. | ||
| 844 | */ | ||
| 845 | ret = pm_runtime_get_sync(dev); | ||
| 846 | if (ret < 0) | ||
| 847 | goto err_irq; | ||
| 848 | |||
| 849 | ret = fimc_is_setup_clocks(is); | ||
| 850 | pm_runtime_put_sync(dev); | ||
| 851 | 837 | ||
| 838 | ret = pm_runtime_get_sync(dev); | ||
| 852 | if (ret < 0) | 839 | if (ret < 0) |
| 853 | goto err_irq; | 840 | goto err_irq; |
| 854 | 841 | ||
| 855 | is->clk_init = true; | ||
| 856 | |||
| 857 | is->alloc_ctx = vb2_dma_contig_init_ctx(dev); | 842 | is->alloc_ctx = vb2_dma_contig_init_ctx(dev); |
| 858 | if (IS_ERR(is->alloc_ctx)) { | 843 | if (IS_ERR(is->alloc_ctx)) { |
| 859 | ret = PTR_ERR(is->alloc_ctx); | 844 | ret = PTR_ERR(is->alloc_ctx); |
| @@ -875,6 +860,8 @@ static int fimc_is_probe(struct platform_device *pdev) | |||
| 875 | if (ret < 0) | 860 | if (ret < 0) |
| 876 | goto err_dfs; | 861 | goto err_dfs; |
| 877 | 862 | ||
| 863 | pm_runtime_put_sync(dev); | ||
| 864 | |||
| 878 | dev_dbg(dev, "FIMC-IS registered successfully\n"); | 865 | dev_dbg(dev, "FIMC-IS registered successfully\n"); |
| 879 | return 0; | 866 | return 0; |
| 880 | 867 | ||
| @@ -894,9 +881,11 @@ err_clk: | |||
| 894 | static int fimc_is_runtime_resume(struct device *dev) | 881 | static int fimc_is_runtime_resume(struct device *dev) |
| 895 | { | 882 | { |
| 896 | struct fimc_is *is = dev_get_drvdata(dev); | 883 | struct fimc_is *is = dev_get_drvdata(dev); |
| 884 | int ret; | ||
| 897 | 885 | ||
| 898 | if (!is->clk_init) | 886 | ret = fimc_is_setup_clocks(is); |
| 899 | return 0; | 887 | if (ret) |
| 888 | return ret; | ||
| 900 | 889 | ||
| 901 | return fimc_is_enable_clocks(is); | 890 | return fimc_is_enable_clocks(is); |
| 902 | } | 891 | } |
| @@ -905,9 +894,7 @@ static int fimc_is_runtime_suspend(struct device *dev) | |||
| 905 | { | 894 | { |
| 906 | struct fimc_is *is = dev_get_drvdata(dev); | 895 | struct fimc_is *is = dev_get_drvdata(dev); |
| 907 | 896 | ||
| 908 | if (is->clk_init) | 897 | fimc_is_disable_clocks(is); |
| 909 | fimc_is_disable_clocks(is); | ||
| 910 | |||
| 911 | return 0; | 898 | return 0; |
| 912 | } | 899 | } |
| 913 | 900 | ||
| @@ -941,7 +928,8 @@ static int fimc_is_remove(struct platform_device *pdev) | |||
| 941 | vb2_dma_contig_cleanup_ctx(is->alloc_ctx); | 928 | vb2_dma_contig_cleanup_ctx(is->alloc_ctx); |
| 942 | fimc_is_put_clocks(is); | 929 | fimc_is_put_clocks(is); |
| 943 | fimc_is_debugfs_remove(is); | 930 | fimc_is_debugfs_remove(is); |
| 944 | release_firmware(is->fw.f_w); | 931 | if (is->fw.f_w) |
| 932 | release_firmware(is->fw.f_w); | ||
| 945 | fimc_is_free_cpu_memory(is); | 933 | fimc_is_free_cpu_memory(is); |
| 946 | 934 | ||
| 947 | return 0; | 935 | return 0; |
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h index f5275a5b0156..d7db133b493f 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ b/drivers/media/platform/exynos4-is/fimc-is.h | |||
| @@ -73,7 +73,6 @@ enum { | |||
| 73 | ISS_CLK_LITE0, | 73 | ISS_CLK_LITE0, |
| 74 | ISS_CLK_LITE1, | 74 | ISS_CLK_LITE1, |
| 75 | ISS_CLK_MPLL, | 75 | ISS_CLK_MPLL, |
| 76 | ISS_CLK_SYSREG, | ||
| 77 | ISS_CLK_ISP, | 76 | ISS_CLK_ISP, |
| 78 | ISS_CLK_DRC, | 77 | ISS_CLK_DRC, |
| 79 | ISS_CLK_FD, | 78 | ISS_CLK_FD, |
| @@ -265,7 +264,6 @@ struct fimc_is { | |||
| 265 | spinlock_t slock; | 264 | spinlock_t slock; |
| 266 | 265 | ||
| 267 | struct clk *clocks[ISS_CLKS_MAX]; | 266 | struct clk *clocks[ISS_CLKS_MAX]; |
| 268 | bool clk_init; | ||
| 269 | void __iomem *regs; | 267 | void __iomem *regs; |
| 270 | void __iomem *pmu_regs; | 268 | void __iomem *pmu_regs; |
| 271 | int irq; | 269 | int irq; |
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index d63947f7b302..7ede30b5910f 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c | |||
| @@ -138,7 +138,7 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, | |||
| 138 | return 0; | 138 | return 0; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 141 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
| 142 | 142 | ||
| 143 | mutex_lock(&isp->subdev_lock); | 143 | mutex_lock(&isp->subdev_lock); |
| 144 | __is_get_frame_size(is, &cur_fmt); | 144 | __is_get_frame_size(is, &cur_fmt); |
| @@ -194,7 +194,7 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd, | |||
| 194 | v4l2_dbg(1, debug, sd, "%s: pad%d: code: 0x%x, %dx%d\n", | 194 | v4l2_dbg(1, debug, sd, "%s: pad%d: code: 0x%x, %dx%d\n", |
| 195 | __func__, fmt->pad, mf->code, mf->width, mf->height); | 195 | __func__, fmt->pad, mf->code, mf->width, mf->height); |
| 196 | 196 | ||
| 197 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 197 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
| 198 | 198 | ||
| 199 | mutex_lock(&isp->subdev_lock); | 199 | mutex_lock(&isp->subdev_lock); |
| 200 | __isp_subdev_try_format(isp, fmt); | 200 | __isp_subdev_try_format(isp, fmt); |
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index a2eda9d5ac87..254d70fe762a 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c | |||
| @@ -746,7 +746,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, | |||
| 746 | node = v4l2_of_get_next_endpoint(node, NULL); | 746 | node = v4l2_of_get_next_endpoint(node, NULL); |
| 747 | if (!node) { | 747 | if (!node) { |
| 748 | dev_err(&pdev->dev, "No port node at %s\n", | 748 | dev_err(&pdev->dev, "No port node at %s\n", |
| 749 | node->full_name); | 749 | pdev->dev.of_node->full_name); |
| 750 | return -EINVAL; | 750 | return -EINVAL; |
| 751 | } | 751 | } |
| 752 | /* Get port node and validate MIPI-CSI channel id. */ | 752 | /* Get port node and validate MIPI-CSI channel id. */ |
diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h index 261134baa655..35d2fcdc0036 100644 --- a/drivers/media/platform/s3c-camif/camif-core.h +++ b/drivers/media/platform/s3c-camif/camif-core.h | |||
| @@ -229,7 +229,7 @@ struct camif_vp { | |||
| 229 | unsigned int state; | 229 | unsigned int state; |
| 230 | u16 fmt_flags; | 230 | u16 fmt_flags; |
| 231 | u8 id; | 231 | u8 id; |
| 232 | u8 rotation; | 232 | u16 rotation; |
| 233 | u8 hflip; | 233 | u8 hflip; |
| 234 | u8 vflip; | 234 | u8 vflip; |
| 235 | unsigned int offset; | 235 | unsigned int offset; |
diff --git a/drivers/media/platform/s5p-jpeg/Makefile b/drivers/media/platform/s5p-jpeg/Makefile index ddc2900d88a2..d18cb5edd2d5 100644 --- a/drivers/media/platform/s5p-jpeg/Makefile +++ b/drivers/media/platform/s5p-jpeg/Makefile | |||
| @@ -1,2 +1,2 @@ | |||
| 1 | s5p-jpeg-objs := jpeg-core.o | 1 | s5p-jpeg-objs := jpeg-core.o |
| 2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) := s5p-jpeg.o | 2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o |
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile index 379008c6d09a..15f59b324fef 100644 --- a/drivers/media/platform/s5p-mfc/Makefile +++ b/drivers/media/platform/s5p-mfc/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o | 1 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc.o |
| 2 | s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o | 2 | s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o |
| 3 | s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o | 3 | s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o |
| 4 | s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o | 4 | s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 01f9ae0dadb0..d12faa691af8 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
| @@ -397,7 +397,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, | |||
| 397 | leave_handle_frame: | 397 | leave_handle_frame: |
| 398 | spin_unlock_irqrestore(&dev->irqlock, flags); | 398 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 399 | if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) | 399 | if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING) |
| 400 | || ctx->dst_queue_cnt < ctx->dpb_count) | 400 | || ctx->dst_queue_cnt < ctx->pb_count) |
| 401 | clear_work_bit(ctx); | 401 | clear_work_bit(ctx); |
| 402 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | 402 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); |
| 403 | wake_up_ctx(ctx, reason, err); | 403 | wake_up_ctx(ctx, reason, err); |
| @@ -473,7 +473,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, | |||
| 473 | 473 | ||
| 474 | s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); | 474 | s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx); |
| 475 | 475 | ||
| 476 | ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, | 476 | ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count, |
| 477 | dev); | 477 | dev); |
| 478 | ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count, | 478 | ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count, |
| 479 | dev); | 479 | dev); |
| @@ -562,7 +562,7 @@ static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, | |||
| 562 | struct s5p_mfc_dev *dev = ctx->dev; | 562 | struct s5p_mfc_dev *dev = ctx->dev; |
| 563 | struct s5p_mfc_buf *mb_entry; | 563 | struct s5p_mfc_buf *mb_entry; |
| 564 | 564 | ||
| 565 | mfc_debug(2, "Stream completed"); | 565 | mfc_debug(2, "Stream completed\n"); |
| 566 | 566 | ||
| 567 | s5p_mfc_clear_int_flags(dev); | 567 | s5p_mfc_clear_int_flags(dev); |
| 568 | ctx->int_type = reason; | 568 | ctx->int_type = reason; |
| @@ -1362,7 +1362,6 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = { | |||
| 1362 | .port_num = MFC_NUM_PORTS, | 1362 | .port_num = MFC_NUM_PORTS, |
| 1363 | .buf_size = &buf_size_v5, | 1363 | .buf_size = &buf_size_v5, |
| 1364 | .buf_align = &mfc_buf_align_v5, | 1364 | .buf_align = &mfc_buf_align_v5, |
| 1365 | .mclk_name = "sclk_mfc", | ||
| 1366 | .fw_name = "s5p-mfc.fw", | 1365 | .fw_name = "s5p-mfc.fw", |
| 1367 | }; | 1366 | }; |
| 1368 | 1367 | ||
| @@ -1389,7 +1388,6 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = { | |||
| 1389 | .port_num = MFC_NUM_PORTS_V6, | 1388 | .port_num = MFC_NUM_PORTS_V6, |
| 1390 | .buf_size = &buf_size_v6, | 1389 | .buf_size = &buf_size_v6, |
| 1391 | .buf_align = &mfc_buf_align_v6, | 1390 | .buf_align = &mfc_buf_align_v6, |
| 1392 | .mclk_name = "aclk_333", | ||
| 1393 | .fw_name = "s5p-mfc-v6.fw", | 1391 | .fw_name = "s5p-mfc-v6.fw", |
| 1394 | }; | 1392 | }; |
| 1395 | 1393 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 202d1d7a37a8..ef4074cd5316 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
| @@ -138,6 +138,7 @@ enum s5p_mfc_inst_state { | |||
| 138 | MFCINST_INIT = 100, | 138 | MFCINST_INIT = 100, |
| 139 | MFCINST_GOT_INST, | 139 | MFCINST_GOT_INST, |
| 140 | MFCINST_HEAD_PARSED, | 140 | MFCINST_HEAD_PARSED, |
| 141 | MFCINST_HEAD_PRODUCED, | ||
| 141 | MFCINST_BUFS_SET, | 142 | MFCINST_BUFS_SET, |
| 142 | MFCINST_RUNNING, | 143 | MFCINST_RUNNING, |
| 143 | MFCINST_FINISHING, | 144 | MFCINST_FINISHING, |
| @@ -231,7 +232,6 @@ struct s5p_mfc_variant { | |||
| 231 | unsigned int port_num; | 232 | unsigned int port_num; |
| 232 | struct s5p_mfc_buf_size *buf_size; | 233 | struct s5p_mfc_buf_size *buf_size; |
| 233 | struct s5p_mfc_buf_align *buf_align; | 234 | struct s5p_mfc_buf_align *buf_align; |
| 234 | char *mclk_name; | ||
| 235 | char *fw_name; | 235 | char *fw_name; |
| 236 | }; | 236 | }; |
| 237 | 237 | ||
| @@ -438,7 +438,7 @@ struct s5p_mfc_enc_params { | |||
| 438 | u32 rc_framerate_num; | 438 | u32 rc_framerate_num; |
| 439 | u32 rc_framerate_denom; | 439 | u32 rc_framerate_denom; |
| 440 | 440 | ||
| 441 | union { | 441 | struct { |
| 442 | struct s5p_mfc_h264_enc_params h264; | 442 | struct s5p_mfc_h264_enc_params h264; |
| 443 | struct s5p_mfc_mpeg4_enc_params mpeg4; | 443 | struct s5p_mfc_mpeg4_enc_params mpeg4; |
| 444 | } codec; | 444 | } codec; |
| @@ -602,7 +602,7 @@ struct s5p_mfc_ctx { | |||
| 602 | int after_packed_pb; | 602 | int after_packed_pb; |
| 603 | int sei_fp_parse; | 603 | int sei_fp_parse; |
| 604 | 604 | ||
| 605 | int dpb_count; | 605 | int pb_count; |
| 606 | int total_dpb_count; | 606 | int total_dpb_count; |
| 607 | int mv_count; | 607 | int mv_count; |
| 608 | /* Buffers */ | 608 | /* Buffers */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 2e5f30b40dea..dc1fc94a488d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
| @@ -38,7 +38,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) | |||
| 38 | dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, | 38 | dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, |
| 39 | &dev->bank1, GFP_KERNEL); | 39 | &dev->bank1, GFP_KERNEL); |
| 40 | 40 | ||
| 41 | if (IS_ERR(dev->fw_virt_addr)) { | 41 | if (IS_ERR_OR_NULL(dev->fw_virt_addr)) { |
| 42 | dev->fw_virt_addr = NULL; | 42 | dev->fw_virt_addr = NULL; |
| 43 | mfc_err("Allocating bitprocessor buffer failed\n"); | 43 | mfc_err("Allocating bitprocessor buffer failed\n"); |
| 44 | return -ENOMEM; | 44 | return -ENOMEM; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h index bd5cd4ae993c..8e608f5aa0d7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h | |||
| @@ -30,8 +30,8 @@ extern int debug; | |||
| 30 | #define mfc_debug(level, fmt, args...) | 30 | #define mfc_debug(level, fmt, args...) |
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #define mfc_debug_enter() mfc_debug(5, "enter") | 33 | #define mfc_debug_enter() mfc_debug(5, "enter\n") |
| 34 | #define mfc_debug_leave() mfc_debug(5, "leave") | 34 | #define mfc_debug_leave() mfc_debug(5, "leave\n") |
| 35 | 35 | ||
| 36 | #define mfc_err(fmt, args...) \ | 36 | #define mfc_err(fmt, args...) \ |
| 37 | do { \ | 37 | do { \ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 4af53bd2f182..00b07032f4f0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
| @@ -210,11 +210,11 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | |||
| 210 | /* Context is to decode a frame */ | 210 | /* Context is to decode a frame */ |
| 211 | if (ctx->src_queue_cnt >= 1 && | 211 | if (ctx->src_queue_cnt >= 1 && |
| 212 | ctx->state == MFCINST_RUNNING && | 212 | ctx->state == MFCINST_RUNNING && |
| 213 | ctx->dst_queue_cnt >= ctx->dpb_count) | 213 | ctx->dst_queue_cnt >= ctx->pb_count) |
| 214 | return 1; | 214 | return 1; |
| 215 | /* Context is to return last frame */ | 215 | /* Context is to return last frame */ |
| 216 | if (ctx->state == MFCINST_FINISHING && | 216 | if (ctx->state == MFCINST_FINISHING && |
| 217 | ctx->dst_queue_cnt >= ctx->dpb_count) | 217 | ctx->dst_queue_cnt >= ctx->pb_count) |
| 218 | return 1; | 218 | return 1; |
| 219 | /* Context is to set buffers */ | 219 | /* Context is to set buffers */ |
| 220 | if (ctx->src_queue_cnt >= 1 && | 220 | if (ctx->src_queue_cnt >= 1 && |
| @@ -224,7 +224,7 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | |||
| 224 | /* Resolution change */ | 224 | /* Resolution change */ |
| 225 | if ((ctx->state == MFCINST_RES_CHANGE_INIT || | 225 | if ((ctx->state == MFCINST_RES_CHANGE_INIT || |
| 226 | ctx->state == MFCINST_RES_CHANGE_FLUSH) && | 226 | ctx->state == MFCINST_RES_CHANGE_FLUSH) && |
| 227 | ctx->dst_queue_cnt >= ctx->dpb_count) | 227 | ctx->dst_queue_cnt >= ctx->pb_count) |
| 228 | return 1; | 228 | return 1; |
| 229 | if (ctx->state == MFCINST_RES_CHANGE_END && | 229 | if (ctx->state == MFCINST_RES_CHANGE_END && |
| 230 | ctx->src_queue_cnt >= 1) | 230 | ctx->src_queue_cnt >= 1) |
| @@ -537,7 +537,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
| 537 | mfc_err("vb2_reqbufs on capture failed\n"); | 537 | mfc_err("vb2_reqbufs on capture failed\n"); |
| 538 | return ret; | 538 | return ret; |
| 539 | } | 539 | } |
| 540 | if (reqbufs->count < ctx->dpb_count) { | 540 | if (reqbufs->count < ctx->pb_count) { |
| 541 | mfc_err("Not enough buffers allocated\n"); | 541 | mfc_err("Not enough buffers allocated\n"); |
| 542 | reqbufs->count = 0; | 542 | reqbufs->count = 0; |
| 543 | s5p_mfc_clock_on(); | 543 | s5p_mfc_clock_on(); |
| @@ -751,7 +751,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) | |||
| 751 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: | 751 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: |
| 752 | if (ctx->state >= MFCINST_HEAD_PARSED && | 752 | if (ctx->state >= MFCINST_HEAD_PARSED && |
| 753 | ctx->state < MFCINST_ABORT) { | 753 | ctx->state < MFCINST_ABORT) { |
| 754 | ctrl->val = ctx->dpb_count; | 754 | ctrl->val = ctx->pb_count; |
| 755 | break; | 755 | break; |
| 756 | } else if (ctx->state != MFCINST_INIT) { | 756 | } else if (ctx->state != MFCINST_INIT) { |
| 757 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); | 757 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); |
| @@ -763,7 +763,7 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) | |||
| 763 | S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); | 763 | S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); |
| 764 | if (ctx->state >= MFCINST_HEAD_PARSED && | 764 | if (ctx->state >= MFCINST_HEAD_PARSED && |
| 765 | ctx->state < MFCINST_ABORT) { | 765 | ctx->state < MFCINST_ABORT) { |
| 766 | ctrl->val = ctx->dpb_count; | 766 | ctrl->val = ctx->pb_count; |
| 767 | } else { | 767 | } else { |
| 768 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); | 768 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); |
| 769 | return -EINVAL; | 769 | return -EINVAL; |
| @@ -924,10 +924,10 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
| 924 | /* Output plane count is 2 - one for Y and one for CbCr */ | 924 | /* Output plane count is 2 - one for Y and one for CbCr */ |
| 925 | *plane_count = 2; | 925 | *plane_count = 2; |
| 926 | /* Setup buffer count */ | 926 | /* Setup buffer count */ |
| 927 | if (*buf_count < ctx->dpb_count) | 927 | if (*buf_count < ctx->pb_count) |
| 928 | *buf_count = ctx->dpb_count; | 928 | *buf_count = ctx->pb_count; |
| 929 | if (*buf_count > ctx->dpb_count + MFC_MAX_EXTRA_DPB) | 929 | if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB) |
| 930 | *buf_count = ctx->dpb_count + MFC_MAX_EXTRA_DPB; | 930 | *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB; |
| 931 | if (*buf_count > MFC_MAX_BUFFERS) | 931 | if (*buf_count > MFC_MAX_BUFFERS) |
| 932 | *buf_count = MFC_MAX_BUFFERS; | 932 | *buf_count = MFC_MAX_BUFFERS; |
| 933 | } else { | 933 | } else { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 4f6b553c4b2d..2549967b2f85 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
| @@ -592,7 +592,7 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | |||
| 592 | return 1; | 592 | return 1; |
| 593 | /* context is ready to encode a frame */ | 593 | /* context is ready to encode a frame */ |
| 594 | if ((ctx->state == MFCINST_RUNNING || | 594 | if ((ctx->state == MFCINST_RUNNING || |
| 595 | ctx->state == MFCINST_HEAD_PARSED) && | 595 | ctx->state == MFCINST_HEAD_PRODUCED) && |
| 596 | ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) | 596 | ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) |
| 597 | return 1; | 597 | return 1; |
| 598 | /* context is ready to encode remaining frames */ | 598 | /* context is ready to encode remaining frames */ |
| @@ -649,6 +649,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) | |||
| 649 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | 649 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 650 | struct s5p_mfc_buf *dst_mb; | 650 | struct s5p_mfc_buf *dst_mb; |
| 651 | unsigned long flags; | 651 | unsigned long flags; |
| 652 | unsigned int enc_pb_count; | ||
| 652 | 653 | ||
| 653 | if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) { | 654 | if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) { |
| 654 | spin_lock_irqsave(&dev->irqlock, flags); | 655 | spin_lock_irqsave(&dev->irqlock, flags); |
| @@ -661,18 +662,19 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) | |||
| 661 | vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); | 662 | vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); |
| 662 | spin_unlock_irqrestore(&dev->irqlock, flags); | 663 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 663 | } | 664 | } |
| 664 | if (IS_MFCV6(dev)) { | 665 | |
| 665 | ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */ | 666 | if (!IS_MFCV6(dev)) { |
| 666 | } else { | ||
| 667 | ctx->state = MFCINST_RUNNING; | 667 | ctx->state = MFCINST_RUNNING; |
| 668 | if (s5p_mfc_ctx_ready(ctx)) | 668 | if (s5p_mfc_ctx_ready(ctx)) |
| 669 | set_work_bit_irqsave(ctx); | 669 | set_work_bit_irqsave(ctx); |
| 670 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | 670 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
| 671 | } | 671 | } else { |
| 672 | 672 | enc_pb_count = s5p_mfc_hw_call(dev->mfc_ops, | |
| 673 | if (IS_MFCV6(dev)) | ||
| 674 | ctx->dpb_count = s5p_mfc_hw_call(dev->mfc_ops, | ||
| 675 | get_enc_dpb_count, dev); | 673 | get_enc_dpb_count, dev); |
| 674 | if (ctx->pb_count < enc_pb_count) | ||
| 675 | ctx->pb_count = enc_pb_count; | ||
| 676 | ctx->state = MFCINST_HEAD_PRODUCED; | ||
| 677 | } | ||
| 676 | 678 | ||
| 677 | return 0; | 679 | return 0; |
| 678 | } | 680 | } |
| @@ -717,9 +719,9 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) | |||
| 717 | 719 | ||
| 718 | slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); | 720 | slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); |
| 719 | strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); | 721 | strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); |
| 720 | mfc_debug(2, "Encoded slice type: %d", slice_type); | 722 | mfc_debug(2, "Encoded slice type: %d\n", slice_type); |
| 721 | mfc_debug(2, "Encoded stream size: %d", strm_size); | 723 | mfc_debug(2, "Encoded stream size: %d\n", strm_size); |
| 722 | mfc_debug(2, "Display order: %d", | 724 | mfc_debug(2, "Display order: %d\n", |
| 723 | mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); | 725 | mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT)); |
| 724 | spin_lock_irqsave(&dev->irqlock, flags); | 726 | spin_lock_irqsave(&dev->irqlock, flags); |
| 725 | if (slice_type >= 0) { | 727 | if (slice_type >= 0) { |
| @@ -1055,15 +1057,13 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
| 1055 | } | 1057 | } |
| 1056 | ctx->capture_state = QUEUE_BUFS_REQUESTED; | 1058 | ctx->capture_state = QUEUE_BUFS_REQUESTED; |
| 1057 | 1059 | ||
| 1058 | if (!IS_MFCV6(dev)) { | 1060 | ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, |
| 1059 | ret = s5p_mfc_hw_call(ctx->dev->mfc_ops, | 1061 | alloc_codec_buffers, ctx); |
| 1060 | alloc_codec_buffers, ctx); | 1062 | if (ret) { |
| 1061 | if (ret) { | 1063 | mfc_err("Failed to allocate encoding buffers\n"); |
| 1062 | mfc_err("Failed to allocate encoding buffers\n"); | 1064 | reqbufs->count = 0; |
| 1063 | reqbufs->count = 0; | 1065 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); |
| 1064 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | 1066 | return -ENOMEM; |
| 1065 | return -ENOMEM; | ||
| 1066 | } | ||
| 1067 | } | 1067 | } |
| 1068 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 1068 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| 1069 | if (ctx->output_state != QUEUE_FREE) { | 1069 | if (ctx->output_state != QUEUE_FREE) { |
| @@ -1071,6 +1071,19 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
| 1071 | ctx->output_state); | 1071 | ctx->output_state); |
| 1072 | return -EINVAL; | 1072 | return -EINVAL; |
| 1073 | } | 1073 | } |
| 1074 | |||
| 1075 | if (IS_MFCV6(dev)) { | ||
| 1076 | /* Check for min encoder buffers */ | ||
| 1077 | if (ctx->pb_count && | ||
| 1078 | (reqbufs->count < ctx->pb_count)) { | ||
| 1079 | reqbufs->count = ctx->pb_count; | ||
| 1080 | mfc_debug(2, "Minimum %d output buffers needed\n", | ||
| 1081 | ctx->pb_count); | ||
| 1082 | } else { | ||
| 1083 | ctx->pb_count = reqbufs->count; | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | |||
| 1074 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | 1087 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); |
| 1075 | if (ret != 0) { | 1088 | if (ret != 0) { |
| 1076 | mfc_err("error in vb2_reqbufs() for E(S)\n"); | 1089 | mfc_err("error in vb2_reqbufs() for E(S)\n"); |
| @@ -1533,14 +1546,14 @@ int vidioc_encoder_cmd(struct file *file, void *priv, | |||
| 1533 | 1546 | ||
| 1534 | spin_lock_irqsave(&dev->irqlock, flags); | 1547 | spin_lock_irqsave(&dev->irqlock, flags); |
| 1535 | if (list_empty(&ctx->src_queue)) { | 1548 | if (list_empty(&ctx->src_queue)) { |
| 1536 | mfc_debug(2, "EOS: empty src queue, entering finishing state"); | 1549 | mfc_debug(2, "EOS: empty src queue, entering finishing state\n"); |
| 1537 | ctx->state = MFCINST_FINISHING; | 1550 | ctx->state = MFCINST_FINISHING; |
| 1538 | if (s5p_mfc_ctx_ready(ctx)) | 1551 | if (s5p_mfc_ctx_ready(ctx)) |
| 1539 | set_work_bit_irqsave(ctx); | 1552 | set_work_bit_irqsave(ctx); |
| 1540 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1553 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 1541 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | 1554 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
| 1542 | } else { | 1555 | } else { |
| 1543 | mfc_debug(2, "EOS: marking last buffer of stream"); | 1556 | mfc_debug(2, "EOS: marking last buffer of stream\n"); |
| 1544 | buf = list_entry(ctx->src_queue.prev, | 1557 | buf = list_entry(ctx->src_queue.prev, |
| 1545 | struct s5p_mfc_buf, list); | 1558 | struct s5p_mfc_buf, list); |
| 1546 | if (buf->flags & MFC_BUF_FLAG_USED) | 1559 | if (buf->flags & MFC_BUF_FLAG_USED) |
| @@ -1609,9 +1622,9 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) | |||
| 1609 | mfc_err("failed to get plane cookie\n"); | 1622 | mfc_err("failed to get plane cookie\n"); |
| 1610 | return -EINVAL; | 1623 | return -EINVAL; |
| 1611 | } | 1624 | } |
| 1612 | mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx", | 1625 | mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx\n", |
| 1613 | vb->v4l2_buf.index, i, | 1626 | vb->v4l2_buf.index, i, |
| 1614 | vb2_dma_contig_plane_dma_addr(vb, i)); | 1627 | vb2_dma_contig_plane_dma_addr(vb, i)); |
| 1615 | } | 1628 | } |
| 1616 | return 0; | 1629 | return 0; |
| 1617 | } | 1630 | } |
| @@ -1760,11 +1773,27 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1760 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | 1773 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); |
| 1761 | struct s5p_mfc_dev *dev = ctx->dev; | 1774 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1762 | 1775 | ||
| 1763 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | 1776 | if (IS_MFCV6(dev) && (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { |
| 1777 | |||
| 1778 | if ((ctx->state == MFCINST_GOT_INST) && | ||
| 1779 | (dev->curr_ctx == ctx->num) && dev->hw_lock) { | ||
| 1780 | s5p_mfc_wait_for_done_ctx(ctx, | ||
| 1781 | S5P_MFC_R2H_CMD_SEQ_DONE_RET, | ||
| 1782 | 0); | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | if (ctx->src_bufs_cnt < ctx->pb_count) { | ||
| 1786 | mfc_err("Need minimum %d OUTPUT buffers\n", | ||
| 1787 | ctx->pb_count); | ||
| 1788 | return -EINVAL; | ||
| 1789 | } | ||
| 1790 | } | ||
| 1791 | |||
| 1764 | /* If context is ready then dev = work->data;schedule it to run */ | 1792 | /* If context is ready then dev = work->data;schedule it to run */ |
| 1765 | if (s5p_mfc_ctx_ready(ctx)) | 1793 | if (s5p_mfc_ctx_ready(ctx)) |
| 1766 | set_work_bit_irqsave(ctx); | 1794 | set_work_bit_irqsave(ctx); |
| 1767 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | 1795 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
| 1796 | |||
| 1768 | return 0; | 1797 | return 0; |
| 1769 | } | 1798 | } |
| 1770 | 1799 | ||
| @@ -1920,6 +1949,7 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) | |||
| 1920 | if (controls[i].is_volatile && ctx->ctrls[i]) | 1949 | if (controls[i].is_volatile && ctx->ctrls[i]) |
| 1921 | ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE; | 1950 | ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE; |
| 1922 | } | 1951 | } |
| 1952 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | ||
| 1923 | return 0; | 1953 | return 0; |
| 1924 | } | 1954 | } |
| 1925 | 1955 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 0af05a2d1cd4..368582b091bf 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | |||
| @@ -1275,8 +1275,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | |||
| 1275 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1275 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 1276 | dev->curr_ctx = ctx->num; | 1276 | dev->curr_ctx = ctx->num; |
| 1277 | s5p_mfc_clean_ctx_int_flags(ctx); | 1277 | s5p_mfc_clean_ctx_int_flags(ctx); |
| 1278 | mfc_debug(2, "encoding buffer with index=%d state=%d", | 1278 | mfc_debug(2, "encoding buffer with index=%d state=%d\n", |
| 1279 | src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); | 1279 | src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); |
| 1280 | s5p_mfc_encode_one_frame_v5(ctx); | 1280 | s5p_mfc_encode_one_frame_v5(ctx); |
| 1281 | return 0; | 1281 | return 0; |
| 1282 | } | 1282 | } |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 7e76fce2e524..66f0d042357f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
| @@ -62,12 +62,6 @@ static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
| 62 | /* NOP */ | 62 | /* NOP */ |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) | ||
| 66 | { | ||
| 67 | /* NOP */ | ||
| 68 | return -1; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* Allocate codec buffers */ | 65 | /* Allocate codec buffers */ |
| 72 | static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | 66 | static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) |
| 73 | { | 67 | { |
| @@ -167,7 +161,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 167 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 161 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 168 | ctx->bank1.size = | 162 | ctx->bank1.size = |
| 169 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | 163 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
| 170 | (ctx->dpb_count * (ctx->luma_dpb_size + | 164 | (ctx->pb_count * (ctx->luma_dpb_size + |
| 171 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 165 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
| 172 | ctx->bank2.size = 0; | 166 | ctx->bank2.size = 0; |
| 173 | break; | 167 | break; |
| @@ -181,7 +175,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 181 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 175 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 182 | ctx->bank1.size = | 176 | ctx->bank1.size = |
| 183 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | 177 | ctx->scratch_buf_size + ctx->tmv_buffer_size + |
| 184 | (ctx->dpb_count * (ctx->luma_dpb_size + | 178 | (ctx->pb_count * (ctx->luma_dpb_size + |
| 185 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 179 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
| 186 | ctx->bank2.size = 0; | 180 | ctx->bank2.size = 0; |
| 187 | break; | 181 | break; |
| @@ -198,7 +192,6 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 198 | } | 192 | } |
| 199 | BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); | 193 | BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); |
| 200 | } | 194 | } |
| 201 | |||
| 202 | return 0; | 195 | return 0; |
| 203 | } | 196 | } |
| 204 | 197 | ||
| @@ -449,8 +442,8 @@ static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
| 449 | WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */ | 442 | WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */ |
| 450 | WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); | 443 | WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); |
| 451 | 444 | ||
| 452 | mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d", | 445 | mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n", |
| 453 | addr, size); | 446 | addr, size); |
| 454 | 447 | ||
| 455 | return 0; | 448 | return 0; |
| 456 | } | 449 | } |
| @@ -463,8 +456,8 @@ static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
| 463 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ | 456 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ |
| 464 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | 457 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); |
| 465 | 458 | ||
| 466 | mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr); | 459 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); |
| 467 | mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr); | 460 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); |
| 468 | } | 461 | } |
| 469 | 462 | ||
| 470 | static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | 463 | static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, |
| @@ -479,8 +472,8 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
| 479 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | 472 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); |
| 480 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | 473 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); |
| 481 | 474 | ||
| 482 | mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr); | 475 | mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr); |
| 483 | mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr); | 476 | mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr); |
| 484 | } | 477 | } |
| 485 | 478 | ||
| 486 | /* Set encoding ref & codec buffer */ | 479 | /* Set encoding ref & codec buffer */ |
| @@ -497,7 +490,7 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
| 497 | 490 | ||
| 498 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); | 491 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); |
| 499 | 492 | ||
| 500 | for (i = 0; i < ctx->dpb_count; i++) { | 493 | for (i = 0; i < ctx->pb_count; i++) { |
| 501 | WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i)); | 494 | WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i)); |
| 502 | buf_addr1 += ctx->luma_dpb_size; | 495 | buf_addr1 += ctx->luma_dpb_size; |
| 503 | WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i)); | 496 | WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i)); |
| @@ -520,7 +513,7 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
| 520 | buf_size1 -= ctx->tmv_buffer_size; | 513 | buf_size1 -= ctx->tmv_buffer_size; |
| 521 | 514 | ||
| 522 | mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n", | 515 | mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n", |
| 523 | buf_addr1, buf_size1, ctx->dpb_count); | 516 | buf_addr1, buf_size1, ctx->pb_count); |
| 524 | if (buf_size1 < 0) { | 517 | if (buf_size1 < 0) { |
| 525 | mfc_debug(2, "Not enough memory has been allocated.\n"); | 518 | mfc_debug(2, "Not enough memory has been allocated.\n"); |
| 526 | return -ENOMEM; | 519 | return -ENOMEM; |
| @@ -1431,8 +1424,8 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) | |||
| 1431 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); | 1424 | src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); |
| 1432 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); | 1425 | src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); |
| 1433 | 1426 | ||
| 1434 | mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr); | 1427 | mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr); |
| 1435 | mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr); | 1428 | mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr); |
| 1436 | 1429 | ||
| 1437 | s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); | 1430 | s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr); |
| 1438 | 1431 | ||
| @@ -1522,22 +1515,6 @@ static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx) | |||
| 1522 | struct s5p_mfc_dev *dev = ctx->dev; | 1515 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1523 | int ret; | 1516 | int ret; |
| 1524 | 1517 | ||
| 1525 | ret = s5p_mfc_alloc_codec_buffers_v6(ctx); | ||
| 1526 | if (ret) { | ||
| 1527 | mfc_err("Failed to allocate encoding buffers.\n"); | ||
| 1528 | return -ENOMEM; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | /* Header was generated now starting processing | ||
| 1532 | * First set the reference frame buffers | ||
| 1533 | */ | ||
| 1534 | if (ctx->capture_state != QUEUE_BUFS_REQUESTED) { | ||
| 1535 | mfc_err("It seems that destionation buffers were not\n" | ||
| 1536 | "requested.MFC requires that header should be generated\n" | ||
| 1537 | "before allocating codec buffer.\n"); | ||
| 1538 | return -EAGAIN; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | dev->curr_ctx = ctx->num; | 1518 | dev->curr_ctx = ctx->num; |
| 1542 | s5p_mfc_clean_ctx_int_flags(ctx); | 1519 | s5p_mfc_clean_ctx_int_flags(ctx); |
| 1543 | ret = s5p_mfc_set_enc_ref_buffer_v6(ctx); | 1520 | ret = s5p_mfc_set_enc_ref_buffer_v6(ctx); |
| @@ -1582,7 +1559,7 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) | |||
| 1582 | mfc_debug(1, "Seting new context to %p\n", ctx); | 1559 | mfc_debug(1, "Seting new context to %p\n", ctx); |
| 1583 | /* Got context to run in ctx */ | 1560 | /* Got context to run in ctx */ |
| 1584 | mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n", | 1561 | mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n", |
| 1585 | ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt); | 1562 | ctx->dst_queue_cnt, ctx->pb_count, ctx->src_queue_cnt); |
| 1586 | mfc_debug(1, "ctx->state=%d\n", ctx->state); | 1563 | mfc_debug(1, "ctx->state=%d\n", ctx->state); |
| 1587 | /* Last frame has already been sent to MFC | 1564 | /* Last frame has already been sent to MFC |
| 1588 | * Now obtaining frames from MFC buffer */ | 1565 | * Now obtaining frames from MFC buffer */ |
| @@ -1647,7 +1624,7 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) | |||
| 1647 | case MFCINST_GOT_INST: | 1624 | case MFCINST_GOT_INST: |
| 1648 | s5p_mfc_run_init_enc(ctx); | 1625 | s5p_mfc_run_init_enc(ctx); |
| 1649 | break; | 1626 | break; |
| 1650 | case MFCINST_HEAD_PARSED: /* Only for MFC6.x */ | 1627 | case MFCINST_HEAD_PRODUCED: |
| 1651 | ret = s5p_mfc_run_init_enc_buffers(ctx); | 1628 | ret = s5p_mfc_run_init_enc_buffers(ctx); |
| 1652 | break; | 1629 | break; |
| 1653 | default: | 1630 | default: |
| @@ -1730,7 +1707,7 @@ static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) | |||
| 1730 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6); | 1707 | return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6); |
| 1731 | } | 1708 | } |
| 1732 | 1709 | ||
| 1733 | static int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev) | 1710 | static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) |
| 1734 | { | 1711 | { |
| 1735 | return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6); | 1712 | return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6); |
| 1736 | } | 1713 | } |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 6aa38a56aaf2..11d5f1dada32 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | |||
| @@ -50,19 +50,6 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
| 50 | goto err_p_ip_clk; | 50 | goto err_p_ip_clk; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | pm->clock = clk_get(&dev->plat_dev->dev, dev->variant->mclk_name); | ||
| 54 | if (IS_ERR(pm->clock)) { | ||
| 55 | mfc_err("Failed to get MFC clock\n"); | ||
| 56 | ret = PTR_ERR(pm->clock); | ||
| 57 | goto err_g_ip_clk_2; | ||
| 58 | } | ||
| 59 | |||
| 60 | ret = clk_prepare(pm->clock); | ||
| 61 | if (ret) { | ||
| 62 | mfc_err("Failed to prepare MFC clock\n"); | ||
| 63 | goto err_p_ip_clk_2; | ||
| 64 | } | ||
| 65 | |||
| 66 | atomic_set(&pm->power, 0); | 53 | atomic_set(&pm->power, 0); |
| 67 | #ifdef CONFIG_PM_RUNTIME | 54 | #ifdef CONFIG_PM_RUNTIME |
| 68 | pm->device = &dev->plat_dev->dev; | 55 | pm->device = &dev->plat_dev->dev; |
| @@ -72,10 +59,6 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
| 72 | atomic_set(&clk_ref, 0); | 59 | atomic_set(&clk_ref, 0); |
| 73 | #endif | 60 | #endif |
| 74 | return 0; | 61 | return 0; |
| 75 | err_p_ip_clk_2: | ||
| 76 | clk_put(pm->clock); | ||
| 77 | err_g_ip_clk_2: | ||
| 78 | clk_unprepare(pm->clock_gate); | ||
| 79 | err_p_ip_clk: | 62 | err_p_ip_clk: |
| 80 | clk_put(pm->clock_gate); | 63 | clk_put(pm->clock_gate); |
| 81 | err_g_ip_clk: | 64 | err_g_ip_clk: |
| @@ -86,8 +69,6 @@ void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) | |||
| 86 | { | 69 | { |
| 87 | clk_unprepare(pm->clock_gate); | 70 | clk_unprepare(pm->clock_gate); |
| 88 | clk_put(pm->clock_gate); | 71 | clk_put(pm->clock_gate); |
| 89 | clk_unprepare(pm->clock); | ||
| 90 | clk_put(pm->clock); | ||
| 91 | #ifdef CONFIG_PM_RUNTIME | 72 | #ifdef CONFIG_PM_RUNTIME |
| 92 | pm_runtime_disable(pm->device); | 73 | pm_runtime_disable(pm->device); |
| 93 | #endif | 74 | #endif |
| @@ -98,7 +79,7 @@ int s5p_mfc_clock_on(void) | |||
| 98 | int ret; | 79 | int ret; |
| 99 | #ifdef CLK_DEBUG | 80 | #ifdef CLK_DEBUG |
| 100 | atomic_inc(&clk_ref); | 81 | atomic_inc(&clk_ref); |
| 101 | mfc_debug(3, "+ %d", atomic_read(&clk_ref)); | 82 | mfc_debug(3, "+ %d\n", atomic_read(&clk_ref)); |
| 102 | #endif | 83 | #endif |
| 103 | ret = clk_enable(pm->clock_gate); | 84 | ret = clk_enable(pm->clock_gate); |
| 104 | return ret; | 85 | return ret; |
| @@ -108,7 +89,7 @@ void s5p_mfc_clock_off(void) | |||
| 108 | { | 89 | { |
| 109 | #ifdef CLK_DEBUG | 90 | #ifdef CLK_DEBUG |
| 110 | atomic_dec(&clk_ref); | 91 | atomic_dec(&clk_ref); |
| 111 | mfc_debug(3, "- %d", atomic_read(&clk_ref)); | 92 | mfc_debug(3, "- %d\n", atomic_read(&clk_ref)); |
| 112 | #endif | 93 | #endif |
| 113 | clk_disable(pm->clock_gate); | 94 | clk_disable(pm->clock_gate); |
| 114 | } | 95 | } |
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 0b32cc3f6a47..59a9deefb242 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c | |||
| @@ -905,11 +905,11 @@ static int sh_veu_queue_setup(struct vb2_queue *vq, | |||
| 905 | if (ftmp.fmt.pix.width != pix->width || | 905 | if (ftmp.fmt.pix.width != pix->width || |
| 906 | ftmp.fmt.pix.height != pix->height) | 906 | ftmp.fmt.pix.height != pix->height) |
| 907 | return -EINVAL; | 907 | return -EINVAL; |
| 908 | size = pix->bytesperline ? pix->bytesperline * pix->height : | 908 | size = pix->bytesperline ? pix->bytesperline * pix->height * fmt->depth / fmt->ydepth : |
| 909 | pix->width * pix->height * fmt->depth >> 3; | 909 | pix->width * pix->height * fmt->depth / fmt->ydepth; |
| 910 | } else { | 910 | } else { |
| 911 | vfmt = sh_veu_get_vfmt(veu, vq->type); | 911 | vfmt = sh_veu_get_vfmt(veu, vq->type); |
| 912 | size = vfmt->bytesperline * vfmt->frame.height; | 912 | size = vfmt->bytesperline * vfmt->frame.height * vfmt->fmt->depth / vfmt->fmt->ydepth; |
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | if (count < 2) | 915 | if (count < 2) |
| @@ -1033,8 +1033,6 @@ static int sh_veu_release(struct file *file) | |||
| 1033 | 1033 | ||
| 1034 | dev_dbg(veu->dev, "Releasing instance %p\n", veu_file); | 1034 | dev_dbg(veu->dev, "Releasing instance %p\n", veu_file); |
| 1035 | 1035 | ||
| 1036 | pm_runtime_put(veu->dev); | ||
| 1037 | |||
| 1038 | if (veu_file == veu->capture) { | 1036 | if (veu_file == veu->capture) { |
| 1039 | veu->capture = NULL; | 1037 | veu->capture = NULL; |
| 1040 | vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)); | 1038 | vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)); |
| @@ -1050,6 +1048,8 @@ static int sh_veu_release(struct file *file) | |||
| 1050 | veu->m2m_ctx = NULL; | 1048 | veu->m2m_ctx = NULL; |
| 1051 | } | 1049 | } |
| 1052 | 1050 | ||
| 1051 | pm_runtime_put(veu->dev); | ||
| 1052 | |||
| 1053 | kfree(veu_file); | 1053 | kfree(veu_file); |
| 1054 | 1054 | ||
| 1055 | return 0; | 1055 | return 0; |
| @@ -1138,10 +1138,7 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id) | |||
| 1138 | 1138 | ||
| 1139 | veu->xaction++; | 1139 | veu->xaction++; |
| 1140 | 1140 | ||
| 1141 | if (!veu->aborting) | 1141 | return IRQ_WAKE_THREAD; |
| 1142 | return IRQ_WAKE_THREAD; | ||
| 1143 | |||
| 1144 | return IRQ_HANDLED; | ||
| 1145 | } | 1142 | } |
| 1146 | 1143 | ||
| 1147 | static int sh_veu_probe(struct platform_device *pdev) | 1144 | static int sh_veu_probe(struct platform_device *pdev) |
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index eea832c5fd01..3a4efbdc7668 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
| @@ -643,9 +643,9 @@ static int soc_camera_close(struct file *file) | |||
| 643 | 643 | ||
| 644 | if (ici->ops->init_videobuf2) | 644 | if (ici->ops->init_videobuf2) |
| 645 | vb2_queue_release(&icd->vb2_vidq); | 645 | vb2_queue_release(&icd->vb2_vidq); |
| 646 | ici->ops->remove(icd); | ||
| 647 | |||
| 648 | __soc_camera_power_off(icd); | 646 | __soc_camera_power_off(icd); |
| 647 | |||
| 648 | ici->ops->remove(icd); | ||
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | if (icd->streamer == file) | 651 | if (icd->streamer == file) |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index c0beee2fa37c..d529ba788f41 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
| @@ -22,6 +22,7 @@ config RADIO_SI476X | |||
| 22 | tristate "Silicon Laboratories Si476x I2C FM Radio" | 22 | tristate "Silicon Laboratories Si476x I2C FM Radio" |
| 23 | depends on I2C && VIDEO_V4L2 | 23 | depends on I2C && VIDEO_V4L2 |
| 24 | depends on MFD_SI476X_CORE | 24 | depends on MFD_SI476X_CORE |
| 25 | depends on SND_SOC | ||
| 25 | select SND_SOC_SI476X | 26 | select SND_SOC_SI476X |
| 26 | ---help--- | 27 | ---help--- |
| 27 | Choose Y here if you have this FM radio chip. | 28 | Choose Y here if you have this FM radio chip. |
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9430c6a29937..9dc8bafe6486 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | #define FREQ_MUL (10000000 / 625) | 45 | #define FREQ_MUL (10000000 / 625) |
| 46 | 46 | ||
| 47 | #define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0b10000000 & (status)) | 47 | #define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0x80 & (status)) |
| 48 | 48 | ||
| 49 | #define DRIVER_NAME "si476x-radio" | 49 | #define DRIVER_NAME "si476x-radio" |
| 50 | #define DRIVER_CARD "SI476x AM/FM Receiver" | 50 | #define DRIVER_CARD "SI476x AM/FM Receiver" |
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig index f6768cad001a..15665debc572 100644 --- a/drivers/media/tuners/Kconfig +++ b/drivers/media/tuners/Kconfig | |||
| @@ -1,23 +1,3 @@ | |||
| 1 | config MEDIA_ATTACH | ||
| 2 | bool "Load and attach frontend and tuner driver modules as needed" | ||
| 3 | depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT | ||
| 4 | depends on MODULES | ||
| 5 | default y if !EXPERT | ||
| 6 | help | ||
| 7 | Remove the static dependency of DVB card drivers on all | ||
| 8 | frontend modules for all possible card variants. Instead, | ||
| 9 | allow the card drivers to only load the frontend modules | ||
| 10 | they require. | ||
| 11 | |||
| 12 | Also, tuner module will automatically load a tuner driver | ||
| 13 | when needed, for analog mode. | ||
| 14 | |||
| 15 | This saves several KBytes of memory. | ||
| 16 | |||
| 17 | Note: You will need module-init-tools v3.2 or later for this feature. | ||
| 18 | |||
| 19 | If unsure say Y. | ||
| 20 | |||
| 21 | # Analog TV tuners, auto-loaded via tuner.ko | 1 | # Analog TV tuners, auto-loaded via tuner.ko |
| 22 | config MEDIA_TUNER | 2 | config MEDIA_TUNER |
| 23 | tristate | 3 | tristate |
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 22015fe1a0f3..2cc8ec70e3b6 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |||
| @@ -376,7 +376,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
| 376 | struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; | 376 | struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; |
| 377 | struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; | 377 | struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; |
| 378 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; | 378 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; |
| 379 | struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 5, buf}; | 379 | struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf}; |
| 380 | 380 | ||
| 381 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | 381 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
| 382 | 382 | ||
| @@ -481,9 +481,9 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) | |||
| 481 | goto found; | 481 | goto found; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | /* check R820T by reading tuner stats at I2C addr 0x1a */ | 484 | /* check R820T ID register; reg=00 val=69 */ |
| 485 | ret = rtl28xxu_ctrl_msg(d, &req_r820t); | 485 | ret = rtl28xxu_ctrl_msg(d, &req_r820t); |
| 486 | if (ret == 0) { | 486 | if (ret == 0 && buf[0] == 0x69) { |
| 487 | priv->tuner = TUNER_RTL2832_R820T; | 487 | priv->tuner = TUNER_RTL2832_R820T; |
| 488 | priv->tuner_name = "R820T"; | 488 | priv->tuner_name = "R820T"; |
| 489 | goto found; | 489 | goto found; |
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 3fe207e038c7..d7ff3b9687c5 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c | |||
| @@ -1159,6 +1159,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 1159 | regs[0x01] = 0x44; /* Select 24 Mhz clock */ | 1159 | regs[0x01] = 0x44; /* Select 24 Mhz clock */ |
| 1160 | regs[0x12] = 0x02; /* Set hstart to 2 */ | 1160 | regs[0x12] = 0x02; /* Set hstart to 2 */ |
| 1161 | } | 1161 | } |
| 1162 | break; | ||
| 1163 | case SENSOR_PAS202: | ||
| 1164 | /* For some unknown reason we need to increase hstart by 1 on | ||
| 1165 | the sn9c103, otherwise we get wrong colors (bayer shift). */ | ||
| 1166 | if (sd->bridge == BRIDGE_103) | ||
| 1167 | regs[0x12] += 1; | ||
| 1168 | break; | ||
| 1162 | } | 1169 | } |
| 1163 | /* Disable compression when the raw bayer format has been selected */ | 1170 | /* Disable compression when the raw bayer format has been selected */ |
| 1164 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) | 1171 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) |
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h index 7a6a0d39c2c6..81b017a554bc 100644 --- a/drivers/media/usb/pwc/pwc.h +++ b/drivers/media/usb/pwc/pwc.h | |||
| @@ -226,7 +226,7 @@ struct pwc_device | |||
| 226 | struct list_head queued_bufs; | 226 | struct list_head queued_bufs; |
| 227 | spinlock_t queued_bufs_lock; /* Protects queued_bufs */ | 227 | spinlock_t queued_bufs_lock; /* Protects queued_bufs */ |
| 228 | 228 | ||
| 229 | /* Note if taking both locks v4l2_lock must always be locked first! */ | 229 | /* If taking both locks vb_queue_lock must always be locked first! */ |
| 230 | struct mutex v4l2_lock; /* Protects everything else */ | 230 | struct mutex v4l2_lock; /* Protects everything else */ |
| 231 | struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ | 231 | struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ |
| 232 | 232 | ||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index ebb8e48619a2..fccd08b66d1a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
| @@ -1835,6 +1835,8 @@ bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl) | |||
| 1835 | { | 1835 | { |
| 1836 | if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) | 1836 | if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) |
| 1837 | return true; | 1837 | return true; |
| 1838 | if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_RX) | ||
| 1839 | return true; | ||
| 1838 | switch (ctrl->id) { | 1840 | switch (ctrl->id) { |
| 1839 | case V4L2_CID_AUDIO_MUTE: | 1841 | case V4L2_CID_AUDIO_MUTE: |
| 1840 | case V4L2_CID_AUDIO_VOLUME: | 1842 | case V4L2_CID_AUDIO_VOLUME: |
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index f81bda1a48ec..7658586fe5f4 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c | |||
| @@ -243,7 +243,6 @@ static void v4l_print_format(const void *arg, bool write_only) | |||
| 243 | const struct v4l2_vbi_format *vbi; | 243 | const struct v4l2_vbi_format *vbi; |
| 244 | const struct v4l2_sliced_vbi_format *sliced; | 244 | const struct v4l2_sliced_vbi_format *sliced; |
| 245 | const struct v4l2_window *win; | 245 | const struct v4l2_window *win; |
| 246 | const struct v4l2_clip *clip; | ||
| 247 | unsigned i; | 246 | unsigned i; |
| 248 | 247 | ||
| 249 | pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); | 248 | pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); |
| @@ -253,7 +252,7 @@ static void v4l_print_format(const void *arg, bool write_only) | |||
| 253 | pix = &p->fmt.pix; | 252 | pix = &p->fmt.pix; |
| 254 | pr_cont(", width=%u, height=%u, " | 253 | pr_cont(", width=%u, height=%u, " |
| 255 | "pixelformat=%c%c%c%c, field=%s, " | 254 | "pixelformat=%c%c%c%c, field=%s, " |
| 256 | "bytesperline=%u sizeimage=%u, colorspace=%d\n", | 255 | "bytesperline=%u, sizeimage=%u, colorspace=%d\n", |
| 257 | pix->width, pix->height, | 256 | pix->width, pix->height, |
| 258 | (pix->pixelformat & 0xff), | 257 | (pix->pixelformat & 0xff), |
| 259 | (pix->pixelformat >> 8) & 0xff, | 258 | (pix->pixelformat >> 8) & 0xff, |
| @@ -284,20 +283,14 @@ static void v4l_print_format(const void *arg, bool write_only) | |||
| 284 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 283 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
| 285 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: | 284 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: |
| 286 | win = &p->fmt.win; | 285 | win = &p->fmt.win; |
| 287 | pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, " | 286 | /* Note: we can't print the clip list here since the clips |
| 288 | "chromakey=0x%08x, bitmap=%p, " | 287 | * pointer is a userspace pointer, not a kernelspace |
| 289 | "global_alpha=0x%02x\n", | 288 | * pointer. */ |
| 290 | win->w.width, win->w.height, | 289 | pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, clipcount=%u, clips=%p, bitmap=%p, global_alpha=0x%02x\n", |
| 291 | win->w.left, win->w.top, | 290 | win->w.width, win->w.height, win->w.left, win->w.top, |
| 292 | prt_names(win->field, v4l2_field_names), | 291 | prt_names(win->field, v4l2_field_names), |
| 293 | win->chromakey, win->bitmap, win->global_alpha); | 292 | win->chromakey, win->clipcount, win->clips, |
| 294 | clip = win->clips; | 293 | win->bitmap, win->global_alpha); |
| 295 | for (i = 0; i < win->clipcount; i++) { | ||
| 296 | printk(KERN_DEBUG "clip %u: wxh=%dx%d, x,y=%d,%d\n", | ||
| 297 | i, clip->c.width, clip->c.height, | ||
| 298 | clip->c.left, clip->c.top); | ||
| 299 | clip = clip->next; | ||
| 300 | } | ||
| 301 | break; | 294 | break; |
| 302 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 295 | case V4L2_BUF_TYPE_VBI_CAPTURE: |
| 303 | case V4L2_BUF_TYPE_VBI_OUTPUT: | 296 | case V4L2_BUF_TYPE_VBI_OUTPUT: |
| @@ -332,7 +325,7 @@ static void v4l_print_framebuffer(const void *arg, bool write_only) | |||
| 332 | 325 | ||
| 333 | pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, " | 326 | pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, " |
| 334 | "height=%u, pixelformat=%c%c%c%c, " | 327 | "height=%u, pixelformat=%c%c%c%c, " |
| 335 | "bytesperline=%u sizeimage=%u, colorspace=%d\n", | 328 | "bytesperline=%u, sizeimage=%u, colorspace=%d\n", |
| 336 | p->capability, p->flags, p->base, | 329 | p->capability, p->flags, p->base, |
| 337 | p->fmt.width, p->fmt.height, | 330 | p->fmt.width, p->fmt.height, |
| 338 | (p->fmt.pixelformat & 0xff), | 331 | (p->fmt.pixelformat & 0xff), |
| @@ -353,7 +346,7 @@ static void v4l_print_modulator(const void *arg, bool write_only) | |||
| 353 | const struct v4l2_modulator *p = arg; | 346 | const struct v4l2_modulator *p = arg; |
| 354 | 347 | ||
| 355 | if (write_only) | 348 | if (write_only) |
| 356 | pr_cont("index=%u, txsubchans=0x%x", p->index, p->txsubchans); | 349 | pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans); |
| 357 | else | 350 | else |
| 358 | pr_cont("index=%u, name=%.*s, capability=0x%x, " | 351 | pr_cont("index=%u, name=%.*s, capability=0x%x, " |
| 359 | "rangelow=%u, rangehigh=%u, txsubchans=0x%x\n", | 352 | "rangelow=%u, rangehigh=%u, txsubchans=0x%x\n", |
| @@ -445,13 +438,13 @@ static void v4l_print_buffer(const void *arg, bool write_only) | |||
| 445 | for (i = 0; i < p->length; ++i) { | 438 | for (i = 0; i < p->length; ++i) { |
| 446 | plane = &p->m.planes[i]; | 439 | plane = &p->m.planes[i]; |
| 447 | printk(KERN_DEBUG | 440 | printk(KERN_DEBUG |
| 448 | "plane %d: bytesused=%d, data_offset=0x%08x " | 441 | "plane %d: bytesused=%d, data_offset=0x%08x, " |
| 449 | "offset/userptr=0x%lx, length=%d\n", | 442 | "offset/userptr=0x%lx, length=%d\n", |
| 450 | i, plane->bytesused, plane->data_offset, | 443 | i, plane->bytesused, plane->data_offset, |
| 451 | plane->m.userptr, plane->length); | 444 | plane->m.userptr, plane->length); |
| 452 | } | 445 | } |
| 453 | } else { | 446 | } else { |
| 454 | pr_cont("bytesused=%d, offset/userptr=0x%lx, length=%d\n", | 447 | pr_cont(", bytesused=%d, offset/userptr=0x%lx, length=%d\n", |
| 455 | p->bytesused, p->m.userptr, p->length); | 448 | p->bytesused, p->m.userptr, p->length); |
| 456 | } | 449 | } |
| 457 | 450 | ||
| @@ -504,6 +497,8 @@ static void v4l_print_streamparm(const void *arg, bool write_only) | |||
| 504 | c->capability, c->outputmode, | 497 | c->capability, c->outputmode, |
| 505 | c->timeperframe.numerator, c->timeperframe.denominator, | 498 | c->timeperframe.numerator, c->timeperframe.denominator, |
| 506 | c->extendedmode, c->writebuffers); | 499 | c->extendedmode, c->writebuffers); |
| 500 | } else { | ||
| 501 | pr_cont("\n"); | ||
| 507 | } | 502 | } |
| 508 | } | 503 | } |
| 509 | 504 | ||
| @@ -734,11 +729,11 @@ static void v4l_print_frmsizeenum(const void *arg, bool write_only) | |||
| 734 | p->type); | 729 | p->type); |
| 735 | switch (p->type) { | 730 | switch (p->type) { |
| 736 | case V4L2_FRMSIZE_TYPE_DISCRETE: | 731 | case V4L2_FRMSIZE_TYPE_DISCRETE: |
| 737 | pr_cont(" wxh=%ux%u\n", | 732 | pr_cont(", wxh=%ux%u\n", |
| 738 | p->discrete.width, p->discrete.height); | 733 | p->discrete.width, p->discrete.height); |
| 739 | break; | 734 | break; |
| 740 | case V4L2_FRMSIZE_TYPE_STEPWISE: | 735 | case V4L2_FRMSIZE_TYPE_STEPWISE: |
| 741 | pr_cont(" min=%ux%u, max=%ux%u, step=%ux%u\n", | 736 | pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n", |
| 742 | p->stepwise.min_width, p->stepwise.min_height, | 737 | p->stepwise.min_width, p->stepwise.min_height, |
| 743 | p->stepwise.step_width, p->stepwise.step_height, | 738 | p->stepwise.step_width, p->stepwise.step_height, |
| 744 | p->stepwise.max_width, p->stepwise.max_height); | 739 | p->stepwise.max_width, p->stepwise.max_height); |
| @@ -764,12 +759,12 @@ static void v4l_print_frmivalenum(const void *arg, bool write_only) | |||
| 764 | p->width, p->height, p->type); | 759 | p->width, p->height, p->type); |
| 765 | switch (p->type) { | 760 | switch (p->type) { |
| 766 | case V4L2_FRMIVAL_TYPE_DISCRETE: | 761 | case V4L2_FRMIVAL_TYPE_DISCRETE: |
| 767 | pr_cont(" fps=%d/%d\n", | 762 | pr_cont(", fps=%d/%d\n", |
| 768 | p->discrete.numerator, | 763 | p->discrete.numerator, |
| 769 | p->discrete.denominator); | 764 | p->discrete.denominator); |
| 770 | break; | 765 | break; |
| 771 | case V4L2_FRMIVAL_TYPE_STEPWISE: | 766 | case V4L2_FRMIVAL_TYPE_STEPWISE: |
| 772 | pr_cont(" min=%d/%d, max=%d/%d, step=%d/%d\n", | 767 | pr_cont(", min=%d/%d, max=%d/%d, step=%d/%d\n", |
| 773 | p->stepwise.min.numerator, | 768 | p->stepwise.min.numerator, |
| 774 | p->stepwise.min.denominator, | 769 | p->stepwise.min.denominator, |
| 775 | p->stepwise.max.numerator, | 770 | p->stepwise.max.numerator, |
| @@ -807,8 +802,8 @@ static void v4l_print_event(const void *arg, bool write_only) | |||
| 807 | pr_cont("value64=%lld, ", c->value64); | 802 | pr_cont("value64=%lld, ", c->value64); |
| 808 | else | 803 | else |
| 809 | pr_cont("value=%d, ", c->value); | 804 | pr_cont("value=%d, ", c->value); |
| 810 | pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d," | 805 | pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, " |
| 811 | " default_value=%d\n", | 806 | "default_value=%d\n", |
| 812 | c->flags, c->minimum, c->maximum, | 807 | c->flags, c->minimum, c->maximum, |
| 813 | c->step, c->default_value); | 808 | c->step, c->default_value); |
| 814 | break; | 809 | break; |
| @@ -845,7 +840,7 @@ static void v4l_print_freq_band(const void *arg, bool write_only) | |||
| 845 | const struct v4l2_frequency_band *p = arg; | 840 | const struct v4l2_frequency_band *p = arg; |
| 846 | 841 | ||
| 847 | pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, " | 842 | pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, " |
| 848 | "rangelow=%u, rangehigh=%u, modulation=0x%x\n", | 843 | "rangelow=%u, rangehigh=%u, modulation=0x%x\n", |
| 849 | p->tuner, p->type, p->index, | 844 | p->tuner, p->type, p->index, |
| 850 | p->capability, p->rangelow, | 845 | p->capability, p->rangelow, |
| 851 | p->rangehigh, p->modulation); | 846 | p->rangehigh, p->modulation); |
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 66f599fcb829..e96497f7c3ed 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | |||
| @@ -205,7 +205,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) | |||
| 205 | static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | 205 | static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) |
| 206 | { | 206 | { |
| 207 | struct v4l2_m2m_dev *m2m_dev; | 207 | struct v4l2_m2m_dev *m2m_dev; |
| 208 | unsigned long flags_job, flags; | 208 | unsigned long flags_job, flags_out, flags_cap; |
| 209 | 209 | ||
| 210 | m2m_dev = m2m_ctx->m2m_dev; | 210 | m2m_dev = m2m_ctx->m2m_dev; |
| 211 | dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); | 211 | dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); |
| @@ -223,23 +223,26 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
| 223 | return; | 223 | return; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); | 226 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); |
| 227 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { | 227 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { |
| 228 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); | 228 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, |
| 229 | flags_out); | ||
| 229 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | 230 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); |
| 230 | dprintk("No input buffers available\n"); | 231 | dprintk("No input buffers available\n"); |
| 231 | return; | 232 | return; |
| 232 | } | 233 | } |
| 233 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); | 234 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); |
| 234 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { | 235 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { |
| 235 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); | 236 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, |
| 236 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); | 237 | flags_cap); |
| 238 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, | ||
| 239 | flags_out); | ||
| 237 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | 240 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); |
| 238 | dprintk("No output buffers available\n"); | 241 | dprintk("No output buffers available\n"); |
| 239 | return; | 242 | return; |
| 240 | } | 243 | } |
| 241 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); | 244 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); |
| 242 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); | 245 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); |
| 243 | 246 | ||
| 244 | if (m2m_dev->m2m_ops->job_ready | 247 | if (m2m_dev->m2m_ops->job_ready |
| 245 | && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { | 248 | && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { |
| @@ -372,6 +375,20 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 372 | EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); | 375 | EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); |
| 373 | 376 | ||
| 374 | /** | 377 | /** |
| 378 | * v4l2_m2m_create_bufs() - create a source or destination buffer, depending | ||
| 379 | * on the type | ||
| 380 | */ | ||
| 381 | int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
| 382 | struct v4l2_create_buffers *create) | ||
| 383 | { | ||
| 384 | struct vb2_queue *vq; | ||
| 385 | |||
| 386 | vq = v4l2_m2m_get_vq(m2m_ctx, create->format.type); | ||
| 387 | return vb2_create_bufs(vq, create); | ||
| 388 | } | ||
| 389 | EXPORT_SYMBOL_GPL(v4l2_m2m_create_bufs); | ||
| 390 | |||
| 391 | /** | ||
| 375 | * v4l2_m2m_expbuf() - export a source or destination buffer, depending on | 392 | * v4l2_m2m_expbuf() - export a source or destination buffer, depending on |
| 376 | * the type | 393 | * the type |
| 377 | */ | 394 | */ |
| @@ -486,8 +503,10 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 486 | if (m2m_ctx->m2m_dev->m2m_ops->unlock) | 503 | if (m2m_ctx->m2m_dev->m2m_ops->unlock) |
| 487 | m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv); | 504 | m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv); |
| 488 | 505 | ||
| 489 | poll_wait(file, &src_q->done_wq, wait); | 506 | if (list_empty(&src_q->done_list)) |
| 490 | poll_wait(file, &dst_q->done_wq, wait); | 507 | poll_wait(file, &src_q->done_wq, wait); |
| 508 | if (list_empty(&dst_q->done_list)) | ||
| 509 | poll_wait(file, &dst_q->done_wq, wait); | ||
| 491 | 510 | ||
| 492 | if (m2m_ctx->m2m_dev->m2m_ops->lock) | 511 | if (m2m_ctx->m2m_dev->m2m_ops->lock) |
| 493 | m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv); | 512 | m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv); |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 7d833eefaf4e..e3bdc3be91e1 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
| @@ -2014,7 +2014,8 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) | |||
| 2014 | if (list_empty(&q->queued_list)) | 2014 | if (list_empty(&q->queued_list)) |
| 2015 | return res | POLLERR; | 2015 | return res | POLLERR; |
| 2016 | 2016 | ||
| 2017 | poll_wait(file, &q->done_wq, wait); | 2017 | if (list_empty(&q->done_list)) |
| 2018 | poll_wait(file, &q->done_wq, wait); | ||
| 2018 | 2019 | ||
| 2019 | /* | 2020 | /* |
| 2020 | * Take first buffer available for dequeuing. | 2021 | * Take first buffer available for dequeuing. |
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/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c index 6e8bc9d88c41..94d957d203a6 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c +++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c | |||
| @@ -244,7 +244,7 @@ bnad_debugfs_lseek(struct file *file, loff_t offset, int orig) | |||
| 244 | file->f_pos += offset; | 244 | file->f_pos += offset; |
| 245 | break; | 245 | break; |
| 246 | case 2: | 246 | case 2: |
| 247 | file->f_pos = debug->buffer_len - offset; | 247 | file->f_pos = debug->buffer_len + offset; |
| 248 | break; | 248 | break; |
| 249 | default: | 249 | default: |
| 250 | return -EINVAL; | 250 | return -EINVAL; |
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 9544cdc0d1af..e79e006eb9ab 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
| @@ -811,6 +811,70 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) | |||
| 811 | return pcidev->irq; | 811 | return pcidev->irq; |
| 812 | } | 812 | } |
| 813 | 813 | ||
| 814 | static struct iosapic_info *first_isi = NULL; | ||
| 815 | |||
| 816 | #ifdef CONFIG_64BIT | ||
| 817 | int iosapic_serial_irq(int num) | ||
| 818 | { | ||
| 819 | struct iosapic_info *isi = first_isi; | ||
| 820 | struct irt_entry *irte = NULL; /* only used if PAT PDC */ | ||
| 821 | struct vector_info *vi; | ||
| 822 | int isi_line; /* line used by device */ | ||
| 823 | |||
| 824 | /* lookup IRT entry for isi/slot/pin set */ | ||
| 825 | irte = &irt_cell[num]; | ||
| 826 | |||
| 827 | DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n", | ||
| 828 | irte, | ||
| 829 | irte->entry_type, | ||
| 830 | irte->entry_length, | ||
| 831 | irte->polarity_trigger, | ||
| 832 | irte->src_bus_irq_devno, | ||
| 833 | irte->src_bus_id, | ||
| 834 | irte->src_seg_id, | ||
| 835 | irte->dest_iosapic_intin, | ||
| 836 | (u32) irte->dest_iosapic_addr); | ||
| 837 | isi_line = irte->dest_iosapic_intin; | ||
| 838 | |||
| 839 | /* get vector info for this input line */ | ||
| 840 | vi = isi->isi_vector + isi_line; | ||
| 841 | DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", isi_line, vi); | ||
| 842 | |||
| 843 | /* If this IRQ line has already been setup, skip it */ | ||
| 844 | if (vi->irte) | ||
| 845 | goto out; | ||
| 846 | |||
| 847 | vi->irte = irte; | ||
| 848 | |||
| 849 | /* | ||
| 850 | * Allocate processor IRQ | ||
| 851 | * | ||
| 852 | * XXX/FIXME The txn_alloc_irq() code and related code should be | ||
| 853 | * moved to enable_irq(). That way we only allocate processor IRQ | ||
| 854 | * bits for devices that actually have drivers claiming them. | ||
| 855 | * Right now we assign an IRQ to every PCI device present, | ||
| 856 | * regardless of whether it's used or not. | ||
| 857 | */ | ||
| 858 | vi->txn_irq = txn_alloc_irq(8); | ||
| 859 | |||
| 860 | if (vi->txn_irq < 0) | ||
| 861 | panic("I/O sapic: couldn't get TXN IRQ\n"); | ||
| 862 | |||
| 863 | /* enable_irq() will use txn_* to program IRdT */ | ||
| 864 | vi->txn_addr = txn_alloc_addr(vi->txn_irq); | ||
| 865 | vi->txn_data = txn_alloc_data(vi->txn_irq); | ||
| 866 | |||
| 867 | vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; | ||
| 868 | vi->eoi_data = cpu_to_le32(vi->txn_data); | ||
| 869 | |||
| 870 | cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); | ||
| 871 | |||
| 872 | out: | ||
| 873 | |||
| 874 | return vi->txn_irq; | ||
| 875 | } | ||
| 876 | #endif | ||
| 877 | |||
| 814 | 878 | ||
| 815 | /* | 879 | /* |
| 816 | ** squirrel away the I/O Sapic Version | 880 | ** squirrel away the I/O Sapic Version |
| @@ -877,6 +941,8 @@ void *iosapic_register(unsigned long hpa) | |||
| 877 | vip->irqline = (unsigned char) cnt; | 941 | vip->irqline = (unsigned char) cnt; |
| 878 | vip->iosapic = isi; | 942 | vip->iosapic = isi; |
| 879 | } | 943 | } |
| 944 | if (!first_isi) | ||
| 945 | first_isi = isi; | ||
| 880 | return isi; | 946 | return isi; |
| 881 | } | 947 | } |
| 882 | 948 | ||
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c index 439c012be763..b63d534192e3 100644 --- a/drivers/scsi/bfa/bfad_debugfs.c +++ b/drivers/scsi/bfa/bfad_debugfs.c | |||
| @@ -186,7 +186,7 @@ bfad_debugfs_lseek(struct file *file, loff_t offset, int orig) | |||
| 186 | file->f_pos += offset; | 186 | file->f_pos += offset; |
| 187 | break; | 187 | break; |
| 188 | case 2: | 188 | case 2: |
| 189 | file->f_pos = debug->buffer_len - offset; | 189 | file->f_pos = debug->buffer_len + offset; |
| 190 | break; | 190 | break; |
| 191 | default: | 191 | default: |
| 192 | return -EINVAL; | 192 | return -EINVAL; |
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index adc1f7f471f5..85e1ffd0e5c5 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c | |||
| @@ -174,7 +174,7 @@ static loff_t fnic_trace_debugfs_lseek(struct file *file, | |||
| 174 | pos = file->f_pos + offset; | 174 | pos = file->f_pos + offset; |
| 175 | break; | 175 | break; |
| 176 | case 2: | 176 | case 2: |
| 177 | pos = fnic_dbg_prt->buffer_len - offset; | 177 | pos = fnic_dbg_prt->buffer_len + offset; |
| 178 | } | 178 | } |
| 179 | return (pos < 0 || pos > fnic_dbg_prt->buffer_len) ? | 179 | return (pos < 0 || pos > fnic_dbg_prt->buffer_len) ? |
| 180 | -EINVAL : (file->f_pos = pos); | 180 | -EINVAL : (file->f_pos = pos); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index f63f5ff7f274..f525ecb7a9c6 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
| @@ -1178,7 +1178,7 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence) | |||
| 1178 | pos = file->f_pos + off; | 1178 | pos = file->f_pos + off; |
| 1179 | break; | 1179 | break; |
| 1180 | case 2: | 1180 | case 2: |
| 1181 | pos = debug->len - off; | 1181 | pos = debug->len + off; |
| 1182 | } | 1182 | } |
| 1183 | return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos); | 1183 | return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos); |
| 1184 | } | 1184 | } |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7a3870f385f6..66b0b26a1381 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
| @@ -688,8 +688,12 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) | |||
| 688 | * For FCP_READ with CHECK_CONDITION status, clear cmd->bufflen | 688 | * For FCP_READ with CHECK_CONDITION status, clear cmd->bufflen |
| 689 | * for qla_tgt_xmit_response LLD code | 689 | * for qla_tgt_xmit_response LLD code |
| 690 | */ | 690 | */ |
| 691 | if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
| 692 | se_cmd->se_cmd_flags &= ~SCF_OVERFLOW_BIT; | ||
| 693 | se_cmd->residual_count = 0; | ||
| 694 | } | ||
| 691 | se_cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; | 695 | se_cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; |
| 692 | se_cmd->residual_count = se_cmd->data_length; | 696 | se_cmd->residual_count += se_cmd->data_length; |
| 693 | 697 | ||
| 694 | cmd->bufflen = 0; | 698 | cmd->bufflen = 0; |
| 695 | } | 699 | } |
diff --git a/drivers/staging/media/davinci_vpfe/Kconfig b/drivers/staging/media/davinci_vpfe/Kconfig index 2e4a28b018e8..12f321dd2399 100644 --- a/drivers/staging/media/davinci_vpfe/Kconfig +++ b/drivers/staging/media/davinci_vpfe/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config VIDEO_DM365_VPFE | 1 | config VIDEO_DM365_VPFE |
| 2 | tristate "DM365 VPFE Media Controller Capture Driver" | 2 | tristate "DM365 VPFE Media Controller Capture Driver" |
| 3 | depends on VIDEO_V4L2 && ARCH_DAVINCI_DM365 && !VIDEO_VPFE_CAPTURE | 3 | depends on VIDEO_V4L2 && ARCH_DAVINCI_DM365 && !VIDEO_DM365_ISIF |
| 4 | select VIDEOBUF2_DMA_CONTIG | 4 | select VIDEOBUF2_DMA_CONTIG |
| 5 | help | 5 | help |
| 6 | Support for DM365 VPFE based Media Controller Capture driver. | 6 | Support for DM365 VPFE based Media Controller Capture driver. |
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c index b88e1ddce229..d8ce20d2fbda 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c | |||
| @@ -639,7 +639,8 @@ static int vpfe_probe(struct platform_device *pdev) | |||
| 639 | if (ret) | 639 | if (ret) |
| 640 | goto probe_free_dev_mem; | 640 | goto probe_free_dev_mem; |
| 641 | 641 | ||
| 642 | if (vpfe_initialize_modules(vpfe_dev, pdev)) | 642 | ret = vpfe_initialize_modules(vpfe_dev, pdev); |
| 643 | if (ret) | ||
| 643 | goto probe_disable_clock; | 644 | goto probe_disable_clock; |
| 644 | 645 | ||
| 645 | vpfe_dev->media_dev.dev = vpfe_dev->pdev; | 646 | vpfe_dev->media_dev.dev = vpfe_dev->pdev; |
| @@ -663,7 +664,8 @@ static int vpfe_probe(struct platform_device *pdev) | |||
| 663 | /* set the driver data in platform device */ | 664 | /* set the driver data in platform device */ |
| 664 | platform_set_drvdata(pdev, vpfe_dev); | 665 | platform_set_drvdata(pdev, vpfe_dev); |
| 665 | /* register subdevs/entities */ | 666 | /* register subdevs/entities */ |
| 666 | if (vpfe_register_entities(vpfe_dev)) | 667 | ret = vpfe_register_entities(vpfe_dev); |
| 668 | if (ret) | ||
| 667 | goto probe_out_v4l2_unregister; | 669 | goto probe_out_v4l2_unregister; |
| 668 | 670 | ||
| 669 | ret = vpfe_attach_irq(vpfe_dev); | 671 | ret = vpfe_attach_irq(vpfe_dev); |
diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig index df6569b997b8..34f3b6d02d2a 100644 --- a/drivers/staging/media/solo6x10/Kconfig +++ b/drivers/staging/media/solo6x10/Kconfig | |||
| @@ -5,6 +5,7 @@ config SOLO6X10 | |||
| 5 | select VIDEOBUF2_DMA_SG | 5 | select VIDEOBUF2_DMA_SG |
| 6 | select VIDEOBUF2_DMA_CONTIG | 6 | select VIDEOBUF2_DMA_CONTIG |
| 7 | select SND_PCM | 7 | select SND_PCM |
| 8 | select FONT_8x16 | ||
| 8 | ---help--- | 9 | ---help--- |
| 9 | This driver supports the Softlogic based MPEG-4 and h.264 codec | 10 | This driver supports the Softlogic based MPEG-4 and h.264 codec |
| 10 | cards. | 11 | cards. |
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 13e9e715ad2e..8d8b3ff68490 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c | |||
| @@ -155,7 +155,7 @@ static ssize_t lio_target_np_store_iser( | |||
| 155 | struct iscsi_tpg_np *tpg_np_iser = NULL; | 155 | struct iscsi_tpg_np *tpg_np_iser = NULL; |
| 156 | char *endptr; | 156 | char *endptr; |
| 157 | u32 op; | 157 | u32 op; |
| 158 | int rc; | 158 | int rc = 0; |
| 159 | 159 | ||
| 160 | op = simple_strtoul(page, &endptr, 0); | 160 | op = simple_strtoul(page, &endptr, 0); |
| 161 | if ((op != 1) && (op != 0)) { | 161 | if ((op != 1) && (op != 0)) { |
| @@ -174,31 +174,32 @@ static ssize_t lio_target_np_store_iser( | |||
| 174 | return -EINVAL; | 174 | return -EINVAL; |
| 175 | 175 | ||
| 176 | if (op) { | 176 | if (op) { |
| 177 | int rc = request_module("ib_isert"); | 177 | rc = request_module("ib_isert"); |
| 178 | if (rc != 0) | 178 | if (rc != 0) { |
| 179 | pr_warn("Unable to request_module for ib_isert\n"); | 179 | pr_warn("Unable to request_module for ib_isert\n"); |
| 180 | rc = 0; | ||
| 181 | } | ||
| 180 | 182 | ||
| 181 | tpg_np_iser = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr, | 183 | tpg_np_iser = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr, |
| 182 | np->np_ip, tpg_np, ISCSI_INFINIBAND); | 184 | np->np_ip, tpg_np, ISCSI_INFINIBAND); |
| 183 | if (!tpg_np_iser || IS_ERR(tpg_np_iser)) | 185 | if (IS_ERR(tpg_np_iser)) { |
| 186 | rc = PTR_ERR(tpg_np_iser); | ||
| 184 | goto out; | 187 | goto out; |
| 188 | } | ||
| 185 | } else { | 189 | } else { |
| 186 | tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND); | 190 | tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND); |
| 187 | if (!tpg_np_iser) | 191 | if (tpg_np_iser) { |
| 188 | goto out; | 192 | rc = iscsit_tpg_del_network_portal(tpg, tpg_np_iser); |
| 189 | 193 | if (rc < 0) | |
| 190 | rc = iscsit_tpg_del_network_portal(tpg, tpg_np_iser); | 194 | goto out; |
| 191 | if (rc < 0) | 195 | } |
| 192 | goto out; | ||
| 193 | } | 196 | } |
| 194 | 197 | ||
| 195 | printk("lio_target_np_store_iser() done, op: %d\n", op); | ||
| 196 | |||
| 197 | iscsit_put_tpg(tpg); | 198 | iscsit_put_tpg(tpg); |
| 198 | return count; | 199 | return count; |
| 199 | out: | 200 | out: |
| 200 | iscsit_put_tpg(tpg); | 201 | iscsit_put_tpg(tpg); |
| 201 | return -EINVAL; | 202 | return rc; |
| 202 | } | 203 | } |
| 203 | 204 | ||
| 204 | TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR); | 205 | TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR); |
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 8e6298cc8839..dcb199da06b9 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c | |||
| @@ -842,11 +842,11 @@ int iscsit_stop_time2retain_timer(struct iscsi_session *sess) | |||
| 842 | return 0; | 842 | return 0; |
| 843 | 843 | ||
| 844 | sess->time2retain_timer_flags |= ISCSI_TF_STOP; | 844 | sess->time2retain_timer_flags |= ISCSI_TF_STOP; |
| 845 | spin_unlock_bh(&se_tpg->session_lock); | 845 | spin_unlock(&se_tpg->session_lock); |
| 846 | 846 | ||
| 847 | del_timer_sync(&sess->time2retain_timer); | 847 | del_timer_sync(&sess->time2retain_timer); |
| 848 | 848 | ||
| 849 | spin_lock_bh(&se_tpg->session_lock); | 849 | spin_lock(&se_tpg->session_lock); |
| 850 | sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING; | 850 | sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING; |
| 851 | pr_debug("Stopped Time2Retain Timer for SID: %u\n", | 851 | pr_debug("Stopped Time2Retain Timer for SID: %u\n", |
| 852 | sess->sid); | 852 | sess->sid); |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index bb5d5c5bce65..3402241be87c 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -984,8 +984,6 @@ int iscsi_target_setup_login_socket( | |||
| 984 | } | 984 | } |
| 985 | 985 | ||
| 986 | np->np_transport = t; | 986 | np->np_transport = t; |
| 987 | printk("Set np->np_transport to %p -> %s\n", np->np_transport, | ||
| 988 | np->np_transport->name); | ||
| 989 | return 0; | 987 | return 0; |
| 990 | } | 988 | } |
| 991 | 989 | ||
| @@ -1002,7 +1000,6 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) | |||
| 1002 | 1000 | ||
| 1003 | conn->sock = new_sock; | 1001 | conn->sock = new_sock; |
| 1004 | conn->login_family = np->np_sockaddr.ss_family; | 1002 | conn->login_family = np->np_sockaddr.ss_family; |
| 1005 | printk("iSCSI/TCP: Setup conn->sock from new_sock: %p\n", new_sock); | ||
| 1006 | 1003 | ||
| 1007 | if (np->np_sockaddr.ss_family == AF_INET6) { | 1004 | if (np->np_sockaddr.ss_family == AF_INET6) { |
| 1008 | memset(&sock_in6, 0, sizeof(struct sockaddr_in6)); | 1005 | memset(&sock_in6, 0, sizeof(struct sockaddr_in6)); |
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 7ad912060e21..cd5018ff9cd7 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c | |||
| @@ -721,9 +721,6 @@ int iscsi_target_locate_portal( | |||
| 721 | 721 | ||
| 722 | start += strlen(key) + strlen(value) + 2; | 722 | start += strlen(key) + strlen(value) + 2; |
| 723 | } | 723 | } |
| 724 | |||
| 725 | printk("i_buf: %s, s_buf: %s, t_buf: %s\n", i_buf, s_buf, t_buf); | ||
| 726 | |||
| 727 | /* | 724 | /* |
| 728 | * See 5.3. Login Phase. | 725 | * See 5.3. Login Phase. |
| 729 | */ | 726 | */ |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 59bfaecc4e14..abfd99089781 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
| @@ -244,14 +244,9 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
| 244 | 244 | ||
| 245 | static int pty_open(struct tty_struct *tty, struct file *filp) | 245 | static int pty_open(struct tty_struct *tty, struct file *filp) |
| 246 | { | 246 | { |
| 247 | int retval = -ENODEV; | ||
| 248 | |||
| 249 | if (!tty || !tty->link) | 247 | if (!tty || !tty->link) |
| 250 | goto out; | 248 | return -ENODEV; |
| 251 | |||
| 252 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 253 | 249 | ||
| 254 | retval = -EIO; | ||
| 255 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) | 250 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) |
| 256 | goto out; | 251 | goto out; |
| 257 | if (test_bit(TTY_PTY_LOCK, &tty->link->flags)) | 252 | if (test_bit(TTY_PTY_LOCK, &tty->link->flags)) |
| @@ -262,9 +257,11 @@ static int pty_open(struct tty_struct *tty, struct file *filp) | |||
| 262 | clear_bit(TTY_IO_ERROR, &tty->flags); | 257 | clear_bit(TTY_IO_ERROR, &tty->flags); |
| 263 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); | 258 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); |
| 264 | set_bit(TTY_THROTTLED, &tty->flags); | 259 | set_bit(TTY_THROTTLED, &tty->flags); |
| 265 | retval = 0; | 260 | return 0; |
| 261 | |||
| 266 | out: | 262 | out: |
| 267 | return retval; | 263 | set_bit(TTY_IO_ERROR, &tty->flags); |
| 264 | return -EIO; | ||
| 268 | } | 265 | } |
| 269 | 266 | ||
| 270 | static void pty_set_termios(struct tty_struct *tty, | 267 | static void pty_set_termios(struct tty_struct *tty, |
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 097dff9c08ad..bb91b4713ebd 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c | |||
| @@ -30,6 +30,12 @@ static int __init serial_init_chip(struct parisc_device *dev) | |||
| 30 | unsigned long address; | 30 | unsigned long address; |
| 31 | int err; | 31 | int err; |
| 32 | 32 | ||
| 33 | #ifdef CONFIG_64BIT | ||
| 34 | extern int iosapic_serial_irq(int cellnum); | ||
| 35 | if (!dev->irq && (dev->id.sversion == 0xad)) | ||
| 36 | dev->irq = iosapic_serial_irq(dev->mod_index-1); | ||
| 37 | #endif | ||
| 38 | |||
| 33 | if (!dev->irq) { | 39 | if (!dev->irq) { |
| 34 | /* We find some unattached serial ports by walking native | 40 | /* We find some unattached serial ports by walking native |
| 35 | * busses. These should be silently ignored. Otherwise, | 41 | * busses. These should be silently ignored. Otherwise, |
| @@ -51,7 +57,8 @@ static int __init serial_init_chip(struct parisc_device *dev) | |||
| 51 | memset(&uart, 0, sizeof(uart)); | 57 | memset(&uart, 0, sizeof(uart)); |
| 52 | uart.port.iotype = UPIO_MEM; | 58 | uart.port.iotype = UPIO_MEM; |
| 53 | /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ | 59 | /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ |
| 54 | uart.port.uartclk = 7272727; | 60 | uart.port.uartclk = (dev->id.sversion != 0xad) ? |
| 61 | 7272727 : 1843200; | ||
| 55 | uart.port.mapbase = address; | 62 | uart.port.mapbase = address; |
| 56 | uart.port.membase = ioremap_nocache(address, 16); | 63 | uart.port.membase = ioremap_nocache(address, 16); |
| 57 | uart.port.irq = dev->irq; | 64 | uart.port.irq = dev->irq; |
| @@ -73,6 +80,7 @@ static struct parisc_device_id serial_tbl[] = { | |||
| 73 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, | 80 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, |
| 74 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, | 81 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, |
| 75 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, | 82 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, |
| 83 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x000ad }, | ||
| 76 | { 0 } | 84 | { 0 } |
| 77 | }; | 85 | }; |
| 78 | 86 | ||
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index fc2c06c66e89..2bd78e2ac8ec 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
| @@ -289,13 +289,10 @@ static int vt_disallocate(unsigned int vc_num) | |||
| 289 | struct vc_data *vc = NULL; | 289 | struct vc_data *vc = NULL; |
| 290 | int ret = 0; | 290 | int ret = 0; |
| 291 | 291 | ||
| 292 | if (!vc_num) | ||
| 293 | return 0; | ||
| 294 | |||
| 295 | console_lock(); | 292 | console_lock(); |
| 296 | if (VT_BUSY(vc_num)) | 293 | if (VT_BUSY(vc_num)) |
| 297 | ret = -EBUSY; | 294 | ret = -EBUSY; |
| 298 | else | 295 | else if (vc_num) |
| 299 | vc = vc_deallocate(vc_num); | 296 | vc = vc_deallocate(vc_num); |
| 300 | console_unlock(); | 297 | console_unlock(); |
| 301 | 298 | ||
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 7ef3eb8617a6..2311b1e4e43c 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
| @@ -4,11 +4,17 @@ | |||
| 4 | menuconfig USB_PHY | 4 | menuconfig USB_PHY |
| 5 | bool "USB Physical Layer drivers" | 5 | bool "USB Physical Layer drivers" |
| 6 | help | 6 | help |
| 7 | USB controllers (those which are host, device or DRD) need a | 7 | Most USB controllers have the physical layer signalling part |
| 8 | device to handle the physical layer signalling, commonly called | 8 | (commonly called a PHY) built in. However, dual-role devices |
| 9 | a PHY. | 9 | (a.k.a. USB on-the-go) which support being USB master or slave |
| 10 | with the same connector often use an external PHY. | ||
| 10 | 11 | ||
| 11 | The following drivers add support for such PHY devices. | 12 | The drivers in this submenu add support for such PHY devices. |
| 13 | They are not needed for standard master-only (or the vast | ||
| 14 | majority of slave-only) USB interfaces. | ||
| 15 | |||
| 16 | If you're not sure if this applies to you, it probably doesn't; | ||
| 17 | say N here. | ||
| 12 | 18 | ||
| 13 | if USB_PHY | 19 | if USB_PHY |
| 14 | 20 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index c92c5ed4e580..e581c2549a57 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
| @@ -172,7 +172,8 @@ static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = { | |||
| 172 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | 172 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, |
| 173 | { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, | 173 | { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, |
| 174 | { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, | 174 | { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, |
| 175 | { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, | 175 | { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) }, |
| 176 | { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, | ||
| 176 | { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, | 177 | { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, |
| 177 | }; | 178 | }; |
| 178 | 179 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index b353e7e3d480..4a2423e84d55 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h | |||
| @@ -52,7 +52,9 @@ | |||
| 52 | 52 | ||
| 53 | /* Abbott Diabetics vendor and product ids */ | 53 | /* Abbott Diabetics vendor and product ids */ |
| 54 | #define ABBOTT_VENDOR_ID 0x1a61 | 54 | #define ABBOTT_VENDOR_ID 0x1a61 |
| 55 | #define ABBOTT_PRODUCT_ID 0x3410 | 55 | #define ABBOTT_STEREO_PLUG_ID 0x3410 |
| 56 | #define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID | ||
| 57 | #define ABBOTT_STRIP_PORT_ID 0x3420 | ||
| 56 | 58 | ||
| 57 | /* Commands */ | 59 | /* Commands */ |
| 58 | #define TI_GET_VERSION 0x01 | 60 | #define TI_GET_VERSION 0x01 |
diff --git a/fs/internal.h b/fs/internal.h index eaa75f75b625..68121584ae37 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -132,6 +132,12 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); | |||
| 132 | extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); | 132 | extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); |
| 133 | 133 | ||
| 134 | /* | 134 | /* |
| 135 | * splice.c | ||
| 136 | */ | ||
| 137 | extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | ||
| 138 | loff_t *opos, size_t len, unsigned int flags); | ||
| 139 | |||
| 140 | /* | ||
| 135 | * pipe.c | 141 | * pipe.c |
| 136 | */ | 142 | */ |
| 137 | extern const struct file_operations pipefifo_fops; | 143 | extern const struct file_operations pipefifo_fops; |
diff --git a/fs/read_write.c b/fs/read_write.c index 03430008704e..2cefa417be34 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -1064,6 +1064,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 1064 | struct fd in, out; | 1064 | struct fd in, out; |
| 1065 | struct inode *in_inode, *out_inode; | 1065 | struct inode *in_inode, *out_inode; |
| 1066 | loff_t pos; | 1066 | loff_t pos; |
| 1067 | loff_t out_pos; | ||
| 1067 | ssize_t retval; | 1068 | ssize_t retval; |
| 1068 | int fl; | 1069 | int fl; |
| 1069 | 1070 | ||
| @@ -1077,12 +1078,14 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 1077 | if (!(in.file->f_mode & FMODE_READ)) | 1078 | if (!(in.file->f_mode & FMODE_READ)) |
| 1078 | goto fput_in; | 1079 | goto fput_in; |
| 1079 | retval = -ESPIPE; | 1080 | retval = -ESPIPE; |
| 1080 | if (!ppos) | 1081 | if (!ppos) { |
| 1081 | ppos = &in.file->f_pos; | 1082 | pos = in.file->f_pos; |
| 1082 | else | 1083 | } else { |
| 1084 | pos = *ppos; | ||
| 1083 | if (!(in.file->f_mode & FMODE_PREAD)) | 1085 | if (!(in.file->f_mode & FMODE_PREAD)) |
| 1084 | goto fput_in; | 1086 | goto fput_in; |
| 1085 | retval = rw_verify_area(READ, in.file, ppos, count); | 1087 | } |
| 1088 | retval = rw_verify_area(READ, in.file, &pos, count); | ||
| 1086 | if (retval < 0) | 1089 | if (retval < 0) |
| 1087 | goto fput_in; | 1090 | goto fput_in; |
| 1088 | count = retval; | 1091 | count = retval; |
| @@ -1099,7 +1102,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 1099 | retval = -EINVAL; | 1102 | retval = -EINVAL; |
| 1100 | in_inode = file_inode(in.file); | 1103 | in_inode = file_inode(in.file); |
| 1101 | out_inode = file_inode(out.file); | 1104 | out_inode = file_inode(out.file); |
| 1102 | retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count); | 1105 | out_pos = out.file->f_pos; |
| 1106 | retval = rw_verify_area(WRITE, out.file, &out_pos, count); | ||
| 1103 | if (retval < 0) | 1107 | if (retval < 0) |
| 1104 | goto fput_out; | 1108 | goto fput_out; |
| 1105 | count = retval; | 1109 | count = retval; |
| @@ -1107,7 +1111,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 1107 | if (!max) | 1111 | if (!max) |
| 1108 | max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); | 1112 | max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); |
| 1109 | 1113 | ||
| 1110 | pos = *ppos; | ||
| 1111 | if (unlikely(pos + count > max)) { | 1114 | if (unlikely(pos + count > max)) { |
| 1112 | retval = -EOVERFLOW; | 1115 | retval = -EOVERFLOW; |
| 1113 | if (pos >= max) | 1116 | if (pos >= max) |
| @@ -1126,18 +1129,23 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 1126 | if (in.file->f_flags & O_NONBLOCK) | 1129 | if (in.file->f_flags & O_NONBLOCK) |
| 1127 | fl = SPLICE_F_NONBLOCK; | 1130 | fl = SPLICE_F_NONBLOCK; |
| 1128 | #endif | 1131 | #endif |
| 1129 | retval = do_splice_direct(in.file, ppos, out.file, count, fl); | 1132 | retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl); |
| 1130 | 1133 | ||
| 1131 | if (retval > 0) { | 1134 | if (retval > 0) { |
| 1132 | add_rchar(current, retval); | 1135 | add_rchar(current, retval); |
| 1133 | add_wchar(current, retval); | 1136 | add_wchar(current, retval); |
| 1134 | fsnotify_access(in.file); | 1137 | fsnotify_access(in.file); |
| 1135 | fsnotify_modify(out.file); | 1138 | fsnotify_modify(out.file); |
| 1139 | out.file->f_pos = out_pos; | ||
| 1140 | if (ppos) | ||
| 1141 | *ppos = pos; | ||
| 1142 | else | ||
| 1143 | in.file->f_pos = pos; | ||
| 1136 | } | 1144 | } |
| 1137 | 1145 | ||
| 1138 | inc_syscr(current); | 1146 | inc_syscr(current); |
| 1139 | inc_syscw(current); | 1147 | inc_syscw(current); |
| 1140 | if (*ppos > max) | 1148 | if (pos > max) |
| 1141 | retval = -EOVERFLOW; | 1149 | retval = -EOVERFLOW; |
| 1142 | 1150 | ||
| 1143 | fput_out: | 1151 | fput_out: |
diff --git a/fs/splice.c b/fs/splice.c index e6b25598c8c4..9eca476227d5 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -1274,7 +1274,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, | |||
| 1274 | { | 1274 | { |
| 1275 | struct file *file = sd->u.file; | 1275 | struct file *file = sd->u.file; |
| 1276 | 1276 | ||
| 1277 | return do_splice_from(pipe, file, &file->f_pos, sd->total_len, | 1277 | return do_splice_from(pipe, file, sd->opos, sd->total_len, |
| 1278 | sd->flags); | 1278 | sd->flags); |
| 1279 | } | 1279 | } |
| 1280 | 1280 | ||
| @@ -1294,7 +1294,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, | |||
| 1294 | * | 1294 | * |
| 1295 | */ | 1295 | */ |
| 1296 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | 1296 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, |
| 1297 | size_t len, unsigned int flags) | 1297 | loff_t *opos, size_t len, unsigned int flags) |
| 1298 | { | 1298 | { |
| 1299 | struct splice_desc sd = { | 1299 | struct splice_desc sd = { |
| 1300 | .len = len, | 1300 | .len = len, |
| @@ -1302,6 +1302,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
| 1302 | .flags = flags, | 1302 | .flags = flags, |
| 1303 | .pos = *ppos, | 1303 | .pos = *ppos, |
| 1304 | .u.file = out, | 1304 | .u.file = out, |
| 1305 | .opos = opos, | ||
| 1305 | }; | 1306 | }; |
| 1306 | long ret; | 1307 | long ret; |
| 1307 | 1308 | ||
| @@ -1325,7 +1326,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
| 1325 | { | 1326 | { |
| 1326 | struct pipe_inode_info *ipipe; | 1327 | struct pipe_inode_info *ipipe; |
| 1327 | struct pipe_inode_info *opipe; | 1328 | struct pipe_inode_info *opipe; |
| 1328 | loff_t offset, *off; | 1329 | loff_t offset; |
| 1329 | long ret; | 1330 | long ret; |
| 1330 | 1331 | ||
| 1331 | ipipe = get_pipe_info(in); | 1332 | ipipe = get_pipe_info(in); |
| @@ -1356,13 +1357,15 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
| 1356 | return -EINVAL; | 1357 | return -EINVAL; |
| 1357 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) | 1358 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) |
| 1358 | return -EFAULT; | 1359 | return -EFAULT; |
| 1359 | off = &offset; | 1360 | } else { |
| 1360 | } else | 1361 | offset = out->f_pos; |
| 1361 | off = &out->f_pos; | 1362 | } |
| 1362 | 1363 | ||
| 1363 | ret = do_splice_from(ipipe, out, off, len, flags); | 1364 | ret = do_splice_from(ipipe, out, &offset, len, flags); |
| 1364 | 1365 | ||
| 1365 | if (off_out && copy_to_user(off_out, off, sizeof(loff_t))) | 1366 | if (!off_out) |
| 1367 | out->f_pos = offset; | ||
| 1368 | else if (copy_to_user(off_out, &offset, sizeof(loff_t))) | ||
| 1366 | ret = -EFAULT; | 1369 | ret = -EFAULT; |
| 1367 | 1370 | ||
| 1368 | return ret; | 1371 | return ret; |
| @@ -1376,13 +1379,15 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
| 1376 | return -EINVAL; | 1379 | return -EINVAL; |
| 1377 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) | 1380 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) |
| 1378 | return -EFAULT; | 1381 | return -EFAULT; |
| 1379 | off = &offset; | 1382 | } else { |
| 1380 | } else | 1383 | offset = in->f_pos; |
| 1381 | off = &in->f_pos; | 1384 | } |
| 1382 | 1385 | ||
| 1383 | ret = do_splice_to(in, off, opipe, len, flags); | 1386 | ret = do_splice_to(in, &offset, opipe, len, flags); |
| 1384 | 1387 | ||
| 1385 | if (off_in && copy_to_user(off_in, off, sizeof(loff_t))) | 1388 | if (!off_in) |
| 1389 | in->f_pos = offset; | ||
| 1390 | else if (copy_to_user(off_in, &offset, sizeof(loff_t))) | ||
| 1386 | ret = -EFAULT; | 1391 | ret = -EFAULT; |
| 1387 | 1392 | ||
| 1388 | return ret; | 1393 | return ret; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 636c59f2003a..c13c919ab99e 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state); | |||
| 382 | int acpi_device_get_power(struct acpi_device *device, int *state); | 382 | int acpi_device_get_power(struct acpi_device *device, int *state); |
| 383 | int acpi_device_set_power(struct acpi_device *device, int state); | 383 | int acpi_device_set_power(struct acpi_device *device, int state); |
| 384 | int acpi_bus_init_power(struct acpi_device *device); | 384 | int acpi_bus_init_power(struct acpi_device *device); |
| 385 | int acpi_device_fix_up_power(struct acpi_device *device); | ||
| 385 | int acpi_bus_update_power(acpi_handle handle, int *state_p); | 386 | int acpi_bus_update_power(acpi_handle handle, int *state_p); |
| 386 | bool acpi_bus_power_manageable(acpi_handle handle); | 387 | bool acpi_bus_power_manageable(acpi_handle handle); |
| 387 | 388 | ||
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h index 365f4a61bf04..fc09d7b0dacf 100644 --- a/include/linux/context_tracking.h +++ b/include/linux/context_tracking.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
| 5 | #include <linux/percpu.h> | 5 | #include <linux/percpu.h> |
| 6 | #include <linux/vtime.h> | ||
| 6 | #include <asm/ptrace.h> | 7 | #include <asm/ptrace.h> |
| 7 | 8 | ||
| 8 | struct context_tracking { | 9 | struct context_tracking { |
| @@ -19,6 +20,26 @@ struct context_tracking { | |||
| 19 | } state; | 20 | } state; |
| 20 | }; | 21 | }; |
| 21 | 22 | ||
| 23 | static inline void __guest_enter(void) | ||
| 24 | { | ||
| 25 | /* | ||
| 26 | * This is running in ioctl context so we can avoid | ||
| 27 | * the call to vtime_account() with its unnecessary idle check. | ||
| 28 | */ | ||
| 29 | vtime_account_system(current); | ||
| 30 | current->flags |= PF_VCPU; | ||
| 31 | } | ||
| 32 | |||
| 33 | static inline void __guest_exit(void) | ||
| 34 | { | ||
| 35 | /* | ||
| 36 | * This is running in ioctl context so we can avoid | ||
| 37 | * the call to vtime_account() with its unnecessary idle check. | ||
| 38 | */ | ||
| 39 | vtime_account_system(current); | ||
| 40 | current->flags &= ~PF_VCPU; | ||
| 41 | } | ||
| 42 | |||
| 22 | #ifdef CONFIG_CONTEXT_TRACKING | 43 | #ifdef CONFIG_CONTEXT_TRACKING |
| 23 | DECLARE_PER_CPU(struct context_tracking, context_tracking); | 44 | DECLARE_PER_CPU(struct context_tracking, context_tracking); |
| 24 | 45 | ||
| @@ -35,6 +56,9 @@ static inline bool context_tracking_active(void) | |||
| 35 | extern void user_enter(void); | 56 | extern void user_enter(void); |
| 36 | extern void user_exit(void); | 57 | extern void user_exit(void); |
| 37 | 58 | ||
| 59 | extern void guest_enter(void); | ||
| 60 | extern void guest_exit(void); | ||
| 61 | |||
| 38 | static inline enum ctx_state exception_enter(void) | 62 | static inline enum ctx_state exception_enter(void) |
| 39 | { | 63 | { |
| 40 | enum ctx_state prev_ctx; | 64 | enum ctx_state prev_ctx; |
| @@ -57,6 +81,17 @@ extern void context_tracking_task_switch(struct task_struct *prev, | |||
| 57 | static inline bool context_tracking_in_user(void) { return false; } | 81 | static inline bool context_tracking_in_user(void) { return false; } |
| 58 | static inline void user_enter(void) { } | 82 | static inline void user_enter(void) { } |
| 59 | static inline void user_exit(void) { } | 83 | static inline void user_exit(void) { } |
| 84 | |||
| 85 | static inline void guest_enter(void) | ||
| 86 | { | ||
| 87 | __guest_enter(); | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline void guest_exit(void) | ||
| 91 | { | ||
| 92 | __guest_exit(); | ||
| 93 | } | ||
| 94 | |||
| 60 | static inline enum ctx_state exception_enter(void) { return 0; } | 95 | static inline enum ctx_state exception_enter(void) { return 0; } |
| 61 | static inline void exception_exit(enum ctx_state prev_ctx) { } | 96 | static inline void exception_exit(enum ctx_state prev_ctx) { } |
| 62 | static inline void context_tracking_task_switch(struct task_struct *prev, | 97 | static inline void context_tracking_task_switch(struct task_struct *prev, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 43db02e9c9fa..65c2be22b601 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -2414,8 +2414,6 @@ extern ssize_t generic_file_splice_write(struct pipe_inode_info *, | |||
| 2414 | struct file *, loff_t *, size_t, unsigned int); | 2414 | struct file *, loff_t *, size_t, unsigned int); |
| 2415 | extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, | 2415 | extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, |
| 2416 | struct file *out, loff_t *, size_t len, unsigned int flags); | 2416 | struct file *out, loff_t *, size_t len, unsigned int flags); |
| 2417 | extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | ||
| 2418 | size_t len, unsigned int flags); | ||
| 2419 | 2417 | ||
| 2420 | extern void | 2418 | extern void |
| 2421 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); | 2419 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index f0eea07d2c2b..8db53cfaccdb 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/ratelimit.h> | 23 | #include <linux/ratelimit.h> |
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/irqflags.h> | 25 | #include <linux/irqflags.h> |
| 26 | #include <linux/context_tracking.h> | ||
| 26 | #include <asm/signal.h> | 27 | #include <asm/signal.h> |
| 27 | 28 | ||
| 28 | #include <linux/kvm.h> | 29 | #include <linux/kvm.h> |
| @@ -760,42 +761,6 @@ static inline int kvm_iommu_unmap_guest(struct kvm *kvm) | |||
| 760 | } | 761 | } |
| 761 | #endif | 762 | #endif |
| 762 | 763 | ||
| 763 | static inline void __guest_enter(void) | ||
| 764 | { | ||
| 765 | /* | ||
| 766 | * This is running in ioctl context so we can avoid | ||
| 767 | * the call to vtime_account() with its unnecessary idle check. | ||
| 768 | */ | ||
| 769 | vtime_account_system(current); | ||
| 770 | current->flags |= PF_VCPU; | ||
| 771 | } | ||
| 772 | |||
| 773 | static inline void __guest_exit(void) | ||
| 774 | { | ||
| 775 | /* | ||
| 776 | * This is running in ioctl context so we can avoid | ||
| 777 | * the call to vtime_account() with its unnecessary idle check. | ||
| 778 | */ | ||
| 779 | vtime_account_system(current); | ||
| 780 | current->flags &= ~PF_VCPU; | ||
| 781 | } | ||
| 782 | |||
| 783 | #ifdef CONFIG_CONTEXT_TRACKING | ||
| 784 | extern void guest_enter(void); | ||
| 785 | extern void guest_exit(void); | ||
| 786 | |||
| 787 | #else /* !CONFIG_CONTEXT_TRACKING */ | ||
| 788 | static inline void guest_enter(void) | ||
| 789 | { | ||
| 790 | __guest_enter(); | ||
| 791 | } | ||
| 792 | |||
| 793 | static inline void guest_exit(void) | ||
| 794 | { | ||
| 795 | __guest_exit(); | ||
| 796 | } | ||
| 797 | #endif /* !CONFIG_CONTEXT_TRACKING */ | ||
| 798 | |||
| 799 | static inline void kvm_guest_enter(void) | 764 | static inline void kvm_guest_enter(void) |
| 800 | { | 765 | { |
| 801 | unsigned long flags; | 766 | unsigned long flags; |
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/twl6040.h b/include/linux/mfd/twl6040.h index 94ac944d12f0..7e7fbce7a308 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h | |||
| @@ -125,8 +125,15 @@ | |||
| 125 | 125 | ||
| 126 | #define TWL6040_HSDACENA (1 << 0) | 126 | #define TWL6040_HSDACENA (1 << 0) |
| 127 | #define TWL6040_HSDACMODE (1 << 1) | 127 | #define TWL6040_HSDACMODE (1 << 1) |
| 128 | #define TWL6040_HSDRVENA (1 << 2) | ||
| 128 | #define TWL6040_HSDRVMODE (1 << 3) | 129 | #define TWL6040_HSDRVMODE (1 << 3) |
| 129 | 130 | ||
| 131 | /* HFLCTL/R (0x14/0x16) fields */ | ||
| 132 | |||
| 133 | #define TWL6040_HFDACENA (1 << 0) | ||
| 134 | #define TWL6040_HFPGAENA (1 << 1) | ||
| 135 | #define TWL6040_HFDRVENA (1 << 4) | ||
| 136 | |||
| 130 | /* VIBCTLL/R (0x18/0x1A) fields */ | 137 | /* VIBCTLL/R (0x18/0x1A) fields */ |
| 131 | 138 | ||
| 132 | #define TWL6040_VIBENA (1 << 0) | 139 | #define TWL6040_VIBENA (1 << 0) |
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/perf_event.h b/include/linux/perf_event.h index f463a46424e2..c5b6dbf9c2fc 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -389,8 +389,7 @@ struct perf_event { | |||
| 389 | /* mmap bits */ | 389 | /* mmap bits */ |
| 390 | struct mutex mmap_mutex; | 390 | struct mutex mmap_mutex; |
| 391 | atomic_t mmap_count; | 391 | atomic_t mmap_count; |
| 392 | int mmap_locked; | 392 | |
| 393 | struct user_struct *mmap_user; | ||
| 394 | struct ring_buffer *rb; | 393 | struct ring_buffer *rb; |
| 395 | struct list_head rb_entry; | 394 | struct list_head rb_entry; |
| 396 | 395 | ||
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/linux/preempt.h b/include/linux/preempt.h index 87a03c746f17..f5d4723cdb3d 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h | |||
| @@ -33,9 +33,25 @@ do { \ | |||
| 33 | preempt_schedule(); \ | 33 | preempt_schedule(); \ |
| 34 | } while (0) | 34 | } while (0) |
| 35 | 35 | ||
| 36 | #ifdef CONFIG_CONTEXT_TRACKING | ||
| 37 | |||
| 38 | void preempt_schedule_context(void); | ||
| 39 | |||
| 40 | #define preempt_check_resched_context() \ | ||
| 41 | do { \ | ||
| 42 | if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ | ||
| 43 | preempt_schedule_context(); \ | ||
| 44 | } while (0) | ||
| 45 | #else | ||
| 46 | |||
| 47 | #define preempt_check_resched_context() preempt_check_resched() | ||
| 48 | |||
| 49 | #endif /* CONFIG_CONTEXT_TRACKING */ | ||
| 50 | |||
| 36 | #else /* !CONFIG_PREEMPT */ | 51 | #else /* !CONFIG_PREEMPT */ |
| 37 | 52 | ||
| 38 | #define preempt_check_resched() do { } while (0) | 53 | #define preempt_check_resched() do { } while (0) |
| 54 | #define preempt_check_resched_context() do { } while (0) | ||
| 39 | 55 | ||
| 40 | #endif /* CONFIG_PREEMPT */ | 56 | #endif /* CONFIG_PREEMPT */ |
| 41 | 57 | ||
| @@ -88,7 +104,7 @@ do { \ | |||
| 88 | do { \ | 104 | do { \ |
| 89 | preempt_enable_no_resched_notrace(); \ | 105 | preempt_enable_no_resched_notrace(); \ |
| 90 | barrier(); \ | 106 | barrier(); \ |
| 91 | preempt_check_resched(); \ | 107 | preempt_check_resched_context(); \ |
| 92 | } while (0) | 108 | } while (0) |
| 93 | 109 | ||
| 94 | #else /* !CONFIG_PREEMPT_COUNT */ | 110 | #else /* !CONFIG_PREEMPT_COUNT */ |
diff --git a/include/linux/splice.h b/include/linux/splice.h index 09a545a7dfa3..74575cbf2d6f 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h | |||
| @@ -35,6 +35,7 @@ struct splice_desc { | |||
| 35 | void *data; /* cookie */ | 35 | void *data; /* cookie */ |
| 36 | } u; | 36 | } u; |
| 37 | loff_t pos; /* file position */ | 37 | loff_t pos; /* file position */ |
| 38 | loff_t *opos; /* sendfile: output position */ | ||
| 38 | size_t num_spliced; /* number of bytes already spliced */ | 39 | size_t num_spliced; /* number of bytes already spliced */ |
| 39 | bool need_wakeup; /* need to wake up writer */ | 40 | bool need_wakeup; /* need to wake up writer */ |
| 40 | }; | 41 | }; |
diff --git a/include/linux/vtime.h b/include/linux/vtime.h index 71a5782d8c59..b1dd2db80076 100644 --- a/include/linux/vtime.h +++ b/include/linux/vtime.h | |||
| @@ -34,7 +34,7 @@ static inline void vtime_user_exit(struct task_struct *tsk) | |||
| 34 | } | 34 | } |
| 35 | extern void vtime_guest_enter(struct task_struct *tsk); | 35 | extern void vtime_guest_enter(struct task_struct *tsk); |
| 36 | extern void vtime_guest_exit(struct task_struct *tsk); | 36 | extern void vtime_guest_exit(struct task_struct *tsk); |
| 37 | extern void vtime_init_idle(struct task_struct *tsk); | 37 | extern void vtime_init_idle(struct task_struct *tsk, int cpu); |
| 38 | #else | 38 | #else |
| 39 | static inline void vtime_account_irq_exit(struct task_struct *tsk) | 39 | static inline void vtime_account_irq_exit(struct task_struct *tsk) |
| 40 | { | 40 | { |
| @@ -45,7 +45,7 @@ static inline void vtime_user_enter(struct task_struct *tsk) { } | |||
| 45 | static inline void vtime_user_exit(struct task_struct *tsk) { } | 45 | static inline void vtime_user_exit(struct task_struct *tsk) { } |
| 46 | static inline void vtime_guest_enter(struct task_struct *tsk) { } | 46 | static inline void vtime_guest_enter(struct task_struct *tsk) { } |
| 47 | static inline void vtime_guest_exit(struct task_struct *tsk) { } | 47 | static inline void vtime_guest_exit(struct task_struct *tsk) { } |
| 48 | static inline void vtime_init_idle(struct task_struct *tsk) { } | 48 | static inline void vtime_init_idle(struct task_struct *tsk, int cpu) { } |
| 49 | #endif | 49 | #endif |
| 50 | 50 | ||
| 51 | #ifdef CONFIG_IRQ_TIME_ACCOUNTING | 51 | #ifdef CONFIG_IRQ_TIME_ACCOUNTING |
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index d3eef01da648..0f4555b2a31b 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h | |||
| @@ -110,6 +110,8 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 110 | struct v4l2_buffer *buf); | 110 | struct v4l2_buffer *buf); |
| 111 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 111 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
| 112 | struct v4l2_buffer *buf); | 112 | struct v4l2_buffer *buf); |
| 113 | int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
| 114 | struct v4l2_create_buffers *create); | ||
| 113 | 115 | ||
| 114 | int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 116 | int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
| 115 | struct v4l2_exportbuffer *eb); | 117 | struct v4l2_exportbuffer *eb); |
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/sound/soc.h b/include/sound/soc.h index 85c15226103b..6eabee7ec15a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
| @@ -340,7 +340,7 @@ struct snd_soc_jack_gpio; | |||
| 340 | 340 | ||
| 341 | typedef int (*hw_write_t)(void *,const char* ,int); | 341 | typedef int (*hw_write_t)(void *,const char* ,int); |
| 342 | 342 | ||
| 343 | extern struct snd_ac97_bus_ops soc_ac97_ops; | 343 | extern struct snd_ac97_bus_ops *soc_ac97_ops; |
| 344 | 344 | ||
| 345 | enum snd_soc_control_type { | 345 | enum snd_soc_control_type { |
| 346 | SND_SOC_I2C = 1, | 346 | SND_SOC_I2C = 1, |
| @@ -467,6 +467,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
| 467 | struct snd_ac97_bus_ops *ops, int num); | 467 | struct snd_ac97_bus_ops *ops, int num); |
| 468 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); | 468 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); |
| 469 | 469 | ||
| 470 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); | ||
| 471 | |||
| 470 | /* | 472 | /* |
| 471 | *Controls | 473 | *Controls |
| 472 | */ | 474 | */ |
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/kernel/context_tracking.c b/kernel/context_tracking.c index 65349f07b878..383f8231e436 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/context_tracking.h> | 17 | #include <linux/context_tracking.h> |
| 18 | #include <linux/kvm_host.h> | ||
| 19 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
| 20 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 21 | #include <linux/hardirq.h> | 20 | #include <linux/hardirq.h> |
| @@ -71,6 +70,46 @@ void user_enter(void) | |||
| 71 | local_irq_restore(flags); | 70 | local_irq_restore(flags); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 73 | #ifdef CONFIG_PREEMPT | ||
| 74 | /** | ||
| 75 | * preempt_schedule_context - preempt_schedule called by tracing | ||
| 76 | * | ||
| 77 | * The tracing infrastructure uses preempt_enable_notrace to prevent | ||
| 78 | * recursion and tracing preempt enabling caused by the tracing | ||
| 79 | * infrastructure itself. But as tracing can happen in areas coming | ||
| 80 | * from userspace or just about to enter userspace, a preempt enable | ||
| 81 | * can occur before user_exit() is called. This will cause the scheduler | ||
| 82 | * to be called when the system is still in usermode. | ||
| 83 | * | ||
| 84 | * To prevent this, the preempt_enable_notrace will use this function | ||
| 85 | * instead of preempt_schedule() to exit user context if needed before | ||
| 86 | * calling the scheduler. | ||
| 87 | */ | ||
| 88 | void __sched notrace preempt_schedule_context(void) | ||
| 89 | { | ||
| 90 | struct thread_info *ti = current_thread_info(); | ||
| 91 | enum ctx_state prev_ctx; | ||
| 92 | |||
| 93 | if (likely(ti->preempt_count || irqs_disabled())) | ||
| 94 | return; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Need to disable preemption in case user_exit() is traced | ||
| 98 | * and the tracer calls preempt_enable_notrace() causing | ||
| 99 | * an infinite recursion. | ||
| 100 | */ | ||
| 101 | preempt_disable_notrace(); | ||
| 102 | prev_ctx = exception_enter(); | ||
| 103 | preempt_enable_no_resched_notrace(); | ||
| 104 | |||
| 105 | preempt_schedule(); | ||
| 106 | |||
| 107 | preempt_disable_notrace(); | ||
| 108 | exception_exit(prev_ctx); | ||
| 109 | preempt_enable_notrace(); | ||
| 110 | } | ||
| 111 | EXPORT_SYMBOL_GPL(preempt_schedule_context); | ||
| 112 | #endif /* CONFIG_PREEMPT */ | ||
| 74 | 113 | ||
| 75 | /** | 114 | /** |
| 76 | * user_exit - Inform the context tracking that the CPU is | 115 | * user_exit - Inform the context tracking that the CPU is |
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index d5585f5e038e..e695c0a0bcb5 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/cpu.h> | 5 | #include <linux/cpu.h> |
| 6 | #include <linux/tick.h> | 6 | #include <linux/tick.h> |
| 7 | #include <linux/mm.h> | 7 | #include <linux/mm.h> |
| 8 | #include <linux/stackprotector.h> | ||
| 8 | 9 | ||
| 9 | #include <asm/tlb.h> | 10 | #include <asm/tlb.h> |
| 10 | 11 | ||
| @@ -58,6 +59,7 @@ void __weak arch_cpu_idle_dead(void) { } | |||
| 58 | void __weak arch_cpu_idle(void) | 59 | void __weak arch_cpu_idle(void) |
| 59 | { | 60 | { |
| 60 | cpu_idle_force_poll = 1; | 61 | cpu_idle_force_poll = 1; |
| 62 | local_irq_enable(); | ||
| 61 | } | 63 | } |
| 62 | 64 | ||
| 63 | /* | 65 | /* |
| @@ -112,6 +114,21 @@ static void cpu_idle_loop(void) | |||
| 112 | 114 | ||
| 113 | void cpu_startup_entry(enum cpuhp_state state) | 115 | void cpu_startup_entry(enum cpuhp_state state) |
| 114 | { | 116 | { |
| 117 | /* | ||
| 118 | * This #ifdef needs to die, but it's too late in the cycle to | ||
| 119 | * make this generic (arm and sh have never invoked the canary | ||
| 120 | * init for the non boot cpus!). Will be fixed in 3.11 | ||
| 121 | */ | ||
| 122 | #ifdef CONFIG_X86 | ||
| 123 | /* | ||
| 124 | * If we're the non-boot CPU, nothing set the stack canary up | ||
| 125 | * for us. The boot CPU already has it initialized but no harm | ||
| 126 | * in doing it again. This is a good place for updating it, as | ||
| 127 | * we wont ever return from this function (so the invalid | ||
| 128 | * canaries already on the stack wont ever trigger). | ||
| 129 | */ | ||
| 130 | boot_init_stack_canary(); | ||
| 131 | #endif | ||
| 115 | current_set_polling(); | 132 | current_set_polling(); |
| 116 | arch_cpu_idle_prepare(); | 133 | arch_cpu_idle_prepare(); |
| 117 | cpu_idle_loop(); | 134 | cpu_idle_loop(); |
diff --git a/kernel/events/core.c b/kernel/events/core.c index 9dc297faf7c0..b391907d5352 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -196,9 +196,6 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, | |||
| 196 | static void update_context_time(struct perf_event_context *ctx); | 196 | static void update_context_time(struct perf_event_context *ctx); |
| 197 | static u64 perf_event_time(struct perf_event *event); | 197 | static u64 perf_event_time(struct perf_event *event); |
| 198 | 198 | ||
| 199 | static void ring_buffer_attach(struct perf_event *event, | ||
| 200 | struct ring_buffer *rb); | ||
| 201 | |||
| 202 | void __weak perf_event_print_debug(void) { } | 199 | void __weak perf_event_print_debug(void) { } |
| 203 | 200 | ||
| 204 | extern __weak const char *perf_pmu_name(void) | 201 | extern __weak const char *perf_pmu_name(void) |
| @@ -2918,6 +2915,7 @@ static void free_event_rcu(struct rcu_head *head) | |||
| 2918 | } | 2915 | } |
| 2919 | 2916 | ||
| 2920 | static void ring_buffer_put(struct ring_buffer *rb); | 2917 | static void ring_buffer_put(struct ring_buffer *rb); |
| 2918 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); | ||
| 2921 | 2919 | ||
| 2922 | static void free_event(struct perf_event *event) | 2920 | static void free_event(struct perf_event *event) |
| 2923 | { | 2921 | { |
| @@ -2942,15 +2940,30 @@ static void free_event(struct perf_event *event) | |||
| 2942 | if (has_branch_stack(event)) { | 2940 | if (has_branch_stack(event)) { |
| 2943 | static_key_slow_dec_deferred(&perf_sched_events); | 2941 | static_key_slow_dec_deferred(&perf_sched_events); |
| 2944 | /* is system-wide event */ | 2942 | /* is system-wide event */ |
| 2945 | if (!(event->attach_state & PERF_ATTACH_TASK)) | 2943 | if (!(event->attach_state & PERF_ATTACH_TASK)) { |
| 2946 | atomic_dec(&per_cpu(perf_branch_stack_events, | 2944 | atomic_dec(&per_cpu(perf_branch_stack_events, |
| 2947 | event->cpu)); | 2945 | event->cpu)); |
| 2946 | } | ||
| 2948 | } | 2947 | } |
| 2949 | } | 2948 | } |
| 2950 | 2949 | ||
| 2951 | if (event->rb) { | 2950 | if (event->rb) { |
| 2952 | ring_buffer_put(event->rb); | 2951 | struct ring_buffer *rb; |
| 2953 | event->rb = NULL; | 2952 | |
| 2953 | /* | ||
| 2954 | * Can happen when we close an event with re-directed output. | ||
| 2955 | * | ||
| 2956 | * Since we have a 0 refcount, perf_mmap_close() will skip | ||
| 2957 | * over us; possibly making our ring_buffer_put() the last. | ||
| 2958 | */ | ||
| 2959 | mutex_lock(&event->mmap_mutex); | ||
| 2960 | rb = event->rb; | ||
| 2961 | if (rb) { | ||
| 2962 | rcu_assign_pointer(event->rb, NULL); | ||
| 2963 | ring_buffer_detach(event, rb); | ||
| 2964 | ring_buffer_put(rb); /* could be last */ | ||
| 2965 | } | ||
| 2966 | mutex_unlock(&event->mmap_mutex); | ||
| 2954 | } | 2967 | } |
| 2955 | 2968 | ||
| 2956 | if (is_cgroup_event(event)) | 2969 | if (is_cgroup_event(event)) |
| @@ -3188,30 +3201,13 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) | |||
| 3188 | unsigned int events = POLL_HUP; | 3201 | unsigned int events = POLL_HUP; |
| 3189 | 3202 | ||
| 3190 | /* | 3203 | /* |
| 3191 | * Race between perf_event_set_output() and perf_poll(): perf_poll() | 3204 | * Pin the event->rb by taking event->mmap_mutex; otherwise |
| 3192 | * grabs the rb reference but perf_event_set_output() overrides it. | 3205 | * perf_event_set_output() can swizzle our rb and make us miss wakeups. |
| 3193 | * Here is the timeline for two threads T1, T2: | ||
| 3194 | * t0: T1, rb = rcu_dereference(event->rb) | ||
| 3195 | * t1: T2, old_rb = event->rb | ||
| 3196 | * t2: T2, event->rb = new rb | ||
| 3197 | * t3: T2, ring_buffer_detach(old_rb) | ||
| 3198 | * t4: T1, ring_buffer_attach(rb1) | ||
| 3199 | * t5: T1, poll_wait(event->waitq) | ||
| 3200 | * | ||
| 3201 | * To avoid this problem, we grab mmap_mutex in perf_poll() | ||
| 3202 | * thereby ensuring that the assignment of the new ring buffer | ||
| 3203 | * and the detachment of the old buffer appear atomic to perf_poll() | ||
| 3204 | */ | 3206 | */ |
| 3205 | mutex_lock(&event->mmap_mutex); | 3207 | mutex_lock(&event->mmap_mutex); |
| 3206 | 3208 | rb = event->rb; | |
| 3207 | rcu_read_lock(); | 3209 | if (rb) |
| 3208 | rb = rcu_dereference(event->rb); | ||
| 3209 | if (rb) { | ||
| 3210 | ring_buffer_attach(event, rb); | ||
| 3211 | events = atomic_xchg(&rb->poll, 0); | 3210 | events = atomic_xchg(&rb->poll, 0); |
| 3212 | } | ||
| 3213 | rcu_read_unlock(); | ||
| 3214 | |||
| 3215 | mutex_unlock(&event->mmap_mutex); | 3211 | mutex_unlock(&event->mmap_mutex); |
| 3216 | 3212 | ||
| 3217 | poll_wait(file, &event->waitq, wait); | 3213 | poll_wait(file, &event->waitq, wait); |
| @@ -3521,16 +3517,12 @@ static void ring_buffer_attach(struct perf_event *event, | |||
| 3521 | return; | 3517 | return; |
| 3522 | 3518 | ||
| 3523 | spin_lock_irqsave(&rb->event_lock, flags); | 3519 | spin_lock_irqsave(&rb->event_lock, flags); |
| 3524 | if (!list_empty(&event->rb_entry)) | 3520 | if (list_empty(&event->rb_entry)) |
| 3525 | goto unlock; | 3521 | list_add(&event->rb_entry, &rb->event_list); |
| 3526 | |||
| 3527 | list_add(&event->rb_entry, &rb->event_list); | ||
| 3528 | unlock: | ||
| 3529 | spin_unlock_irqrestore(&rb->event_lock, flags); | 3522 | spin_unlock_irqrestore(&rb->event_lock, flags); |
| 3530 | } | 3523 | } |
| 3531 | 3524 | ||
| 3532 | static void ring_buffer_detach(struct perf_event *event, | 3525 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb) |
| 3533 | struct ring_buffer *rb) | ||
| 3534 | { | 3526 | { |
| 3535 | unsigned long flags; | 3527 | unsigned long flags; |
| 3536 | 3528 | ||
| @@ -3549,13 +3541,10 @@ static void ring_buffer_wakeup(struct perf_event *event) | |||
| 3549 | 3541 | ||
| 3550 | rcu_read_lock(); | 3542 | rcu_read_lock(); |
| 3551 | rb = rcu_dereference(event->rb); | 3543 | rb = rcu_dereference(event->rb); |
| 3552 | if (!rb) | 3544 | if (rb) { |
| 3553 | goto unlock; | 3545 | list_for_each_entry_rcu(event, &rb->event_list, rb_entry) |
| 3554 | 3546 | wake_up_all(&event->waitq); | |
| 3555 | list_for_each_entry_rcu(event, &rb->event_list, rb_entry) | 3547 | } |
| 3556 | wake_up_all(&event->waitq); | ||
| 3557 | |||
| 3558 | unlock: | ||
| 3559 | rcu_read_unlock(); | 3548 | rcu_read_unlock(); |
| 3560 | } | 3549 | } |
| 3561 | 3550 | ||
| @@ -3584,18 +3573,10 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event) | |||
| 3584 | 3573 | ||
| 3585 | static void ring_buffer_put(struct ring_buffer *rb) | 3574 | static void ring_buffer_put(struct ring_buffer *rb) |
| 3586 | { | 3575 | { |
| 3587 | struct perf_event *event, *n; | ||
| 3588 | unsigned long flags; | ||
| 3589 | |||
| 3590 | if (!atomic_dec_and_test(&rb->refcount)) | 3576 | if (!atomic_dec_and_test(&rb->refcount)) |
| 3591 | return; | 3577 | return; |
| 3592 | 3578 | ||
| 3593 | spin_lock_irqsave(&rb->event_lock, flags); | 3579 | WARN_ON_ONCE(!list_empty(&rb->event_list)); |
| 3594 | list_for_each_entry_safe(event, n, &rb->event_list, rb_entry) { | ||
| 3595 | list_del_init(&event->rb_entry); | ||
| 3596 | wake_up_all(&event->waitq); | ||
| 3597 | } | ||
| 3598 | spin_unlock_irqrestore(&rb->event_lock, flags); | ||
| 3599 | 3580 | ||
| 3600 | call_rcu(&rb->rcu_head, rb_free_rcu); | 3581 | call_rcu(&rb->rcu_head, rb_free_rcu); |
| 3601 | } | 3582 | } |
| @@ -3605,26 +3586,100 @@ static void perf_mmap_open(struct vm_area_struct *vma) | |||
| 3605 | struct perf_event *event = vma->vm_file->private_data; | 3586 | struct perf_event *event = vma->vm_file->private_data; |
| 3606 | 3587 | ||
| 3607 | atomic_inc(&event->mmap_count); | 3588 | atomic_inc(&event->mmap_count); |
| 3589 | atomic_inc(&event->rb->mmap_count); | ||
| 3608 | } | 3590 | } |
| 3609 | 3591 | ||
| 3592 | /* | ||
| 3593 | * A buffer can be mmap()ed multiple times; either directly through the same | ||
| 3594 | * event, or through other events by use of perf_event_set_output(). | ||
| 3595 | * | ||
| 3596 | * In order to undo the VM accounting done by perf_mmap() we need to destroy | ||
| 3597 | * the buffer here, where we still have a VM context. This means we need | ||
| 3598 | * to detach all events redirecting to us. | ||
| 3599 | */ | ||
| 3610 | static void perf_mmap_close(struct vm_area_struct *vma) | 3600 | static void perf_mmap_close(struct vm_area_struct *vma) |
| 3611 | { | 3601 | { |
| 3612 | struct perf_event *event = vma->vm_file->private_data; | 3602 | struct perf_event *event = vma->vm_file->private_data; |
| 3613 | 3603 | ||
| 3614 | if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) { | 3604 | struct ring_buffer *rb = event->rb; |
| 3615 | unsigned long size = perf_data_size(event->rb); | 3605 | struct user_struct *mmap_user = rb->mmap_user; |
| 3616 | struct user_struct *user = event->mmap_user; | 3606 | int mmap_locked = rb->mmap_locked; |
| 3617 | struct ring_buffer *rb = event->rb; | 3607 | unsigned long size = perf_data_size(rb); |
| 3608 | |||
| 3609 | atomic_dec(&rb->mmap_count); | ||
| 3610 | |||
| 3611 | if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) | ||
| 3612 | return; | ||
| 3618 | 3613 | ||
| 3619 | atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm); | 3614 | /* Detach current event from the buffer. */ |
| 3620 | vma->vm_mm->pinned_vm -= event->mmap_locked; | 3615 | rcu_assign_pointer(event->rb, NULL); |
| 3621 | rcu_assign_pointer(event->rb, NULL); | 3616 | ring_buffer_detach(event, rb); |
| 3622 | ring_buffer_detach(event, rb); | 3617 | mutex_unlock(&event->mmap_mutex); |
| 3618 | |||
| 3619 | /* If there's still other mmap()s of this buffer, we're done. */ | ||
| 3620 | if (atomic_read(&rb->mmap_count)) { | ||
| 3621 | ring_buffer_put(rb); /* can't be last */ | ||
| 3622 | return; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | /* | ||
| 3626 | * No other mmap()s, detach from all other events that might redirect | ||
| 3627 | * into the now unreachable buffer. Somewhat complicated by the | ||
| 3628 | * fact that rb::event_lock otherwise nests inside mmap_mutex. | ||
| 3629 | */ | ||
| 3630 | again: | ||
| 3631 | rcu_read_lock(); | ||
| 3632 | list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { | ||
| 3633 | if (!atomic_long_inc_not_zero(&event->refcount)) { | ||
| 3634 | /* | ||
| 3635 | * This event is en-route to free_event() which will | ||
| 3636 | * detach it and remove it from the list. | ||
| 3637 | */ | ||
| 3638 | continue; | ||
| 3639 | } | ||
| 3640 | rcu_read_unlock(); | ||
| 3641 | |||
| 3642 | mutex_lock(&event->mmap_mutex); | ||
| 3643 | /* | ||
| 3644 | * Check we didn't race with perf_event_set_output() which can | ||
| 3645 | * swizzle the rb from under us while we were waiting to | ||
| 3646 | * acquire mmap_mutex. | ||
| 3647 | * | ||
| 3648 | * If we find a different rb; ignore this event, a next | ||
| 3649 | * iteration will no longer find it on the list. We have to | ||
| 3650 | * still restart the iteration to make sure we're not now | ||
| 3651 | * iterating the wrong list. | ||
| 3652 | */ | ||
| 3653 | if (event->rb == rb) { | ||
| 3654 | rcu_assign_pointer(event->rb, NULL); | ||
| 3655 | ring_buffer_detach(event, rb); | ||
| 3656 | ring_buffer_put(rb); /* can't be last, we still have one */ | ||
| 3657 | } | ||
| 3623 | mutex_unlock(&event->mmap_mutex); | 3658 | mutex_unlock(&event->mmap_mutex); |
| 3659 | put_event(event); | ||
| 3624 | 3660 | ||
| 3625 | ring_buffer_put(rb); | 3661 | /* |
| 3626 | free_uid(user); | 3662 | * Restart the iteration; either we're on the wrong list or |
| 3663 | * destroyed its integrity by doing a deletion. | ||
| 3664 | */ | ||
| 3665 | goto again; | ||
| 3627 | } | 3666 | } |
| 3667 | rcu_read_unlock(); | ||
| 3668 | |||
| 3669 | /* | ||
| 3670 | * It could be there's still a few 0-ref events on the list; they'll | ||
| 3671 | * get cleaned up by free_event() -- they'll also still have their | ||
| 3672 | * ref on the rb and will free it whenever they are done with it. | ||
| 3673 | * | ||
| 3674 | * Aside from that, this buffer is 'fully' detached and unmapped, | ||
| 3675 | * undo the VM accounting. | ||
| 3676 | */ | ||
| 3677 | |||
| 3678 | atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm); | ||
| 3679 | vma->vm_mm->pinned_vm -= mmap_locked; | ||
| 3680 | free_uid(mmap_user); | ||
| 3681 | |||
| 3682 | ring_buffer_put(rb); /* could be last */ | ||
| 3628 | } | 3683 | } |
| 3629 | 3684 | ||
| 3630 | static const struct vm_operations_struct perf_mmap_vmops = { | 3685 | static const struct vm_operations_struct perf_mmap_vmops = { |
| @@ -3674,12 +3729,24 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 3674 | return -EINVAL; | 3729 | return -EINVAL; |
| 3675 | 3730 | ||
| 3676 | WARN_ON_ONCE(event->ctx->parent_ctx); | 3731 | WARN_ON_ONCE(event->ctx->parent_ctx); |
| 3732 | again: | ||
| 3677 | mutex_lock(&event->mmap_mutex); | 3733 | mutex_lock(&event->mmap_mutex); |
| 3678 | if (event->rb) { | 3734 | if (event->rb) { |
| 3679 | if (event->rb->nr_pages == nr_pages) | 3735 | if (event->rb->nr_pages != nr_pages) { |
| 3680 | atomic_inc(&event->rb->refcount); | ||
| 3681 | else | ||
| 3682 | ret = -EINVAL; | 3736 | ret = -EINVAL; |
| 3737 | goto unlock; | ||
| 3738 | } | ||
| 3739 | |||
| 3740 | if (!atomic_inc_not_zero(&event->rb->mmap_count)) { | ||
| 3741 | /* | ||
| 3742 | * Raced against perf_mmap_close() through | ||
| 3743 | * perf_event_set_output(). Try again, hope for better | ||
| 3744 | * luck. | ||
| 3745 | */ | ||
| 3746 | mutex_unlock(&event->mmap_mutex); | ||
| 3747 | goto again; | ||
| 3748 | } | ||
| 3749 | |||
| 3683 | goto unlock; | 3750 | goto unlock; |
| 3684 | } | 3751 | } |
| 3685 | 3752 | ||
| @@ -3720,12 +3787,16 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 3720 | ret = -ENOMEM; | 3787 | ret = -ENOMEM; |
| 3721 | goto unlock; | 3788 | goto unlock; |
| 3722 | } | 3789 | } |
| 3723 | rcu_assign_pointer(event->rb, rb); | 3790 | |
| 3791 | atomic_set(&rb->mmap_count, 1); | ||
| 3792 | rb->mmap_locked = extra; | ||
| 3793 | rb->mmap_user = get_current_user(); | ||
| 3724 | 3794 | ||
| 3725 | atomic_long_add(user_extra, &user->locked_vm); | 3795 | atomic_long_add(user_extra, &user->locked_vm); |
| 3726 | event->mmap_locked = extra; | 3796 | vma->vm_mm->pinned_vm += extra; |
| 3727 | event->mmap_user = get_current_user(); | 3797 | |
| 3728 | vma->vm_mm->pinned_vm += event->mmap_locked; | 3798 | ring_buffer_attach(event, rb); |
| 3799 | rcu_assign_pointer(event->rb, rb); | ||
| 3729 | 3800 | ||
| 3730 | perf_event_update_userpage(event); | 3801 | perf_event_update_userpage(event); |
| 3731 | 3802 | ||
| @@ -3734,7 +3805,11 @@ unlock: | |||
| 3734 | atomic_inc(&event->mmap_count); | 3805 | atomic_inc(&event->mmap_count); |
| 3735 | mutex_unlock(&event->mmap_mutex); | 3806 | mutex_unlock(&event->mmap_mutex); |
| 3736 | 3807 | ||
| 3737 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; | 3808 | /* |
| 3809 | * Since pinned accounting is per vm we cannot allow fork() to copy our | ||
| 3810 | * vma. | ||
| 3811 | */ | ||
| 3812 | vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP; | ||
| 3738 | vma->vm_ops = &perf_mmap_vmops; | 3813 | vma->vm_ops = &perf_mmap_vmops; |
| 3739 | 3814 | ||
| 3740 | return ret; | 3815 | return ret; |
| @@ -6412,6 +6487,8 @@ set: | |||
| 6412 | if (atomic_read(&event->mmap_count)) | 6487 | if (atomic_read(&event->mmap_count)) |
| 6413 | goto unlock; | 6488 | goto unlock; |
| 6414 | 6489 | ||
| 6490 | old_rb = event->rb; | ||
| 6491 | |||
| 6415 | if (output_event) { | 6492 | if (output_event) { |
| 6416 | /* get the rb we want to redirect to */ | 6493 | /* get the rb we want to redirect to */ |
| 6417 | rb = ring_buffer_get(output_event); | 6494 | rb = ring_buffer_get(output_event); |
| @@ -6419,16 +6496,28 @@ set: | |||
| 6419 | goto unlock; | 6496 | goto unlock; |
| 6420 | } | 6497 | } |
| 6421 | 6498 | ||
| 6422 | old_rb = event->rb; | ||
| 6423 | rcu_assign_pointer(event->rb, rb); | ||
| 6424 | if (old_rb) | 6499 | if (old_rb) |
| 6425 | ring_buffer_detach(event, old_rb); | 6500 | ring_buffer_detach(event, old_rb); |
| 6501 | |||
| 6502 | if (rb) | ||
| 6503 | ring_buffer_attach(event, rb); | ||
| 6504 | |||
| 6505 | rcu_assign_pointer(event->rb, rb); | ||
| 6506 | |||
| 6507 | if (old_rb) { | ||
| 6508 | ring_buffer_put(old_rb); | ||
| 6509 | /* | ||
| 6510 | * Since we detached before setting the new rb, so that we | ||
| 6511 | * could attach the new rb, we could have missed a wakeup. | ||
| 6512 | * Provide it now. | ||
| 6513 | */ | ||
| 6514 | wake_up_all(&event->waitq); | ||
| 6515 | } | ||
| 6516 | |||
| 6426 | ret = 0; | 6517 | ret = 0; |
| 6427 | unlock: | 6518 | unlock: |
| 6428 | mutex_unlock(&event->mmap_mutex); | 6519 | mutex_unlock(&event->mmap_mutex); |
| 6429 | 6520 | ||
| 6430 | if (old_rb) | ||
| 6431 | ring_buffer_put(old_rb); | ||
| 6432 | out: | 6521 | out: |
| 6433 | return ret; | 6522 | return ret; |
| 6434 | } | 6523 | } |
diff --git a/kernel/events/internal.h b/kernel/events/internal.h index eb675c4d59df..ca6599723be5 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h | |||
| @@ -31,6 +31,10 @@ struct ring_buffer { | |||
| 31 | spinlock_t event_lock; | 31 | spinlock_t event_lock; |
| 32 | struct list_head event_list; | 32 | struct list_head event_list; |
| 33 | 33 | ||
| 34 | atomic_t mmap_count; | ||
| 35 | unsigned long mmap_locked; | ||
| 36 | struct user_struct *mmap_user; | ||
| 37 | |||
| 34 | struct perf_event_mmap_page *user_page; | 38 | struct perf_event_mmap_page *user_page; |
| 35 | void *data_pages[0]; | 39 | void *data_pages[0]; |
| 36 | }; | 40 | }; |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 3fed7f0cbcdf..bddf3b201a48 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -467,6 +467,7 @@ static struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr) | |||
| 467 | /* Optimization staging list, protected by kprobe_mutex */ | 467 | /* Optimization staging list, protected by kprobe_mutex */ |
| 468 | static LIST_HEAD(optimizing_list); | 468 | static LIST_HEAD(optimizing_list); |
| 469 | static LIST_HEAD(unoptimizing_list); | 469 | static LIST_HEAD(unoptimizing_list); |
| 470 | static LIST_HEAD(freeing_list); | ||
| 470 | 471 | ||
| 471 | static void kprobe_optimizer(struct work_struct *work); | 472 | static void kprobe_optimizer(struct work_struct *work); |
| 472 | static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer); | 473 | static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer); |
| @@ -504,7 +505,7 @@ static __kprobes void do_optimize_kprobes(void) | |||
| 504 | * Unoptimize (replace a jump with a breakpoint and remove the breakpoint | 505 | * Unoptimize (replace a jump with a breakpoint and remove the breakpoint |
| 505 | * if need) kprobes listed on unoptimizing_list. | 506 | * if need) kprobes listed on unoptimizing_list. |
| 506 | */ | 507 | */ |
| 507 | static __kprobes void do_unoptimize_kprobes(struct list_head *free_list) | 508 | static __kprobes void do_unoptimize_kprobes(void) |
| 508 | { | 509 | { |
| 509 | struct optimized_kprobe *op, *tmp; | 510 | struct optimized_kprobe *op, *tmp; |
| 510 | 511 | ||
| @@ -515,9 +516,9 @@ static __kprobes void do_unoptimize_kprobes(struct list_head *free_list) | |||
| 515 | /* Ditto to do_optimize_kprobes */ | 516 | /* Ditto to do_optimize_kprobes */ |
| 516 | get_online_cpus(); | 517 | get_online_cpus(); |
| 517 | mutex_lock(&text_mutex); | 518 | mutex_lock(&text_mutex); |
| 518 | arch_unoptimize_kprobes(&unoptimizing_list, free_list); | 519 | arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); |
| 519 | /* Loop free_list for disarming */ | 520 | /* Loop free_list for disarming */ |
| 520 | list_for_each_entry_safe(op, tmp, free_list, list) { | 521 | list_for_each_entry_safe(op, tmp, &freeing_list, list) { |
| 521 | /* Disarm probes if marked disabled */ | 522 | /* Disarm probes if marked disabled */ |
| 522 | if (kprobe_disabled(&op->kp)) | 523 | if (kprobe_disabled(&op->kp)) |
| 523 | arch_disarm_kprobe(&op->kp); | 524 | arch_disarm_kprobe(&op->kp); |
| @@ -536,11 +537,11 @@ static __kprobes void do_unoptimize_kprobes(struct list_head *free_list) | |||
| 536 | } | 537 | } |
| 537 | 538 | ||
| 538 | /* Reclaim all kprobes on the free_list */ | 539 | /* Reclaim all kprobes on the free_list */ |
| 539 | static __kprobes void do_free_cleaned_kprobes(struct list_head *free_list) | 540 | static __kprobes void do_free_cleaned_kprobes(void) |
| 540 | { | 541 | { |
| 541 | struct optimized_kprobe *op, *tmp; | 542 | struct optimized_kprobe *op, *tmp; |
| 542 | 543 | ||
| 543 | list_for_each_entry_safe(op, tmp, free_list, list) { | 544 | list_for_each_entry_safe(op, tmp, &freeing_list, list) { |
| 544 | BUG_ON(!kprobe_unused(&op->kp)); | 545 | BUG_ON(!kprobe_unused(&op->kp)); |
| 545 | list_del_init(&op->list); | 546 | list_del_init(&op->list); |
| 546 | free_aggr_kprobe(&op->kp); | 547 | free_aggr_kprobe(&op->kp); |
| @@ -556,8 +557,6 @@ static __kprobes void kick_kprobe_optimizer(void) | |||
| 556 | /* Kprobe jump optimizer */ | 557 | /* Kprobe jump optimizer */ |
| 557 | static __kprobes void kprobe_optimizer(struct work_struct *work) | 558 | static __kprobes void kprobe_optimizer(struct work_struct *work) |
| 558 | { | 559 | { |
| 559 | LIST_HEAD(free_list); | ||
| 560 | |||
| 561 | mutex_lock(&kprobe_mutex); | 560 | mutex_lock(&kprobe_mutex); |
| 562 | /* Lock modules while optimizing kprobes */ | 561 | /* Lock modules while optimizing kprobes */ |
| 563 | mutex_lock(&module_mutex); | 562 | mutex_lock(&module_mutex); |
| @@ -566,7 +565,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) | |||
| 566 | * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed) | 565 | * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed) |
| 567 | * kprobes before waiting for quiesence period. | 566 | * kprobes before waiting for quiesence period. |
| 568 | */ | 567 | */ |
| 569 | do_unoptimize_kprobes(&free_list); | 568 | do_unoptimize_kprobes(); |
| 570 | 569 | ||
| 571 | /* | 570 | /* |
| 572 | * Step 2: Wait for quiesence period to ensure all running interrupts | 571 | * Step 2: Wait for quiesence period to ensure all running interrupts |
| @@ -581,7 +580,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) | |||
| 581 | do_optimize_kprobes(); | 580 | do_optimize_kprobes(); |
| 582 | 581 | ||
| 583 | /* Step 4: Free cleaned kprobes after quiesence period */ | 582 | /* Step 4: Free cleaned kprobes after quiesence period */ |
| 584 | do_free_cleaned_kprobes(&free_list); | 583 | do_free_cleaned_kprobes(); |
| 585 | 584 | ||
| 586 | mutex_unlock(&module_mutex); | 585 | mutex_unlock(&module_mutex); |
| 587 | mutex_unlock(&kprobe_mutex); | 586 | mutex_unlock(&kprobe_mutex); |
| @@ -723,8 +722,19 @@ static void __kprobes kill_optimized_kprobe(struct kprobe *p) | |||
| 723 | if (!list_empty(&op->list)) | 722 | if (!list_empty(&op->list)) |
| 724 | /* Dequeue from the (un)optimization queue */ | 723 | /* Dequeue from the (un)optimization queue */ |
| 725 | list_del_init(&op->list); | 724 | list_del_init(&op->list); |
| 726 | |||
| 727 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | 725 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; |
| 726 | |||
| 727 | if (kprobe_unused(p)) { | ||
| 728 | /* Enqueue if it is unused */ | ||
| 729 | list_add(&op->list, &freeing_list); | ||
| 730 | /* | ||
| 731 | * Remove unused probes from the hash list. After waiting | ||
| 732 | * for synchronization, this probe is reclaimed. | ||
| 733 | * (reclaiming is done by do_free_cleaned_kprobes().) | ||
| 734 | */ | ||
| 735 | hlist_del_rcu(&op->kp.hlist); | ||
| 736 | } | ||
| 737 | |||
| 728 | /* Don't touch the code, because it is already freed. */ | 738 | /* Don't touch the code, because it is already freed. */ |
| 729 | arch_remove_optimized_kprobe(op); | 739 | arch_remove_optimized_kprobe(op); |
| 730 | } | 740 | } |
diff --git a/kernel/range.c b/kernel/range.c index eb911dbce267..322ea8e93e4b 100644 --- a/kernel/range.c +++ b/kernel/range.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
| 5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
| 6 | #include <linux/sort.h> | 6 | #include <linux/sort.h> |
| 7 | 7 | #include <linux/string.h> | |
| 8 | #include <linux/range.h> | 8 | #include <linux/range.h> |
| 9 | 9 | ||
| 10 | int add_range(struct range *range, int az, int nr_range, u64 start, u64 end) | 10 | int add_range(struct range *range, int az, int nr_range, u64 start, u64 end) |
| @@ -32,9 +32,8 @@ int add_range_with_merge(struct range *range, int az, int nr_range, | |||
| 32 | if (start >= end) | 32 | if (start >= end) |
| 33 | return nr_range; | 33 | return nr_range; |
| 34 | 34 | ||
| 35 | /* Try to merge it with old one: */ | 35 | /* get new start/end: */ |
| 36 | for (i = 0; i < nr_range; i++) { | 36 | for (i = 0; i < nr_range; i++) { |
| 37 | u64 final_start, final_end; | ||
| 38 | u64 common_start, common_end; | 37 | u64 common_start, common_end; |
| 39 | 38 | ||
| 40 | if (!range[i].end) | 39 | if (!range[i].end) |
| @@ -45,14 +44,16 @@ int add_range_with_merge(struct range *range, int az, int nr_range, | |||
| 45 | if (common_start > common_end) | 44 | if (common_start > common_end) |
| 46 | continue; | 45 | continue; |
| 47 | 46 | ||
| 48 | final_start = min(range[i].start, start); | 47 | /* new start/end, will add it back at last */ |
| 49 | final_end = max(range[i].end, end); | 48 | start = min(range[i].start, start); |
| 49 | end = max(range[i].end, end); | ||
| 50 | 50 | ||
| 51 | /* clear it and add it back for further merge */ | 51 | memmove(&range[i], &range[i + 1], |
| 52 | range[i].start = 0; | 52 | (nr_range - (i + 1)) * sizeof(range[i])); |
| 53 | range[i].end = 0; | 53 | range[nr_range - 1].start = 0; |
| 54 | return add_range_with_merge(range, az, nr_range, | 54 | range[nr_range - 1].end = 0; |
| 55 | final_start, final_end); | 55 | nr_range--; |
| 56 | i--; | ||
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | /* Need to add it: */ | 59 | /* Need to add it: */ |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 58453b8272fd..e8b335016c52 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -633,7 +633,19 @@ void wake_up_nohz_cpu(int cpu) | |||
| 633 | static inline bool got_nohz_idle_kick(void) | 633 | static inline bool got_nohz_idle_kick(void) |
| 634 | { | 634 | { |
| 635 | int cpu = smp_processor_id(); | 635 | int cpu = smp_processor_id(); |
| 636 | return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); | 636 | |
| 637 | if (!test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu))) | ||
| 638 | return false; | ||
| 639 | |||
| 640 | if (idle_cpu(cpu) && !need_resched()) | ||
| 641 | return true; | ||
| 642 | |||
| 643 | /* | ||
| 644 | * We can't run Idle Load Balance on this CPU for this time so we | ||
| 645 | * cancel it and clear NOHZ_BALANCE_KICK | ||
| 646 | */ | ||
| 647 | clear_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); | ||
| 648 | return false; | ||
| 637 | } | 649 | } |
| 638 | 650 | ||
| 639 | #else /* CONFIG_NO_HZ_COMMON */ | 651 | #else /* CONFIG_NO_HZ_COMMON */ |
| @@ -1393,8 +1405,9 @@ static void sched_ttwu_pending(void) | |||
| 1393 | 1405 | ||
| 1394 | void scheduler_ipi(void) | 1406 | void scheduler_ipi(void) |
| 1395 | { | 1407 | { |
| 1396 | if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick() | 1408 | if (llist_empty(&this_rq()->wake_list) |
| 1397 | && !tick_nohz_full_cpu(smp_processor_id())) | 1409 | && !tick_nohz_full_cpu(smp_processor_id()) |
| 1410 | && !got_nohz_idle_kick()) | ||
| 1398 | return; | 1411 | return; |
| 1399 | 1412 | ||
| 1400 | /* | 1413 | /* |
| @@ -1417,7 +1430,7 @@ void scheduler_ipi(void) | |||
| 1417 | /* | 1430 | /* |
| 1418 | * Check if someone kicked us for doing the nohz idle load balance. | 1431 | * Check if someone kicked us for doing the nohz idle load balance. |
| 1419 | */ | 1432 | */ |
| 1420 | if (unlikely(got_nohz_idle_kick() && !need_resched())) { | 1433 | if (unlikely(got_nohz_idle_kick())) { |
| 1421 | this_rq()->idle_balance = 1; | 1434 | this_rq()->idle_balance = 1; |
| 1422 | raise_softirq_irqoff(SCHED_SOFTIRQ); | 1435 | raise_softirq_irqoff(SCHED_SOFTIRQ); |
| 1423 | } | 1436 | } |
| @@ -4745,7 +4758,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) | |||
| 4745 | */ | 4758 | */ |
| 4746 | idle->sched_class = &idle_sched_class; | 4759 | idle->sched_class = &idle_sched_class; |
| 4747 | ftrace_graph_init_idle_task(idle, cpu); | 4760 | ftrace_graph_init_idle_task(idle, cpu); |
| 4748 | vtime_init_idle(idle); | 4761 | vtime_init_idle(idle, cpu); |
| 4749 | #if defined(CONFIG_SMP) | 4762 | #if defined(CONFIG_SMP) |
| 4750 | sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); | 4763 | sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); |
| 4751 | #endif | 4764 | #endif |
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index cc2dc3eea8a3..b5ccba22603b 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c | |||
| @@ -747,17 +747,17 @@ void arch_vtime_task_switch(struct task_struct *prev) | |||
| 747 | 747 | ||
| 748 | write_seqlock(¤t->vtime_seqlock); | 748 | write_seqlock(¤t->vtime_seqlock); |
| 749 | current->vtime_snap_whence = VTIME_SYS; | 749 | current->vtime_snap_whence = VTIME_SYS; |
| 750 | current->vtime_snap = sched_clock(); | 750 | current->vtime_snap = sched_clock_cpu(smp_processor_id()); |
| 751 | write_sequnlock(¤t->vtime_seqlock); | 751 | write_sequnlock(¤t->vtime_seqlock); |
| 752 | } | 752 | } |
| 753 | 753 | ||
| 754 | void vtime_init_idle(struct task_struct *t) | 754 | void vtime_init_idle(struct task_struct *t, int cpu) |
| 755 | { | 755 | { |
| 756 | unsigned long flags; | 756 | unsigned long flags; |
| 757 | 757 | ||
| 758 | write_seqlock_irqsave(&t->vtime_seqlock, flags); | 758 | write_seqlock_irqsave(&t->vtime_seqlock, flags); |
| 759 | t->vtime_snap_whence = VTIME_SYS; | 759 | t->vtime_snap_whence = VTIME_SYS; |
| 760 | t->vtime_snap = sched_clock(); | 760 | t->vtime_snap = sched_clock_cpu(cpu); |
| 761 | write_sequnlock_irqrestore(&t->vtime_seqlock, flags); | 761 | write_sequnlock_irqrestore(&t->vtime_seqlock, flags); |
| 762 | } | 762 | } |
| 763 | 763 | ||
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 0c739423b0f9..b4c245580b79 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
| @@ -698,10 +698,6 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) | |||
| 698 | 698 | ||
| 699 | bc->event_handler = tick_handle_oneshot_broadcast; | 699 | bc->event_handler = tick_handle_oneshot_broadcast; |
| 700 | 700 | ||
| 701 | /* Take the do_timer update */ | ||
| 702 | if (!tick_nohz_full_cpu(cpu)) | ||
| 703 | tick_do_timer_cpu = cpu; | ||
| 704 | |||
| 705 | /* | 701 | /* |
| 706 | * We must be careful here. There might be other CPUs | 702 | * We must be careful here. There might be other CPUs |
| 707 | * waiting for periodic broadcast. We need to set the | 703 | * waiting for periodic broadcast. We need to set the |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f4208138fbf4..0cf1c1453181 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -306,7 +306,7 @@ static int __cpuinit tick_nohz_cpu_down_callback(struct notifier_block *nfb, | |||
| 306 | * we can't safely shutdown that CPU. | 306 | * we can't safely shutdown that CPU. |
| 307 | */ | 307 | */ |
| 308 | if (have_nohz_full_mask && tick_do_timer_cpu == cpu) | 308 | if (have_nohz_full_mask && tick_do_timer_cpu == cpu) |
| 309 | return -EINVAL; | 309 | return NOTIFY_BAD; |
| 310 | break; | 310 | break; |
| 311 | } | 311 | } |
| 312 | return NOTIFY_OK; | 312 | return NOTIFY_OK; |
diff --git a/mm/slab_common.c b/mm/slab_common.c index ff3218a0f5e1..2d414508e9ec 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
| @@ -373,8 +373,10 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags) | |||
| 373 | { | 373 | { |
| 374 | int index; | 374 | int index; |
| 375 | 375 | ||
| 376 | if (WARN_ON_ONCE(size > KMALLOC_MAX_SIZE)) | 376 | if (size > KMALLOC_MAX_SIZE) { |
| 377 | WARN_ON_ONCE(!(flags & __GFP_NOWARN)); | ||
| 377 | return NULL; | 378 | return NULL; |
| 379 | } | ||
| 378 | 380 | ||
| 379 | if (size <= 192) { | 381 | if (size <= 192) { |
| 380 | if (!size) | 382 | if (!size) |
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/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index 44b8dcecf571..d6f7694fcad4 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c | |||
| @@ -179,13 +179,12 @@ static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | /* AC97 controller operations */ | 181 | /* AC97 controller operations */ |
| 182 | struct snd_ac97_bus_ops soc_ac97_ops = { | 182 | static struct snd_ac97_bus_ops ac97c_bus_ops = { |
| 183 | .read = au1xac97c_ac97_read, | 183 | .read = au1xac97c_ac97_read, |
| 184 | .write = au1xac97c_ac97_write, | 184 | .write = au1xac97c_ac97_write, |
| 185 | .reset = au1xac97c_ac97_cold_reset, | 185 | .reset = au1xac97c_ac97_cold_reset, |
| 186 | .warm_reset = au1xac97c_ac97_warm_reset, | 186 | .warm_reset = au1xac97c_ac97_warm_reset, |
| 187 | }; | 187 | }; |
| 188 | EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ | ||
| 189 | 188 | ||
| 190 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, | 189 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, |
| 191 | struct snd_soc_dai *dai) | 190 | struct snd_soc_dai *dai) |
| @@ -272,6 +271,10 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) | |||
| 272 | 271 | ||
| 273 | platform_set_drvdata(pdev, ctx); | 272 | platform_set_drvdata(pdev, ctx); |
| 274 | 273 | ||
| 274 | ret = snd_soc_set_ac97_ops(&ac97c_bus_ops); | ||
| 275 | if (ret) | ||
| 276 | return ret; | ||
| 277 | |||
| 275 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, | 278 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, |
| 276 | &au1xac97c_dai_driver, 1); | 279 | &au1xac97c_dai_driver, 1); |
| 277 | if (ret) | 280 | if (ret) |
| @@ -338,19 +341,7 @@ static struct platform_driver au1xac97c_driver = { | |||
| 338 | .remove = au1xac97c_drvremove, | 341 | .remove = au1xac97c_drvremove, |
| 339 | }; | 342 | }; |
| 340 | 343 | ||
| 341 | static int __init au1xac97c_load(void) | 344 | module_platform_driver(&au1xac97c_driver); |
| 342 | { | ||
| 343 | ac97c_workdata = NULL; | ||
| 344 | return platform_driver_register(&au1xac97c_driver); | ||
| 345 | } | ||
| 346 | |||
| 347 | static void __exit au1xac97c_unload(void) | ||
| 348 | { | ||
| 349 | platform_driver_unregister(&au1xac97c_driver); | ||
| 350 | } | ||
| 351 | |||
| 352 | module_init(au1xac97c_load); | ||
| 353 | module_exit(au1xac97c_unload); | ||
| 354 | 345 | ||
| 355 | MODULE_LICENSE("GPL"); | 346 | MODULE_LICENSE("GPL"); |
| 356 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); | 347 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 8f1862aa7333..a822ab822bb7 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
| @@ -201,13 +201,12 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | /* AC97 controller operations */ | 203 | /* AC97 controller operations */ |
| 204 | struct snd_ac97_bus_ops soc_ac97_ops = { | 204 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
| 205 | .read = au1xpsc_ac97_read, | 205 | .read = au1xpsc_ac97_read, |
| 206 | .write = au1xpsc_ac97_write, | 206 | .write = au1xpsc_ac97_write, |
| 207 | .reset = au1xpsc_ac97_cold_reset, | 207 | .reset = au1xpsc_ac97_cold_reset, |
| 208 | .warm_reset = au1xpsc_ac97_warm_reset, | 208 | .warm_reset = au1xpsc_ac97_warm_reset, |
| 209 | }; | 209 | }; |
| 210 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 211 | 210 | ||
| 212 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | 211 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, |
| 213 | struct snd_pcm_hw_params *params, | 212 | struct snd_pcm_hw_params *params, |
| @@ -383,15 +382,9 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
| 383 | if (!iores) | 382 | if (!iores) |
| 384 | return -ENODEV; | 383 | return -ENODEV; |
| 385 | 384 | ||
| 386 | if (!devm_request_mem_region(&pdev->dev, iores->start, | 385 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); |
| 387 | resource_size(iores), | 386 | if (IS_ERR(wd->mmio)) |
| 388 | pdev->name)) | 387 | return PTR_ERR(wd->mmio); |
| 389 | return -EBUSY; | ||
| 390 | |||
| 391 | wd->mmio = devm_ioremap(&pdev->dev, iores->start, | ||
| 392 | resource_size(iores)); | ||
| 393 | if (!wd->mmio) | ||
| 394 | return -EBUSY; | ||
| 395 | 388 | ||
| 396 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 389 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| 397 | if (!dmares) | 390 | if (!dmares) |
| @@ -423,6 +416,10 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
| 423 | 416 | ||
| 424 | platform_set_drvdata(pdev, wd); | 417 | platform_set_drvdata(pdev, wd); |
| 425 | 418 | ||
| 419 | ret = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
| 420 | if (ret) | ||
| 421 | return ret; | ||
| 422 | |||
| 426 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, | 423 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, |
| 427 | &wd->dai_drv, 1); | 424 | &wd->dai_drv, 1); |
| 428 | if (ret) | 425 | if (ret) |
| @@ -503,19 +500,7 @@ static struct platform_driver au1xpsc_ac97_driver = { | |||
| 503 | .remove = au1xpsc_ac97_drvremove, | 500 | .remove = au1xpsc_ac97_drvremove, |
| 504 | }; | 501 | }; |
| 505 | 502 | ||
| 506 | static int __init au1xpsc_ac97_load(void) | 503 | module_platform_driver(au1xpsc_ac97_driver); |
| 507 | { | ||
| 508 | au1xpsc_ac97_workdata = NULL; | ||
| 509 | return platform_driver_register(&au1xpsc_ac97_driver); | ||
| 510 | } | ||
| 511 | |||
| 512 | static void __exit au1xpsc_ac97_unload(void) | ||
| 513 | { | ||
| 514 | platform_driver_unregister(&au1xpsc_ac97_driver); | ||
| 515 | } | ||
| 516 | |||
| 517 | module_init(au1xpsc_ac97_load); | ||
| 518 | module_exit(au1xpsc_ac97_unload); | ||
| 519 | 504 | ||
| 520 | MODULE_LICENSE("GPL"); | 505 | MODULE_LICENSE("GPL"); |
| 521 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); | 506 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); |
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 490217325975..efb1daecd0dd 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
| @@ -198,13 +198,12 @@ static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 198 | #endif | 198 | #endif |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | struct snd_ac97_bus_ops soc_ac97_ops = { | 201 | static struct snd_ac97_bus_ops bf5xx_ac97_ops = { |
| 202 | .read = bf5xx_ac97_read, | 202 | .read = bf5xx_ac97_read, |
| 203 | .write = bf5xx_ac97_write, | 203 | .write = bf5xx_ac97_write, |
| 204 | .warm_reset = bf5xx_ac97_warm_reset, | 204 | .warm_reset = bf5xx_ac97_warm_reset, |
| 205 | .reset = bf5xx_ac97_cold_reset, | 205 | .reset = bf5xx_ac97_cold_reset, |
| 206 | }; | 206 | }; |
| 207 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 208 | 207 | ||
| 209 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
| 210 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) | 209 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
| @@ -231,9 +230,9 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
| 231 | return 0; | 230 | return 0; |
| 232 | 231 | ||
| 233 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | 232 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) |
| 234 | ret = sport_set_multichannel(sport, 16, 0x3FF, 1); | 233 | ret = sport_set_multichannel(sport, 16, 0x3FF, 0x3FF, 1); |
| 235 | #else | 234 | #else |
| 236 | ret = sport_set_multichannel(sport, 16, 0x1F, 1); | 235 | ret = sport_set_multichannel(sport, 16, 0x1F, 0x1F, 1); |
| 237 | #endif | 236 | #endif |
| 238 | if (ret) { | 237 | if (ret) { |
| 239 | pr_err("SPORT is busy!\n"); | 238 | pr_err("SPORT is busy!\n"); |
| @@ -293,13 +292,14 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
| 293 | 292 | ||
| 294 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 293 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
| 295 | /* Request PB3 as reset pin */ | 294 | /* Request PB3 as reset pin */ |
| 296 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 295 | ret = devm_gpio_request_one(&pdev->dev, |
| 297 | pr_err("Failed to request GPIO_%d for reset\n", | 296 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, |
| 298 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 297 | GPIOF_OUT_INIT_HIGH, "SND_AD198x RESET") { |
| 299 | ret = -1; | 298 | dev_err(&pdev->dev, |
| 299 | "Failed to request GPIO_%d for reset: %d\n", | ||
| 300 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, ret); | ||
| 300 | goto gpio_err; | 301 | goto gpio_err; |
| 301 | } | 302 | } |
| 302 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | ||
| 303 | #endif | 303 | #endif |
| 304 | 304 | ||
| 305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), | 305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), |
| @@ -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"); |
| @@ -335,6 +335,12 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
| 335 | goto sport_config_err; | 335 | goto sport_config_err; |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | ret = snd_soc_set_ac97_ops(&bf5xx_ac97_ops); | ||
| 339 | if (ret != 0) { | ||
| 340 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
| 341 | goto sport_config_err; | ||
| 342 | } | ||
| 343 | |||
| 338 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, | 344 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, |
| 339 | &bfin_ac97_dai, 1); | 345 | &bfin_ac97_dai, 1); |
| 340 | if (ret) { | 346 | if (ret) { |
| @@ -349,10 +355,7 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
| 349 | sport_config_err: | 355 | sport_config_err: |
| 350 | sport_done(sport_handle); | 356 | sport_done(sport_handle); |
| 351 | sport_err: | 357 | sport_err: |
| 352 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 358 | snd_soc_set_ac97_ops(NULL); |
| 353 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
| 354 | gpio_err: | ||
| 355 | #endif | ||
| 356 | 359 | ||
| 357 | return ret; | 360 | return ret; |
| 358 | } | 361 | } |
| @@ -363,9 +366,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev) | |||
| 363 | 366 | ||
| 364 | snd_soc_unregister_component(&pdev->dev); | 367 | snd_soc_unregister_component(&pdev->dev); |
| 365 | sport_done(sport_handle); | 368 | sport_done(sport_handle); |
| 366 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 369 | snd_soc_set_ac97_ops(NULL); |
| 367 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
| 368 | #endif | ||
| 369 | 370 | ||
| 370 | return 0; | 371 | return 0; |
| 371 | } | 372 | } |
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 7798fbd5e81d..ac73c607410a 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
| @@ -237,13 +237,12 @@ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) | |||
| 237 | return IRQ_HANDLED; | 237 | return IRQ_HANDLED; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | struct snd_ac97_bus_ops soc_ac97_ops = { | 240 | static struct snd_ac97_bus_ops ep93xx_ac97_ops = { |
| 241 | .read = ep93xx_ac97_read, | 241 | .read = ep93xx_ac97_read, |
| 242 | .write = ep93xx_ac97_write, | 242 | .write = ep93xx_ac97_write, |
| 243 | .reset = ep93xx_ac97_cold_reset, | 243 | .reset = ep93xx_ac97_cold_reset, |
| 244 | .warm_reset = ep93xx_ac97_warm_reset, | 244 | .warm_reset = ep93xx_ac97_warm_reset, |
| 245 | }; | 245 | }; |
| 246 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 247 | 246 | ||
| 248 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | 247 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, |
| 249 | int cmd, struct snd_soc_dai *dai) | 248 | int cmd, struct snd_soc_dai *dai) |
| @@ -314,22 +313,15 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | |||
| 314 | return 0; | 313 | return 0; |
| 315 | } | 314 | } |
| 316 | 315 | ||
| 317 | static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, | 316 | static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai) |
| 318 | struct snd_soc_dai *dai) | ||
| 319 | { | 317 | { |
| 320 | struct ep93xx_dma_data *dma_data; | 318 | dai->playback_dma_data = &ep93xx_ac97_pcm_out; |
| 319 | dai->capture_dma_data = &ep93xx_ac97_pcm_in; | ||
| 321 | 320 | ||
| 322 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 323 | dma_data = &ep93xx_ac97_pcm_out; | ||
| 324 | else | ||
| 325 | dma_data = &ep93xx_ac97_pcm_in; | ||
| 326 | |||
| 327 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | ||
| 328 | return 0; | 321 | return 0; |
| 329 | } | 322 | } |
| 330 | 323 | ||
| 331 | static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { | 324 | static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { |
| 332 | .startup = ep93xx_ac97_startup, | ||
| 333 | .trigger = ep93xx_ac97_trigger, | 325 | .trigger = ep93xx_ac97_trigger, |
| 334 | }; | 326 | }; |
| 335 | 327 | ||
| @@ -337,6 +329,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = { | |||
| 337 | .name = "ep93xx-ac97", | 329 | .name = "ep93xx-ac97", |
| 338 | .id = 0, | 330 | .id = 0, |
| 339 | .ac97_control = 1, | 331 | .ac97_control = 1, |
| 332 | .probe = ep93xx_ac97_dai_probe, | ||
| 340 | .playback = { | 333 | .playback = { |
| 341 | .stream_name = "AC97 Playback", | 334 | .stream_name = "AC97 Playback", |
| 342 | .channels_min = 2, | 335 | .channels_min = 2, |
| @@ -395,6 +388,10 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
| 395 | ep93xx_ac97_info = info; | 388 | ep93xx_ac97_info = info; |
| 396 | platform_set_drvdata(pdev, info); | 389 | platform_set_drvdata(pdev, info); |
| 397 | 390 | ||
| 391 | ret = snd_soc_set_ac97_ops(&ep93xx_ac97_ops); | ||
| 392 | if (ret) | ||
| 393 | goto fail; | ||
| 394 | |||
| 398 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, | 395 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, |
| 399 | &ep93xx_ac97_dai, 1); | 396 | &ep93xx_ac97_dai, 1); |
| 400 | if (ret) | 397 | if (ret) |
| @@ -403,9 +400,8 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
| 403 | return 0; | 400 | return 0; |
| 404 | 401 | ||
| 405 | fail: | 402 | fail: |
| 406 | platform_set_drvdata(pdev, NULL); | ||
| 407 | ep93xx_ac97_info = NULL; | 403 | ep93xx_ac97_info = NULL; |
| 408 | dev_set_drvdata(&pdev->dev, NULL); | 404 | snd_soc_set_ac97_ops(NULL); |
| 409 | return ret; | 405 | return ret; |
| 410 | } | 406 | } |
| 411 | 407 | ||
| @@ -418,9 +414,9 @@ static int ep93xx_ac97_remove(struct platform_device *pdev) | |||
| 418 | /* disable the AC97 controller */ | 414 | /* disable the AC97 controller */ |
| 419 | ep93xx_ac97_write_reg(info, AC97GCR, 0); | 415 | ep93xx_ac97_write_reg(info, AC97GCR, 0); |
| 420 | 416 | ||
| 421 | platform_set_drvdata(pdev, NULL); | ||
| 422 | ep93xx_ac97_info = NULL; | 417 | ep93xx_ac97_info = NULL; |
| 423 | dev_set_drvdata(&pdev->dev, NULL); | 418 | |
| 419 | snd_soc_set_ac97_ops(NULL); | ||
| 424 | 420 | ||
| 425 | return 0; | 421 | return 0; |
| 426 | } | 422 | } |
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 60159c07448d..8af04343cc1a 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
| @@ -120,10 +120,8 @@ | |||
| 120 | * before DAC & PGA in DAPM power-off sequence. | 120 | * before DAC & PGA in DAPM power-off sequence. |
| 121 | */ | 121 | */ |
| 122 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ | 122 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ |
| 123 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 123 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, 0, 0, NULL, 0, wevent, \ |
| 124 | .shift = 0, .invert = 0, .kcontrol_news = NULL, \ | 124 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD) |
| 125 | .num_kcontrols = 0, .event = wevent, \ | ||
| 126 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } | ||
| 127 | 125 | ||
| 128 | struct pm860x_det { | 126 | struct pm860x_det { |
| 129 | struct snd_soc_jack *hp_jack; | 127 | struct snd_soc_jack *hp_jack; |
| @@ -1444,7 +1442,7 @@ static int pm860x_codec_probe(struct platform_device *pdev) | |||
| 1444 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 1442 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
| 1445 | if (!res) { | 1443 | if (!res) { |
| 1446 | dev_err(&pdev->dev, "Failed to get IRQ resources\n"); | 1444 | dev_err(&pdev->dev, "Failed to get IRQ resources\n"); |
| 1447 | goto out; | 1445 | return -EINVAL; |
| 1448 | } | 1446 | } |
| 1449 | pm860x->irq[i] = res->start + chip->irq_base; | 1447 | pm860x->irq[i] = res->start + chip->irq_base; |
| 1450 | strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); | 1448 | strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); |
| @@ -1454,19 +1452,14 @@ static int pm860x_codec_probe(struct platform_device *pdev) | |||
| 1454 | pm860x_dai, ARRAY_SIZE(pm860x_dai)); | 1452 | pm860x_dai, ARRAY_SIZE(pm860x_dai)); |
| 1455 | if (ret) { | 1453 | if (ret) { |
| 1456 | dev_err(&pdev->dev, "Failed to register codec\n"); | 1454 | dev_err(&pdev->dev, "Failed to register codec\n"); |
| 1457 | goto out; | 1455 | return -EINVAL; |
| 1458 | } | 1456 | } |
| 1459 | return ret; | 1457 | return ret; |
| 1460 | |||
| 1461 | out: | ||
| 1462 | platform_set_drvdata(pdev, NULL); | ||
| 1463 | return -EINVAL; | ||
| 1464 | } | 1458 | } |
| 1465 | 1459 | ||
| 1466 | static int pm860x_codec_remove(struct platform_device *pdev) | 1460 | static int pm860x_codec_remove(struct platform_device *pdev) |
| 1467 | { | 1461 | { |
| 1468 | snd_soc_unregister_codec(&pdev->dev); | 1462 | snd_soc_unregister_codec(&pdev->dev); |
| 1469 | platform_set_drvdata(pdev, NULL); | ||
| 1470 | return 0; | 1463 | return 0; |
| 1471 | } | 1464 | } |
| 1472 | 1465 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5841674b6993..badb6fbacaa6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -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/ac97.c b/sound/soc/codecs/ac97.c index ef2ae32ffc66..ec7351803c24 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
| @@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
| 62 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 62 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
| 63 | unsigned int reg) | 63 | unsigned int reg) |
| 64 | { | 64 | { |
| 65 | return soc_ac97_ops.read(codec->ac97, reg); | 65 | return soc_ac97_ops->read(codec->ac97, reg); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
| 69 | unsigned int val) | 69 | unsigned int val) |
| 70 | { | 70 | { |
| 71 | soc_ac97_ops.write(codec->ac97, reg, val); | 71 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -79,7 +79,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
| 79 | int ret; | 79 | int ret; |
| 80 | 80 | ||
| 81 | /* add codec as bus device for standard ac97 */ | 81 | /* add codec as bus device for standard ac97 */ |
| 82 | ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); | 82 | ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL, |
| 83 | &ac97_bus); | ||
| 83 | if (ret < 0) | 84 | if (ret < 0) |
| 84 | return ret; | 85 | return ret; |
| 85 | 86 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index f385342947d3..89fcf7d6e7b8 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
| @@ -108,7 +108,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
| 108 | case AC97_EXTENDED_STATUS: | 108 | case AC97_EXTENDED_STATUS: |
| 109 | case AC97_VENDOR_ID1: | 109 | case AC97_VENDOR_ID1: |
| 110 | case AC97_VENDOR_ID2: | 110 | case AC97_VENDOR_ID2: |
| 111 | return soc_ac97_ops.read(codec->ac97, reg); | 111 | return soc_ac97_ops->read(codec->ac97, reg); |
| 112 | default: | 112 | default: |
| 113 | reg = reg >> 1; | 113 | reg = reg >> 1; |
| 114 | 114 | ||
| @@ -124,7 +124,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 124 | { | 124 | { |
| 125 | u16 *cache = codec->reg_cache; | 125 | u16 *cache = codec->reg_cache; |
| 126 | 126 | ||
| 127 | soc_ac97_ops.write(codec->ac97, reg, val); | 127 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 128 | reg = reg >> 1; | 128 | reg = reg >> 1; |
| 129 | if (reg < ARRAY_SIZE(ad1980_reg)) | 129 | if (reg < ARRAY_SIZE(ad1980_reg)) |
| 130 | cache[reg] = val; | 130 | cache[reg] = val; |
| @@ -154,13 +154,13 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | |||
| 154 | u16 retry_cnt = 0; | 154 | u16 retry_cnt = 0; |
| 155 | 155 | ||
| 156 | retry: | 156 | retry: |
| 157 | if (try_warm && soc_ac97_ops.warm_reset) { | 157 | if (try_warm && soc_ac97_ops->warm_reset) { |
| 158 | soc_ac97_ops.warm_reset(codec->ac97); | 158 | soc_ac97_ops->warm_reset(codec->ac97); |
| 159 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 159 | if (ac97_read(codec, AC97_RESET) == 0x0090) |
| 160 | return 1; | 160 | return 1; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | soc_ac97_ops.reset(codec->ac97); | 163 | soc_ac97_ops->reset(codec->ac97); |
| 164 | /* Set bit 16slot in register 74h, then every slot will has only 16 | 164 | /* Set bit 16slot in register 74h, then every slot will has only 16 |
| 165 | * bits. This command is sent out in 20bit mode, in which case the | 165 | * bits. This command is sent out in 20bit mode, in which case the |
| 166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ | 166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ |
| @@ -186,7 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
| 186 | 186 | ||
| 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
| 188 | 188 | ||
| 189 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 189 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
| 190 | if (ret < 0) { | 190 | if (ret < 0) { |
| 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
| 192 | return ret; | 192 | return ret; |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index dafdbe87edeb..0e250f118c0e 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
| @@ -13,6 +13,10 @@ | |||
| 13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/of_gpio.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 19 | #include <linux/regmap.h> | ||
| 16 | #include <sound/core.h> | 20 | #include <sound/core.h> |
| 17 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
| 18 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
| @@ -21,16 +25,19 @@ | |||
| 21 | #include "sigmadsp.h" | 25 | #include "sigmadsp.h" |
| 22 | #include "adau1701.h" | 26 | #include "adau1701.h" |
| 23 | 27 | ||
| 24 | #define ADAU1701_DSPCTRL 0x1c | 28 | #define ADAU1701_DSPCTRL 0x081c |
| 25 | #define ADAU1701_SEROCTL 0x1e | 29 | #define ADAU1701_SEROCTL 0x081e |
| 26 | #define ADAU1701_SERICTL 0x1f | 30 | #define ADAU1701_SERICTL 0x081f |
| 27 | 31 | ||
| 28 | #define ADAU1701_AUXNPOW 0x22 | 32 | #define ADAU1701_AUXNPOW 0x0822 |
| 33 | #define ADAU1701_PINCONF_0 0x0820 | ||
| 34 | #define ADAU1701_PINCONF_1 0x0821 | ||
| 35 | #define ADAU1701_AUXNPOW 0x0822 | ||
| 29 | 36 | ||
| 30 | #define ADAU1701_OSCIPOW 0x26 | 37 | #define ADAU1701_OSCIPOW 0x0826 |
| 31 | #define ADAU1701_DACSET 0x27 | 38 | #define ADAU1701_DACSET 0x0827 |
| 32 | 39 | ||
| 33 | #define ADAU1701_NUM_REGS 0x28 | 40 | #define ADAU1701_MAX_REGISTER 0x0828 |
| 34 | 41 | ||
| 35 | #define ADAU1701_DSPCTRL_CR (1 << 2) | 42 | #define ADAU1701_DSPCTRL_CR (1 << 2) |
| 36 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | 43 | #define ADAU1701_DSPCTRL_DAM (1 << 3) |
| @@ -84,10 +91,18 @@ | |||
| 84 | #define ADAU1701_OSCIPOW_OPD 0x04 | 91 | #define ADAU1701_OSCIPOW_OPD 0x04 |
| 85 | #define ADAU1701_DACSET_DACINIT 1 | 92 | #define ADAU1701_DACSET_DACINIT 1 |
| 86 | 93 | ||
| 94 | #define ADAU1707_CLKDIV_UNSET (-1UL) | ||
| 95 | |||
| 87 | #define ADAU1701_FIRMWARE "adau1701.bin" | 96 | #define ADAU1701_FIRMWARE "adau1701.bin" |
| 88 | 97 | ||
| 89 | struct adau1701 { | 98 | struct adau1701 { |
| 99 | int gpio_nreset; | ||
| 100 | int gpio_pll_mode[2]; | ||
| 90 | unsigned int dai_fmt; | 101 | unsigned int dai_fmt; |
| 102 | unsigned int pll_clkdiv; | ||
| 103 | unsigned int sysclk; | ||
| 104 | struct regmap *regmap; | ||
| 105 | u8 pin_config[12]; | ||
| 91 | }; | 106 | }; |
| 92 | 107 | ||
| 93 | static const struct snd_kcontrol_new adau1701_controls[] = { | 108 | static const struct snd_kcontrol_new adau1701_controls[] = { |
| @@ -119,10 +134,13 @@ static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { | |||
| 119 | { "ADC", NULL, "IN1" }, | 134 | { "ADC", NULL, "IN1" }, |
| 120 | }; | 135 | }; |
| 121 | 136 | ||
| 122 | static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | 137 | static unsigned int adau1701_register_size(struct device *dev, |
| 123 | unsigned int reg) | 138 | unsigned int reg) |
| 124 | { | 139 | { |
| 125 | switch (reg) { | 140 | switch (reg) { |
| 141 | case ADAU1701_PINCONF_0: | ||
| 142 | case ADAU1701_PINCONF_1: | ||
| 143 | return 3; | ||
| 126 | case ADAU1701_DSPCTRL: | 144 | case ADAU1701_DSPCTRL: |
| 127 | case ADAU1701_SEROCTL: | 145 | case ADAU1701_SEROCTL: |
| 128 | case ADAU1701_AUXNPOW: | 146 | case ADAU1701_AUXNPOW: |
| @@ -133,33 +151,42 @@ static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | |||
| 133 | return 1; | 151 | return 1; |
| 134 | } | 152 | } |
| 135 | 153 | ||
| 136 | dev_err(codec->dev, "Unsupported register address: %d\n", reg); | 154 | dev_err(dev, "Unsupported register address: %d\n", reg); |
| 137 | return 0; | 155 | return 0; |
| 138 | } | 156 | } |
| 139 | 157 | ||
| 140 | static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | 158 | static bool adau1701_volatile_reg(struct device *dev, unsigned int reg) |
| 141 | unsigned int value) | ||
| 142 | { | 159 | { |
| 160 | switch (reg) { | ||
| 161 | case ADAU1701_DACSET: | ||
| 162 | return true; | ||
| 163 | default: | ||
| 164 | return false; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | static int adau1701_reg_write(void *context, unsigned int reg, | ||
| 169 | unsigned int value) | ||
| 170 | { | ||
| 171 | struct i2c_client *client = context; | ||
| 143 | unsigned int i; | 172 | unsigned int i; |
| 144 | unsigned int size; | 173 | unsigned int size; |
| 145 | uint8_t buf[4]; | 174 | uint8_t buf[5]; |
| 146 | int ret; | 175 | int ret; |
| 147 | 176 | ||
| 148 | size = adau1701_register_size(codec, reg); | 177 | size = adau1701_register_size(&client->dev, reg); |
| 149 | if (size == 0) | 178 | if (size == 0) |
| 150 | return -EINVAL; | 179 | return -EINVAL; |
| 151 | 180 | ||
| 152 | snd_soc_cache_write(codec, reg, value); | 181 | buf[0] = reg >> 8; |
| 153 | 182 | buf[1] = reg & 0xff; | |
| 154 | buf[0] = 0x08; | ||
| 155 | buf[1] = reg; | ||
| 156 | 183 | ||
| 157 | for (i = size + 1; i >= 2; --i) { | 184 | for (i = size + 1; i >= 2; --i) { |
| 158 | buf[i] = value; | 185 | buf[i] = value; |
| 159 | value >>= 8; | 186 | value >>= 8; |
| 160 | } | 187 | } |
| 161 | 188 | ||
| 162 | ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); | 189 | ret = i2c_master_send(client, buf, size + 2); |
| 163 | if (ret == size + 2) | 190 | if (ret == size + 2) |
| 164 | return 0; | 191 | return 0; |
| 165 | else if (ret < 0) | 192 | else if (ret < 0) |
| @@ -168,21 +195,107 @@ static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 168 | return -EIO; | 195 | return -EIO; |
| 169 | } | 196 | } |
| 170 | 197 | ||
| 171 | static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) | 198 | static int adau1701_reg_read(void *context, unsigned int reg, |
| 199 | unsigned int *value) | ||
| 172 | { | 200 | { |
| 173 | unsigned int value; | 201 | int ret; |
| 174 | unsigned int ret; | 202 | unsigned int i; |
| 203 | unsigned int size; | ||
| 204 | uint8_t send_buf[2], recv_buf[3]; | ||
| 205 | struct i2c_client *client = context; | ||
| 206 | struct i2c_msg msgs[2]; | ||
| 207 | |||
| 208 | size = adau1701_register_size(&client->dev, reg); | ||
| 209 | if (size == 0) | ||
| 210 | return -EINVAL; | ||
| 211 | |||
| 212 | send_buf[0] = reg >> 8; | ||
| 213 | send_buf[1] = reg & 0xff; | ||
| 214 | |||
| 215 | msgs[0].addr = client->addr; | ||
| 216 | msgs[0].len = sizeof(send_buf); | ||
| 217 | msgs[0].buf = send_buf; | ||
| 218 | msgs[0].flags = 0; | ||
| 219 | |||
| 220 | msgs[1].addr = client->addr; | ||
| 221 | msgs[1].len = size; | ||
| 222 | msgs[1].buf = recv_buf; | ||
| 223 | msgs[1].flags = I2C_M_RD; | ||
| 175 | 224 | ||
| 176 | ret = snd_soc_cache_read(codec, reg, &value); | 225 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
| 177 | if (ret) | 226 | if (ret < 0) |
| 178 | return ret; | 227 | return ret; |
| 228 | else if (ret != ARRAY_SIZE(msgs)) | ||
| 229 | return -EIO; | ||
| 230 | |||
| 231 | *value = 0; | ||
| 232 | |||
| 233 | for (i = 0; i < size; i++) | ||
| 234 | *value |= recv_buf[i] << (i * 8); | ||
| 179 | 235 | ||
| 180 | return value; | 236 | return 0; |
| 181 | } | 237 | } |
| 182 | 238 | ||
| 183 | static int adau1701_load_firmware(struct snd_soc_codec *codec) | 239 | static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) |
| 184 | { | 240 | { |
| 185 | return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); | 241 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
| 242 | struct i2c_client *client = to_i2c_client(codec->dev); | ||
| 243 | int ret; | ||
| 244 | |||
| 245 | if (clkdiv != ADAU1707_CLKDIV_UNSET && | ||
| 246 | gpio_is_valid(adau1701->gpio_pll_mode[0]) && | ||
| 247 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { | ||
| 248 | switch (clkdiv) { | ||
| 249 | case 64: | ||
| 250 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
| 251 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
| 252 | break; | ||
| 253 | case 256: | ||
| 254 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
| 255 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
| 256 | break; | ||
| 257 | case 384: | ||
| 258 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
| 259 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
| 260 | break; | ||
| 261 | case 0: /* fallback */ | ||
| 262 | case 512: | ||
| 263 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
| 264 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | adau1701->pll_clkdiv = clkdiv; | ||
| 270 | |||
| 271 | if (gpio_is_valid(adau1701->gpio_nreset)) { | ||
| 272 | gpio_set_value(adau1701->gpio_nreset, 0); | ||
| 273 | /* minimum reset time is 20ns */ | ||
| 274 | udelay(1); | ||
| 275 | gpio_set_value(adau1701->gpio_nreset, 1); | ||
| 276 | /* power-up time may be as long as 85ms */ | ||
| 277 | mdelay(85); | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Postpone the firmware download to a point in time when we | ||
| 282 | * know the correct PLL setup | ||
| 283 | */ | ||
| 284 | if (clkdiv != ADAU1707_CLKDIV_UNSET) { | ||
| 285 | ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); | ||
| 286 | if (ret) { | ||
| 287 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
| 288 | return ret; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | regmap_write(adau1701->regmap, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | ||
| 293 | regmap_write(adau1701->regmap, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
| 294 | |||
| 295 | regcache_mark_dirty(adau1701->regmap); | ||
| 296 | regcache_sync(adau1701->regmap); | ||
| 297 | |||
| 298 | return 0; | ||
| 186 | } | 299 | } |
| 187 | 300 | ||
| 188 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | 301 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, |
| @@ -259,8 +372,22 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
| 259 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 372 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
| 260 | { | 373 | { |
| 261 | struct snd_soc_codec *codec = dai->codec; | 374 | struct snd_soc_codec *codec = dai->codec; |
| 375 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
| 376 | unsigned int clkdiv = adau1701->sysclk / params_rate(params); | ||
| 262 | snd_pcm_format_t format; | 377 | snd_pcm_format_t format; |
| 263 | unsigned int val; | 378 | unsigned int val; |
| 379 | int ret; | ||
| 380 | |||
| 381 | /* | ||
| 382 | * If the mclk/lrclk ratio changes, the chip needs updated PLL | ||
| 383 | * mode GPIO settings, and a full reset cycle, including a new | ||
| 384 | * firmware upload. | ||
| 385 | */ | ||
| 386 | if (clkdiv != adau1701->pll_clkdiv) { | ||
| 387 | ret = adau1701_reset(codec, clkdiv); | ||
| 388 | if (ret < 0) | ||
| 389 | return ret; | ||
| 390 | } | ||
| 264 | 391 | ||
| 265 | switch (params_rate(params)) { | 392 | switch (params_rate(params)) { |
| 266 | case 192000: | 393 | case 192000: |
| @@ -352,8 +479,8 @@ static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 352 | 479 | ||
| 353 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | 480 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
| 354 | 481 | ||
| 355 | snd_soc_write(codec, ADAU1701_SERICTL, serictl); | 482 | regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl); |
| 356 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, | 483 | regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, |
| 357 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); | 484 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); |
| 358 | 485 | ||
| 359 | return 0; | 486 | return 0; |
| @@ -403,6 +530,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
| 403 | int source, unsigned int freq, int dir) | 530 | int source, unsigned int freq, int dir) |
| 404 | { | 531 | { |
| 405 | unsigned int val; | 532 | unsigned int val; |
| 533 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
| 406 | 534 | ||
| 407 | switch (clk_id) { | 535 | switch (clk_id) { |
| 408 | case ADAU1701_CLK_SRC_OSC: | 536 | case ADAU1701_CLK_SRC_OSC: |
| @@ -416,6 +544,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
| 416 | } | 544 | } |
| 417 | 545 | ||
| 418 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); | 546 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); |
| 547 | adau1701->sysclk = freq; | ||
| 419 | 548 | ||
| 420 | return 0; | 549 | return 0; |
| 421 | } | 550 | } |
| @@ -452,18 +581,47 @@ static struct snd_soc_dai_driver adau1701_dai = { | |||
| 452 | .symmetric_rates = 1, | 581 | .symmetric_rates = 1, |
| 453 | }; | 582 | }; |
| 454 | 583 | ||
| 584 | #ifdef CONFIG_OF | ||
| 585 | static const struct of_device_id adau1701_dt_ids[] = { | ||
| 586 | { .compatible = "adi,adau1701", }, | ||
| 587 | { } | ||
| 588 | }; | ||
| 589 | MODULE_DEVICE_TABLE(of, adau1701_dt_ids); | ||
| 590 | #endif | ||
| 591 | |||
| 455 | static int adau1701_probe(struct snd_soc_codec *codec) | 592 | static int adau1701_probe(struct snd_soc_codec *codec) |
| 456 | { | 593 | { |
| 457 | int ret; | 594 | int i, ret; |
| 595 | unsigned int val; | ||
| 596 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
| 458 | 597 | ||
| 459 | codec->control_data = to_i2c_client(codec->dev); | 598 | codec->control_data = to_i2c_client(codec->dev); |
| 460 | 599 | ||
| 461 | ret = adau1701_load_firmware(codec); | 600 | /* |
| 462 | if (ret) | 601 | * Let the pll_clkdiv variable default to something that won't happen |
| 463 | dev_warn(codec->dev, "Failed to load firmware\n"); | 602 | * at runtime. That way, we can postpone the firmware download from |
| 603 | * adau1701_reset() to a point in time when we know the correct PLL | ||
| 604 | * mode parameters. | ||
| 605 | */ | ||
| 606 | adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; | ||
| 607 | |||
| 608 | /* initalize with pre-configured pll mode settings */ | ||
| 609 | ret = adau1701_reset(codec, adau1701->pll_clkdiv); | ||
| 610 | if (ret < 0) | ||
| 611 | return ret; | ||
| 612 | |||
| 613 | /* set up pin config */ | ||
| 614 | val = 0; | ||
| 615 | for (i = 0; i < 6; i++) | ||
| 616 | val |= adau1701->pin_config[i] << (i * 4); | ||
| 464 | 617 | ||
| 465 | snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | 618 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_0, val); |
| 466 | snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | 619 | |
| 620 | val = 0; | ||
| 621 | for (i = 0; i < 6; i++) | ||
| 622 | val |= adau1701->pin_config[i + 6] << (i * 4); | ||
| 623 | |||
| 624 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); | ||
| 467 | 625 | ||
| 468 | return 0; | 626 | return 0; |
| 469 | } | 627 | } |
| @@ -473,9 +631,6 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
| 473 | .set_bias_level = adau1701_set_bias_level, | 631 | .set_bias_level = adau1701_set_bias_level, |
| 474 | .idle_bias_off = true, | 632 | .idle_bias_off = true, |
| 475 | 633 | ||
| 476 | .reg_cache_size = ADAU1701_NUM_REGS, | ||
| 477 | .reg_word_size = sizeof(u16), | ||
| 478 | |||
| 479 | .controls = adau1701_controls, | 634 | .controls = adau1701_controls, |
| 480 | .num_controls = ARRAY_SIZE(adau1701_controls), | 635 | .num_controls = ARRAY_SIZE(adau1701_controls), |
| 481 | .dapm_widgets = adau1701_dapm_widgets, | 636 | .dapm_widgets = adau1701_dapm_widgets, |
| @@ -483,22 +638,86 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
| 483 | .dapm_routes = adau1701_dapm_routes, | 638 | .dapm_routes = adau1701_dapm_routes, |
| 484 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), | 639 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), |
| 485 | 640 | ||
| 486 | .write = adau1701_write, | ||
| 487 | .read = adau1701_read, | ||
| 488 | |||
| 489 | .set_sysclk = adau1701_set_sysclk, | 641 | .set_sysclk = adau1701_set_sysclk, |
| 490 | }; | 642 | }; |
| 491 | 643 | ||
| 644 | static const struct regmap_config adau1701_regmap = { | ||
| 645 | .reg_bits = 16, | ||
| 646 | .val_bits = 32, | ||
| 647 | .max_register = ADAU1701_MAX_REGISTER, | ||
| 648 | .cache_type = REGCACHE_RBTREE, | ||
| 649 | .volatile_reg = adau1701_volatile_reg, | ||
| 650 | .reg_write = adau1701_reg_write, | ||
| 651 | .reg_read = adau1701_reg_read, | ||
| 652 | }; | ||
| 653 | |||
| 492 | static int adau1701_i2c_probe(struct i2c_client *client, | 654 | static int adau1701_i2c_probe(struct i2c_client *client, |
| 493 | const struct i2c_device_id *id) | 655 | const struct i2c_device_id *id) |
| 494 | { | 656 | { |
| 495 | struct adau1701 *adau1701; | 657 | struct adau1701 *adau1701; |
| 658 | struct device *dev = &client->dev; | ||
| 659 | int gpio_nreset = -EINVAL; | ||
| 660 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; | ||
| 496 | int ret; | 661 | int ret; |
| 497 | 662 | ||
| 498 | adau1701 = devm_kzalloc(&client->dev, sizeof(*adau1701), GFP_KERNEL); | 663 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); |
| 499 | if (!adau1701) | 664 | if (!adau1701) |
| 500 | return -ENOMEM; | 665 | return -ENOMEM; |
| 501 | 666 | ||
| 667 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | ||
| 668 | &adau1701_regmap); | ||
| 669 | if (IS_ERR(adau1701->regmap)) | ||
| 670 | return PTR_ERR(adau1701->regmap); | ||
| 671 | |||
| 672 | if (dev->of_node) { | ||
| 673 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); | ||
| 674 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) | ||
| 675 | return gpio_nreset; | ||
| 676 | |||
| 677 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, | ||
| 678 | "adi,pll-mode-gpios", 0); | ||
| 679 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) | ||
| 680 | return gpio_pll_mode[0]; | ||
| 681 | |||
| 682 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, | ||
| 683 | "adi,pll-mode-gpios", 1); | ||
| 684 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) | ||
| 685 | return gpio_pll_mode[1]; | ||
| 686 | |||
| 687 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", | ||
| 688 | &adau1701->pll_clkdiv); | ||
| 689 | |||
| 690 | of_property_read_u8_array(dev->of_node, "adi,pin-config", | ||
| 691 | adau1701->pin_config, | ||
| 692 | ARRAY_SIZE(adau1701->pin_config)); | ||
| 693 | } | ||
| 694 | |||
| 695 | if (gpio_is_valid(gpio_nreset)) { | ||
| 696 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, | ||
| 697 | "ADAU1701 Reset"); | ||
| 698 | if (ret < 0) | ||
| 699 | return ret; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (gpio_is_valid(gpio_pll_mode[0]) && | ||
| 703 | gpio_is_valid(gpio_pll_mode[1])) { | ||
| 704 | ret = devm_gpio_request_one(dev, gpio_pll_mode[0], | ||
| 705 | GPIOF_OUT_INIT_LOW, | ||
| 706 | "ADAU1701 PLL mode 0"); | ||
| 707 | if (ret < 0) | ||
| 708 | return ret; | ||
| 709 | |||
| 710 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], | ||
| 711 | GPIOF_OUT_INIT_LOW, | ||
| 712 | "ADAU1701 PLL mode 1"); | ||
| 713 | if (ret < 0) | ||
| 714 | return ret; | ||
| 715 | } | ||
| 716 | |||
| 717 | adau1701->gpio_nreset = gpio_nreset; | ||
| 718 | adau1701->gpio_pll_mode[0] = gpio_pll_mode[0]; | ||
| 719 | adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; | ||
| 720 | |||
| 502 | i2c_set_clientdata(client, adau1701); | 721 | i2c_set_clientdata(client, adau1701); |
| 503 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 722 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
| 504 | &adau1701_dai, 1); | 723 | &adau1701_dai, 1); |
| @@ -521,6 +740,7 @@ static struct i2c_driver adau1701_i2c_driver = { | |||
| 521 | .driver = { | 740 | .driver = { |
| 522 | .name = "adau1701", | 741 | .name = "adau1701", |
| 523 | .owner = THIS_MODULE, | 742 | .owner = THIS_MODULE, |
| 743 | .of_match_table = of_match_ptr(adau1701_dt_ids), | ||
| 524 | }, | 744 | }, |
| 525 | .probe = adau1701_i2c_probe, | 745 | .probe = adau1701_i2c_probe, |
| 526 | .remove = adau1701_i2c_remove, | 746 | .remove = adau1701_i2c_remove, |
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/stac9766.c b/sound/soc/codecs/stac9766.c index 2eda85ba79ac..a5455c1aea42 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
| @@ -28,8 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #include "stac9766.h" | 29 | #include "stac9766.h" |
| 30 | 30 | ||
| 31 | #define STAC9766_VERSION "0.10" | ||
| 32 | |||
| 33 | /* | 31 | /* |
| 34 | * STAC9766 register cache | 32 | * STAC9766 register cache |
| 35 | */ | 33 | */ |
| @@ -145,14 +143,14 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 145 | 143 | ||
| 146 | if (reg > AC97_STAC_PAGE0) { | 144 | if (reg > AC97_STAC_PAGE0) { |
| 147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
| 148 | soc_ac97_ops.write(codec->ac97, reg, val); | 146 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 149 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
| 150 | return 0; | 148 | return 0; |
| 151 | } | 149 | } |
| 152 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
| 153 | return -EIO; | 151 | return -EIO; |
| 154 | 152 | ||
| 155 | soc_ac97_ops.write(codec->ac97, reg, val); | 153 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 156 | cache[reg / 2] = val; | 154 | cache[reg / 2] = val; |
| 157 | return 0; | 155 | return 0; |
| 158 | } | 156 | } |
| @@ -164,7 +162,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
| 164 | 162 | ||
| 165 | if (reg > AC97_STAC_PAGE0) { | 163 | if (reg > AC97_STAC_PAGE0) { |
| 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
| 167 | val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); | 165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); |
| 168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
| 169 | return val; | 167 | return val; |
| 170 | } | 168 | } |
| @@ -175,7 +173,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
| 175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
| 176 | reg == AC97_VENDOR_ID2) { | 174 | reg == AC97_VENDOR_ID2) { |
| 177 | 175 | ||
| 178 | val = soc_ac97_ops.read(codec->ac97, reg); | 176 | val = soc_ac97_ops->read(codec->ac97, reg); |
| 179 | return val; | 177 | return val; |
| 180 | } | 178 | } |
| 181 | return cache[reg / 2]; | 179 | return cache[reg / 2]; |
| @@ -242,15 +240,15 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
| 242 | 240 | ||
| 243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
| 244 | { | 242 | { |
| 245 | if (try_warm && soc_ac97_ops.warm_reset) { | 243 | if (try_warm && soc_ac97_ops->warm_reset) { |
| 246 | soc_ac97_ops.warm_reset(codec->ac97); | 244 | soc_ac97_ops->warm_reset(codec->ac97); |
| 247 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
| 248 | return 1; | 246 | return 1; |
| 249 | } | 247 | } |
| 250 | 248 | ||
| 251 | soc_ac97_ops.reset(codec->ac97); | 249 | soc_ac97_ops->reset(codec->ac97); |
| 252 | if (soc_ac97_ops.warm_reset) | 250 | if (soc_ac97_ops->warm_reset) |
| 253 | soc_ac97_ops.warm_reset(codec->ac97); | 251 | soc_ac97_ops->warm_reset(codec->ac97); |
| 254 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
| 255 | return -EIO; | 253 | return -EIO; |
| 256 | return 0; | 254 | return 0; |
| @@ -274,7 +272,7 @@ reset: | |||
| 274 | return -EIO; | 272 | return -EIO; |
| 275 | } | 273 | } |
| 276 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 274 | codec->ac97->bus->ops->warm_reset(codec->ac97); |
| 277 | id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2); | 275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); |
| 278 | if (id != 0x4c13) { | 276 | if (id != 0x4c13) { |
| 279 | stac9766_reset(codec, 0); | 277 | stac9766_reset(codec, 0); |
| 280 | reset++; | 278 | reset++; |
| @@ -338,9 +336,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
| 338 | { | 336 | { |
| 339 | int ret = 0; | 337 | int ret = 0; |
| 340 | 338 | ||
| 341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
| 342 | |||
| 343 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
| 344 | if (ret < 0) | 340 | if (ret < 0) |
| 345 | goto codec_err; | 341 | goto codec_err; |
| 346 | 342 | ||
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d447c4aa1d5e..6d31d88f7204 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c | |||
| @@ -83,6 +83,14 @@ | |||
| 83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ | 83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ |
| 84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ | 84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ |
| 85 | #define TAS5086_BKNDERR 0x1c | 85 | #define TAS5086_BKNDERR 0x1c |
| 86 | #define TAS5086_INPUT_MUX 0x20 | ||
| 87 | #define TAS5086_PWM_OUTPUT_MUX 0x25 | ||
| 88 | |||
| 89 | #define TAS5086_MAX_REGISTER TAS5086_PWM_OUTPUT_MUX | ||
| 90 | |||
| 91 | #define TAS5086_PWM_START_MIDZ_FOR_START_1 (1 << 7) | ||
| 92 | #define TAS5086_PWM_START_MIDZ_FOR_START_2 (1 << 6) | ||
| 93 | #define TAS5086_PWM_START_CHANNEL_MASK (0x3f) | ||
| 86 | 94 | ||
| 87 | /* | 95 | /* |
| 88 | * Default TAS5086 power-up configuration | 96 | * Default TAS5086 power-up configuration |
| @@ -119,9 +127,30 @@ static const struct reg_default tas5086_reg_defaults[] = { | |||
| 119 | { 0x1c, 0x05 }, | 127 | { 0x1c, 0x05 }, |
| 120 | }; | 128 | }; |
| 121 | 129 | ||
| 130 | static int tas5086_register_size(struct device *dev, unsigned int reg) | ||
| 131 | { | ||
| 132 | switch (reg) { | ||
| 133 | case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR: | ||
| 134 | return 1; | ||
| 135 | case TAS5086_INPUT_MUX: | ||
| 136 | case TAS5086_PWM_OUTPUT_MUX: | ||
| 137 | return 4; | ||
| 138 | } | ||
| 139 | |||
| 140 | dev_err(dev, "Unsupported register address: %d\n", reg); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 122 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) | 144 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) |
| 123 | { | 145 | { |
| 124 | return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17)); | 146 | switch (reg) { |
| 147 | case 0x0f: | ||
| 148 | case 0x11 ... 0x17: | ||
| 149 | case 0x1d ... 0x1f: | ||
| 150 | return false; | ||
| 151 | default: | ||
| 152 | return true; | ||
| 153 | } | ||
| 125 | } | 154 | } |
| 126 | 155 | ||
| 127 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) | 156 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) |
| @@ -140,6 +169,76 @@ static bool tas5086_writeable_reg(struct device *dev, unsigned int reg) | |||
| 140 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); | 169 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); |
| 141 | } | 170 | } |
| 142 | 171 | ||
| 172 | static int tas5086_reg_write(void *context, unsigned int reg, | ||
| 173 | unsigned int value) | ||
| 174 | { | ||
| 175 | struct i2c_client *client = context; | ||
| 176 | unsigned int i, size; | ||
| 177 | uint8_t buf[5]; | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | size = tas5086_register_size(&client->dev, reg); | ||
| 181 | if (size == 0) | ||
| 182 | return -EINVAL; | ||
| 183 | |||
| 184 | buf[0] = reg; | ||
| 185 | |||
| 186 | for (i = size; i >= 1; --i) { | ||
| 187 | buf[i] = value; | ||
| 188 | value >>= 8; | ||
| 189 | } | ||
| 190 | |||
| 191 | ret = i2c_master_send(client, buf, size + 1); | ||
| 192 | if (ret == size + 1) | ||
| 193 | return 0; | ||
| 194 | else if (ret < 0) | ||
| 195 | return ret; | ||
| 196 | else | ||
| 197 | return -EIO; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int tas5086_reg_read(void *context, unsigned int reg, | ||
| 201 | unsigned int *value) | ||
| 202 | { | ||
| 203 | struct i2c_client *client = context; | ||
| 204 | uint8_t send_buf, recv_buf[4]; | ||
| 205 | struct i2c_msg msgs[2]; | ||
| 206 | unsigned int size; | ||
| 207 | unsigned int i; | ||
| 208 | int ret; | ||
| 209 | |||
| 210 | size = tas5086_register_size(&client->dev, reg); | ||
| 211 | if (size == 0) | ||
| 212 | return -EINVAL; | ||
| 213 | |||
| 214 | send_buf = reg; | ||
| 215 | |||
| 216 | msgs[0].addr = client->addr; | ||
| 217 | msgs[0].len = sizeof(send_buf); | ||
| 218 | msgs[0].buf = &send_buf; | ||
| 219 | msgs[0].flags = 0; | ||
| 220 | |||
| 221 | msgs[1].addr = client->addr; | ||
| 222 | msgs[1].len = size; | ||
| 223 | msgs[1].buf = recv_buf; | ||
| 224 | msgs[1].flags = I2C_M_RD; | ||
| 225 | |||
| 226 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 227 | if (ret < 0) | ||
| 228 | return ret; | ||
| 229 | else if (ret != ARRAY_SIZE(msgs)) | ||
| 230 | return -EIO; | ||
| 231 | |||
| 232 | *value = 0; | ||
| 233 | |||
| 234 | for (i = 0; i < size; i++) { | ||
| 235 | *value <<= 8; | ||
| 236 | *value |= recv_buf[i]; | ||
| 237 | } | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 143 | struct tas5086_private { | 242 | struct tas5086_private { |
| 144 | struct regmap *regmap; | 243 | struct regmap *regmap; |
| 145 | unsigned int mclk, sclk; | 244 | unsigned int mclk, sclk; |
| @@ -376,6 +475,202 @@ static const struct snd_kcontrol_new tas5086_controls[] = { | |||
| 376 | tas5086_get_deemph, tas5086_put_deemph), | 475 | tas5086_get_deemph, tas5086_put_deemph), |
| 377 | }; | 476 | }; |
| 378 | 477 | ||
| 478 | /* Input mux controls */ | ||
| 479 | static const char *tas5086_dapm_sdin_texts[] = | ||
| 480 | { | ||
| 481 | "SDIN1-L", "SDIN1-R", "SDIN2-L", "SDIN2-R", | ||
| 482 | "SDIN3-L", "SDIN3-R", "Ground (0)", "nc" | ||
| 483 | }; | ||
| 484 | |||
| 485 | static const struct soc_enum tas5086_dapm_input_mux_enum[] = { | ||
| 486 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 20, 8, tas5086_dapm_sdin_texts), | ||
| 487 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 16, 8, tas5086_dapm_sdin_texts), | ||
| 488 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 12, 8, tas5086_dapm_sdin_texts), | ||
| 489 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 8, 8, tas5086_dapm_sdin_texts), | ||
| 490 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 4, 8, tas5086_dapm_sdin_texts), | ||
| 491 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 0, 8, tas5086_dapm_sdin_texts), | ||
| 492 | }; | ||
| 493 | |||
| 494 | static const struct snd_kcontrol_new tas5086_dapm_input_mux_controls[] = { | ||
| 495 | SOC_DAPM_ENUM("Channel 1 input", tas5086_dapm_input_mux_enum[0]), | ||
| 496 | SOC_DAPM_ENUM("Channel 2 input", tas5086_dapm_input_mux_enum[1]), | ||
| 497 | SOC_DAPM_ENUM("Channel 3 input", tas5086_dapm_input_mux_enum[2]), | ||
| 498 | SOC_DAPM_ENUM("Channel 4 input", tas5086_dapm_input_mux_enum[3]), | ||
| 499 | SOC_DAPM_ENUM("Channel 5 input", tas5086_dapm_input_mux_enum[4]), | ||
| 500 | SOC_DAPM_ENUM("Channel 6 input", tas5086_dapm_input_mux_enum[5]), | ||
| 501 | }; | ||
| 502 | |||
| 503 | /* Output mux controls */ | ||
| 504 | static const char *tas5086_dapm_channel_texts[] = | ||
| 505 | { "Channel 1 Mux", "Channel 2 Mux", "Channel 3 Mux", | ||
| 506 | "Channel 4 Mux", "Channel 5 Mux", "Channel 6 Mux" }; | ||
| 507 | |||
| 508 | static const struct soc_enum tas5086_dapm_output_mux_enum[] = { | ||
| 509 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 20, 6, tas5086_dapm_channel_texts), | ||
| 510 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 16, 6, tas5086_dapm_channel_texts), | ||
| 511 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 12, 6, tas5086_dapm_channel_texts), | ||
| 512 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 8, 6, tas5086_dapm_channel_texts), | ||
| 513 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 4, 6, tas5086_dapm_channel_texts), | ||
| 514 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 0, 6, tas5086_dapm_channel_texts), | ||
| 515 | }; | ||
| 516 | |||
| 517 | static const struct snd_kcontrol_new tas5086_dapm_output_mux_controls[] = { | ||
| 518 | SOC_DAPM_ENUM("PWM1 Output", tas5086_dapm_output_mux_enum[0]), | ||
| 519 | SOC_DAPM_ENUM("PWM2 Output", tas5086_dapm_output_mux_enum[1]), | ||
| 520 | SOC_DAPM_ENUM("PWM3 Output", tas5086_dapm_output_mux_enum[2]), | ||
| 521 | SOC_DAPM_ENUM("PWM4 Output", tas5086_dapm_output_mux_enum[3]), | ||
| 522 | SOC_DAPM_ENUM("PWM5 Output", tas5086_dapm_output_mux_enum[4]), | ||
| 523 | SOC_DAPM_ENUM("PWM6 Output", tas5086_dapm_output_mux_enum[5]), | ||
| 524 | }; | ||
| 525 | |||
| 526 | static const struct snd_soc_dapm_widget tas5086_dapm_widgets[] = { | ||
| 527 | SND_SOC_DAPM_INPUT("SDIN1-L"), | ||
| 528 | SND_SOC_DAPM_INPUT("SDIN1-R"), | ||
| 529 | SND_SOC_DAPM_INPUT("SDIN2-L"), | ||
| 530 | SND_SOC_DAPM_INPUT("SDIN2-R"), | ||
| 531 | SND_SOC_DAPM_INPUT("SDIN3-L"), | ||
| 532 | SND_SOC_DAPM_INPUT("SDIN3-R"), | ||
| 533 | SND_SOC_DAPM_INPUT("SDIN4-L"), | ||
| 534 | SND_SOC_DAPM_INPUT("SDIN4-R"), | ||
| 535 | |||
| 536 | SND_SOC_DAPM_OUTPUT("PWM1"), | ||
| 537 | SND_SOC_DAPM_OUTPUT("PWM2"), | ||
| 538 | SND_SOC_DAPM_OUTPUT("PWM3"), | ||
| 539 | SND_SOC_DAPM_OUTPUT("PWM4"), | ||
| 540 | SND_SOC_DAPM_OUTPUT("PWM5"), | ||
| 541 | SND_SOC_DAPM_OUTPUT("PWM6"), | ||
| 542 | |||
| 543 | SND_SOC_DAPM_MUX("Channel 1 Mux", SND_SOC_NOPM, 0, 0, | ||
| 544 | &tas5086_dapm_input_mux_controls[0]), | ||
| 545 | SND_SOC_DAPM_MUX("Channel 2 Mux", SND_SOC_NOPM, 0, 0, | ||
| 546 | &tas5086_dapm_input_mux_controls[1]), | ||
| 547 | SND_SOC_DAPM_MUX("Channel 3 Mux", SND_SOC_NOPM, 0, 0, | ||
| 548 | &tas5086_dapm_input_mux_controls[2]), | ||
| 549 | SND_SOC_DAPM_MUX("Channel 4 Mux", SND_SOC_NOPM, 0, 0, | ||
| 550 | &tas5086_dapm_input_mux_controls[3]), | ||
| 551 | SND_SOC_DAPM_MUX("Channel 5 Mux", SND_SOC_NOPM, 0, 0, | ||
| 552 | &tas5086_dapm_input_mux_controls[4]), | ||
| 553 | SND_SOC_DAPM_MUX("Channel 6 Mux", SND_SOC_NOPM, 0, 0, | ||
| 554 | &tas5086_dapm_input_mux_controls[5]), | ||
| 555 | |||
| 556 | SND_SOC_DAPM_MUX("PWM1 Mux", SND_SOC_NOPM, 0, 0, | ||
| 557 | &tas5086_dapm_output_mux_controls[0]), | ||
| 558 | SND_SOC_DAPM_MUX("PWM2 Mux", SND_SOC_NOPM, 0, 0, | ||
| 559 | &tas5086_dapm_output_mux_controls[1]), | ||
| 560 | SND_SOC_DAPM_MUX("PWM3 Mux", SND_SOC_NOPM, 0, 0, | ||
| 561 | &tas5086_dapm_output_mux_controls[2]), | ||
| 562 | SND_SOC_DAPM_MUX("PWM4 Mux", SND_SOC_NOPM, 0, 0, | ||
| 563 | &tas5086_dapm_output_mux_controls[3]), | ||
| 564 | SND_SOC_DAPM_MUX("PWM5 Mux", SND_SOC_NOPM, 0, 0, | ||
| 565 | &tas5086_dapm_output_mux_controls[4]), | ||
| 566 | SND_SOC_DAPM_MUX("PWM6 Mux", SND_SOC_NOPM, 0, 0, | ||
| 567 | &tas5086_dapm_output_mux_controls[5]), | ||
| 568 | }; | ||
| 569 | |||
| 570 | static const struct snd_soc_dapm_route tas5086_dapm_routes[] = { | ||
| 571 | /* SDIN inputs -> channel muxes */ | ||
| 572 | { "Channel 1 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 573 | { "Channel 1 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 574 | { "Channel 1 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 575 | { "Channel 1 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 576 | { "Channel 1 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 577 | { "Channel 1 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 578 | |||
| 579 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 580 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 581 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 582 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 583 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 584 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 585 | |||
| 586 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 587 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 588 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 589 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 590 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 591 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 592 | |||
| 593 | { "Channel 3 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 594 | { "Channel 3 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 595 | { "Channel 3 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 596 | { "Channel 3 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 597 | { "Channel 3 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 598 | { "Channel 3 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 599 | |||
| 600 | { "Channel 4 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 601 | { "Channel 4 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 602 | { "Channel 4 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 603 | { "Channel 4 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 604 | { "Channel 4 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 605 | { "Channel 4 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 606 | |||
| 607 | { "Channel 5 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 608 | { "Channel 5 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 609 | { "Channel 5 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 610 | { "Channel 5 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 611 | { "Channel 5 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 612 | { "Channel 5 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 613 | |||
| 614 | { "Channel 6 Mux", "SDIN1-L", "SDIN1-L" }, | ||
| 615 | { "Channel 6 Mux", "SDIN1-R", "SDIN1-R" }, | ||
| 616 | { "Channel 6 Mux", "SDIN2-L", "SDIN2-L" }, | ||
| 617 | { "Channel 6 Mux", "SDIN2-R", "SDIN2-R" }, | ||
| 618 | { "Channel 6 Mux", "SDIN3-L", "SDIN3-L" }, | ||
| 619 | { "Channel 6 Mux", "SDIN3-R", "SDIN3-R" }, | ||
| 620 | |||
| 621 | /* Channel muxes -> PWM muxes */ | ||
| 622 | { "PWM1 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 623 | { "PWM2 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 624 | { "PWM3 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 625 | { "PWM4 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 626 | { "PWM5 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 627 | { "PWM6 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
| 628 | |||
| 629 | { "PWM1 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 630 | { "PWM2 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 631 | { "PWM3 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 632 | { "PWM4 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 633 | { "PWM5 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 634 | { "PWM6 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
| 635 | |||
| 636 | { "PWM1 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 637 | { "PWM2 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 638 | { "PWM3 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 639 | { "PWM4 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 640 | { "PWM5 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 641 | { "PWM6 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
| 642 | |||
| 643 | { "PWM1 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 644 | { "PWM2 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 645 | { "PWM3 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 646 | { "PWM4 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 647 | { "PWM5 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 648 | { "PWM6 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
| 649 | |||
| 650 | { "PWM1 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 651 | { "PWM2 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 652 | { "PWM3 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 653 | { "PWM4 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 654 | { "PWM5 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 655 | { "PWM6 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
| 656 | |||
| 657 | { "PWM1 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 658 | { "PWM2 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 659 | { "PWM3 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 660 | { "PWM4 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 661 | { "PWM5 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 662 | { "PWM6 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
| 663 | |||
| 664 | /* The PWM muxes are directly connected to the PWM outputs */ | ||
| 665 | { "PWM1", NULL, "PWM1 Mux" }, | ||
| 666 | { "PWM2", NULL, "PWM2 Mux" }, | ||
| 667 | { "PWM3", NULL, "PWM3 Mux" }, | ||
| 668 | { "PWM4", NULL, "PWM4 Mux" }, | ||
| 669 | { "PWM5", NULL, "PWM5 Mux" }, | ||
| 670 | { "PWM6", NULL, "PWM6 Mux" }, | ||
| 671 | |||
| 672 | }; | ||
| 673 | |||
| 379 | static const struct snd_soc_dai_ops tas5086_dai_ops = { | 674 | static const struct snd_soc_dai_ops tas5086_dai_ops = { |
| 380 | .hw_params = tas5086_hw_params, | 675 | .hw_params = tas5086_hw_params, |
| 381 | .set_sysclk = tas5086_set_dai_sysclk, | 676 | .set_sysclk = tas5086_set_dai_sysclk, |
| @@ -426,13 +721,34 @@ static int tas5086_probe(struct snd_soc_codec *codec) | |||
| 426 | { | 721 | { |
| 427 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 722 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
| 428 | int charge_period = 1300000; /* hardware default is 1300 ms */ | 723 | int charge_period = 1300000; /* hardware default is 1300 ms */ |
| 724 | u8 pwm_start_mid_z = 0; | ||
| 429 | int i, ret; | 725 | int i, ret; |
| 430 | 726 | ||
| 431 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { | 727 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { |
| 432 | struct device_node *of_node = codec->dev->of_node; | 728 | struct device_node *of_node = codec->dev->of_node; |
| 433 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); | 729 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); |
| 730 | |||
| 731 | for (i = 0; i < 6; i++) { | ||
| 732 | char name[25]; | ||
| 733 | |||
| 734 | snprintf(name, sizeof(name), | ||
| 735 | "ti,mid-z-channel-%d", i + 1); | ||
| 736 | |||
| 737 | if (of_get_property(of_node, name, NULL) != NULL) | ||
| 738 | pwm_start_mid_z |= 1 << i; | ||
| 739 | } | ||
| 434 | } | 740 | } |
| 435 | 741 | ||
| 742 | /* | ||
| 743 | * If any of the channels is configured to start in Mid-Z mode, | ||
| 744 | * configure 'part 1' of the PWM starts to use Mid-Z, and tell | ||
| 745 | * all configured mid-z channels to start start under 'part 1'. | ||
| 746 | */ | ||
| 747 | if (pwm_start_mid_z) | ||
| 748 | regmap_write(priv->regmap, TAS5086_PWM_START, | ||
| 749 | TAS5086_PWM_START_MIDZ_FOR_START_1 | | ||
| 750 | pwm_start_mid_z); | ||
| 751 | |||
| 436 | /* lookup and set split-capacitor charge period */ | 752 | /* lookup and set split-capacitor charge period */ |
| 437 | if (charge_period == 0) { | 753 | if (charge_period == 0) { |
| 438 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); | 754 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); |
| @@ -490,6 +806,10 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { | |||
| 490 | .resume = tas5086_soc_resume, | 806 | .resume = tas5086_soc_resume, |
| 491 | .controls = tas5086_controls, | 807 | .controls = tas5086_controls, |
| 492 | .num_controls = ARRAY_SIZE(tas5086_controls), | 808 | .num_controls = ARRAY_SIZE(tas5086_controls), |
| 809 | .dapm_widgets = tas5086_dapm_widgets, | ||
| 810 | .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), | ||
| 811 | .dapm_routes = tas5086_dapm_routes, | ||
| 812 | .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), | ||
| 493 | }; | 813 | }; |
| 494 | 814 | ||
| 495 | static const struct i2c_device_id tas5086_i2c_id[] = { | 815 | static const struct i2c_device_id tas5086_i2c_id[] = { |
| @@ -500,14 +820,16 @@ MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); | |||
| 500 | 820 | ||
| 501 | static const struct regmap_config tas5086_regmap = { | 821 | static const struct regmap_config tas5086_regmap = { |
| 502 | .reg_bits = 8, | 822 | .reg_bits = 8, |
| 503 | .val_bits = 8, | 823 | .val_bits = 32, |
| 504 | .max_register = ARRAY_SIZE(tas5086_reg_defaults), | 824 | .max_register = TAS5086_MAX_REGISTER, |
| 505 | .reg_defaults = tas5086_reg_defaults, | 825 | .reg_defaults = tas5086_reg_defaults, |
| 506 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), | 826 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), |
| 507 | .cache_type = REGCACHE_RBTREE, | 827 | .cache_type = REGCACHE_RBTREE, |
| 508 | .volatile_reg = tas5086_volatile_reg, | 828 | .volatile_reg = tas5086_volatile_reg, |
| 509 | .writeable_reg = tas5086_writeable_reg, | 829 | .writeable_reg = tas5086_writeable_reg, |
| 510 | .readable_reg = tas5086_accessible_reg, | 830 | .readable_reg = tas5086_accessible_reg, |
| 831 | .reg_read = tas5086_reg_read, | ||
| 832 | .reg_write = tas5086_reg_write, | ||
| 511 | }; | 833 | }; |
| 512 | 834 | ||
| 513 | static int tas5086_i2c_probe(struct i2c_client *i2c, | 835 | static int tas5086_i2c_probe(struct i2c_client *i2c, |
| @@ -522,7 +844,7 @@ static int tas5086_i2c_probe(struct i2c_client *i2c, | |||
| 522 | if (!priv) | 844 | if (!priv) |
| 523 | return -ENOMEM; | 845 | return -ENOMEM; |
| 524 | 846 | ||
| 525 | priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap); | 847 | priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); |
| 526 | if (IS_ERR(priv->regmap)) { | 848 | if (IS_ERR(priv->regmap)) { |
| 527 | ret = PTR_ERR(priv->regmap); | 849 | ret = PTR_ERR(priv->regmap); |
| 528 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | 850 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 1514bf845e4b..e5b926883131 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
| @@ -128,10 +128,8 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | |||
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ | 130 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
| 131 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 131 | SOC_SINGLE_EXT(xname, reg, shift, mask, invert, \ |
| 132 | .info = snd_soc_info_volsw, \ | 132 | snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw_aic3x) |
| 133 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw_aic3x, \ | ||
| 134 | .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } | ||
| 135 | 133 | ||
| 136 | /* | 134 | /* |
| 137 | * All input lines are connected when !0xf and disconnected with 0xf bit field, | 135 | * All input lines are connected when !0xf and disconnected with 0xf bit field, |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 9b9a6e587610..44621ddc332d 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
| @@ -38,6 +38,14 @@ | |||
| 38 | 38 | ||
| 39 | #include "twl6040.h" | 39 | #include "twl6040.h" |
| 40 | 40 | ||
| 41 | enum twl6040_dai_id { | ||
| 42 | TWL6040_DAI_LEGACY = 0, | ||
| 43 | TWL6040_DAI_UL, | ||
| 44 | TWL6040_DAI_DL1, | ||
| 45 | TWL6040_DAI_DL2, | ||
| 46 | TWL6040_DAI_VIB, | ||
| 47 | }; | ||
| 48 | |||
| 41 | #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 | 49 | #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 |
| 42 | #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) | 50 | #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) |
| 43 | 51 | ||
| @@ -67,6 +75,8 @@ struct twl6040_data { | |||
| 67 | int pll_power_mode; | 75 | int pll_power_mode; |
| 68 | int hs_power_mode; | 76 | int hs_power_mode; |
| 69 | int hs_power_mode_locked; | 77 | int hs_power_mode_locked; |
| 78 | bool dl1_unmuted; | ||
| 79 | bool dl2_unmuted; | ||
| 70 | unsigned int clk_in; | 80 | unsigned int clk_in; |
| 71 | unsigned int sysclk; | 81 | unsigned int sysclk; |
| 72 | struct twl6040_jack_data hs_jack; | 82 | struct twl6040_jack_data hs_jack; |
| @@ -220,6 +230,25 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, | |||
| 220 | return value; | 230 | return value; |
| 221 | } | 231 | } |
| 222 | 232 | ||
| 233 | static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec, | ||
| 234 | unsigned int reg) | ||
| 235 | { | ||
| 236 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
| 237 | |||
| 238 | switch (reg) { | ||
| 239 | case TWL6040_REG_HSLCTL: | ||
| 240 | case TWL6040_REG_HSRCTL: | ||
| 241 | case TWL6040_REG_EARCTL: | ||
| 242 | /* DL1 path */ | ||
| 243 | return priv->dl1_unmuted; | ||
| 244 | case TWL6040_REG_HFLCTL: | ||
| 245 | case TWL6040_REG_HFRCTL: | ||
| 246 | return priv->dl2_unmuted; | ||
| 247 | default: | ||
| 248 | return 1; | ||
| 249 | }; | ||
| 250 | } | ||
| 251 | |||
| 223 | /* | 252 | /* |
| 224 | * write to the twl6040 register space | 253 | * write to the twl6040 register space |
| 225 | */ | 254 | */ |
| @@ -232,7 +261,8 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
| 232 | return -EIO; | 261 | return -EIO; |
| 233 | 262 | ||
| 234 | twl6040_write_reg_cache(codec, reg, value); | 263 | twl6040_write_reg_cache(codec, reg, value); |
| 235 | if (likely(reg < TWL6040_REG_SW_SHADOW)) | 264 | if (likely(reg < TWL6040_REG_SW_SHADOW) && |
| 265 | twl6040_is_path_unmuted(codec, reg)) | ||
| 236 | return twl6040_reg_write(twl6040, reg, value); | 266 | return twl6040_reg_write(twl6040, reg, value); |
| 237 | else | 267 | else |
| 238 | return 0; | 268 | return 0; |
| @@ -1026,16 +1056,84 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
| 1026 | return 0; | 1056 | return 0; |
| 1027 | } | 1057 | } |
| 1028 | 1058 | ||
| 1059 | static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id id, | ||
| 1060 | int mute) | ||
| 1061 | { | ||
| 1062 | struct twl6040 *twl6040 = codec->control_data; | ||
| 1063 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
| 1064 | int hslctl, hsrctl, earctl; | ||
| 1065 | int hflctl, hfrctl; | ||
| 1066 | |||
| 1067 | switch (id) { | ||
| 1068 | case TWL6040_DAI_DL1: | ||
| 1069 | hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); | ||
| 1070 | hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); | ||
| 1071 | earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL); | ||
| 1072 | |||
| 1073 | if (mute) { | ||
| 1074 | /* Power down drivers and DACs */ | ||
| 1075 | earctl &= ~0x01; | ||
| 1076 | hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); | ||
| 1077 | hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); | ||
| 1078 | |||
| 1079 | } | ||
| 1080 | |||
| 1081 | twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl); | ||
| 1082 | twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl); | ||
| 1083 | twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl); | ||
| 1084 | priv->dl1_unmuted = !mute; | ||
| 1085 | break; | ||
| 1086 | case TWL6040_DAI_DL2: | ||
| 1087 | hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); | ||
| 1088 | hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); | ||
| 1089 | |||
| 1090 | if (mute) { | ||
| 1091 | /* Power down drivers and DACs */ | ||
| 1092 | hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | | ||
| 1093 | TWL6040_HFDRVENA); | ||
| 1094 | hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | | ||
| 1095 | TWL6040_HFDRVENA); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl); | ||
| 1099 | twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl); | ||
| 1100 | priv->dl2_unmuted = !mute; | ||
| 1101 | break; | ||
| 1102 | default: | ||
| 1103 | break; | ||
| 1104 | }; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) | ||
| 1108 | { | ||
| 1109 | switch (dai->id) { | ||
| 1110 | case TWL6040_DAI_LEGACY: | ||
| 1111 | twl6040_mute_path(dai->codec, TWL6040_DAI_DL1, mute); | ||
| 1112 | twl6040_mute_path(dai->codec, TWL6040_DAI_DL2, mute); | ||
| 1113 | break; | ||
| 1114 | case TWL6040_DAI_DL1: | ||
| 1115 | case TWL6040_DAI_DL2: | ||
| 1116 | twl6040_mute_path(dai->codec, dai->id, mute); | ||
| 1117 | break; | ||
| 1118 | default: | ||
| 1119 | break; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | return 0; | ||
| 1123 | } | ||
| 1124 | |||
| 1029 | static const struct snd_soc_dai_ops twl6040_dai_ops = { | 1125 | static const struct snd_soc_dai_ops twl6040_dai_ops = { |
| 1030 | .startup = twl6040_startup, | 1126 | .startup = twl6040_startup, |
| 1031 | .hw_params = twl6040_hw_params, | 1127 | .hw_params = twl6040_hw_params, |
| 1032 | .prepare = twl6040_prepare, | 1128 | .prepare = twl6040_prepare, |
| 1033 | .set_sysclk = twl6040_set_dai_sysclk, | 1129 | .set_sysclk = twl6040_set_dai_sysclk, |
| 1130 | .digital_mute = twl6040_digital_mute, | ||
| 1034 | }; | 1131 | }; |
| 1035 | 1132 | ||
| 1036 | static struct snd_soc_dai_driver twl6040_dai[] = { | 1133 | static struct snd_soc_dai_driver twl6040_dai[] = { |
| 1037 | { | 1134 | { |
| 1038 | .name = "twl6040-legacy", | 1135 | .name = "twl6040-legacy", |
| 1136 | .id = TWL6040_DAI_LEGACY, | ||
| 1039 | .playback = { | 1137 | .playback = { |
| 1040 | .stream_name = "Legacy Playback", | 1138 | .stream_name = "Legacy Playback", |
| 1041 | .channels_min = 1, | 1139 | .channels_min = 1, |
| @@ -1054,6 +1152,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
| 1054 | }, | 1152 | }, |
| 1055 | { | 1153 | { |
| 1056 | .name = "twl6040-ul", | 1154 | .name = "twl6040-ul", |
| 1155 | .id = TWL6040_DAI_UL, | ||
| 1057 | .capture = { | 1156 | .capture = { |
| 1058 | .stream_name = "Capture", | 1157 | .stream_name = "Capture", |
| 1059 | .channels_min = 1, | 1158 | .channels_min = 1, |
| @@ -1065,6 +1164,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
| 1065 | }, | 1164 | }, |
| 1066 | { | 1165 | { |
| 1067 | .name = "twl6040-dl1", | 1166 | .name = "twl6040-dl1", |
| 1167 | .id = TWL6040_DAI_DL1, | ||
| 1068 | .playback = { | 1168 | .playback = { |
| 1069 | .stream_name = "Headset Playback", | 1169 | .stream_name = "Headset Playback", |
| 1070 | .channels_min = 1, | 1170 | .channels_min = 1, |
| @@ -1076,6 +1176,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
| 1076 | }, | 1176 | }, |
| 1077 | { | 1177 | { |
| 1078 | .name = "twl6040-dl2", | 1178 | .name = "twl6040-dl2", |
| 1179 | .id = TWL6040_DAI_DL2, | ||
| 1079 | .playback = { | 1180 | .playback = { |
| 1080 | .stream_name = "Handsfree Playback", | 1181 | .stream_name = "Handsfree Playback", |
| 1081 | .channels_min = 1, | 1182 | .channels_min = 1, |
| @@ -1087,6 +1188,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
| 1087 | }, | 1188 | }, |
| 1088 | { | 1189 | { |
| 1089 | .name = "twl6040-vib", | 1190 | .name = "twl6040-vib", |
| 1191 | .id = TWL6040_DAI_VIB, | ||
| 1090 | .playback = { | 1192 | .playback = { |
| 1091 | .stream_name = "Vibra Playback", | 1193 | .stream_name = "Vibra Playback", |
| 1092 | .channels_min = 1, | 1194 | .channels_min = 1, |
| @@ -1143,7 +1245,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
| 1143 | 1245 | ||
| 1144 | mutex_init(&priv->mutex); | 1246 | mutex_init(&priv->mutex); |
| 1145 | 1247 | ||
| 1146 | ret = devm_request_threaded_irq(codec->dev, priv->plug_irq, NULL, | 1248 | ret = request_threaded_irq(priv->plug_irq, NULL, |
| 1147 | twl6040_audio_handler, IRQF_NO_SUSPEND, | 1249 | twl6040_audio_handler, IRQF_NO_SUSPEND, |
| 1148 | "twl6040_irq_plug", codec); | 1250 | "twl6040_irq_plug", codec); |
| 1149 | if (ret) { | 1251 | if (ret) { |
| @@ -1159,6 +1261,9 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
| 1159 | 1261 | ||
| 1160 | static int twl6040_remove(struct snd_soc_codec *codec) | 1262 | static int twl6040_remove(struct snd_soc_codec *codec) |
| 1161 | { | 1263 | { |
| 1264 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
| 1265 | |||
| 1266 | free_irq(priv->plug_irq, codec); | ||
| 1162 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1267 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 1163 | 1268 | ||
| 1164 | return 0; | 1269 | return 0; |
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/wm8400.c b/sound/soc/codecs/wm8400.c index af6d227e67be..d2a092850283 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
| @@ -143,13 +143,8 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ | 145 | #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ |
| 146 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 146 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
| 147 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 147 | snd_soc_get_volsw, wm8400_outpga_put_volsw_vu, tlv_array) |
| 148 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
| 149 | .tlv.p = (tlv_array), \ | ||
| 150 | .info = snd_soc_info_volsw, \ | ||
| 151 | .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ | ||
| 152 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 153 | 148 | ||
| 154 | 149 | ||
| 155 | static const char *wm8400_digital_sidetone[] = | 150 | static const char *wm8400_digital_sidetone[] = |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 9d88437cdcd1..fa24cedee687 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
| @@ -403,10 +403,8 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | #define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ | 405 | #define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ |
| 406 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 406 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
| 407 | .info = snd_soc_info_volsw, \ | 407 | snd_soc_dapm_get_volsw, wm8903_class_w_put) |
| 408 | .get = snd_soc_dapm_get_volsw, .put = wm8903_class_w_put, \ | ||
| 409 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 410 | 408 | ||
| 411 | 409 | ||
| 412 | static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; | 410 | static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 3ff195c541db..4c9fb142cb2d 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
| @@ -603,13 +603,8 @@ SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0, | |||
| 603 | 603 | ||
| 604 | SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), | 604 | SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), |
| 605 | SOC_ENUM("High Pass Filter Mode", hpf_mode), | 605 | SOC_ENUM("High Pass Filter Mode", hpf_mode), |
| 606 | 606 | SOC_SINGLE_EXT("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0, | |
| 607 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 607 | snd_soc_get_volsw, wm8904_adc_osr_put), |
| 608 | .name = "ADC 128x OSR Switch", | ||
| 609 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, | ||
| 610 | .put = wm8904_adc_osr_put, | ||
| 611 | .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0), | ||
| 612 | }, | ||
| 613 | }; | 608 | }; |
| 614 | 609 | ||
| 615 | static const char *drc_path_text[] = { | 610 | static const char *drc_path_text[] = { |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 4b7915bec2f1..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 | ||
| @@ -2347,12 +2348,13 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = { | |||
| 2347 | 2348 | ||
| 2348 | static int wm8962_add_widgets(struct snd_soc_codec *codec) | 2349 | static int wm8962_add_widgets(struct snd_soc_codec *codec) |
| 2349 | { | 2350 | { |
| 2350 | 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; | ||
| 2351 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2353 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 2352 | 2354 | ||
| 2353 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, | 2355 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, |
| 2354 | ARRAY_SIZE(wm8962_snd_controls)); | 2356 | ARRAY_SIZE(wm8962_snd_controls)); |
| 2355 | if (pdata && pdata->spk_mono) | 2357 | if (pdata->spk_mono) |
| 2356 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, | 2358 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, |
| 2357 | ARRAY_SIZE(wm8962_spk_mono_controls)); | 2359 | ARRAY_SIZE(wm8962_spk_mono_controls)); |
| 2358 | else | 2360 | else |
| @@ -2362,7 +2364,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
| 2362 | 2364 | ||
| 2363 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, | 2365 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, |
| 2364 | ARRAY_SIZE(wm8962_dapm_widgets)); | 2366 | ARRAY_SIZE(wm8962_dapm_widgets)); |
| 2365 | if (pdata && pdata->spk_mono) | 2367 | if (pdata->spk_mono) |
| 2366 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, | 2368 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, |
| 2367 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); | 2369 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); |
| 2368 | else | 2370 | else |
| @@ -2371,7 +2373,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
| 2371 | 2373 | ||
| 2372 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, | 2374 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, |
| 2373 | ARRAY_SIZE(wm8962_intercon)); | 2375 | ARRAY_SIZE(wm8962_intercon)); |
| 2374 | if (pdata && pdata->spk_mono) | 2376 | if (pdata->spk_mono) |
| 2375 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, | 2377 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, |
| 2376 | ARRAY_SIZE(wm8962_spk_mono_intercon)); | 2378 | ARRAY_SIZE(wm8962_spk_mono_intercon)); |
| 2377 | else | 2379 | else |
| @@ -3335,14 +3337,14 @@ static struct gpio_chip wm8962_template_chip = { | |||
| 3335 | static void wm8962_init_gpio(struct snd_soc_codec *codec) | 3337 | static void wm8962_init_gpio(struct snd_soc_codec *codec) |
| 3336 | { | 3338 | { |
| 3337 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3339 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
| 3338 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3340 | struct wm8962_pdata *pdata = &wm8962->pdata; |
| 3339 | int ret; | 3341 | int ret; |
| 3340 | 3342 | ||
| 3341 | wm8962->gpio_chip = wm8962_template_chip; | 3343 | wm8962->gpio_chip = wm8962_template_chip; |
| 3342 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; | 3344 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; |
| 3343 | wm8962->gpio_chip.dev = codec->dev; | 3345 | wm8962->gpio_chip.dev = codec->dev; |
| 3344 | 3346 | ||
| 3345 | if (pdata && pdata->gpio_base) | 3347 | if (pdata->gpio_base) |
| 3346 | wm8962->gpio_chip.base = pdata->gpio_base; | 3348 | wm8962->gpio_chip.base = pdata->gpio_base; |
| 3347 | else | 3349 | else |
| 3348 | wm8962->gpio_chip.base = -1; | 3350 | wm8962->gpio_chip.base = -1; |
| @@ -3422,31 +3424,29 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
| 3422 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, | 3424 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, |
| 3423 | 0); | 3425 | 0); |
| 3424 | 3426 | ||
| 3425 | if (pdata) { | 3427 | /* Apply static configuration for GPIOs */ |
| 3426 | /* Apply static configuration for GPIOs */ | 3428 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) |
| 3427 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) | 3429 | if (pdata->gpio_init[i]) { |
| 3428 | if (pdata->gpio_init[i]) { | 3430 | wm8962_set_gpio_mode(codec, i + 1); |
| 3429 | wm8962_set_gpio_mode(codec, i + 1); | 3431 | snd_soc_write(codec, 0x200 + i, |
| 3430 | snd_soc_write(codec, 0x200 + i, | 3432 | pdata->gpio_init[i] & 0xffff); |
| 3431 | pdata->gpio_init[i] & 0xffff); | 3433 | } |
| 3432 | } | ||
| 3433 | 3434 | ||
| 3434 | /* Put the speakers into mono mode? */ | 3435 | |
| 3435 | if (pdata->spk_mono) | 3436 | /* Put the speakers into mono mode? */ |
| 3436 | snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2, | 3437 | if (pdata->spk_mono) |
| 3438 | snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2, | ||
| 3437 | WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); | 3439 | WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); |
| 3438 | 3440 | ||
| 3439 | 3441 | /* Micbias setup, detection enable and detection | |
| 3440 | /* Micbias setup, detection enable and detection | 3442 | * threasholds. */ |
| 3441 | * threasholds. */ | 3443 | if (pdata->mic_cfg) |
| 3442 | if (pdata->mic_cfg) | 3444 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, |
| 3443 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, | 3445 | WM8962_MICDET_ENA | |
| 3444 | WM8962_MICDET_ENA | | 3446 | WM8962_MICDET_THR_MASK | |
| 3445 | WM8962_MICDET_THR_MASK | | 3447 | WM8962_MICSHORT_THR_MASK | |
| 3446 | WM8962_MICSHORT_THR_MASK | | 3448 | WM8962_MICBIAS_LVL, |
| 3447 | WM8962_MICBIAS_LVL, | 3449 | pdata->mic_cfg); |
| 3448 | pdata->mic_cfg); | ||
| 3449 | } | ||
| 3450 | 3450 | ||
| 3451 | /* Latch volume update bits */ | 3451 | /* Latch volume update bits */ |
| 3452 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, | 3452 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, |
| @@ -3508,7 +3508,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
| 3508 | wm8962_init_gpio(codec); | 3508 | wm8962_init_gpio(codec); |
| 3509 | 3509 | ||
| 3510 | if (wm8962->irq) { | 3510 | if (wm8962->irq) { |
| 3511 | if (pdata && pdata->irq_active_low) { | 3511 | if (pdata->irq_active_low) { |
| 3512 | trigger = IRQF_TRIGGER_LOW; | 3512 | trigger = IRQF_TRIGGER_LOW; |
| 3513 | irq_pol = WM8962_IRQ_POL; | 3513 | irq_pol = WM8962_IRQ_POL; |
| 3514 | } else { | 3514 | } else { |
| @@ -3586,6 +3586,34 @@ static const struct regmap_config wm8962_regmap = { | |||
| 3586 | .cache_type = REGCACHE_RBTREE, | 3586 | .cache_type = REGCACHE_RBTREE, |
| 3587 | }; | 3587 | }; |
| 3588 | 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 | |||
| 3589 | static int wm8962_i2c_probe(struct i2c_client *i2c, | 3617 | static int wm8962_i2c_probe(struct i2c_client *i2c, |
| 3590 | const struct i2c_device_id *id) | 3618 | const struct i2c_device_id *id) |
| 3591 | { | 3619 | { |
| @@ -3605,6 +3633,15 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
| 3605 | init_completion(&wm8962->fll_lock); | 3633 | init_completion(&wm8962->fll_lock); |
| 3606 | wm8962->irq = i2c->irq; | 3634 | wm8962->irq = i2c->irq; |
| 3607 | 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 | |||
| 3608 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3645 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
| 3609 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3646 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
| 3610 | 3647 | ||
| @@ -3668,7 +3705,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
| 3668 | goto err_enable; | 3705 | goto err_enable; |
| 3669 | } | 3706 | } |
| 3670 | 3707 | ||
| 3671 | if (pdata && pdata->in4_dc_measure) { | 3708 | if (wm8962->pdata.in4_dc_measure) { |
| 3672 | ret = regmap_register_patch(wm8962->regmap, | 3709 | ret = regmap_register_patch(wm8962->regmap, |
| 3673 | wm8962_dc_measure, | 3710 | wm8962_dc_measure, |
| 3674 | ARRAY_SIZE(wm8962_dc_measure)); | 3711 | ARRAY_SIZE(wm8962_dc_measure)); |
| @@ -3721,6 +3758,21 @@ static int wm8962_runtime_resume(struct device *dev) | |||
| 3721 | 3758 | ||
| 3722 | wm8962_reset(wm8962); | 3759 | wm8962_reset(wm8962); |
| 3723 | 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 | |||
| 3724 | regcache_sync(wm8962->regmap); | 3776 | regcache_sync(wm8962->regmap); |
| 3725 | 3777 | ||
| 3726 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, | 3778 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 837978e16e9d..253c88bb7a4c 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
| @@ -151,14 +151,9 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ | 153 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ |
| 154 | tlv_array) {\ | 154 | tlv_array) \ |
| 155 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 155 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
| 156 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 156 | snd_soc_get_volsw, wm899x_outpga_put_volsw_vu, tlv_array) |
| 157 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
| 158 | .tlv.p = (tlv_array), \ | ||
| 159 | .info = snd_soc_info_volsw, \ | ||
| 160 | .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ | ||
| 161 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 162 | 157 | ||
| 163 | 158 | ||
| 164 | static const char *wm8990_digital_sidetone[] = | 159 | static const char *wm8990_digital_sidetone[] = |
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h index 8a942efd18a5..07707d8d7e20 100644 --- a/sound/soc/codecs/wm8991.h +++ b/sound/soc/codecs/wm8991.h | |||
| @@ -822,12 +822,7 @@ | |||
| 822 | 822 | ||
| 823 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ | 823 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ |
| 824 | tlv_array) \ | 824 | tlv_array) \ |
| 825 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 825 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
| 826 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 826 | snd_soc_get_volsw, wm899x_outpga_put_volsw_vu, tlv_array) |
| 827 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
| 828 | .tlv.p = (tlv_array), \ | ||
| 829 | .info = snd_soc_info_volsw, \ | ||
| 830 | .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ | ||
| 831 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 832 | 827 | ||
| 833 | #endif /* _WM8991_H */ | 828 | #endif /* _WM8991_H */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 29e95f93d482..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> |
| @@ -289,10 +290,8 @@ static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | |||
| 289 | static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); | 290 | static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); |
| 290 | 291 | ||
| 291 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | 292 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
| 292 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 293 | SOC_SINGLE_EXT(xname, reg, shift, 1, 0, \ |
| 293 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | 294 | snd_soc_get_volsw, wm8994_put_drc_sw) |
| 294 | .put = wm8994_put_drc_sw, \ | ||
| 295 | .private_value = SOC_SINGLE_VALUE(reg, shift, 1, 0) } | ||
| 296 | 295 | ||
| 297 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | 296 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, |
| 298 | struct snd_ctl_elem_value *ucontrol) | 297 | struct snd_ctl_elem_value *ucontrol) |
| @@ -1432,10 +1431,8 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | |||
| 1432 | }; | 1431 | }; |
| 1433 | 1432 | ||
| 1434 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ | 1433 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ |
| 1435 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 1434 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
| 1436 | .info = snd_soc_info_volsw, \ | 1435 | snd_soc_get_volsw, wm8994_put_class_w) |
| 1437 | .get = snd_soc_dapm_get_volsw, .put = wm8994_put_class_w, \ | ||
| 1438 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 1439 | 1436 | ||
| 1440 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, | 1437 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, |
| 1441 | struct snd_ctl_elem_value *ucontrol) | 1438 | struct snd_ctl_elem_value *ucontrol) |
| @@ -1498,6 +1495,24 @@ static const char *aif1dac_text[] = { | |||
| 1498 | "AIF1DACDAT", "AIF3DACDAT", | 1495 | "AIF1DACDAT", "AIF3DACDAT", |
| 1499 | }; | 1496 | }; |
| 1500 | 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 | |||
| 1501 | static const struct soc_enum aif1dac_enum = | 1516 | static const struct soc_enum aif1dac_enum = |
| 1502 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); | 1517 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); |
| 1503 | 1518 | ||
| @@ -1744,6 +1759,9 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), | |||
| 1744 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | 1759 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), |
| 1745 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | 1760 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
| 1746 | 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 | |||
| 1747 | SND_SOC_DAPM_POST("Debug log", post_ev), | 1765 | SND_SOC_DAPM_POST("Debug log", post_ev), |
| 1748 | }; | 1766 | }; |
| 1749 | 1767 | ||
| @@ -1875,9 +1893,9 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
| 1875 | { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, | 1893 | { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, |
| 1876 | { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, | 1894 | { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, |
| 1877 | 1895 | ||
| 1878 | { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, | 1896 | { "AIF1DAC Mux", "AIF1DACDAT", "AIF1 Loopback" }, |
| 1879 | { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | 1897 | { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, |
| 1880 | { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, | 1898 | { "AIF2DAC Mux", "AIF2DACDAT", "AIF2 Loopback" }, |
| 1881 | { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | 1899 | { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, |
| 1882 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, | 1900 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, |
| 1883 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, | 1901 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, |
| @@ -1928,6 +1946,12 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
| 1928 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, | 1946 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, |
| 1929 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, | 1947 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, |
| 1930 | 1948 | ||
| 1949 | /* Loopback */ | ||
| 1950 | { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" }, | ||
| 1951 | { "AIF1 Loopback", "None", "AIF1DACDAT" }, | ||
| 1952 | { "AIF2 Loopback", "ADCDAT", "AIF2ADCDAT" }, | ||
| 1953 | { "AIF2 Loopback", "None", "AIF2DACDAT" }, | ||
| 1954 | |||
| 1931 | /* Sidetone */ | 1955 | /* Sidetone */ |
| 1932 | { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, | 1956 | { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, |
| 1933 | { "Left Sidetone", "DMIC2", "DMIC2L" }, | 1957 | { "Left Sidetone", "DMIC2", "DMIC2L" }, |
| @@ -2010,15 +2034,16 @@ struct fll_div { | |||
| 2010 | u16 outdiv; | 2034 | u16 outdiv; |
| 2011 | u16 n; | 2035 | u16 n; |
| 2012 | u16 k; | 2036 | u16 k; |
| 2037 | u16 lambda; | ||
| 2013 | u16 clk_ref_div; | 2038 | u16 clk_ref_div; |
| 2014 | u16 fll_fratio; | 2039 | u16 fll_fratio; |
| 2015 | }; | 2040 | }; |
| 2016 | 2041 | ||
| 2017 | static int wm8994_get_fll_config(struct fll_div *fll, | 2042 | static int wm8994_get_fll_config(struct wm8994 *control, struct fll_div *fll, |
| 2018 | int freq_in, int freq_out) | 2043 | int freq_in, int freq_out) |
| 2019 | { | 2044 | { |
| 2020 | u64 Kpart; | 2045 | u64 Kpart; |
| 2021 | unsigned int K, Ndiv, Nmod; | 2046 | unsigned int K, Ndiv, Nmod, gcd_fll; |
| 2022 | 2047 | ||
| 2023 | 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); |
| 2024 | 2049 | ||
| @@ -2067,20 +2092,32 @@ static int wm8994_get_fll_config(struct fll_div *fll, | |||
| 2067 | Nmod = freq_out % freq_in; | 2092 | Nmod = freq_out % freq_in; |
| 2068 | pr_debug("Nmod=%d\n", Nmod); | 2093 | pr_debug("Nmod=%d\n", Nmod); |
| 2069 | 2094 | ||
| 2070 | /* Calculate fractional part - scale up so we can round. */ | 2095 | switch (control->type) { |
| 2071 | 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; | ||
| 2072 | 2103 | ||
| 2073 | do_div(Kpart, freq_in); | 2104 | if ((K % 10) >= 5) |
| 2105 | K += 5; | ||
| 2074 | 2106 | ||
| 2075 | K = Kpart & 0xFFFFFFFF; | 2107 | /* Move down to proper range now rounding is done */ |
| 2108 | fll->k = K / 10; | ||
| 2109 | fll->lambda = 0; | ||
| 2076 | 2110 | ||
| 2077 | if ((K % 10) >= 5) | 2111 | pr_debug("N=%x K=%x\n", fll->n, fll->k); |
| 2078 | K += 5; | 2112 | break; |
| 2079 | 2113 | ||
| 2080 | /* Move down to proper range now rounding is done */ | 2114 | default: |
| 2081 | fll->k = K / 10; | 2115 | gcd_fll = gcd(freq_out, freq_in); |
| 2082 | 2116 | ||
| 2083 | 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 | } | ||
| 2084 | 2121 | ||
| 2085 | return 0; | 2122 | return 0; |
| 2086 | } | 2123 | } |
| @@ -2144,9 +2181,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
| 2144 | * analysis bugs spewing warnings. | 2181 | * analysis bugs spewing warnings. |
| 2145 | */ | 2182 | */ |
| 2146 | if (freq_out) | 2183 | if (freq_out) |
| 2147 | ret = wm8994_get_fll_config(&fll, freq_in, freq_out); | 2184 | ret = wm8994_get_fll_config(control, &fll, freq_in, freq_out); |
| 2148 | else | 2185 | else |
| 2149 | ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, | 2186 | ret = wm8994_get_fll_config(control, &fll, wm8994->fll[id].in, |
| 2150 | wm8994->fll[id].out); | 2187 | wm8994->fll[id].out); |
| 2151 | if (ret < 0) | 2188 | if (ret < 0) |
| 2152 | return ret; | 2189 | return ret; |
| @@ -2191,6 +2228,17 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
| 2191 | WM8994_FLL1_N_MASK, | 2228 | WM8994_FLL1_N_MASK, |
| 2192 | fll.n << WM8994_FLL1_N_SHIFT); | 2229 | fll.n << WM8994_FLL1_N_SHIFT); |
| 2193 | 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 | |||
| 2194 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | 2242 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, |
| 2195 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | | 2243 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
| 2196 | WM8994_FLL1_REFCLK_DIV_MASK | | 2244 | WM8994_FLL1_REFCLK_DIV_MASK | |
| @@ -2555,17 +2603,24 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 2555 | struct wm8994 *control = wm8994->wm8994; | 2603 | struct wm8994 *control = wm8994->wm8994; |
| 2556 | int ms_reg; | 2604 | int ms_reg; |
| 2557 | int aif1_reg; | 2605 | int aif1_reg; |
| 2606 | int dac_reg; | ||
| 2607 | int adc_reg; | ||
| 2558 | int ms = 0; | 2608 | int ms = 0; |
| 2559 | int aif1 = 0; | 2609 | int aif1 = 0; |
| 2610 | int lrclk = 0; | ||
| 2560 | 2611 | ||
| 2561 | switch (dai->id) { | 2612 | switch (dai->id) { |
| 2562 | case 1: | 2613 | case 1: |
| 2563 | ms_reg = WM8994_AIF1_MASTER_SLAVE; | 2614 | ms_reg = WM8994_AIF1_MASTER_SLAVE; |
| 2564 | 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; | ||
| 2565 | break; | 2618 | break; |
| 2566 | case 2: | 2619 | case 2: |
| 2567 | ms_reg = WM8994_AIF2_MASTER_SLAVE; | 2620 | ms_reg = WM8994_AIF2_MASTER_SLAVE; |
| 2568 | 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; | ||
| 2569 | break; | 2624 | break; |
| 2570 | default: | 2625 | default: |
| 2571 | return -EINVAL; | 2626 | return -EINVAL; |
| @@ -2584,6 +2639,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 2584 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 2639 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
| 2585 | case SND_SOC_DAIFMT_DSP_B: | 2640 | case SND_SOC_DAIFMT_DSP_B: |
| 2586 | aif1 |= WM8994_AIF1_LRCLK_INV; | 2641 | aif1 |= WM8994_AIF1_LRCLK_INV; |
| 2642 | lrclk |= WM8958_AIF1_LRCLK_INV; | ||
| 2587 | case SND_SOC_DAIFMT_DSP_A: | 2643 | case SND_SOC_DAIFMT_DSP_A: |
| 2588 | aif1 |= 0x18; | 2644 | aif1 |= 0x18; |
| 2589 | break; | 2645 | break; |
| @@ -2622,12 +2678,14 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 2622 | break; | 2678 | break; |
| 2623 | case SND_SOC_DAIFMT_IB_IF: | 2679 | case SND_SOC_DAIFMT_IB_IF: |
| 2624 | 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; | ||
| 2625 | break; | 2682 | break; |
| 2626 | case SND_SOC_DAIFMT_IB_NF: | 2683 | case SND_SOC_DAIFMT_IB_NF: |
| 2627 | aif1 |= WM8994_AIF1_BCLK_INV; | 2684 | aif1 |= WM8994_AIF1_BCLK_INV; |
| 2628 | break; | 2685 | break; |
| 2629 | case SND_SOC_DAIFMT_NB_IF: | 2686 | case SND_SOC_DAIFMT_NB_IF: |
| 2630 | aif1 |= WM8994_AIF1_LRCLK_INV; | 2687 | aif1 |= WM8994_AIF1_LRCLK_INV; |
| 2688 | lrclk |= WM8958_AIF1_LRCLK_INV; | ||
| 2631 | break; | 2689 | break; |
| 2632 | default: | 2690 | default: |
| 2633 | return -EINVAL; | 2691 | return -EINVAL; |
| @@ -2658,6 +2716,10 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 2658 | aif1); | 2716 | aif1); |
| 2659 | snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, | 2717 | snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, |
| 2660 | 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); | ||
| 2661 | 2723 | ||
| 2662 | return 0; | 2724 | return 0; |
| 2663 | } | 2725 | } |
| @@ -3096,24 +3158,7 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec) | |||
| 3096 | static int wm8994_codec_resume(struct snd_soc_codec *codec) | 3158 | static int wm8994_codec_resume(struct snd_soc_codec *codec) |
| 3097 | { | 3159 | { |
| 3098 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3160 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
| 3099 | struct wm8994 *control = wm8994->wm8994; | ||
| 3100 | int i, ret; | 3161 | int i, ret; |
| 3101 | unsigned int val, mask; | ||
| 3102 | |||
| 3103 | if (control->revision < 4) { | ||
| 3104 | /* force a HW read */ | ||
| 3105 | ret = regmap_read(control->regmap, | ||
| 3106 | WM8994_POWER_MANAGEMENT_5, &val); | ||
| 3107 | |||
| 3108 | /* modify the cache only */ | ||
| 3109 | codec->cache_only = 1; | ||
| 3110 | mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA | | ||
| 3111 | WM8994_DAC2R_ENA | WM8994_DAC2L_ENA; | ||
| 3112 | val &= mask; | ||
| 3113 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, | ||
| 3114 | mask, val); | ||
| 3115 | codec->cache_only = 0; | ||
| 3116 | } | ||
| 3117 | 3162 | ||
| 3118 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 3163 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
| 3119 | if (!wm8994->fll_suspend[i].out) | 3164 | if (!wm8994->fll_suspend[i].out) |
| @@ -3495,6 +3540,31 @@ static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) | |||
| 3495 | wm8994->btn_mask); | 3540 | wm8994->btn_mask); |
| 3496 | } | 3541 | } |
| 3497 | 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 | |||
| 3498 | static void wm8958_mic_id(void *data, u16 status) | 3568 | static void wm8958_mic_id(void *data, u16 status) |
| 3499 | { | 3569 | { |
| 3500 | struct snd_soc_codec *codec = data; | 3570 | struct snd_soc_codec *codec = data; |
| @@ -3504,16 +3574,9 @@ static void wm8958_mic_id(void *data, u16 status) | |||
| 3504 | if (!(status & WM8958_MICD_STS)) { | 3574 | if (!(status & WM8958_MICD_STS)) { |
| 3505 | /* If nothing present then clear our statuses */ | 3575 | /* If nothing present then clear our statuses */ |
| 3506 | dev_dbg(codec->dev, "Detected open circuit\n"); | 3576 | dev_dbg(codec->dev, "Detected open circuit\n"); |
| 3507 | wm8994->jack_mic = false; | ||
| 3508 | wm8994->mic_detecting = true; | ||
| 3509 | |||
| 3510 | wm1811_micd_stop(codec); | ||
| 3511 | |||
| 3512 | wm8958_micd_set_rate(codec); | ||
| 3513 | 3577 | ||
| 3514 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3578 | schedule_delayed_work(&wm8994->open_circuit_work, |
| 3515 | wm8994->btn_mask | | 3579 | msecs_to_jiffies(2500)); |
| 3516 | SND_JACK_HEADSET); | ||
| 3517 | return; | 3580 | return; |
| 3518 | } | 3581 | } |
| 3519 | 3582 | ||
| @@ -3598,6 +3661,8 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
| 3598 | 3661 | ||
| 3599 | pm_runtime_get_sync(codec->dev); | 3662 | pm_runtime_get_sync(codec->dev); |
| 3600 | 3663 | ||
| 3664 | cancel_delayed_work_sync(&wm8994->mic_complete_work); | ||
| 3665 | |||
| 3601 | mutex_lock(&wm8994->accdet_lock); | 3666 | mutex_lock(&wm8994->accdet_lock); |
| 3602 | 3667 | ||
| 3603 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); | 3668 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); |
| @@ -3780,11 +3845,33 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
| 3780 | } | 3845 | } |
| 3781 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); | 3846 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); |
| 3782 | 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 | |||
| 3783 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3870 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
| 3784 | { | 3871 | { |
| 3785 | struct wm8994_priv *wm8994 = data; | 3872 | struct wm8994_priv *wm8994 = data; |
| 3786 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3873 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
| 3787 | int reg, count, ret; | 3874 | int reg, count, ret, id_delay; |
| 3788 | 3875 | ||
| 3789 | /* | 3876 | /* |
| 3790 | * Jack detection may have detected a removal simulataneously | 3877 | * Jack detection may have detected a removal simulataneously |
| @@ -3794,6 +3881,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
| 3794 | 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)) |
| 3795 | return IRQ_HANDLED; | 3882 | return IRQ_HANDLED; |
| 3796 | 3883 | ||
| 3884 | cancel_delayed_work_sync(&wm8994->mic_complete_work); | ||
| 3885 | cancel_delayed_work_sync(&wm8994->open_circuit_work); | ||
| 3886 | |||
| 3797 | pm_runtime_get_sync(codec->dev); | 3887 | pm_runtime_get_sync(codec->dev); |
| 3798 | 3888 | ||
| 3799 | /* We may occasionally read a detection without an impedence | 3889 | /* We may occasionally read a detection without an impedence |
| @@ -3846,8 +3936,12 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
| 3846 | goto out; | 3936 | goto out; |
| 3847 | } | 3937 | } |
| 3848 | 3938 | ||
| 3939 | wm8994->mic_status = reg; | ||
| 3940 | id_delay = wm8994->wm8994->pdata.mic_id_delay; | ||
| 3941 | |||
| 3849 | if (wm8994->mic_detecting) | 3942 | if (wm8994->mic_detecting) |
| 3850 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); | 3943 | schedule_delayed_work(&wm8994->mic_complete_work, |
| 3944 | msecs_to_jiffies(id_delay)); | ||
| 3851 | else | 3945 | else |
| 3852 | wm8958_button_det(codec, reg); | 3946 | wm8958_button_det(codec, reg); |
| 3853 | 3947 | ||
| @@ -3899,6 +3993,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
| 3899 | mutex_init(&wm8994->accdet_lock); | 3993 | mutex_init(&wm8994->accdet_lock); |
| 3900 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | 3994 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, |
| 3901 | wm1811_jackdet_bootstrap); | 3995 | wm1811_jackdet_bootstrap); |
| 3996 | INIT_DELAYED_WORK(&wm8994->open_circuit_work, | ||
| 3997 | wm8958_open_circuit_work); | ||
| 3902 | 3998 | ||
| 3903 | switch (control->type) { | 3999 | switch (control->type) { |
| 3904 | case WM8994: | 4000 | case WM8994: |
| @@ -3911,6 +4007,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
| 3911 | break; | 4007 | break; |
| 3912 | } | 4008 | } |
| 3913 | 4009 | ||
| 4010 | INIT_DELAYED_WORK(&wm8994->mic_complete_work, wm8958_mic_work); | ||
| 4011 | |||
| 3914 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 4012 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
| 3915 | init_completion(&wm8994->fll_locked[i]); | 4013 | init_completion(&wm8994->fll_locked[i]); |
| 3916 | 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/wm8995.h b/sound/soc/codecs/wm8995.h index 5642121c4977..508ad27fe2bb 100644 --- a/sound/soc/codecs/wm8995.h +++ b/sound/soc/codecs/wm8995.h | |||
| @@ -4237,11 +4237,8 @@ | |||
| 4237 | #define WM8995_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ | 4237 | #define WM8995_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ |
| 4238 | 4238 | ||
| 4239 | #define WM8995_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ | 4239 | #define WM8995_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ |
| 4240 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 4240 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
| 4241 | .info = snd_soc_info_volsw, \ | 4241 | snd_soc_dapm_get_volsw, wm8995_put_class_w) |
| 4242 | .get = snd_soc_dapm_get_volsw, .put = wm8995_put_class_w, \ | ||
| 4243 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) \ | ||
| 4244 | } | ||
| 4245 | 4242 | ||
| 4246 | struct wm8995_reg_access { | 4243 | struct wm8995_reg_access { |
| 4247 | u16 read; | 4244 | u16 read; |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 05b1f346695b..70ce6793c5bd 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
| @@ -209,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
| 209 | case AC97_RESET: | 209 | case AC97_RESET: |
| 210 | case AC97_VENDOR_ID1: | 210 | case AC97_VENDOR_ID1: |
| 211 | case AC97_VENDOR_ID2: | 211 | case AC97_VENDOR_ID2: |
| 212 | return soc_ac97_ops.read(codec->ac97, reg); | 212 | return soc_ac97_ops->read(codec->ac97, reg); |
| 213 | default: | 213 | default: |
| 214 | reg = reg >> 1; | 214 | reg = reg >> 1; |
| 215 | 215 | ||
| @@ -225,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 225 | { | 225 | { |
| 226 | u16 *cache = codec->reg_cache; | 226 | u16 *cache = codec->reg_cache; |
| 227 | 227 | ||
| 228 | soc_ac97_ops.write(codec->ac97, reg, val); | 228 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 229 | reg = reg >> 1; | 229 | reg = reg >> 1; |
| 230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 230 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
| 231 | cache[reg] = val; | 231 | cache[reg] = val; |
| @@ -294,8 +294,8 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
| 294 | 294 | ||
| 295 | static int wm9705_reset(struct snd_soc_codec *codec) | 295 | static int wm9705_reset(struct snd_soc_codec *codec) |
| 296 | { | 296 | { |
| 297 | if (soc_ac97_ops.reset) { | 297 | if (soc_ac97_ops->reset) { |
| 298 | soc_ac97_ops.reset(codec->ac97); | 298 | soc_ac97_ops->reset(codec->ac97); |
| 299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 299 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
| 300 | return 0; /* Success */ | 300 | return 0; /* Success */ |
| 301 | } | 301 | } |
| @@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec) | |||
| 306 | #ifdef CONFIG_PM | 306 | #ifdef CONFIG_PM |
| 307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
| 308 | { | 308 | { |
| 309 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); | 309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); |
| 310 | 310 | ||
| 311 | return 0; | 311 | return 0; |
| 312 | } | 312 | } |
| @@ -323,7 +323,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
| 326 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | return 0; | 329 | return 0; |
| @@ -337,9 +337,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) | |||
| 337 | { | 337 | { |
| 338 | int ret = 0; | 338 | int ret = 0; |
| 339 | 339 | ||
| 340 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | 340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
| 341 | |||
| 342 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
| 343 | if (ret < 0) { | 341 | if (ret < 0) { |
| 344 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
| 345 | return ret; | 343 | return ret; |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 8e9a6a3eeb1a..c5eb746087b4 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
| @@ -455,7 +455,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
| 455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
| 456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
| 457 | reg == AC97_REC_GAIN) | 457 | reg == AC97_REC_GAIN) |
| 458 | return soc_ac97_ops.read(codec->ac97, reg); | 458 | return soc_ac97_ops->read(codec->ac97, reg); |
| 459 | else { | 459 | else { |
| 460 | reg = reg >> 1; | 460 | reg = reg >> 1; |
| 461 | 461 | ||
| @@ -472,7 +472,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 472 | u16 *cache = codec->reg_cache; | 472 | u16 *cache = codec->reg_cache; |
| 473 | 473 | ||
| 474 | if (reg < 0x7c) | 474 | if (reg < 0x7c) |
| 475 | soc_ac97_ops.write(codec->ac97, reg, val); | 475 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 476 | reg = reg >> 1; | 476 | reg = reg >> 1; |
| 477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 477 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
| 478 | cache[reg] = val; | 478 | cache[reg] = val; |
| @@ -581,15 +581,15 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
| 581 | 581 | ||
| 582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
| 583 | { | 583 | { |
| 584 | if (try_warm && soc_ac97_ops.warm_reset) { | 584 | if (try_warm && soc_ac97_ops->warm_reset) { |
| 585 | soc_ac97_ops.warm_reset(codec->ac97); | 585 | soc_ac97_ops->warm_reset(codec->ac97); |
| 586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 586 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
| 587 | return 1; | 587 | return 1; |
| 588 | } | 588 | } |
| 589 | 589 | ||
| 590 | soc_ac97_ops.reset(codec->ac97); | 590 | soc_ac97_ops->reset(codec->ac97); |
| 591 | if (soc_ac97_ops.warm_reset) | 591 | if (soc_ac97_ops->warm_reset) |
| 592 | soc_ac97_ops.warm_reset(codec->ac97); | 592 | soc_ac97_ops->warm_reset(codec->ac97); |
| 593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 593 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
| 594 | goto err; | 594 | goto err; |
| 595 | return 0; | 595 | return 0; |
| @@ -624,7 +624,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
| 624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
| 625 | (i > 0x58 && i != 0x5c)) | 625 | (i > 0x58 && i != 0x5c)) |
| 626 | continue; | 626 | continue; |
| 627 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
| 628 | } | 628 | } |
| 629 | } | 629 | } |
| 630 | 630 | ||
| @@ -635,7 +635,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
| 635 | { | 635 | { |
| 636 | int ret = 0; | 636 | int ret = 0; |
| 637 | 637 | ||
| 638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
| 639 | if (ret < 0) { | 639 | if (ret < 0) { |
| 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
| 641 | return ret; | 641 | return ret; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f7afa68d8c7f..a53e175c015a 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
| @@ -652,7 +652,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
| 652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
| 653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
| 654 | reg == AC97_CD) | 654 | reg == AC97_CD) |
| 655 | return soc_ac97_ops.read(codec->ac97, reg); | 655 | return soc_ac97_ops->read(codec->ac97, reg); |
| 656 | else { | 656 | else { |
| 657 | reg = reg >> 1; | 657 | reg = reg >> 1; |
| 658 | 658 | ||
| @@ -668,7 +668,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 668 | { | 668 | { |
| 669 | u16 *cache = codec->reg_cache; | 669 | u16 *cache = codec->reg_cache; |
| 670 | if (reg < 0x7c) | 670 | if (reg < 0x7c) |
| 671 | soc_ac97_ops.write(codec->ac97, reg, val); | 671 | soc_ac97_ops->write(codec->ac97, reg, val); |
| 672 | reg = reg >> 1; | 672 | reg = reg >> 1; |
| 673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 673 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
| 674 | cache[reg] = val; | 674 | cache[reg] = val; |
| @@ -1095,15 +1095,15 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
| 1095 | 1095 | ||
| 1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
| 1097 | { | 1097 | { |
| 1098 | if (try_warm && soc_ac97_ops.warm_reset) { | 1098 | if (try_warm && soc_ac97_ops->warm_reset) { |
| 1099 | soc_ac97_ops.warm_reset(codec->ac97); | 1099 | soc_ac97_ops->warm_reset(codec->ac97); |
| 1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
| 1101 | return 1; | 1101 | return 1; |
| 1102 | } | 1102 | } |
| 1103 | 1103 | ||
| 1104 | soc_ac97_ops.reset(codec->ac97); | 1104 | soc_ac97_ops->reset(codec->ac97); |
| 1105 | if (soc_ac97_ops.warm_reset) | 1105 | if (soc_ac97_ops->warm_reset) |
| 1106 | soc_ac97_ops.warm_reset(codec->ac97); | 1106 | soc_ac97_ops->warm_reset(codec->ac97); |
| 1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) |
| 1108 | return -EIO; | 1108 | return -EIO; |
| 1109 | return 0; | 1109 | return 0; |
| @@ -1180,7 +1180,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
| 1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
| 1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
| 1182 | continue; | 1182 | continue; |
| 1183 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
| 1184 | } | 1184 | } |
| 1185 | } | 1185 | } |
| 1186 | 1186 | ||
| @@ -1197,7 +1197,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
| 1197 | return -ENOMEM; | 1197 | return -ENOMEM; |
| 1198 | snd_soc_codec_set_drvdata(codec, wm9713); | 1198 | snd_soc_codec_set_drvdata(codec, wm9713); |
| 1199 | 1199 | ||
| 1200 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
| 1201 | if (ret < 0) | 1201 | if (ret < 0) |
| 1202 | goto codec_err; | 1202 | goto codec_err; |
| 1203 | 1203 | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 0a3c7f704016..05252ac936a3 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
| 22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/workqueue.h> | ||
| 24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
| 25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
| 26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
| @@ -215,6 +216,36 @@ static struct { | |||
| 215 | [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, | 216 | [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, |
| 216 | }; | 217 | }; |
| 217 | 218 | ||
| 219 | struct wm_coeff_ctl_ops { | ||
| 220 | int (*xget)(struct snd_kcontrol *kcontrol, | ||
| 221 | struct snd_ctl_elem_value *ucontrol); | ||
| 222 | int (*xput)(struct snd_kcontrol *kcontrol, | ||
| 223 | struct snd_ctl_elem_value *ucontrol); | ||
| 224 | int (*xinfo)(struct snd_kcontrol *kcontrol, | ||
| 225 | struct snd_ctl_elem_info *uinfo); | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct wm_coeff { | ||
| 229 | struct device *dev; | ||
| 230 | struct list_head ctl_list; | ||
| 231 | struct regmap *regmap; | ||
| 232 | }; | ||
| 233 | |||
| 234 | struct wm_coeff_ctl { | ||
| 235 | const char *name; | ||
| 236 | struct snd_card *card; | ||
| 237 | struct wm_adsp_alg_region region; | ||
| 238 | struct wm_coeff_ctl_ops ops; | ||
| 239 | struct wm_adsp *adsp; | ||
| 240 | void *private; | ||
| 241 | unsigned int enabled:1; | ||
| 242 | struct list_head list; | ||
| 243 | void *cache; | ||
| 244 | size_t len; | ||
| 245 | unsigned int set:1; | ||
| 246 | struct snd_kcontrol *kcontrol; | ||
| 247 | }; | ||
| 248 | |||
| 218 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 249 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, |
| 219 | struct snd_ctl_elem_value *ucontrol) | 250 | struct snd_ctl_elem_value *ucontrol) |
| 220 | { | 251 | { |
| @@ -334,6 +365,181 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region, | |||
| 334 | } | 365 | } |
| 335 | } | 366 | } |
| 336 | 367 | ||
| 368 | static int wm_coeff_info(struct snd_kcontrol *kcontrol, | ||
| 369 | struct snd_ctl_elem_info *uinfo) | ||
| 370 | { | ||
| 371 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
| 372 | |||
| 373 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
| 374 | uinfo->count = ctl->len; | ||
| 375 | return 0; | ||
| 376 | } | ||
| 377 | |||
| 378 | static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, | ||
| 379 | const void *buf, size_t len) | ||
| 380 | { | ||
| 381 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
| 382 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
| 383 | struct wm_adsp_alg_region *region = &ctl->region; | ||
| 384 | const struct wm_adsp_region *mem; | ||
| 385 | struct wm_adsp *adsp = ctl->adsp; | ||
| 386 | void *scratch; | ||
| 387 | int ret; | ||
| 388 | unsigned int reg; | ||
| 389 | |||
| 390 | mem = wm_adsp_find_region(adsp, region->type); | ||
| 391 | if (!mem) { | ||
| 392 | adsp_err(adsp, "No base for region %x\n", | ||
| 393 | region->type); | ||
| 394 | return -EINVAL; | ||
| 395 | } | ||
| 396 | |||
| 397 | reg = ctl->region.base; | ||
| 398 | reg = wm_adsp_region_to_reg(mem, reg); | ||
| 399 | |||
| 400 | scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); | ||
| 401 | if (!scratch) | ||
| 402 | return -ENOMEM; | ||
| 403 | |||
| 404 | ret = regmap_raw_write(wm_coeff->regmap, reg, scratch, | ||
| 405 | ctl->len); | ||
| 406 | if (ret) { | ||
| 407 | adsp_err(adsp, "Failed to write %zu bytes to %x\n", | ||
| 408 | ctl->len, reg); | ||
| 409 | kfree(scratch); | ||
| 410 | return ret; | ||
| 411 | } | ||
| 412 | |||
| 413 | kfree(scratch); | ||
| 414 | |||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | |||
| 418 | static int wm_coeff_put(struct snd_kcontrol *kcontrol, | ||
| 419 | struct snd_ctl_elem_value *ucontrol) | ||
| 420 | { | ||
| 421 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
| 422 | char *p = ucontrol->value.bytes.data; | ||
| 423 | |||
| 424 | memcpy(ctl->cache, p, ctl->len); | ||
| 425 | |||
| 426 | if (!ctl->enabled) { | ||
| 427 | ctl->set = 1; | ||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | return wm_coeff_write_control(kcontrol, p, ctl->len); | ||
| 432 | } | ||
| 433 | |||
| 434 | static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, | ||
| 435 | void *buf, size_t len) | ||
| 436 | { | ||
| 437 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
| 438 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
| 439 | struct wm_adsp_alg_region *region = &ctl->region; | ||
| 440 | const struct wm_adsp_region *mem; | ||
| 441 | struct wm_adsp *adsp = ctl->adsp; | ||
| 442 | void *scratch; | ||
| 443 | int ret; | ||
| 444 | unsigned int reg; | ||
| 445 | |||
| 446 | mem = wm_adsp_find_region(adsp, region->type); | ||
| 447 | if (!mem) { | ||
| 448 | adsp_err(adsp, "No base for region %x\n", | ||
| 449 | region->type); | ||
| 450 | return -EINVAL; | ||
| 451 | } | ||
| 452 | |||
| 453 | reg = ctl->region.base; | ||
| 454 | reg = wm_adsp_region_to_reg(mem, reg); | ||
| 455 | |||
| 456 | scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); | ||
| 457 | if (!scratch) | ||
| 458 | return -ENOMEM; | ||
| 459 | |||
| 460 | ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len); | ||
| 461 | if (ret) { | ||
| 462 | adsp_err(adsp, "Failed to read %zu bytes from %x\n", | ||
| 463 | ctl->len, reg); | ||
| 464 | kfree(scratch); | ||
| 465 | return ret; | ||
| 466 | } | ||
| 467 | |||
| 468 | memcpy(buf, scratch, ctl->len); | ||
| 469 | kfree(scratch); | ||
| 470 | |||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | static int wm_coeff_get(struct snd_kcontrol *kcontrol, | ||
| 475 | struct snd_ctl_elem_value *ucontrol) | ||
| 476 | { | ||
| 477 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
| 478 | char *p = ucontrol->value.bytes.data; | ||
| 479 | |||
| 480 | memcpy(p, ctl->cache, ctl->len); | ||
| 481 | return 0; | ||
| 482 | } | ||
| 483 | |||
| 484 | static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff, | ||
| 485 | struct wm_coeff_ctl *ctl, | ||
| 486 | const struct snd_kcontrol_new *kctl) | ||
| 487 | { | ||
| 488 | int ret; | ||
| 489 | struct snd_kcontrol *kcontrol; | ||
| 490 | |||
| 491 | kcontrol = snd_ctl_new1(kctl, wm_coeff); | ||
| 492 | ret = snd_ctl_add(ctl->card, kcontrol); | ||
| 493 | if (ret < 0) { | ||
| 494 | dev_err(wm_coeff->dev, "Failed to add %s: %d\n", | ||
| 495 | kctl->name, ret); | ||
| 496 | return ret; | ||
| 497 | } | ||
| 498 | ctl->kcontrol = kcontrol; | ||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | struct wmfw_ctl_work { | ||
| 503 | struct wm_coeff *wm_coeff; | ||
| 504 | struct wm_coeff_ctl *ctl; | ||
| 505 | struct work_struct work; | ||
| 506 | }; | ||
| 507 | |||
| 508 | static int wmfw_add_ctl(struct wm_coeff *wm_coeff, | ||
| 509 | struct wm_coeff_ctl *ctl) | ||
| 510 | { | ||
| 511 | struct snd_kcontrol_new *kcontrol; | ||
| 512 | int ret; | ||
| 513 | |||
| 514 | if (!wm_coeff || !ctl || !ctl->name || !ctl->card) | ||
| 515 | return -EINVAL; | ||
| 516 | |||
| 517 | kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); | ||
| 518 | if (!kcontrol) | ||
| 519 | return -ENOMEM; | ||
| 520 | kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
| 521 | |||
| 522 | kcontrol->name = ctl->name; | ||
| 523 | kcontrol->info = wm_coeff_info; | ||
| 524 | kcontrol->get = wm_coeff_get; | ||
| 525 | kcontrol->put = wm_coeff_put; | ||
| 526 | kcontrol->private_value = (unsigned long)ctl; | ||
| 527 | |||
| 528 | ret = wm_coeff_add_kcontrol(wm_coeff, | ||
| 529 | ctl, kcontrol); | ||
| 530 | if (ret < 0) | ||
| 531 | goto err_kcontrol; | ||
| 532 | |||
| 533 | kfree(kcontrol); | ||
| 534 | |||
| 535 | list_add(&ctl->list, &wm_coeff->ctl_list); | ||
| 536 | return 0; | ||
| 537 | |||
| 538 | err_kcontrol: | ||
| 539 | kfree(kcontrol); | ||
| 540 | return ret; | ||
| 541 | } | ||
| 542 | |||
| 337 | static int wm_adsp_load(struct wm_adsp *dsp) | 543 | static int wm_adsp_load(struct wm_adsp *dsp) |
| 338 | { | 544 | { |
| 339 | LIST_HEAD(buf_list); | 545 | LIST_HEAD(buf_list); |
| @@ -547,7 +753,157 @@ out: | |||
| 547 | return ret; | 753 | return ret; |
| 548 | } | 754 | } |
| 549 | 755 | ||
| 550 | static int wm_adsp_setup_algs(struct wm_adsp *dsp) | 756 | static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff) |
| 757 | { | ||
| 758 | struct wm_coeff_ctl *ctl; | ||
| 759 | int ret; | ||
| 760 | |||
| 761 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | ||
| 762 | list) { | ||
| 763 | if (!ctl->enabled || ctl->set) | ||
| 764 | continue; | ||
| 765 | ret = wm_coeff_read_control(ctl->kcontrol, | ||
| 766 | ctl->cache, | ||
| 767 | ctl->len); | ||
| 768 | if (ret < 0) | ||
| 769 | return ret; | ||
| 770 | } | ||
| 771 | |||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff) | ||
| 776 | { | ||
| 777 | struct wm_coeff_ctl *ctl; | ||
| 778 | int ret; | ||
| 779 | |||
| 780 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | ||
| 781 | list) { | ||
| 782 | if (!ctl->enabled) | ||
| 783 | continue; | ||
| 784 | if (ctl->set) { | ||
| 785 | ret = wm_coeff_write_control(ctl->kcontrol, | ||
| 786 | ctl->cache, | ||
| 787 | ctl->len); | ||
| 788 | if (ret < 0) | ||
| 789 | return ret; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | return 0; | ||
| 794 | } | ||
| 795 | |||
| 796 | static void wm_adsp_ctl_work(struct work_struct *work) | ||
| 797 | { | ||
| 798 | struct wmfw_ctl_work *ctl_work = container_of(work, | ||
| 799 | struct wmfw_ctl_work, | ||
| 800 | work); | ||
| 801 | |||
| 802 | wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl); | ||
| 803 | kfree(ctl_work); | ||
| 804 | } | ||
| 805 | |||
| 806 | static int wm_adsp_create_control(struct snd_soc_codec *codec, | ||
| 807 | const struct wm_adsp_alg_region *region) | ||
| 808 | |||
| 809 | { | ||
| 810 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); | ||
| 811 | struct wm_coeff_ctl *ctl; | ||
| 812 | struct wmfw_ctl_work *ctl_work; | ||
| 813 | char *name; | ||
| 814 | char *region_name; | ||
| 815 | int ret; | ||
| 816 | |||
| 817 | name = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 818 | if (!name) | ||
| 819 | return -ENOMEM; | ||
| 820 | |||
| 821 | switch (region->type) { | ||
| 822 | case WMFW_ADSP1_PM: | ||
| 823 | region_name = "PM"; | ||
| 824 | break; | ||
| 825 | case WMFW_ADSP1_DM: | ||
| 826 | region_name = "DM"; | ||
| 827 | break; | ||
| 828 | case WMFW_ADSP2_XM: | ||
| 829 | region_name = "XM"; | ||
| 830 | break; | ||
| 831 | case WMFW_ADSP2_YM: | ||
| 832 | region_name = "YM"; | ||
| 833 | break; | ||
| 834 | case WMFW_ADSP1_ZM: | ||
| 835 | region_name = "ZM"; | ||
| 836 | break; | ||
| 837 | default: | ||
| 838 | ret = -EINVAL; | ||
| 839 | goto err_name; | ||
| 840 | } | ||
| 841 | |||
| 842 | snprintf(name, PAGE_SIZE, "DSP%d %s %x", | ||
| 843 | dsp->num, region_name, region->alg); | ||
| 844 | |||
| 845 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
| 846 | list) { | ||
| 847 | if (!strcmp(ctl->name, name)) { | ||
| 848 | if (!ctl->enabled) | ||
| 849 | ctl->enabled = 1; | ||
| 850 | goto found; | ||
| 851 | } | ||
| 852 | } | ||
| 853 | |||
| 854 | ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); | ||
| 855 | if (!ctl) { | ||
| 856 | ret = -ENOMEM; | ||
| 857 | goto err_name; | ||
| 858 | } | ||
| 859 | ctl->region = *region; | ||
| 860 | ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); | ||
| 861 | if (!ctl->name) { | ||
| 862 | ret = -ENOMEM; | ||
| 863 | goto err_ctl; | ||
| 864 | } | ||
| 865 | ctl->enabled = 1; | ||
| 866 | ctl->set = 0; | ||
| 867 | ctl->ops.xget = wm_coeff_get; | ||
| 868 | ctl->ops.xput = wm_coeff_put; | ||
| 869 | ctl->card = codec->card->snd_card; | ||
| 870 | ctl->adsp = dsp; | ||
| 871 | |||
| 872 | ctl->len = region->len; | ||
| 873 | ctl->cache = kzalloc(ctl->len, GFP_KERNEL); | ||
| 874 | if (!ctl->cache) { | ||
| 875 | ret = -ENOMEM; | ||
| 876 | goto err_ctl_name; | ||
| 877 | } | ||
| 878 | |||
| 879 | ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); | ||
| 880 | if (!ctl_work) { | ||
| 881 | ret = -ENOMEM; | ||
| 882 | goto err_ctl_cache; | ||
| 883 | } | ||
| 884 | |||
| 885 | ctl_work->wm_coeff = dsp->wm_coeff; | ||
| 886 | ctl_work->ctl = ctl; | ||
| 887 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); | ||
| 888 | schedule_work(&ctl_work->work); | ||
| 889 | |||
| 890 | found: | ||
| 891 | kfree(name); | ||
| 892 | |||
| 893 | return 0; | ||
| 894 | |||
| 895 | err_ctl_cache: | ||
| 896 | kfree(ctl->cache); | ||
| 897 | err_ctl_name: | ||
| 898 | kfree(ctl->name); | ||
| 899 | err_ctl: | ||
| 900 | kfree(ctl); | ||
| 901 | err_name: | ||
| 902 | kfree(name); | ||
| 903 | return ret; | ||
| 904 | } | ||
| 905 | |||
| 906 | static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | ||
| 551 | { | 907 | { |
| 552 | struct regmap *regmap = dsp->regmap; | 908 | struct regmap *regmap = dsp->regmap; |
| 553 | struct wmfw_adsp1_id_hdr adsp1_id; | 909 | struct wmfw_adsp1_id_hdr adsp1_id; |
| @@ -730,7 +1086,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
| 730 | region->type = WMFW_ADSP1_DM; | 1086 | region->type = WMFW_ADSP1_DM; |
| 731 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1087 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
| 732 | region->base = be32_to_cpu(adsp1_alg[i].dm); | 1088 | region->base = be32_to_cpu(adsp1_alg[i].dm); |
| 1089 | region->len = 0; | ||
| 733 | list_add_tail(®ion->list, &dsp->alg_regions); | 1090 | list_add_tail(®ion->list, &dsp->alg_regions); |
| 1091 | if (i + 1 < algs) { | ||
| 1092 | region->len = be32_to_cpu(adsp1_alg[i + 1].dm); | ||
| 1093 | region->len -= be32_to_cpu(adsp1_alg[i].dm); | ||
| 1094 | wm_adsp_create_control(codec, region); | ||
| 1095 | } else { | ||
| 1096 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", | ||
| 1097 | be32_to_cpu(adsp1_alg[i].alg.id)); | ||
| 1098 | } | ||
| 734 | 1099 | ||
| 735 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1100 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
| 736 | if (!region) | 1101 | if (!region) |
| @@ -738,7 +1103,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
| 738 | region->type = WMFW_ADSP1_ZM; | 1103 | region->type = WMFW_ADSP1_ZM; |
| 739 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1104 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
| 740 | region->base = be32_to_cpu(adsp1_alg[i].zm); | 1105 | region->base = be32_to_cpu(adsp1_alg[i].zm); |
| 1106 | region->len = 0; | ||
| 741 | list_add_tail(®ion->list, &dsp->alg_regions); | 1107 | list_add_tail(®ion->list, &dsp->alg_regions); |
| 1108 | if (i + 1 < algs) { | ||
| 1109 | region->len = be32_to_cpu(adsp1_alg[i + 1].zm); | ||
| 1110 | region->len -= be32_to_cpu(adsp1_alg[i].zm); | ||
| 1111 | wm_adsp_create_control(codec, region); | ||
| 1112 | } else { | ||
| 1113 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | ||
| 1114 | be32_to_cpu(adsp1_alg[i].alg.id)); | ||
| 1115 | } | ||
| 742 | break; | 1116 | break; |
| 743 | 1117 | ||
| 744 | case WMFW_ADSP2: | 1118 | case WMFW_ADSP2: |
| @@ -758,7 +1132,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
| 758 | region->type = WMFW_ADSP2_XM; | 1132 | region->type = WMFW_ADSP2_XM; |
| 759 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1133 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
| 760 | region->base = be32_to_cpu(adsp2_alg[i].xm); | 1134 | region->base = be32_to_cpu(adsp2_alg[i].xm); |
| 1135 | region->len = 0; | ||
| 761 | list_add_tail(®ion->list, &dsp->alg_regions); | 1136 | list_add_tail(®ion->list, &dsp->alg_regions); |
| 1137 | if (i + 1 < algs) { | ||
| 1138 | region->len = be32_to_cpu(adsp2_alg[i + 1].xm); | ||
| 1139 | region->len -= be32_to_cpu(adsp2_alg[i].xm); | ||
| 1140 | wm_adsp_create_control(codec, region); | ||
| 1141 | } else { | ||
| 1142 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", | ||
| 1143 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
| 1144 | } | ||
| 762 | 1145 | ||
| 763 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1146 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
| 764 | if (!region) | 1147 | if (!region) |
| @@ -766,7 +1149,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
| 766 | region->type = WMFW_ADSP2_YM; | 1149 | region->type = WMFW_ADSP2_YM; |
| 767 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1150 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
| 768 | region->base = be32_to_cpu(adsp2_alg[i].ym); | 1151 | region->base = be32_to_cpu(adsp2_alg[i].ym); |
| 1152 | region->len = 0; | ||
| 769 | list_add_tail(®ion->list, &dsp->alg_regions); | 1153 | list_add_tail(®ion->list, &dsp->alg_regions); |
| 1154 | if (i + 1 < algs) { | ||
| 1155 | region->len = be32_to_cpu(adsp2_alg[i + 1].ym); | ||
| 1156 | region->len -= be32_to_cpu(adsp2_alg[i].ym); | ||
| 1157 | wm_adsp_create_control(codec, region); | ||
| 1158 | } else { | ||
| 1159 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", | ||
| 1160 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
| 1161 | } | ||
| 770 | 1162 | ||
| 771 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1163 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
| 772 | if (!region) | 1164 | if (!region) |
| @@ -774,7 +1166,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
| 774 | region->type = WMFW_ADSP2_ZM; | 1166 | region->type = WMFW_ADSP2_ZM; |
| 775 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1167 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
| 776 | region->base = be32_to_cpu(adsp2_alg[i].zm); | 1168 | region->base = be32_to_cpu(adsp2_alg[i].zm); |
| 1169 | region->len = 0; | ||
| 777 | list_add_tail(®ion->list, &dsp->alg_regions); | 1170 | list_add_tail(®ion->list, &dsp->alg_regions); |
| 1171 | if (i + 1 < algs) { | ||
| 1172 | region->len = be32_to_cpu(adsp2_alg[i + 1].zm); | ||
| 1173 | region->len -= be32_to_cpu(adsp2_alg[i].zm); | ||
| 1174 | wm_adsp_create_control(codec, region); | ||
| 1175 | } else { | ||
| 1176 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | ||
| 1177 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
| 1178 | } | ||
| 778 | break; | 1179 | break; |
| 779 | } | 1180 | } |
| 780 | } | 1181 | } |
| @@ -986,6 +1387,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 986 | struct snd_soc_codec *codec = w->codec; | 1387 | struct snd_soc_codec *codec = w->codec; |
| 987 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1388 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
| 988 | struct wm_adsp *dsp = &dsps[w->shift]; | 1389 | struct wm_adsp *dsp = &dsps[w->shift]; |
| 1390 | struct wm_coeff_ctl *ctl; | ||
| 989 | int ret; | 1391 | int ret; |
| 990 | int val; | 1392 | int val; |
| 991 | 1393 | ||
| @@ -1023,7 +1425,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1023 | if (ret != 0) | 1425 | if (ret != 0) |
| 1024 | goto err; | 1426 | goto err; |
| 1025 | 1427 | ||
| 1026 | ret = wm_adsp_setup_algs(dsp); | 1428 | ret = wm_adsp_setup_algs(dsp, codec); |
| 1027 | if (ret != 0) | 1429 | if (ret != 0) |
| 1028 | goto err; | 1430 | goto err; |
| 1029 | 1431 | ||
| @@ -1031,6 +1433,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1031 | if (ret != 0) | 1433 | if (ret != 0) |
| 1032 | goto err; | 1434 | goto err; |
| 1033 | 1435 | ||
| 1436 | /* Initialize caches for enabled and unset controls */ | ||
| 1437 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | ||
| 1438 | if (ret != 0) | ||
| 1439 | goto err; | ||
| 1440 | |||
| 1441 | /* Sync set controls */ | ||
| 1442 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | ||
| 1443 | if (ret != 0) | ||
| 1444 | goto err; | ||
| 1445 | |||
| 1034 | /* Start the core running */ | 1446 | /* Start the core running */ |
| 1035 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1447 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
| 1036 | ADSP1_CORE_ENA | ADSP1_START, | 1448 | ADSP1_CORE_ENA | ADSP1_START, |
| @@ -1047,6 +1459,11 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1047 | 1459 | ||
| 1048 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1460 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
| 1049 | ADSP1_SYS_ENA, 0); | 1461 | ADSP1_SYS_ENA, 0); |
| 1462 | |||
| 1463 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
| 1464 | list) { | ||
| 1465 | ctl->enabled = 0; | ||
| 1466 | } | ||
| 1050 | break; | 1467 | break; |
| 1051 | 1468 | ||
| 1052 | default: | 1469 | default: |
| @@ -1099,6 +1516,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1099 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1516 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
| 1100 | struct wm_adsp *dsp = &dsps[w->shift]; | 1517 | struct wm_adsp *dsp = &dsps[w->shift]; |
| 1101 | struct wm_adsp_alg_region *alg_region; | 1518 | struct wm_adsp_alg_region *alg_region; |
| 1519 | struct wm_coeff_ctl *ctl; | ||
| 1102 | unsigned int val; | 1520 | unsigned int val; |
| 1103 | int ret; | 1521 | int ret; |
| 1104 | 1522 | ||
| @@ -1164,7 +1582,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1164 | if (ret != 0) | 1582 | if (ret != 0) |
| 1165 | goto err; | 1583 | goto err; |
| 1166 | 1584 | ||
| 1167 | ret = wm_adsp_setup_algs(dsp); | 1585 | ret = wm_adsp_setup_algs(dsp, codec); |
| 1168 | if (ret != 0) | 1586 | if (ret != 0) |
| 1169 | goto err; | 1587 | goto err; |
| 1170 | 1588 | ||
| @@ -1172,6 +1590,16 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1172 | if (ret != 0) | 1590 | if (ret != 0) |
| 1173 | goto err; | 1591 | goto err; |
| 1174 | 1592 | ||
| 1593 | /* Initialize caches for enabled and unset controls */ | ||
| 1594 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | ||
| 1595 | if (ret != 0) | ||
| 1596 | goto err; | ||
| 1597 | |||
| 1598 | /* Sync set controls */ | ||
| 1599 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | ||
| 1600 | if (ret != 0) | ||
| 1601 | goto err; | ||
| 1602 | |||
| 1175 | ret = regmap_update_bits(dsp->regmap, | 1603 | ret = regmap_update_bits(dsp->regmap, |
| 1176 | dsp->base + ADSP2_CONTROL, | 1604 | dsp->base + ADSP2_CONTROL, |
| 1177 | ADSP2_CORE_ENA | ADSP2_START, | 1605 | ADSP2_CORE_ENA | ADSP2_START, |
| @@ -1209,6 +1637,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1209 | ret); | 1637 | ret); |
| 1210 | } | 1638 | } |
| 1211 | 1639 | ||
| 1640 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
| 1641 | list) { | ||
| 1642 | ctl->enabled = 0; | ||
| 1643 | } | ||
| 1644 | |||
| 1212 | while (!list_empty(&dsp->alg_regions)) { | 1645 | while (!list_empty(&dsp->alg_regions)) { |
| 1213 | alg_region = list_first_entry(&dsp->alg_regions, | 1646 | alg_region = list_first_entry(&dsp->alg_regions, |
| 1214 | struct wm_adsp_alg_region, | 1647 | struct wm_adsp_alg_region, |
| @@ -1247,36 +1680,48 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
| 1247 | 1680 | ||
| 1248 | INIT_LIST_HEAD(&adsp->alg_regions); | 1681 | INIT_LIST_HEAD(&adsp->alg_regions); |
| 1249 | 1682 | ||
| 1683 | adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff), | ||
| 1684 | GFP_KERNEL); | ||
| 1685 | if (!adsp->wm_coeff) | ||
| 1686 | return -ENOMEM; | ||
| 1687 | adsp->wm_coeff->regmap = adsp->regmap; | ||
| 1688 | adsp->wm_coeff->dev = adsp->dev; | ||
| 1689 | INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list); | ||
| 1690 | |||
| 1250 | if (dvfs) { | 1691 | if (dvfs) { |
| 1251 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | 1692 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); |
| 1252 | if (IS_ERR(adsp->dvfs)) { | 1693 | if (IS_ERR(adsp->dvfs)) { |
| 1253 | ret = PTR_ERR(adsp->dvfs); | 1694 | ret = PTR_ERR(adsp->dvfs); |
| 1254 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); | 1695 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); |
| 1255 | return ret; | 1696 | goto out_coeff; |
| 1256 | } | 1697 | } |
| 1257 | 1698 | ||
| 1258 | ret = regulator_enable(adsp->dvfs); | 1699 | ret = regulator_enable(adsp->dvfs); |
| 1259 | if (ret != 0) { | 1700 | if (ret != 0) { |
| 1260 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", | 1701 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", |
| 1261 | ret); | 1702 | ret); |
| 1262 | return ret; | 1703 | goto out_coeff; |
| 1263 | } | 1704 | } |
| 1264 | 1705 | ||
| 1265 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); | 1706 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); |
| 1266 | if (ret != 0) { | 1707 | if (ret != 0) { |
| 1267 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", | 1708 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", |
| 1268 | ret); | 1709 | ret); |
| 1269 | return ret; | 1710 | goto out_coeff; |
| 1270 | } | 1711 | } |
| 1271 | 1712 | ||
| 1272 | ret = regulator_disable(adsp->dvfs); | 1713 | ret = regulator_disable(adsp->dvfs); |
| 1273 | if (ret != 0) { | 1714 | if (ret != 0) { |
| 1274 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", | 1715 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", |
| 1275 | ret); | 1716 | ret); |
| 1276 | return ret; | 1717 | goto out_coeff; |
| 1277 | } | 1718 | } |
| 1278 | } | 1719 | } |
| 1279 | 1720 | ||
| 1280 | return 0; | 1721 | return 0; |
| 1722 | |||
| 1723 | out_coeff: | ||
| 1724 | kfree(adsp->wm_coeff); | ||
| 1725 | return ret; | ||
| 1281 | } | 1726 | } |
| 1282 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1727 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index fea514627526..9f922c82536c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
| @@ -30,6 +30,7 @@ struct wm_adsp_alg_region { | |||
| 30 | unsigned int alg; | 30 | unsigned int alg; |
| 31 | int type; | 31 | int type; |
| 32 | unsigned int base; | 32 | unsigned int base; |
| 33 | size_t len; | ||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | struct wm_adsp { | 36 | struct wm_adsp { |
| @@ -55,17 +56,17 @@ struct wm_adsp { | |||
| 55 | bool running; | 56 | bool running; |
| 56 | 57 | ||
| 57 | struct regulator *dvfs; | 58 | struct regulator *dvfs; |
| 59 | |||
| 60 | struct wm_coeff *wm_coeff; | ||
| 58 | }; | 61 | }; |
| 59 | 62 | ||
| 60 | #define WM_ADSP1(wname, num) \ | 63 | #define WM_ADSP1(wname, num) \ |
| 61 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 64 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
| 62 | .shift = num, .event = wm_adsp1_event, \ | 65 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
| 63 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
| 64 | 66 | ||
| 65 | #define WM_ADSP2(wname, num) \ | 67 | #define WM_ADSP2(wname, num) \ |
| 66 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 68 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
| 67 | .shift = num, .event = wm_adsp2_event, \ | 69 | wm_adsp2_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
| 68 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
| 69 | 70 | ||
| 70 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; | 71 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; |
| 71 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; | 72 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index f5d81b948759..2d9e099415a5 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
| @@ -693,10 +693,8 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec) | |||
| 693 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); | 693 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); |
| 694 | 694 | ||
| 695 | #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \ | 695 | #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \ |
| 696 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 696 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
| 697 | .info = snd_soc_info_volsw, \ | 697 | snd_soc_dapm_get_volsw, class_w_put_volsw) |
| 698 | .get = snd_soc_dapm_get_volsw, .put = class_w_put_volsw, \ | ||
| 699 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
| 700 | 698 | ||
| 701 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, | 699 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, |
| 702 | struct snd_ctl_elem_value *ucontrol) | 700 | struct snd_ctl_elem_value *ucontrol) |
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 c6fa03e2114a..51be3772cba9 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
| @@ -501,13 +501,12 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) | |||
| 501 | imx_ssi_ac97_read(ac97, 0); | 501 | imx_ssi_ac97_read(ac97, 0); |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | struct snd_ac97_bus_ops soc_ac97_ops = { | 504 | static struct snd_ac97_bus_ops imx_ssi_ac97_ops = { |
| 505 | .read = imx_ssi_ac97_read, | 505 | .read = imx_ssi_ac97_read, |
| 506 | .write = imx_ssi_ac97_write, | 506 | .write = imx_ssi_ac97_write, |
| 507 | .reset = imx_ssi_ac97_reset, | 507 | .reset = imx_ssi_ac97_reset, |
| 508 | .warm_reset = imx_ssi_ac97_warm_reset | 508 | .warm_reset = imx_ssi_ac97_warm_reset |
| 509 | }; | 509 | }; |
| 510 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 511 | 510 | ||
| 512 | static int imx_ssi_probe(struct platform_device *pdev) | 511 | static int imx_ssi_probe(struct platform_device *pdev) |
| 513 | { | 512 | { |
| @@ -583,6 +582,12 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 583 | 582 | ||
| 584 | platform_set_drvdata(pdev, ssi); | 583 | platform_set_drvdata(pdev, ssi); |
| 585 | 584 | ||
| 585 | ret = snd_soc_set_ac97_ops(&imx_ssi_ac97_ops); | ||
| 586 | if (ret != 0) { | ||
| 587 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
| 588 | goto failed_register; | ||
| 589 | } | ||
| 590 | |||
| 586 | ret = snd_soc_register_component(&pdev->dev, &imx_component, | 591 | ret = snd_soc_register_component(&pdev->dev, &imx_component, |
| 587 | dai, 1); | 592 | dai, 1); |
| 588 | if (ret) { | 593 | if (ret) { |
| @@ -590,46 +595,25 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 590 | goto failed_register; | 595 | goto failed_register; |
| 591 | } | 596 | } |
| 592 | 597 | ||
| 593 | ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); | 598 | ret = imx_pcm_fiq_init(pdev); |
| 594 | if (!ssi->soc_platform_pdev_fiq) { | 599 | if (ret) |
| 595 | ret = -ENOMEM; | 600 | goto failed_pcm_fiq; |
| 596 | goto failed_pdev_fiq_alloc; | ||
| 597 | } | ||
| 598 | 601 | ||
| 599 | platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi); | 602 | ret = imx_pcm_dma_init(pdev); |
| 600 | ret = platform_device_add(ssi->soc_platform_pdev_fiq); | 603 | if (ret) |
| 601 | if (ret) { | 604 | goto failed_pcm_dma; |
| 602 | dev_err(&pdev->dev, "failed to add platform device\n"); | ||
| 603 | goto failed_pdev_fiq_add; | ||
| 604 | } | ||
| 605 | |||
| 606 | ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id); | ||
| 607 | if (!ssi->soc_platform_pdev) { | ||
| 608 | ret = -ENOMEM; | ||
| 609 | goto failed_pdev_alloc; | ||
| 610 | } | ||
| 611 | |||
| 612 | platform_set_drvdata(ssi->soc_platform_pdev, ssi); | ||
| 613 | ret = platform_device_add(ssi->soc_platform_pdev); | ||
| 614 | if (ret) { | ||
| 615 | dev_err(&pdev->dev, "failed to add platform device\n"); | ||
| 616 | goto failed_pdev_add; | ||
| 617 | } | ||
| 618 | 605 | ||
| 619 | return 0; | 606 | return 0; |
| 620 | 607 | ||
| 621 | failed_pdev_add: | 608 | failed_pcm_dma: |
| 622 | platform_device_put(ssi->soc_platform_pdev); | 609 | imx_pcm_fiq_exit(pdev); |
| 623 | failed_pdev_alloc: | 610 | failed_pcm_fiq: |
| 624 | platform_device_del(ssi->soc_platform_pdev_fiq); | ||
| 625 | failed_pdev_fiq_add: | ||
| 626 | platform_device_put(ssi->soc_platform_pdev_fiq); | ||
| 627 | failed_pdev_fiq_alloc: | ||
| 628 | snd_soc_unregister_component(&pdev->dev); | 611 | snd_soc_unregister_component(&pdev->dev); |
| 629 | failed_register: | 612 | failed_register: |
| 630 | release_mem_region(res->start, resource_size(res)); | 613 | release_mem_region(res->start, resource_size(res)); |
| 631 | clk_disable_unprepare(ssi->clk); | 614 | clk_disable_unprepare(ssi->clk); |
| 632 | failed_clk: | 615 | failed_clk: |
| 616 | snd_soc_set_ac97_ops(NULL); | ||
| 633 | 617 | ||
| 634 | return ret; | 618 | return ret; |
| 635 | } | 619 | } |
| @@ -639,8 +623,8 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
| 639 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 623 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 640 | struct imx_ssi *ssi = platform_get_drvdata(pdev); | 624 | struct imx_ssi *ssi = platform_get_drvdata(pdev); |
| 641 | 625 | ||
| 642 | platform_device_unregister(ssi->soc_platform_pdev); | 626 | imx_pcm_dma_exit(pdev); |
| 643 | platform_device_unregister(ssi->soc_platform_pdev_fiq); | 627 | imx_pcm_fiq_exit(pdev); |
| 644 | 628 | ||
| 645 | snd_soc_unregister_component(&pdev->dev); | 629 | snd_soc_unregister_component(&pdev->dev); |
| 646 | 630 | ||
| @@ -649,6 +633,7 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
| 649 | 633 | ||
| 650 | release_mem_region(res->start, resource_size(res)); | 634 | release_mem_region(res->start, resource_size(res)); |
| 651 | clk_disable_unprepare(ssi->clk); | 635 | clk_disable_unprepare(ssi->clk); |
| 636 | snd_soc_set_ac97_ops(NULL); | ||
| 652 | 637 | ||
| 653 | return 0; | 638 | return 0; |
| 654 | } | 639 | } |
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/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 4141b35ef0bb..3ef7a0c92efa 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
| @@ -131,13 +131,12 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 131 | psc_ac97_warm_reset(ac97); | 131 | psc_ac97_warm_reset(ac97); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | struct snd_ac97_bus_ops soc_ac97_ops = { | 134 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
| 135 | .read = psc_ac97_read, | 135 | .read = psc_ac97_read, |
| 136 | .write = psc_ac97_write, | 136 | .write = psc_ac97_write, |
| 137 | .reset = psc_ac97_cold_reset, | 137 | .reset = psc_ac97_cold_reset, |
| 138 | .warm_reset = psc_ac97_warm_reset, | 138 | .warm_reset = psc_ac97_warm_reset, |
| 139 | }; | 139 | }; |
| 140 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 141 | 140 | ||
| 142 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, | 141 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, |
| 143 | struct snd_pcm_hw_params *params, | 142 | struct snd_pcm_hw_params *params, |
| @@ -290,6 +289,12 @@ static int psc_ac97_of_probe(struct platform_device *op) | |||
| 290 | if (rc != 0) | 289 | if (rc != 0) |
| 291 | return rc; | 290 | return rc; |
| 292 | 291 | ||
| 292 | rc = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
| 293 | if (rc != 0) { | ||
| 294 | dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
| 295 | return rc; | ||
| 296 | } | ||
| 297 | |||
| 293 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, | 298 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, |
| 294 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | 299 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
| 295 | if (rc != 0) { | 300 | if (rc != 0) { |
| @@ -318,6 +323,7 @@ static int psc_ac97_of_remove(struct platform_device *op) | |||
| 318 | { | 323 | { |
| 319 | mpc5200_audio_dma_destroy(op); | 324 | mpc5200_audio_dma_destroy(op); |
| 320 | snd_soc_unregister_component(&op->dev); | 325 | snd_soc_unregister_component(&op->dev); |
| 326 | snd_soc_set_ac97_ops(NULL); | ||
| 321 | return 0; | 327 | return 0; |
| 322 | } | 328 | } |
| 323 | 329 | ||
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/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 4139116c33b5..ee363845759e 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
| @@ -371,7 +371,7 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) | |||
| 371 | 371 | ||
| 372 | /* audio interrupt base of SRAM location where | 372 | /* audio interrupt base of SRAM location where |
| 373 | * interrupts are stored by System FW */ | 373 | * interrupts are stored by System FW */ |
| 374 | mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC); | 374 | mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC); |
| 375 | if (!mc_drv_ctx) { | 375 | if (!mc_drv_ctx) { |
| 376 | pr_err("allocation failed\n"); | 376 | pr_err("allocation failed\n"); |
| 377 | return -ENOMEM; | 377 | return -ENOMEM; |
| @@ -381,51 +381,39 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) | |||
| 381 | pdev, IORESOURCE_MEM, "IRQ_BASE"); | 381 | pdev, IORESOURCE_MEM, "IRQ_BASE"); |
| 382 | if (!irq_mem) { | 382 | if (!irq_mem) { |
| 383 | pr_err("no mem resource given\n"); | 383 | pr_err("no mem resource given\n"); |
| 384 | ret_val = -ENODEV; | 384 | return -ENODEV; |
| 385 | goto unalloc; | ||
| 386 | } | 385 | } |
| 387 | mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start, | 386 | mc_drv_ctx->int_base = devm_ioremap_nocache(&pdev->dev, irq_mem->start, |
| 388 | resource_size(irq_mem)); | 387 | resource_size(irq_mem)); |
| 389 | if (!mc_drv_ctx->int_base) { | 388 | if (!mc_drv_ctx->int_base) { |
| 390 | pr_err("Mapping of cache failed\n"); | 389 | pr_err("Mapping of cache failed\n"); |
| 391 | ret_val = -ENOMEM; | 390 | return -ENOMEM; |
| 392 | goto unalloc; | ||
| 393 | } | 391 | } |
| 394 | /* register for interrupt */ | 392 | /* register for interrupt */ |
| 395 | ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler, | 393 | ret_val = devm_request_threaded_irq(&pdev->dev, irq, |
| 394 | snd_mfld_jack_intr_handler, | ||
| 396 | snd_mfld_jack_detection, | 395 | snd_mfld_jack_detection, |
| 397 | IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); | 396 | IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); |
| 398 | if (ret_val) { | 397 | if (ret_val) { |
| 399 | pr_err("cannot register IRQ\n"); | 398 | pr_err("cannot register IRQ\n"); |
| 400 | goto unalloc; | 399 | return ret_val; |
| 401 | } | 400 | } |
| 402 | /* register the soc card */ | 401 | /* register the soc card */ |
| 403 | snd_soc_card_mfld.dev = &pdev->dev; | 402 | snd_soc_card_mfld.dev = &pdev->dev; |
| 404 | ret_val = snd_soc_register_card(&snd_soc_card_mfld); | 403 | ret_val = snd_soc_register_card(&snd_soc_card_mfld); |
| 405 | if (ret_val) { | 404 | if (ret_val) { |
| 406 | pr_debug("snd_soc_register_card failed %d\n", ret_val); | 405 | pr_debug("snd_soc_register_card failed %d\n", ret_val); |
| 407 | goto freeirq; | 406 | return ret_val; |
| 408 | } | 407 | } |
| 409 | platform_set_drvdata(pdev, mc_drv_ctx); | 408 | platform_set_drvdata(pdev, mc_drv_ctx); |
| 410 | pr_debug("successfully exited probe\n"); | 409 | pr_debug("successfully exited probe\n"); |
| 411 | return ret_val; | 410 | return 0; |
| 412 | |||
| 413 | freeirq: | ||
| 414 | free_irq(irq, mc_drv_ctx); | ||
| 415 | unalloc: | ||
| 416 | kfree(mc_drv_ctx); | ||
| 417 | return ret_val; | ||
| 418 | } | 411 | } |
| 419 | 412 | ||
| 420 | static int snd_mfld_mc_remove(struct platform_device *pdev) | 413 | static int snd_mfld_mc_remove(struct platform_device *pdev) |
| 421 | { | 414 | { |
| 422 | struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev); | ||
| 423 | |||
| 424 | pr_debug("snd_mfld_mc_remove called\n"); | 415 | pr_debug("snd_mfld_mc_remove called\n"); |
| 425 | free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); | ||
| 426 | snd_soc_unregister_card(&snd_soc_card_mfld); | 416 | snd_soc_unregister_card(&snd_soc_card_mfld); |
| 427 | kfree(mc_drv_ctx); | ||
| 428 | platform_set_drvdata(pdev, NULL); | ||
| 429 | return 0; | 417 | return 0; |
| 430 | } | 418 | } |
| 431 | 419 | ||
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/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index fe3285ceaf5b..f4c2417a8730 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
| @@ -197,13 +197,12 @@ static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | /* AC97 controller operations */ | 199 | /* AC97 controller operations */ |
| 200 | struct snd_ac97_bus_ops soc_ac97_ops = { | 200 | static struct snd_ac97_bus_ops nuc900_ac97_ops = { |
| 201 | .read = nuc900_ac97_read, | 201 | .read = nuc900_ac97_read, |
| 202 | .write = nuc900_ac97_write, | 202 | .write = nuc900_ac97_write, |
| 203 | .reset = nuc900_ac97_cold_reset, | 203 | .reset = nuc900_ac97_cold_reset, |
| 204 | .warm_reset = nuc900_ac97_warm_reset, | 204 | .warm_reset = nuc900_ac97_warm_reset, |
| 205 | } | 205 | }; |
| 206 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 207 | 206 | ||
| 208 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, | 207 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, |
| 209 | int cmd, struct snd_soc_dai *dai) | 208 | int cmd, struct snd_soc_dai *dai) |
| @@ -326,64 +325,52 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
| 326 | if (nuc900_ac97_data) | 325 | if (nuc900_ac97_data) |
| 327 | return -EBUSY; | 326 | return -EBUSY; |
| 328 | 327 | ||
| 329 | nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL); | 328 | nuc900_audio = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_audio), |
| 329 | GFP_KERNEL); | ||
| 330 | if (!nuc900_audio) | 330 | if (!nuc900_audio) |
| 331 | return -ENOMEM; | 331 | return -ENOMEM; |
| 332 | 332 | ||
| 333 | spin_lock_init(&nuc900_audio->lock); | 333 | spin_lock_init(&nuc900_audio->lock); |
| 334 | 334 | ||
| 335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 336 | if (!nuc900_audio->res) { | 336 | if (!nuc900_audio->res) |
| 337 | ret = -ENODEV; | 337 | return ret; |
| 338 | goto out0; | ||
| 339 | } | ||
| 340 | |||
| 341 | if (!request_mem_region(nuc900_audio->res->start, | ||
| 342 | resource_size(nuc900_audio->res), pdev->name)) { | ||
| 343 | ret = -EBUSY; | ||
| 344 | goto out0; | ||
| 345 | } | ||
| 346 | 338 | ||
| 347 | nuc900_audio->mmio = ioremap(nuc900_audio->res->start, | 339 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, |
| 348 | resource_size(nuc900_audio->res)); | 340 | nuc900_audio->res); |
| 349 | if (!nuc900_audio->mmio) { | 341 | if (IS_ERR(nuc900_audio->mmio)) |
| 350 | ret = -ENOMEM; | 342 | return PTR_ERR(nuc900_audio->mmio); |
| 351 | goto out1; | ||
| 352 | } | ||
| 353 | 343 | ||
| 354 | nuc900_audio->clk = clk_get(&pdev->dev, NULL); | 344 | nuc900_audio->clk = devm_clk_get(&pdev->dev, NULL); |
| 355 | if (IS_ERR(nuc900_audio->clk)) { | 345 | if (IS_ERR(nuc900_audio->clk)) { |
| 356 | ret = PTR_ERR(nuc900_audio->clk); | 346 | ret = PTR_ERR(nuc900_audio->clk); |
| 357 | goto out2; | 347 | goto out; |
| 358 | } | 348 | } |
| 359 | 349 | ||
| 360 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); | 350 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); |
| 361 | if (!nuc900_audio->irq_num) { | 351 | if (!nuc900_audio->irq_num) { |
| 362 | ret = -EBUSY; | 352 | ret = -EBUSY; |
| 363 | goto out3; | 353 | goto out; |
| 364 | } | 354 | } |
| 365 | 355 | ||
| 366 | nuc900_ac97_data = nuc900_audio; | 356 | nuc900_ac97_data = nuc900_audio; |
| 367 | 357 | ||
| 358 | ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); | ||
| 359 | if (ret) | ||
| 360 | goto out; | ||
| 361 | |||
| 368 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, | 362 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, |
| 369 | &nuc900_ac97_dai, 1); | 363 | &nuc900_ac97_dai, 1); |
| 370 | if (ret) | 364 | if (ret) |
| 371 | goto out3; | 365 | goto out; |
| 372 | 366 | ||
| 373 | /* enbale ac97 multifunction pin */ | 367 | /* enbale ac97 multifunction pin */ |
| 374 | mfp_set_groupg(nuc900_audio->dev, NULL); | 368 | mfp_set_groupg(nuc900_audio->dev, NULL); |
| 375 | 369 | ||
| 376 | return 0; | 370 | return 0; |
| 377 | 371 | ||
| 378 | out3: | 372 | out: |
| 379 | clk_put(nuc900_audio->clk); | 373 | snd_soc_set_ac97_ops(NULL); |
| 380 | out2: | ||
| 381 | iounmap(nuc900_audio->mmio); | ||
| 382 | out1: | ||
| 383 | release_mem_region(nuc900_audio->res->start, | ||
| 384 | resource_size(nuc900_audio->res)); | ||
| 385 | out0: | ||
| 386 | kfree(nuc900_audio); | ||
| 387 | return ret; | 374 | return ret; |
| 388 | } | 375 | } |
| 389 | 376 | ||
| @@ -391,13 +378,8 @@ static int nuc900_ac97_drvremove(struct platform_device *pdev) | |||
| 391 | { | 378 | { |
| 392 | snd_soc_unregister_component(&pdev->dev); | 379 | snd_soc_unregister_component(&pdev->dev); |
| 393 | 380 | ||
| 394 | clk_put(nuc900_ac97_data->clk); | ||
| 395 | iounmap(nuc900_ac97_data->mmio); | ||
| 396 | release_mem_region(nuc900_ac97_data->res->start, | ||
| 397 | resource_size(nuc900_ac97_data->res)); | ||
| 398 | |||
| 399 | kfree(nuc900_ac97_data); | ||
| 400 | nuc900_ac97_data = NULL; | 381 | nuc900_ac97_data = NULL; |
| 382 | snd_soc_set_ac97_ops(NULL); | ||
| 401 | 383 | ||
| 402 | return 0; | 384 | return 0; |
| 403 | } | 385 | } |
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/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 57ea8e6c5488..a3c22ba25f08 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
| @@ -41,13 +41,12 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 41 | pxa2xx_ac97_finish_reset(ac97); | 41 | pxa2xx_ac97_finish_reset(ac97); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | struct snd_ac97_bus_ops soc_ac97_ops = { | 44 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { |
| 45 | .read = pxa2xx_ac97_read, | 45 | .read = pxa2xx_ac97_read, |
| 46 | .write = pxa2xx_ac97_write, | 46 | .write = pxa2xx_ac97_write, |
| 47 | .warm_reset = pxa2xx_ac97_warm_reset, | 47 | .warm_reset = pxa2xx_ac97_warm_reset, |
| 48 | .reset = pxa2xx_ac97_cold_reset, | 48 | .reset = pxa2xx_ac97_cold_reset, |
| 49 | }; | 49 | }; |
| 50 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 51 | 50 | ||
| 52 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { | 51 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { |
| 53 | .name = "AC97 PCM Stereo out", | 52 | .name = "AC97 PCM Stereo out", |
| @@ -244,6 +243,10 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
| 244 | return -ENXIO; | 243 | return -ENXIO; |
| 245 | } | 244 | } |
| 246 | 245 | ||
| 246 | ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); | ||
| 247 | if (ret != 0) | ||
| 248 | return ret; | ||
| 249 | |||
| 247 | /* Punt most of the init to the SoC probe; we may need the machine | 250 | /* Punt most of the init to the SoC probe; we may need the machine |
| 248 | * driver to do interesting things with the clocking to get us up | 251 | * driver to do interesting things with the clocking to get us up |
| 249 | * and running. | 252 | * and running. |
| @@ -255,6 +258,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
| 255 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) | 258 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
| 256 | { | 259 | { |
| 257 | snd_soc_unregister_component(&pdev->dev); | 260 | snd_soc_unregister_component(&pdev->dev); |
| 261 | snd_soc_set_ac97_ops(NULL); | ||
| 258 | return 0; | 262 | return 0; |
| 259 | } | 263 | } |
| 260 | 264 | ||
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/ac97.c b/sound/soc/samsung/ac97.c index cb88ead98917..2dd623fa3882 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
| @@ -214,13 +214,12 @@ static irqreturn_t s3c_ac97_irq(int irq, void *dev_id) | |||
| 214 | return IRQ_HANDLED; | 214 | return IRQ_HANDLED; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | struct snd_ac97_bus_ops soc_ac97_ops = { | 217 | static struct snd_ac97_bus_ops s3c_ac97_ops = { |
| 218 | .read = s3c_ac97_read, | 218 | .read = s3c_ac97_read, |
| 219 | .write = s3c_ac97_write, | 219 | .write = s3c_ac97_write, |
| 220 | .warm_reset = s3c_ac97_warm_reset, | 220 | .warm_reset = s3c_ac97_warm_reset, |
| 221 | .reset = s3c_ac97_cold_reset, | 221 | .reset = s3c_ac97_cold_reset, |
| 222 | }; | 222 | }; |
| 223 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 224 | 223 | ||
| 225 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | 224 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, |
| 226 | struct snd_pcm_hw_params *params, | 225 | struct snd_pcm_hw_params *params, |
| @@ -417,11 +416,9 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
| 417 | return -ENXIO; | 416 | return -ENXIO; |
| 418 | } | 417 | } |
| 419 | 418 | ||
| 420 | if (!request_mem_region(mem_res->start, | 419 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); |
| 421 | resource_size(mem_res), "ac97")) { | 420 | if (IS_ERR(s3c_ac97.regs)) |
| 422 | dev_err(&pdev->dev, "Unable to request register region\n"); | 421 | return PTR_ERR(s3c_ac97.regs); |
| 423 | return -EBUSY; | ||
| 424 | } | ||
| 425 | 422 | ||
| 426 | s3c_ac97_pcm_out.channel = dmatx_res->start; | 423 | s3c_ac97_pcm_out.channel = dmatx_res->start; |
| 427 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; | 424 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; |
| @@ -433,14 +430,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
| 433 | init_completion(&s3c_ac97.done); | 430 | init_completion(&s3c_ac97.done); |
| 434 | mutex_init(&s3c_ac97.lock); | 431 | mutex_init(&s3c_ac97.lock); |
| 435 | 432 | ||
| 436 | s3c_ac97.regs = ioremap(mem_res->start, resource_size(mem_res)); | 433 | s3c_ac97.ac97_clk = devm_clk_get(&pdev->dev, "ac97"); |
| 437 | if (s3c_ac97.regs == NULL) { | ||
| 438 | dev_err(&pdev->dev, "Unable to ioremap register region\n"); | ||
| 439 | ret = -ENXIO; | ||
| 440 | goto err1; | ||
| 441 | } | ||
| 442 | |||
| 443 | s3c_ac97.ac97_clk = clk_get(&pdev->dev, "ac97"); | ||
| 444 | if (IS_ERR(s3c_ac97.ac97_clk)) { | 434 | if (IS_ERR(s3c_ac97.ac97_clk)) { |
| 445 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); | 435 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); |
| 446 | ret = -ENODEV; | 436 | ret = -ENODEV; |
| @@ -461,6 +451,12 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
| 461 | goto err4; | 451 | goto err4; |
| 462 | } | 452 | } |
| 463 | 453 | ||
| 454 | ret = snd_soc_set_ac97_ops(&s3c_ac97_ops); | ||
| 455 | if (ret != 0) { | ||
| 456 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
| 457 | goto err4; | ||
| 458 | } | ||
| 459 | |||
| 464 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, | 460 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, |
| 465 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | 461 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); |
| 466 | if (ret) | 462 | if (ret) |
| @@ -480,18 +476,14 @@ err5: | |||
| 480 | err4: | 476 | err4: |
| 481 | err3: | 477 | err3: |
| 482 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 478 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
| 483 | clk_put(s3c_ac97.ac97_clk); | ||
| 484 | err2: | 479 | err2: |
| 485 | iounmap(s3c_ac97.regs); | 480 | snd_soc_set_ac97_ops(NULL); |
| 486 | err1: | ||
| 487 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
| 488 | |||
| 489 | return ret; | 481 | return ret; |
| 490 | } | 482 | } |
| 491 | 483 | ||
| 492 | static int s3c_ac97_remove(struct platform_device *pdev) | 484 | static int s3c_ac97_remove(struct platform_device *pdev) |
| 493 | { | 485 | { |
| 494 | struct resource *mem_res, *irq_res; | 486 | struct resource *irq_res; |
| 495 | 487 | ||
| 496 | asoc_dma_platform_unregister(&pdev->dev); | 488 | asoc_dma_platform_unregister(&pdev->dev); |
| 497 | snd_soc_unregister_component(&pdev->dev); | 489 | snd_soc_unregister_component(&pdev->dev); |
| @@ -501,13 +493,7 @@ static int s3c_ac97_remove(struct platform_device *pdev) | |||
| 501 | free_irq(irq_res->start, NULL); | 493 | free_irq(irq_res->start, NULL); |
| 502 | 494 | ||
| 503 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 495 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
| 504 | clk_put(s3c_ac97.ac97_clk); | 496 | snd_soc_set_ac97_ops(NULL); |
| 505 | |||
| 506 | iounmap(s3c_ac97.regs); | ||
| 507 | |||
| 508 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 509 | if (mem_res) | ||
| 510 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
| 511 | 497 | ||
| 512 | return 0; | 498 | return 0; |
| 513 | } | 499 | } |
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/sh/hac.c b/sound/soc/sh/hac.c index af19f77b7bf0..0af2e4dfd139 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
| @@ -227,13 +227,12 @@ static void hac_ac97_coldrst(struct snd_ac97 *ac97) | |||
| 227 | hac_ac97_warmrst(ac97); | 227 | hac_ac97_warmrst(ac97); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | struct snd_ac97_bus_ops soc_ac97_ops = { | 230 | static struct snd_ac97_bus_ops hac_ac97_ops = { |
| 231 | .read = hac_ac97_read, | 231 | .read = hac_ac97_read, |
| 232 | .write = hac_ac97_write, | 232 | .write = hac_ac97_write, |
| 233 | .reset = hac_ac97_coldrst, | 233 | .reset = hac_ac97_coldrst, |
| 234 | .warm_reset = hac_ac97_warmrst, | 234 | .warm_reset = hac_ac97_warmrst, |
| 235 | }; | 235 | }; |
| 236 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 237 | 236 | ||
| 238 | static int hac_hw_params(struct snd_pcm_substream *substream, | 237 | static int hac_hw_params(struct snd_pcm_substream *substream, |
| 239 | struct snd_pcm_hw_params *params, | 238 | struct snd_pcm_hw_params *params, |
| @@ -316,6 +315,10 @@ static const struct snd_soc_component_driver sh4_hac_component = { | |||
| 316 | 315 | ||
| 317 | static int hac_soc_platform_probe(struct platform_device *pdev) | 316 | static int hac_soc_platform_probe(struct platform_device *pdev) |
| 318 | { | 317 | { |
| 318 | ret = snd_soc_set_ac97_ops(&hac_ac97_ops); | ||
| 319 | if (ret != 0) | ||
| 320 | return ret; | ||
| 321 | |||
| 319 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, | 322 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, |
| 320 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); |
| 321 | } | 324 | } |
| @@ -323,6 +326,7 @@ static int hac_soc_platform_probe(struct platform_device *pdev) | |||
| 323 | static int hac_soc_platform_remove(struct platform_device *pdev) | 326 | static int hac_soc_platform_remove(struct platform_device *pdev) |
| 324 | { | 327 | { |
| 325 | snd_soc_unregister_component(&pdev->dev); | 328 | snd_soc_unregister_component(&pdev->dev); |
| 329 | snd_soc_set_ac97_ops(NULL); | ||
| 326 | return 0; | 330 | return 0; |
| 327 | } | 331 | } |
| 328 | 332 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d56bbea6e75e..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; |
| @@ -2079,6 +2080,22 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
| 2079 | } | 2080 | } |
| 2080 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 2081 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
| 2081 | 2082 | ||
| 2083 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
| 2084 | |||
| 2085 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
| 2086 | { | ||
| 2087 | if (ops == soc_ac97_ops) | ||
| 2088 | return 0; | ||
| 2089 | |||
| 2090 | if (soc_ac97_ops && ops) | ||
| 2091 | return -EBUSY; | ||
| 2092 | |||
| 2093 | soc_ac97_ops = ops; | ||
| 2094 | |||
| 2095 | return 0; | ||
| 2096 | } | ||
| 2097 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
| 2098 | |||
| 2082 | /** | 2099 | /** |
| 2083 | * snd_soc_free_ac97_codec - free AC97 codec device | 2100 | * snd_soc_free_ac97_codec - free AC97 codec device |
| 2084 | * @codec: audio codec | 2101 | * @codec: audio codec |
| @@ -2219,29 +2236,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, | |||
| 2219 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); | 2236 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); |
| 2220 | 2237 | ||
| 2221 | /** | 2238 | /** |
| 2222 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters | ||
| 2223 | * @substream: the pcm substream | ||
| 2224 | * @hw: the hardware parameters | ||
| 2225 | * | ||
| 2226 | * Sets the substream runtime hardware parameters. | ||
| 2227 | */ | ||
| 2228 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | ||
| 2229 | const struct snd_pcm_hardware *hw) | ||
| 2230 | { | ||
| 2231 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 2232 | runtime->hw.info = hw->info; | ||
| 2233 | runtime->hw.formats = hw->formats; | ||
| 2234 | runtime->hw.period_bytes_min = hw->period_bytes_min; | ||
| 2235 | runtime->hw.period_bytes_max = hw->period_bytes_max; | ||
| 2236 | runtime->hw.periods_min = hw->periods_min; | ||
| 2237 | runtime->hw.periods_max = hw->periods_max; | ||
| 2238 | runtime->hw.buffer_bytes_max = hw->buffer_bytes_max; | ||
| 2239 | runtime->hw.fifo_size = hw->fifo_size; | ||
| 2240 | return 0; | ||
| 2241 | } | ||
| 2242 | EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); | ||
| 2243 | |||
| 2244 | /** | ||
| 2245 | * snd_soc_cnew - create new control | 2239 | * snd_soc_cnew - create new control |
| 2246 | * @_template: control template | 2240 | * @_template: control template |
| 2247 | * @data: control private data | 2241 | * @data: control private data |
| @@ -2259,7 +2253,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
| 2259 | struct snd_kcontrol_new template; | 2253 | struct snd_kcontrol_new template; |
| 2260 | struct snd_kcontrol *kcontrol; | 2254 | struct snd_kcontrol *kcontrol; |
| 2261 | char *name = NULL; | 2255 | char *name = NULL; |
| 2262 | int name_len; | ||
| 2263 | 2256 | ||
| 2264 | memcpy(&template, _template, sizeof(template)); | 2257 | memcpy(&template, _template, sizeof(template)); |
| 2265 | template.index = 0; | 2258 | template.index = 0; |
| @@ -2268,13 +2261,10 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
| 2268 | long_name = template.name; | 2261 | long_name = template.name; |
| 2269 | 2262 | ||
| 2270 | if (prefix) { | 2263 | if (prefix) { |
| 2271 | name_len = strlen(long_name) + strlen(prefix) + 2; | 2264 | name = kasprintf(GFP_KERNEL, "%s %s", prefix, long_name); |
| 2272 | name = kmalloc(name_len, GFP_KERNEL); | ||
| 2273 | if (!name) | 2265 | if (!name) |
| 2274 | return NULL; | 2266 | return NULL; |
| 2275 | 2267 | ||
| 2276 | snprintf(name, name_len, "%s %s", prefix, long_name); | ||
| 2277 | |||
| 2278 | template.name = name; | 2268 | template.name = name; |
| 2279 | } else { | 2269 | } else { |
| 2280 | template.name = long_name; | 2270 | template.name = long_name; |
| @@ -3586,14 +3576,16 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 3586 | * not both or neither. | 3576 | * not both or neither. |
| 3587 | */ | 3577 | */ |
| 3588 | if (!!link->codec_name == !!link->codec_of_node) { | 3578 | if (!!link->codec_name == !!link->codec_of_node) { |
| 3589 | dev_err(card->dev, "ASoC: Neither/both codec" | 3579 | dev_err(card->dev, |
| 3590 | " 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); | ||
| 3591 | return -EINVAL; | 3582 | return -EINVAL; |
| 3592 | } | 3583 | } |
| 3593 | /* Codec DAI name must be specified */ | 3584 | /* Codec DAI name must be specified */ |
| 3594 | if (!link->codec_dai_name) { | 3585 | if (!link->codec_dai_name) { |
| 3595 | dev_err(card->dev, "ASoC: codec_dai_name not" | 3586 | dev_err(card->dev, |
| 3596 | " set for %s\n", link->name); | 3587 | "ASoC: codec_dai_name not set for %s\n", |
| 3588 | link->name); | ||
| 3597 | return -EINVAL; | 3589 | return -EINVAL; |
| 3598 | } | 3590 | } |
| 3599 | 3591 | ||
| @@ -3602,8 +3594,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 3602 | * can be left unspecified, and a dummy platform will be used. | 3594 | * can be left unspecified, and a dummy platform will be used. |
| 3603 | */ | 3595 | */ |
| 3604 | if (link->platform_name && link->platform_of_node) { | 3596 | if (link->platform_name && link->platform_of_node) { |
| 3605 | dev_err(card->dev, "ASoC: Both platform name/of_node" | 3597 | dev_err(card->dev, |
| 3606 | " are set for %s\n", link->name); | 3598 | "ASoC: Both platform name/of_node are set for %s\n", |
| 3599 | link->name); | ||
| 3607 | return -EINVAL; | 3600 | return -EINVAL; |
| 3608 | } | 3601 | } |
| 3609 | 3602 | ||
| @@ -3613,8 +3606,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 3613 | * name alone.. | 3606 | * name alone.. |
| 3614 | */ | 3607 | */ |
| 3615 | if (link->cpu_name && link->cpu_of_node) { | 3608 | if (link->cpu_name && link->cpu_of_node) { |
| 3616 | dev_err(card->dev, "ASoC: Neither/both " | 3609 | dev_err(card->dev, |
| 3617 | "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); | ||
| 3618 | return -EINVAL; | 3612 | return -EINVAL; |
| 3619 | } | 3613 | } |
| 3620 | /* | 3614 | /* |
| @@ -3623,8 +3617,9 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 3623 | */ | 3617 | */ |
| 3624 | if (!link->cpu_dai_name && | 3618 | if (!link->cpu_dai_name && |
| 3625 | !(link->cpu_name || link->cpu_of_node)) { | 3619 | !(link->cpu_name || link->cpu_of_node)) { |
| 3626 | dev_err(card->dev, "ASoC: Neither cpu_dai_name nor " | 3620 | dev_err(card->dev, |
| 3627 | "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); | ||
| 3628 | return -EINVAL; | 3623 | return -EINVAL; |
| 3629 | } | 3624 | } |
| 3630 | } | 3625 | } |
| @@ -3728,8 +3723,9 @@ static inline char *fmt_multiple_name(struct device *dev, | |||
| 3728 | struct snd_soc_dai_driver *dai_drv) | 3723 | struct snd_soc_dai_driver *dai_drv) |
| 3729 | { | 3724 | { |
| 3730 | if (dai_drv->name == NULL) { | 3725 | if (dai_drv->name == NULL) { |
| 3731 | dev_err(dev, "ASoC: error - multiple DAI %s registered with" | 3726 | dev_err(dev, |
| 3732 | " no name\n", dev_name(dev)); | 3727 | "ASoC: error - multiple DAI %s registered with no name\n", |
| 3728 | dev_name(dev)); | ||
| 3733 | return NULL; | 3729 | return NULL; |
| 3734 | } | 3730 | } |
| 3735 | 3731 | ||
| @@ -3859,8 +3855,9 @@ static int snd_soc_register_dais(struct device *dev, | |||
| 3859 | 3855 | ||
| 3860 | list_for_each_entry(codec, &codec_list, list) { | 3856 | list_for_each_entry(codec, &codec_list, list) { |
| 3861 | if (codec->dev == dev) { | 3857 | if (codec->dev == dev) { |
| 3862 | dev_dbg(dev, "ASoC: Mapped DAI %s to " | 3858 | dev_dbg(dev, |
| 3863 | "CODEC %s\n", dai->name, codec->name); | 3859 | "ASoC: Mapped DAI %s to CODEC %s\n", |
| 3860 | dai->name, codec->name); | ||
| 3864 | dai->codec = codec; | 3861 | dai->codec = codec; |
| 3865 | break; | 3862 | break; |
| 3866 | } | 3863 | } |
| @@ -4296,8 +4293,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 4296 | 4293 | ||
| 4297 | num_routes = of_property_count_strings(np, propname); | 4294 | num_routes = of_property_count_strings(np, propname); |
| 4298 | if (num_routes < 0 || num_routes & 1) { | 4295 | if (num_routes < 0 || num_routes & 1) { |
| 4299 | dev_err(card->dev, "ASoC: Property '%s' does not exist or its" | 4296 | dev_err(card->dev, |
| 4300 | " length is not even\n", propname); | 4297 | "ASoC: Property '%s' does not exist or its length is not even\n", |
| 4298 | propname); | ||
| 4301 | return -EINVAL; | 4299 | return -EINVAL; |
| 4302 | } | 4300 | } |
| 4303 | num_routes /= 2; | 4301 | num_routes /= 2; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fe2be283508b..b94190820e8c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -367,11 +367,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
| 367 | val = soc_widget_read(w, e->reg); | 367 | val = soc_widget_read(w, e->reg); |
| 368 | item = (val >> e->shift_l) & e->mask; | 368 | item = (val >> e->shift_l) & e->mask; |
| 369 | 369 | ||
| 370 | p->connect = 0; | 370 | if (item < e->max && !strcmp(p->name, e->texts[item])) |
| 371 | for (i = 0; i < e->max; i++) { | 371 | p->connect = 1; |
| 372 | if (!(strcmp(p->name, e->texts[i])) && item == i) | 372 | else |
| 373 | p->connect = 1; | 373 | p->connect = 0; |
| 374 | } | ||
| 375 | } | 374 | } |
| 376 | break; | 375 | break; |
| 377 | case snd_soc_dapm_virt_mux: { | 376 | case snd_soc_dapm_virt_mux: { |
| @@ -401,11 +400,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
| 401 | break; | 400 | break; |
| 402 | } | 401 | } |
| 403 | 402 | ||
| 404 | p->connect = 0; | 403 | if (item < e->max && !strcmp(p->name, e->texts[item])) |
| 405 | for (i = 0; i < e->max; i++) { | 404 | p->connect = 1; |
| 406 | if (!(strcmp(p->name, e->texts[i])) && item == i) | 405 | else |
| 407 | p->connect = 1; | 406 | p->connect = 0; |
| 408 | } | ||
| 409 | } | 407 | } |
| 410 | break; | 408 | break; |
| 411 | /* does not affect routing - always connected */ | 409 | /* does not affect routing - always connected */ |
| @@ -509,6 +507,11 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, | |||
| 509 | return 0; | 507 | return 0; |
| 510 | } | 508 | } |
| 511 | 509 | ||
| 510 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) | ||
| 511 | { | ||
| 512 | kfree(kctl->private_data); | ||
| 513 | } | ||
| 514 | |||
| 512 | /* | 515 | /* |
| 513 | * 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, |
| 514 | * 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 |
| @@ -526,7 +529,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 526 | int wlistentries; | 529 | int wlistentries; |
| 527 | size_t wlistsize; | 530 | size_t wlistsize; |
| 528 | bool wname_in_long_name, kcname_in_long_name; | 531 | bool wname_in_long_name, kcname_in_long_name; |
| 529 | size_t name_len; | ||
| 530 | char *long_name; | 532 | char *long_name; |
| 531 | const char *name; | 533 | const char *name; |
| 532 | int ret; | 534 | int ret; |
| @@ -591,25 +593,19 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 591 | } | 593 | } |
| 592 | 594 | ||
| 593 | if (wname_in_long_name && kcname_in_long_name) { | 595 | if (wname_in_long_name && kcname_in_long_name) { |
| 594 | name_len = strlen(w->name) - prefix_len + 1 + | ||
| 595 | strlen(w->kcontrol_news[kci].name) + 1; | ||
| 596 | |||
| 597 | long_name = kmalloc(name_len, GFP_KERNEL); | ||
| 598 | if (long_name == NULL) { | ||
| 599 | kfree(wlist); | ||
| 600 | return -ENOMEM; | ||
| 601 | } | ||
| 602 | |||
| 603 | /* | 596 | /* |
| 604 | * The control will get a prefix from the control | 597 | * The control will get a prefix from the control |
| 605 | * creation process but we're also using the same | 598 | * creation process but we're also using the same |
| 606 | * prefix for widgets so cut the prefix off the | 599 | * prefix for widgets so cut the prefix off the |
| 607 | * front of the widget name. | 600 | * front of the widget name. |
| 608 | */ | 601 | */ |
| 609 | snprintf(long_name, name_len, "%s %s", | 602 | long_name = kasprintf(GFP_KERNEL, "%s %s", |
| 610 | w->name + prefix_len, | 603 | w->name + prefix_len, |
| 611 | w->kcontrol_news[kci].name); | 604 | w->kcontrol_news[kci].name); |
| 612 | long_name[name_len - 1] = '\0'; | 605 | if (long_name == NULL) { |
| 606 | kfree(wlist); | ||
| 607 | return -ENOMEM; | ||
| 608 | } | ||
| 613 | 609 | ||
| 614 | name = long_name; | 610 | name = long_name; |
| 615 | } else if (wname_in_long_name) { | 611 | } else if (wname_in_long_name) { |
| @@ -622,17 +618,16 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 622 | 618 | ||
| 623 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, | 619 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, |
| 624 | prefix); | 620 | prefix); |
| 621 | kcontrol->private_free = dapm_kcontrol_free; | ||
| 622 | kfree(long_name); | ||
| 625 | ret = snd_ctl_add(card, kcontrol); | 623 | ret = snd_ctl_add(card, kcontrol); |
| 626 | if (ret < 0) { | 624 | if (ret < 0) { |
| 627 | dev_err(dapm->dev, | 625 | dev_err(dapm->dev, |
| 628 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", | 626 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", |
| 629 | w->name, name, ret); | 627 | w->name, name, ret); |
| 630 | kfree(wlist); | 628 | kfree(wlist); |
| 631 | kfree(long_name); | ||
| 632 | return ret; | 629 | return ret; |
| 633 | } | 630 | } |
| 634 | |||
| 635 | path->long_name = long_name; | ||
| 636 | } | 631 | } |
| 637 | 632 | ||
| 638 | kcontrol->private_data = wlist; | 633 | kcontrol->private_data = wlist; |
| @@ -1272,6 +1267,14 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, | |||
| 1272 | ev_name = "POST_PMD"; | 1267 | ev_name = "POST_PMD"; |
| 1273 | power = 0; | 1268 | power = 0; |
| 1274 | 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; | ||
| 1275 | default: | 1278 | default: |
| 1276 | BUG(); | 1279 | BUG(); |
| 1277 | return; | 1280 | return; |
| @@ -1732,6 +1735,14 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
| 1732 | &async_domain); | 1735 | &async_domain); |
| 1733 | async_synchronize_full_domain(&async_domain); | 1736 | async_synchronize_full_domain(&async_domain); |
| 1734 | 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 | |||
| 1735 | /* Power down widgets first; try to avoid amplifying pops. */ | 1746 | /* Power down widgets first; try to avoid amplifying pops. */ |
| 1736 | dapm_seq_run(dapm, &down_list, event, false); | 1747 | dapm_seq_run(dapm, &down_list, event, false); |
| 1737 | 1748 | ||
| @@ -2096,6 +2107,14 @@ static void snd_soc_dapm_sys_remove(struct device *dev) | |||
| 2096 | device_remove_file(dev, &dev_attr_dapm_widget); | 2107 | device_remove_file(dev, &dev_attr_dapm_widget); |
| 2097 | } | 2108 | } |
| 2098 | 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 | |||
| 2099 | /* free all dapm widgets and resources */ | 2118 | /* free all dapm widgets and resources */ |
| 2100 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | 2119 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) |
| 2101 | { | 2120 | { |
| @@ -2111,20 +2130,12 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | |||
| 2111 | * While removing the path, remove reference to it from both | 2130 | * While removing the path, remove reference to it from both |
| 2112 | * source and sink widgets so that path is removed only once. | 2131 | * source and sink widgets so that path is removed only once. |
| 2113 | */ | 2132 | */ |
| 2114 | 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) |
| 2115 | list_del(&p->list_sink); | 2134 | dapm_free_path(p); |
| 2116 | list_del(&p->list_source); | 2135 | |
| 2117 | list_del(&p->list); | 2136 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) |
| 2118 | kfree(p->long_name); | 2137 | dapm_free_path(p); |
| 2119 | kfree(p); | 2138 | |
| 2120 | } | ||
| 2121 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { | ||
| 2122 | list_del(&p->list_sink); | ||
| 2123 | list_del(&p->list_source); | ||
| 2124 | list_del(&p->list); | ||
| 2125 | kfree(p->long_name); | ||
| 2126 | kfree(p); | ||
| 2127 | } | ||
| 2128 | kfree(w->kcontrols); | 2139 | kfree(w->kcontrols); |
| 2129 | kfree(w->name); | 2140 | kfree(w->name); |
| 2130 | kfree(w); | 2141 | kfree(w); |
| @@ -2400,10 +2411,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
| 2400 | dapm_mark_dirty(path->source, "Route removed"); | 2411 | dapm_mark_dirty(path->source, "Route removed"); |
| 2401 | dapm_mark_dirty(path->sink, "Route removed"); | 2412 | dapm_mark_dirty(path->sink, "Route removed"); |
| 2402 | 2413 | ||
| 2403 | list_del(&path->list); | 2414 | dapm_free_path(path); |
| 2404 | list_del(&path->list_sink); | ||
| 2405 | list_del(&path->list_source); | ||
| 2406 | kfree(path); | ||
| 2407 | } else { | 2415 | } else { |
| 2408 | 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", |
| 2409 | source, sink); | 2417 | source, sink); |
| @@ -3057,7 +3065,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
| 3057 | const struct snd_soc_dapm_widget *widget) | 3065 | const struct snd_soc_dapm_widget *widget) |
| 3058 | { | 3066 | { |
| 3059 | struct snd_soc_dapm_widget *w; | 3067 | struct snd_soc_dapm_widget *w; |
| 3060 | size_t name_len; | ||
| 3061 | int ret; | 3068 | int ret; |
| 3062 | 3069 | ||
| 3063 | if ((w = dapm_cnew_widget(widget)) == NULL) | 3070 | if ((w = dapm_cnew_widget(widget)) == NULL) |
| @@ -3098,19 +3105,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
| 3098 | break; | 3105 | break; |
| 3099 | } | 3106 | } |
| 3100 | 3107 | ||
| 3101 | name_len = strlen(widget->name) + 1; | ||
| 3102 | if (dapm->codec && dapm->codec->name_prefix) | 3108 | if (dapm->codec && dapm->codec->name_prefix) |
| 3103 | name_len += 1 + strlen(dapm->codec->name_prefix); | 3109 | w->name = kasprintf(GFP_KERNEL, "%s %s", |
| 3104 | 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 | |||
| 3105 | if (w->name == NULL) { | 3114 | if (w->name == NULL) { |
| 3106 | kfree(w); | 3115 | kfree(w); |
| 3107 | return NULL; | 3116 | return NULL; |
| 3108 | } | 3117 | } |
| 3109 | if (dapm->codec && dapm->codec->name_prefix) | ||
| 3110 | snprintf((char *)w->name, name_len, "%s %s", | ||
| 3111 | dapm->codec->name_prefix, widget->name); | ||
| 3112 | else | ||
| 3113 | snprintf((char *)w->name, name_len, "%s", widget->name); | ||
| 3114 | 3118 | ||
| 3115 | switch (w->id) { | 3119 | switch (w->id) { |
| 3116 | 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/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 2f70ea7f6618..f52eab6d2231 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
| @@ -142,13 +142,12 @@ static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, | |||
| 142 | } while (!time_after(jiffies, timeout)); | 142 | } while (!time_after(jiffies, timeout)); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | struct snd_ac97_bus_ops soc_ac97_ops = { | 145 | static struct snd_ac97_bus_ops tegra20_ac97_ops = { |
| 146 | .read = tegra20_ac97_codec_read, | 146 | .read = tegra20_ac97_codec_read, |
| 147 | .write = tegra20_ac97_codec_write, | 147 | .write = tegra20_ac97_codec_write, |
| 148 | .reset = tegra20_ac97_codec_reset, | 148 | .reset = tegra20_ac97_codec_reset, |
| 149 | .warm_reset = tegra20_ac97_codec_warm_reset, | 149 | .warm_reset = tegra20_ac97_codec_warm_reset, |
| 150 | }; | 150 | }; |
| 151 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 152 | 151 | ||
| 153 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) | 152 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) |
| 154 | { | 153 | { |
| @@ -327,7 +326,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 327 | } | 326 | } |
| 328 | dev_set_drvdata(&pdev->dev, ac97); | 327 | dev_set_drvdata(&pdev->dev, ac97); |
| 329 | 328 | ||
| 330 | ac97->clk_ac97 = clk_get(&pdev->dev, NULL); | 329 | ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); |
| 331 | if (IS_ERR(ac97->clk_ac97)) { | 330 | if (IS_ERR(ac97->clk_ac97)) { |
| 332 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); | 331 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); |
| 333 | ret = PTR_ERR(ac97->clk_ac97); | 332 | ret = PTR_ERR(ac97->clk_ac97); |
| @@ -341,18 +340,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 341 | goto err_clk_put; | 340 | goto err_clk_put; |
| 342 | } | 341 | } |
| 343 | 342 | ||
| 344 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | 343 | regs = devm_ioremap_resource(&pdev->dev, mem); |
| 345 | resource_size(mem), DRV_NAME); | 344 | if (IS_ERR(regs)) { |
| 346 | if (!memregion) { | 345 | ret = PTR_ERR(regs); |
| 347 | dev_err(&pdev->dev, "Memory region already claimed\n"); | 346 | dev_err(&pdev->dev, "ioremap failed: %d\n", ret); |
| 348 | ret = -EBUSY; | ||
| 349 | goto err_clk_put; | ||
| 350 | } | ||
| 351 | |||
| 352 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
| 353 | if (!regs) { | ||
| 354 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
| 355 | ret = -ENOMEM; | ||
| 356 | goto err_clk_put; | 347 | goto err_clk_put; |
| 357 | } | 348 | } |
| 358 | 349 | ||
| @@ -403,23 +394,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 403 | ac97->capture_dma_data.maxburst = 4; | 394 | ac97->capture_dma_data.maxburst = 4; |
| 404 | ac97->capture_dma_data.slave_id = of_dma[0]; | 395 | ac97->capture_dma_data.slave_id = of_dma[0]; |
| 405 | 396 | ||
| 406 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
| 407 | &tegra20_ac97_dai, 1); | ||
| 408 | if (ret) { | ||
| 409 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
| 410 | ret = -ENOMEM; | ||
| 411 | goto err_clk_put; | ||
| 412 | } | ||
| 413 | |||
| 414 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
| 415 | if (ret) { | ||
| 416 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
| 417 | goto err_unregister_component; | ||
| 418 | } | ||
| 419 | |||
| 420 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); | 397 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); |
| 421 | if (ret) | 398 | if (ret) |
| 422 | goto err_unregister_pcm; | 399 | goto err_clk_put; |
| 423 | 400 | ||
| 424 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); | 401 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); |
| 425 | if (ret) | 402 | if (ret) |
| @@ -431,20 +408,40 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 431 | goto err_asoc_utils_fini; | 408 | goto err_asoc_utils_fini; |
| 432 | } | 409 | } |
| 433 | 410 | ||
| 411 | ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); | ||
| 412 | if (ret) { | ||
| 413 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
| 414 | goto err_asoc_utils_fini; | ||
| 415 | } | ||
| 416 | |||
| 417 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
| 418 | &tegra20_ac97_dai, 1); | ||
| 419 | if (ret) { | ||
| 420 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
| 421 | ret = -ENOMEM; | ||
| 422 | goto err_asoc_utils_fini; | ||
| 423 | } | ||
| 424 | |||
| 425 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
| 426 | if (ret) { | ||
| 427 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
| 428 | goto err_unregister_component; | ||
| 429 | } | ||
| 430 | |||
| 434 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ | 431 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ |
| 435 | workdata = ac97; | 432 | workdata = ac97; |
| 436 | 433 | ||
| 437 | return 0; | 434 | return 0; |
| 438 | 435 | ||
| 439 | err_asoc_utils_fini: | ||
| 440 | tegra_asoc_utils_fini(&ac97->util_data); | ||
| 441 | err_unregister_pcm: | 436 | err_unregister_pcm: |
| 442 | tegra_pcm_platform_unregister(&pdev->dev); | 437 | tegra_pcm_platform_unregister(&pdev->dev); |
| 443 | err_unregister_component: | 438 | err_unregister_component: |
| 444 | snd_soc_unregister_component(&pdev->dev); | 439 | snd_soc_unregister_component(&pdev->dev); |
| 440 | err_asoc_utils_fini: | ||
| 441 | tegra_asoc_utils_fini(&ac97->util_data); | ||
| 445 | err_clk_put: | 442 | err_clk_put: |
| 446 | clk_put(ac97->clk_ac97); | ||
| 447 | err: | 443 | err: |
| 444 | snd_soc_set_ac97_ops(NULL); | ||
| 448 | return ret; | 445 | return ret; |
| 449 | } | 446 | } |
| 450 | 447 | ||
| @@ -458,7 +455,8 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) | |||
| 458 | tegra_asoc_utils_fini(&ac97->util_data); | 455 | tegra_asoc_utils_fini(&ac97->util_data); |
| 459 | 456 | ||
| 460 | clk_disable_unprepare(ac97->clk_ac97); | 457 | clk_disable_unprepare(ac97->clk_ac97); |
| 461 | clk_put(ac97->clk_ac97); | 458 | |
| 459 | snd_soc_set_ac97_ops(NULL); | ||
| 462 | 460 | ||
| 463 | return 0; | 461 | return 0; |
| 464 | } | 462 | } |
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/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 8a2840304d28..4bcce8a3cded 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
| @@ -119,12 +119,11 @@ static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | /* AC97 controller operations */ | 121 | /* AC97 controller operations */ |
| 122 | struct snd_ac97_bus_ops soc_ac97_ops = { | 122 | static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { |
| 123 | .read = txx9aclc_ac97_read, | 123 | .read = txx9aclc_ac97_read, |
| 124 | .write = txx9aclc_ac97_write, | 124 | .write = txx9aclc_ac97_write, |
| 125 | .reset = txx9aclc_ac97_cold_reset, | 125 | .reset = txx9aclc_ac97_cold_reset, |
| 126 | }; | 126 | }; |
| 127 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
| 128 | 127 | ||
| 129 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) | 128 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) |
| 130 | { | 129 | { |
| @@ -188,9 +187,9 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
| 188 | if (!r) | 187 | if (!r) |
| 189 | return -EBUSY; | 188 | return -EBUSY; |
| 190 | 189 | ||
| 191 | if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), | 190 | drvdata->base = devm_ioremap_resource(&pdev->dev, r); |
| 192 | dev_name(&pdev->dev))) | 191 | if (IS_ERR(drvdata->base)) |
| 193 | return -EBUSY; | 192 | return PTR_ERR(drvdata->base); |
| 194 | 193 | ||
| 195 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | 194 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); |
| 196 | if (!drvdata) | 195 | if (!drvdata) |
| @@ -201,14 +200,15 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
| 201 | r->start >= TXX9_DIRECTMAP_BASE && | 200 | r->start >= TXX9_DIRECTMAP_BASE && |
| 202 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) | 201 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) |
| 203 | drvdata->physbase |= 0xf00000000ull; | 202 | drvdata->physbase |= 0xf00000000ull; |
| 204 | drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); | ||
| 205 | if (!drvdata->base) | ||
| 206 | return -EBUSY; | ||
| 207 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, | 203 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, |
| 208 | 0, dev_name(&pdev->dev), drvdata); | 204 | 0, dev_name(&pdev->dev), drvdata); |
| 209 | if (err < 0) | 205 | if (err < 0) |
| 210 | return err; | 206 | return err; |
| 211 | 207 | ||
| 208 | err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); | ||
| 209 | if (err < 0) | ||
| 210 | return err; | ||
| 211 | |||
| 212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, | 212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, |
| 213 | &txx9aclc_ac97_dai, 1); | 213 | &txx9aclc_ac97_dai, 1); |
| 214 | } | 214 | } |
| @@ -216,6 +216,7 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
| 216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) | 216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
| 217 | { | 217 | { |
| 218 | snd_soc_unregister_component(&pdev->dev); | 218 | snd_soc_unregister_component(&pdev->dev); |
| 219 | snd_soc_set_ac97_ops(NULL); | ||
| 219 | return 0; | 220 | return 0; |
| 220 | } | 221 | } |
| 221 | 222 | ||
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/mixer_quirks.c b/sound/usb/mixer_quirks.c index ebe91440a068..d42a584cf829 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | * Alan Cox (alan@lxorguk.ukuu.org.uk) | 9 | * Alan Cox (alan@lxorguk.ukuu.org.uk) |
| 10 | * Thomas Sailer (sailer@ife.ee.ethz.ch) | 10 | * Thomas Sailer (sailer@ife.ee.ethz.ch) |
| 11 | * | 11 | * |
| 12 | * Audio Advantage Micro II support added by: | ||
| 13 | * Przemek Rudy (prudy1@o2.pl) | ||
| 12 | * | 14 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 15 | * 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 | 16 | * it under the terms of the GNU General Public License as published by |
| @@ -30,6 +32,7 @@ | |||
| 30 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
| 31 | #include <linux/usb/audio.h> | 33 | #include <linux/usb/audio.h> |
| 32 | 34 | ||
| 35 | #include <sound/asoundef.h> | ||
| 33 | #include <sound/core.h> | 36 | #include <sound/core.h> |
| 34 | #include <sound/control.h> | 37 | #include <sound/control.h> |
| 35 | #include <sound/hwdep.h> | 38 | #include <sound/hwdep.h> |
| @@ -1315,6 +1318,211 @@ static struct std_mono_table ebox44_table[] = { | |||
| 1315 | {} | 1318 | {} |
| 1316 | }; | 1319 | }; |
| 1317 | 1320 | ||
| 1321 | /* Audio Advantage Micro II findings: | ||
| 1322 | * | ||
| 1323 | * Mapping spdif AES bits to vendor register.bit: | ||
| 1324 | * AES0: [0 0 0 0 2.3 2.2 2.1 2.0] - default 0x00 | ||
| 1325 | * AES1: [3.3 3.2.3.1.3.0 2.7 2.6 2.5 2.4] - default: 0x01 | ||
| 1326 | * AES2: [0 0 0 0 0 0 0 0] | ||
| 1327 | * AES3: [0 0 0 0 0 0 x 0] - 'x' bit is set basing on standard usb request | ||
| 1328 | * (UAC_EP_CS_ATTR_SAMPLE_RATE) for Audio Devices | ||
| 1329 | * | ||
| 1330 | * power on values: | ||
| 1331 | * r2: 0x10 | ||
| 1332 | * r3: 0x20 (b7 is zeroed just before playback (except IEC61937) and set | ||
| 1333 | * just after it to 0xa0, presumably it disables/mutes some analog | ||
| 1334 | * parts when there is no audio.) | ||
| 1335 | * r9: 0x28 | ||
| 1336 | * | ||
| 1337 | * Optical transmitter on/off: | ||
| 1338 | * vendor register.bit: 9.1 | ||
| 1339 | * 0 - on (0x28 register value) | ||
| 1340 | * 1 - off (0x2a register value) | ||
| 1341 | * | ||
| 1342 | */ | ||
| 1343 | static int snd_microii_spdif_info(struct snd_kcontrol *kcontrol, | ||
| 1344 | struct snd_ctl_elem_info *uinfo) | ||
| 1345 | { | ||
| 1346 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
| 1347 | uinfo->count = 1; | ||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, | ||
| 1352 | struct snd_ctl_elem_value *ucontrol) | ||
| 1353 | { | ||
| 1354 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
| 1355 | int err; | ||
| 1356 | struct usb_interface *iface; | ||
| 1357 | struct usb_host_interface *alts; | ||
| 1358 | unsigned int ep; | ||
| 1359 | unsigned char data[3]; | ||
| 1360 | int rate; | ||
| 1361 | |||
| 1362 | ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff; | ||
| 1363 | ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff; | ||
| 1364 | ucontrol->value.iec958.status[2] = 0x00; | ||
| 1365 | |||
| 1366 | /* use known values for that card: interface#1 altsetting#1 */ | ||
| 1367 | iface = usb_ifnum_to_if(mixer->chip->dev, 1); | ||
| 1368 | alts = &iface->altsetting[1]; | ||
| 1369 | ep = get_endpoint(alts, 0)->bEndpointAddress; | ||
| 1370 | |||
| 1371 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 1372 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
| 1373 | UAC_GET_CUR, | ||
| 1374 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, | ||
| 1375 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, | ||
| 1376 | ep, | ||
| 1377 | data, | ||
| 1378 | sizeof(data)); | ||
| 1379 | if (err < 0) | ||
| 1380 | goto end; | ||
| 1381 | |||
| 1382 | rate = data[0] | (data[1] << 8) | (data[2] << 16); | ||
| 1383 | ucontrol->value.iec958.status[3] = (rate == 48000) ? | ||
| 1384 | IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100; | ||
| 1385 | |||
| 1386 | err = 0; | ||
| 1387 | end: | ||
| 1388 | return err; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, | ||
| 1392 | struct snd_ctl_elem_value *ucontrol) | ||
| 1393 | { | ||
| 1394 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
| 1395 | int err; | ||
| 1396 | u8 reg; | ||
| 1397 | unsigned long priv_backup = kcontrol->private_value; | ||
| 1398 | |||
| 1399 | reg = ((ucontrol->value.iec958.status[1] & 0x0f) << 4) | | ||
| 1400 | (ucontrol->value.iec958.status[0] & 0x0f); | ||
| 1401 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 1402 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
| 1403 | UAC_SET_CUR, | ||
| 1404 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
| 1405 | reg, | ||
| 1406 | 2, | ||
| 1407 | NULL, | ||
| 1408 | 0); | ||
| 1409 | if (err < 0) | ||
| 1410 | goto end; | ||
| 1411 | |||
| 1412 | kcontrol->private_value &= 0xfffff0f0; | ||
| 1413 | kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0x0f) << 8; | ||
| 1414 | kcontrol->private_value |= (ucontrol->value.iec958.status[0] & 0x0f); | ||
| 1415 | |||
| 1416 | reg = (ucontrol->value.iec958.status[0] & IEC958_AES0_NONAUDIO) ? | ||
| 1417 | 0xa0 : 0x20; | ||
| 1418 | reg |= (ucontrol->value.iec958.status[1] >> 4) & 0x0f; | ||
| 1419 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 1420 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
| 1421 | UAC_SET_CUR, | ||
| 1422 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
| 1423 | reg, | ||
| 1424 | 3, | ||
| 1425 | NULL, | ||
| 1426 | 0); | ||
| 1427 | if (err < 0) | ||
| 1428 | goto end; | ||
| 1429 | |||
| 1430 | kcontrol->private_value &= 0xffff0fff; | ||
| 1431 | kcontrol->private_value |= (ucontrol->value.iec958.status[1] & 0xf0) << 8; | ||
| 1432 | |||
| 1433 | /* The frequency bits in AES3 cannot be set via register access. */ | ||
| 1434 | |||
| 1435 | /* Silently ignore any bits from the request that cannot be set. */ | ||
| 1436 | |||
| 1437 | err = (priv_backup != kcontrol->private_value); | ||
| 1438 | end: | ||
| 1439 | return err; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | static int snd_microii_spdif_mask_get(struct snd_kcontrol *kcontrol, | ||
| 1443 | struct snd_ctl_elem_value *ucontrol) | ||
| 1444 | { | ||
| 1445 | ucontrol->value.iec958.status[0] = 0x0f; | ||
| 1446 | ucontrol->value.iec958.status[1] = 0xff; | ||
| 1447 | ucontrol->value.iec958.status[2] = 0x00; | ||
| 1448 | ucontrol->value.iec958.status[3] = 0x00; | ||
| 1449 | |||
| 1450 | return 0; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | static int snd_microii_spdif_switch_get(struct snd_kcontrol *kcontrol, | ||
| 1454 | struct snd_ctl_elem_value *ucontrol) | ||
| 1455 | { | ||
| 1456 | ucontrol->value.integer.value[0] = !(kcontrol->private_value & 0x02); | ||
| 1457 | |||
| 1458 | return 0; | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, | ||
| 1462 | struct snd_ctl_elem_value *ucontrol) | ||
| 1463 | { | ||
| 1464 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
| 1465 | int err; | ||
| 1466 | u8 reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a; | ||
| 1467 | |||
| 1468 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 1469 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
| 1470 | UAC_SET_CUR, | ||
| 1471 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
| 1472 | reg, | ||
| 1473 | 9, | ||
| 1474 | NULL, | ||
| 1475 | 0); | ||
| 1476 | |||
| 1477 | if (!err) { | ||
| 1478 | err = (reg != (kcontrol->private_value & 0x0ff)); | ||
| 1479 | if (err) | ||
| 1480 | kcontrol->private_value = reg; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | return err; | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { | ||
| 1487 | { | ||
| 1488 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 1489 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), | ||
| 1490 | .info = snd_microii_spdif_info, | ||
| 1491 | .get = snd_microii_spdif_default_get, | ||
| 1492 | .put = snd_microii_spdif_default_put, | ||
| 1493 | .private_value = 0x00000100UL,/* reset value */ | ||
| 1494 | }, | ||
| 1495 | { | ||
| 1496 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
| 1497 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 1498 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), | ||
| 1499 | .info = snd_microii_spdif_info, | ||
| 1500 | .get = snd_microii_spdif_mask_get, | ||
| 1501 | }, | ||
| 1502 | { | ||
| 1503 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1504 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), | ||
| 1505 | .info = snd_ctl_boolean_mono_info, | ||
| 1506 | .get = snd_microii_spdif_switch_get, | ||
| 1507 | .put = snd_microii_spdif_switch_put, | ||
| 1508 | .private_value = 0x00000028UL,/* reset value */ | ||
| 1509 | } | ||
| 1510 | }; | ||
| 1511 | |||
| 1512 | static int snd_microii_controls_create(struct usb_mixer_interface *mixer) | ||
| 1513 | { | ||
| 1514 | int err, i; | ||
| 1515 | |||
| 1516 | for (i = 0; i < ARRAY_SIZE(snd_microii_mixer_spdif); ++i) { | ||
| 1517 | err = snd_ctl_add(mixer->chip->card, | ||
| 1518 | snd_ctl_new1(&snd_microii_mixer_spdif[i], mixer)); | ||
| 1519 | if (err < 0) | ||
| 1520 | return err; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | return err; | ||
| 1524 | } | ||
| 1525 | |||
| 1318 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 1526 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
| 1319 | { | 1527 | { |
| 1320 | int err = 0; | 1528 | int err = 0; |
| @@ -1353,6 +1561,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
| 1353 | err = snd_xonar_u1_controls_create(mixer); | 1561 | err = snd_xonar_u1_controls_create(mixer); |
| 1354 | break; | 1562 | break; |
| 1355 | 1563 | ||
| 1564 | case USB_ID(0x0d8c, 0x0103): /* Audio Advantage Micro II */ | ||
| 1565 | err = snd_microii_controls_create(mixer); | ||
| 1566 | break; | ||
| 1567 | |||
| 1356 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ | 1568 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ |
| 1357 | err = snd_nativeinstruments_create_mixer(mixer, | 1569 | err = snd_nativeinstruments_create_mixer(mixer, |
| 1358 | snd_nativeinstruments_ta6_mixers, | 1570 | snd_nativeinstruments_ta6_mixers, |
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..f5f0595ef9c7 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) { | ||
| 1940 | /* .vendor_name = "ROLAND", */ | ||
| 1941 | /* .product_name = "UM-ONE", */ | ||
| 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) { | 1654 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
| 1953 | /* .vendor_name = "BOSS", */ | 1655 | /* .vendor_name = "Roland", */ |
| 1954 | /* .product_name = "BR-800", */ | 1656 | /* .product_name = "QUAD-CAPTURE", */ |
| 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 | ||
| @@ -3434,4 +3119,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
| 3434 | } | 3119 | } |
| 3435 | }, | 3120 | }, |
| 3436 | 3121 | ||
| 3122 | { | ||
| 3123 | /* | ||
| 3124 | * The original product_name is "USB Sound Device", however this name | ||
| 3125 | * is also used by the CM106 based cards, so make it unique. | ||
| 3126 | */ | ||
| 3127 | USB_DEVICE(0x0d8c, 0x0103), | ||
| 3128 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
| 3129 | .product_name = "Audio Advantage MicroII", | ||
| 3130 | .ifnum = QUIRK_NO_INTERFACE | ||
| 3131 | } | ||
| 3132 | }, | ||
| 3133 | |||
| 3437 | #undef USB_DEVICE_VENDOR_SPEC | 3134 | #undef USB_DEVICE_VENDOR_SPEC |
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; |
