diff options
542 files changed, 13471 insertions, 4169 deletions
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl index 6a8b7158697f..9c92bb879b6d 100644 --- a/Documentation/DocBook/media_api.tmpl +++ b/Documentation/DocBook/media_api.tmpl | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
| 2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | 2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
| 3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ | 3 | "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ |
| 4 | <!ENTITY % media-entities SYSTEM "./media-entities.tmpl"> %media-entities; | 4 | <!ENTITY % media-entities SYSTEM "./media-entities.tmpl"> %media-entities; |
| 5 | <!ENTITY media-indices SYSTEM "./media-indices.tmpl"> | 5 | <!ENTITY media-indices SYSTEM "./media-indices.tmpl"> |
| 6 | 6 | ||
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt index a1ee681942cc..6113f9275f42 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | Required properties : | 4 | Required properties : |
| 5 | 5 | ||
| 6 | - reg : Offset and length of the register set for the device | 6 | - reg : Offset and length of the register set for the device |
| 7 | - compatible : Should be "marvell,mv64xxx-i2c" | 7 | - compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c" |
| 8 | - interrupts : The interrupt number | 8 | - interrupts : The interrupt number |
| 9 | 9 | ||
| 10 | Optional properties : | 10 | Optional properties : |
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt index 38e51ad2e07e..a45ae08c8ed1 100644 --- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt +++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt | |||
| @@ -7,9 +7,30 @@ Required properties: | |||
| 7 | - reg: Should contain SSC registers location and length | 7 | - reg: Should contain SSC registers location and length |
| 8 | - interrupts: Should contain SSC interrupt | 8 | - interrupts: Should contain SSC interrupt |
| 9 | 9 | ||
| 10 | Example: | 10 | |
| 11 | Required properties for devices compatible with "atmel,at91sam9g45-ssc": | ||
| 12 | - dmas: DMA specifier, consisting of a phandle to DMA controller node, | ||
| 13 | the memory interface and SSC DMA channel ID (for tx and rx). | ||
| 14 | See Documentation/devicetree/bindings/dma/atmel-dma.txt for details. | ||
| 15 | - dma-names: Must be "tx", "rx". | ||
| 16 | |||
| 17 | Examples: | ||
| 18 | - PDC transfer: | ||
| 11 | ssc0: ssc@fffbc000 { | 19 | ssc0: ssc@fffbc000 { |
| 12 | compatible = "atmel,at91rm9200-ssc"; | 20 | compatible = "atmel,at91rm9200-ssc"; |
| 13 | reg = <0xfffbc000 0x4000>; | 21 | reg = <0xfffbc000 0x4000>; |
| 14 | interrupts = <14 4 5>; | 22 | interrupts = <14 4 5>; |
| 15 | }; | 23 | }; |
| 24 | |||
| 25 | - DMA transfer: | ||
| 26 | ssc0: ssc@f0010000 { | ||
| 27 | compatible = "atmel,at91sam9g45-ssc"; | ||
| 28 | reg = <0xf0010000 0x4000>; | ||
| 29 | interrupts = <28 4 5>; | ||
| 30 | dmas = <&dma0 1 13>, | ||
| 31 | <&dma0 1 14>; | ||
| 32 | dma-names = "tx", "rx"; | ||
| 33 | pinctrl-names = "default"; | ||
| 34 | pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; | ||
| 35 | status = "disabled"; | ||
| 36 | }; | ||
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt index d5a308629c57..30b0581bb1ce 100644 --- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt +++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt | |||
| @@ -31,9 +31,8 @@ Optional nodes: | |||
| 31 | Optional sub-node properties: | 31 | Optional sub-node properties: |
| 32 | ti,warm-reset - maintain voltage during warm reset(boolean) | 32 | ti,warm-reset - maintain voltage during warm reset(boolean) |
| 33 | ti,roof-floor - control voltage selection by pin(boolean) | 33 | ti,roof-floor - control voltage selection by pin(boolean) |
| 34 | ti,sleep-mode - mode to adopt in pmic sleep 0 - off, 1 - auto, | 34 | ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto, |
| 35 | 2 - eco, 3 - forced pwm | 35 | 2 - eco, 3 - forced pwm |
| 36 | ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us | ||
| 37 | ti,smps-range - OTP has the wrong range set for the hardware so override | 36 | ti,smps-range - OTP has the wrong range set for the hardware so override |
| 38 | 0 - low range, 1 - high range. | 37 | 0 - low range, 1 - high range. |
| 39 | 38 | ||
| @@ -59,7 +58,6 @@ pmic { | |||
| 59 | ti,warm-reset; | 58 | ti,warm-reset; |
| 60 | ti,roof-floor; | 59 | ti,roof-floor; |
| 61 | ti,mode-sleep = <0>; | 60 | ti,mode-sleep = <0>; |
| 62 | ti,tstep = <0>; | ||
| 63 | ti,smps-range = <1>; | 61 | ti,smps-range = <1>; |
| 64 | }; | 62 | }; |
| 65 | 63 | ||
diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt new file mode 100644 index 000000000000..669b8140dd79 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | Device tree bindings for Marvell PXA SSP ports | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Must be one of | ||
| 6 | mrvl,pxa25x-ssp | ||
| 7 | mvrl,pxa25x-nssp | ||
| 8 | mrvl,pxa27x-ssp | ||
| 9 | mrvl,pxa3xx-ssp | ||
| 10 | mvrl,pxa168-ssp | ||
| 11 | mrvl,pxa910-ssp | ||
| 12 | mrvl,ce4100-ssp | ||
| 13 | mrvl,lpss-ssp | ||
| 14 | |||
| 15 | - reg: The memory base | ||
| 16 | - dmas: Two dma phandles, one for rx, one for tx | ||
| 17 | - dma-names: Must be "rx", "tx" | ||
| 18 | |||
| 19 | |||
| 20 | Example for PXA3xx: | ||
| 21 | |||
| 22 | ssp0: ssp@41000000 { | ||
| 23 | compatible = "mrvl,pxa3xx-ssp"; | ||
| 24 | reg = <0x41000000 0x40>; | ||
| 25 | ssp-id = <1>; | ||
| 26 | interrupts = <24>; | ||
| 27 | clock-names = "pxa27x-ssp.0"; | ||
| 28 | dmas = <&dma 13 | ||
| 29 | &dma 14>; | ||
| 30 | dma-names = "rx", "tx"; | ||
| 31 | }; | ||
| 32 | |||
| 33 | ssp1: ssp@41700000 { | ||
| 34 | compatible = "mrvl,pxa3xx-ssp"; | ||
| 35 | reg = <0x41700000 0x40>; | ||
| 36 | ssp-id = <2>; | ||
| 37 | interrupts = <16>; | ||
| 38 | clock-names = "pxa27x-ssp.1"; | ||
| 39 | dmas = <&dma 15 | ||
| 40 | &dma 16>; | ||
| 41 | dma-names = "rx", "tx"; | ||
| 42 | }; | ||
| 43 | |||
| 44 | ssp2: ssp@41900000 { | ||
| 45 | compatibl3 = "mrvl,pxa3xx-ssp"; | ||
| 46 | reg = <0x41900000 0x40>; | ||
| 47 | ssp-id = <3>; | ||
| 48 | interrupts = <0>; | ||
| 49 | clock-names = "pxa27x-ssp.2"; | ||
| 50 | dmas = <&dma 66 | ||
| 51 | &dma 67>; | ||
| 52 | dma-names = "rx", "tx"; | ||
| 53 | }; | ||
| 54 | |||
| 55 | ssp3: ssp@41a00000 { | ||
| 56 | compatible = "mrvl,pxa3xx-ssp"; | ||
| 57 | reg = <0x41a00000 0x40>; | ||
| 58 | ssp-id = <4>; | ||
| 59 | interrupts = <13>; | ||
| 60 | clock-names = "pxa27x-ssp.3"; | ||
| 61 | dmas = <&dma 2 | ||
| 62 | &dma 3>; | ||
| 63 | dma-names = "rx", "tx"; | ||
| 64 | }; | ||
| 65 | |||
diff --git a/Documentation/devicetree/bindings/sound/ak4554.c b/Documentation/devicetree/bindings/sound/ak4554.c new file mode 100644 index 000000000000..934fa02754b3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ak4554.c | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | AK4554 ADC/DAC | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible : "asahi-kasei,ak4554" | ||
| 6 | |||
| 7 | Example: | ||
| 8 | |||
| 9 | ak4554-adc-dac { | ||
| 10 | compatible = "asahi-kasei,ak4554"; | ||
| 11 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt index 8608f747dcfe..ffd886d110bd 100644 --- a/Documentation/devicetree/bindings/sound/alc5632.txt +++ b/Documentation/devicetree/bindings/sound/alc5632.txt | |||
| @@ -13,6 +13,25 @@ Required properties: | |||
| 13 | - #gpio-cells : Should be two. The first cell is the pin number and the | 13 | - #gpio-cells : Should be two. The first cell is the pin number and the |
| 14 | second cell is used to specify optional parameters (currently unused). | 14 | second cell is used to specify optional parameters (currently unused). |
| 15 | 15 | ||
| 16 | Pins on the device (for linking into audio routes): | ||
| 17 | |||
| 18 | * SPK_OUTP | ||
| 19 | * SPK_OUTN | ||
| 20 | * HP_OUT_L | ||
| 21 | * HP_OUT_R | ||
| 22 | * AUX_OUT_P | ||
| 23 | * AUX_OUT_N | ||
| 24 | * LINE_IN_L | ||
| 25 | * LINE_IN_R | ||
| 26 | * PHONE_P | ||
| 27 | * PHONE_N | ||
| 28 | * MIC1_P | ||
| 29 | * MIC1_N | ||
| 30 | * MIC2_P | ||
| 31 | * MIC2_N | ||
| 32 | * MICBIAS1 | ||
| 33 | * DMICDAT | ||
| 34 | |||
| 16 | Example: | 35 | Example: |
| 17 | 36 | ||
| 18 | alc5632: alc5632@1e { | 37 | alc5632: alc5632@1e { |
diff --git a/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt new file mode 100644 index 000000000000..0720857089a7 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | * Atmel at91sam9x5ek wm8731 audio complex | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "atmel,sam9x5-wm8731-audio" | ||
| 5 | - atmel,model: The user-visible name of this sound complex. | ||
| 6 | - atmel,ssc-controller: The phandle of the SSC controller | ||
| 7 | - atmel,audio-codec: The phandle of the WM8731 audio codec | ||
| 8 | - atmel,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. | ||
| 11 | |||
| 12 | Available audio endpoints for the audio-routing table: | ||
| 13 | |||
| 14 | Board connectors: | ||
| 15 | * Headphone Jack | ||
| 16 | * Line In Jack | ||
| 17 | |||
| 18 | wm8731 pins: | ||
| 19 | cf Documentation/devicetree/bindings/sound/wm8731.txt | ||
| 20 | |||
| 21 | Example: | ||
| 22 | sound { | ||
| 23 | compatible = "atmel,sam9x5-wm8731-audio"; | ||
| 24 | |||
| 25 | atmel,model = "wm8731 @ AT91SAM9X5EK"; | ||
| 26 | |||
| 27 | atmel,audio-routing = | ||
| 28 | "Headphone Jack", "RHPOUT", | ||
| 29 | "Headphone Jack", "LHPOUT", | ||
| 30 | "LLINEIN", "Line In Jack", | ||
| 31 | "RLINEIN", "Line In Jack"; | ||
| 32 | |||
| 33 | atmel,ssc-controller = <&ssc0>; | ||
| 34 | atmel,audio-codec = <&wm8731>; | ||
| 35 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/atmel-wm8904.txt b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt new file mode 100644 index 000000000000..8bbe50c884b6 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | Atmel ASoC driver with wm8904 audio codec complex | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "atmel,asoc-wm8904" | ||
| 5 | - atmel,model: The user-visible name of this sound complex. | ||
| 6 | - atmel,audio-routing: A list of the connections between audio components. | ||
| 7 | Each entry is a pair of strings, the first being the connection's sink, | ||
| 8 | the second being the connection's source. Valid names for sources and | ||
| 9 | sinks are the WM8904's pins, and the jacks on the board: | ||
| 10 | |||
| 11 | WM8904 pins: | ||
| 12 | |||
| 13 | * IN1L | ||
| 14 | * IN1R | ||
| 15 | * IN2L | ||
| 16 | * IN2R | ||
| 17 | * IN3L | ||
| 18 | * IN3R | ||
| 19 | * HPOUTL | ||
| 20 | * HPOUTR | ||
| 21 | * LINEOUTL | ||
| 22 | * LINEOUTR | ||
| 23 | * MICBIAS | ||
| 24 | |||
| 25 | Board connectors: | ||
| 26 | |||
| 27 | * Headphone Jack | ||
| 28 | * Line In Jack | ||
| 29 | * Mic | ||
| 30 | |||
| 31 | - atmel,ssc-controller: The phandle of the SSC controller | ||
| 32 | - atmel,audio-codec: The phandle of the WM8904 audio codec | ||
| 33 | |||
| 34 | Optional properties: | ||
| 35 | - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt | ||
| 36 | |||
| 37 | Example: | ||
| 38 | sound { | ||
| 39 | compatible = "atmel,asoc-wm8904"; | ||
| 40 | pinctrl-names = "default"; | ||
| 41 | pinctrl-0 = <&pinctrl_pck0_as_mck>; | ||
| 42 | |||
| 43 | atmel,model = "wm8904 @ AT91SAM9N12EK"; | ||
| 44 | |||
| 45 | atmel,audio-routing = | ||
| 46 | "Headphone Jack", "HPOUTL", | ||
| 47 | "Headphone Jack", "HPOUTR", | ||
| 48 | "IN2L", "Line In Jack", | ||
| 49 | "IN2R", "Line In Jack", | ||
| 50 | "Mic", "MICBIAS", | ||
| 51 | "IN1L", "Mic"; | ||
| 52 | |||
| 53 | atmel,ssc-controller = <&ssc0>; | ||
| 54 | atmel,audio-codec = <&wm8904>; | ||
| 55 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt new file mode 100644 index 000000000000..f2ae335670f5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller | ||
| 2 | |||
| 3 | The Freescale S/PDIF audio block is a stereo transceiver that allows the | ||
| 4 | processor to receive and transmit digital audio via an coaxial cable or | ||
| 5 | a fibre cable. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | |||
| 9 | - compatible : Compatible list, must contain "fsl,imx35-spdif". | ||
| 10 | |||
| 11 | - reg : Offset and length of the register set for the device. | ||
| 12 | |||
| 13 | - interrupts : Contains the spdif interrupt. | ||
| 14 | |||
| 15 | - dmas : Generic dma devicetree binding as described in | ||
| 16 | Documentation/devicetree/bindings/dma/dma.txt. | ||
| 17 | |||
| 18 | - dma-names : Two dmas have to be defined, "tx" and "rx". | ||
| 19 | |||
| 20 | - clocks : Contains an entry for each entry in clock-names. | ||
| 21 | |||
| 22 | - clock-names : Includes the following entries: | ||
| 23 | "core" The core clock of spdif controller | ||
| 24 | "rxtx<0-7>" Clock source list for tx and rx clock. | ||
| 25 | This clock list should be identical to | ||
| 26 | the source list connecting to the spdif | ||
| 27 | clock mux in "SPDIF Transceiver Clock | ||
| 28 | Diagram" of SoC reference manual. It | ||
| 29 | can also be referred to TxClk_Source | ||
| 30 | bit of register SPDIF_STC. | ||
| 31 | |||
| 32 | Example: | ||
| 33 | |||
| 34 | spdif: spdif@02004000 { | ||
| 35 | compatible = "fsl,imx35-spdif"; | ||
| 36 | reg = <0x02004000 0x4000>; | ||
| 37 | interrupts = <0 52 0x04>; | ||
| 38 | dmas = <&sdma 14 18 0>, | ||
| 39 | <&sdma 15 18 0>; | ||
| 40 | dma-names = "rx", "tx"; | ||
| 41 | |||
| 42 | clocks = <&clks 197>, <&clks 3>, | ||
| 43 | <&clks 197>, <&clks 107>, | ||
| 44 | <&clks 0>, <&clks 118>, | ||
| 45 | <&clks 62>, <&clks 139>, | ||
| 46 | <&clks 0>; | ||
| 47 | clock-names = "core", "rxtx0", | ||
| 48 | "rxtx1", "rxtx2", | ||
| 49 | "rxtx3", "rxtx4", | ||
| 50 | "rxtx5", "rxtx6", | ||
| 51 | "rxtx7"; | ||
| 52 | |||
| 53 | status = "okay"; | ||
| 54 | }; | ||
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt index 5ff76c9c57d2..4303b6ab6208 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt +++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt | |||
| @@ -43,10 +43,22 @@ Required properties: | |||
| 43 | together. This would still allow different sample sizes, | 43 | together. This would still allow different sample sizes, |
| 44 | but not different sample rates. | 44 | but not different sample rates. |
| 45 | 45 | ||
| 46 | Required are also ac97 link bindings if ac97 is used. See | ||
| 47 | Documentation/devicetree/bindings/sound/soc-ac97link.txt for the necessary | ||
| 48 | bindings. | ||
| 49 | |||
| 46 | Optional properties: | 50 | Optional properties: |
| 47 | - codec-handle: Phandle to a 'codec' node that defines an audio | 51 | - codec-handle: Phandle to a 'codec' node that defines an audio |
| 48 | codec connected to this SSI. This node is typically | 52 | codec connected to this SSI. This node is typically |
| 49 | a child of an I2C or other control node. | 53 | a child of an I2C or other control node. |
| 54 | - fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to | ||
| 55 | filter the codec stream. This is necessary for some boards | ||
| 56 | where an incompatible codec is connected to this SSI, e.g. | ||
| 57 | on pca100 and pcm043. | ||
| 58 | - dmas: Generic dma devicetree binding as described in | ||
| 59 | Documentation/devicetree/bindings/dma/dma.txt. | ||
| 60 | - dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq | ||
| 61 | is not defined. | ||
| 50 | 62 | ||
| 51 | Child 'codec' node required properties: | 63 | Child 'codec' node required properties: |
| 52 | - compatible: Compatible list, contains the name of the codec | 64 | - compatible: Compatible list, contains the name of the codec |
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt index 215aa9817213..f88a00e54c63 100644 --- a/Documentation/devicetree/bindings/sound/imx-audmux.txt +++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt | |||
| @@ -5,6 +5,15 @@ Required properties: | |||
| 5 | or "fsl,imx31-audmux" for the version firstly used on i.MX31. | 5 | or "fsl,imx31-audmux" for the version firstly used on i.MX31. |
| 6 | - reg : Should contain AUDMUX registers location and length | 6 | - reg : Should contain AUDMUX registers location and length |
| 7 | 7 | ||
| 8 | An initial configuration can be setup using child nodes. | ||
| 9 | |||
| 10 | Required properties of optional child nodes: | ||
| 11 | - fsl,audmux-port : Integer of the audmux port that is configured by this | ||
| 12 | child node. | ||
| 13 | - fsl,port-config : List of configuration options for the specific port. For | ||
| 14 | imx31-audmux and above, it is a list of tuples <ptcr pdcr>. For | ||
| 15 | imx21-audmux it is a list of pcr values. | ||
| 16 | |||
| 8 | Example: | 17 | Example: |
| 9 | 18 | ||
| 10 | audmux@021d8000 { | 19 | audmux@021d8000 { |
diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt new file mode 100644 index 000000000000..74c9ba6c2823 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | Marvell PXA SSP CPU DAI bindings | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | compatible Must be "mrvl,pxa-ssp-dai" | ||
| 6 | port A phandle reference to a PXA ssp upstream device | ||
| 7 | |||
| 8 | Example: | ||
| 9 | |||
| 10 | /* upstream device */ | ||
| 11 | |||
| 12 | ssp0: ssp@41000000 { | ||
| 13 | compatible = "mrvl,pxa3xx-ssp"; | ||
| 14 | reg = <0x41000000 0x40>; | ||
| 15 | interrupts = <24>; | ||
| 16 | clock-names = "pxa27x-ssp.0"; | ||
| 17 | dmas = <&dma 13 | ||
| 18 | &dma 14>; | ||
| 19 | dma-names = "rx", "tx"; | ||
| 20 | }; | ||
| 21 | |||
| 22 | /* DAI as user */ | ||
| 23 | |||
| 24 | ssp_dai0: ssp_dai@0 { | ||
| 25 | compatible = "mrvl,pxa-ssp-dai"; | ||
| 26 | port = <&ssp0>; | ||
| 27 | }; | ||
| 28 | |||
diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt new file mode 100644 index 000000000000..551fbb8348c2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | DT bindings for ARM PXA2xx PCM platform driver | ||
| 2 | |||
| 3 | This is just a dummy driver that registers the PXA ASoC platform driver. | ||
| 4 | It does not have any resources assigned. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | |||
| 8 | - compatible 'mrvl,pxa-pcm-audio' | ||
| 9 | |||
| 10 | Example: | ||
| 11 | |||
| 12 | pxa_pcm_audio: snd_soc_pxa_audio { | ||
| 13 | compatible = "mrvl,pxa-pcm-audio"; | ||
| 14 | }; | ||
| 15 | |||
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt index 05ffecb57103..8b8903ef0800 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt | |||
| @@ -11,28 +11,8 @@ Required properties: | |||
| 11 | - nvidia,audio-routing : A list of the connections between audio components. | 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, | 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 | 13 | the second being the connection's source. Valid names for sources and |
| 14 | sinks are the ALC5632's pins: | 14 | sinks are the ALC5632's pins as documented in the binding for the device |
| 15 | 15 | and: | |
| 16 | ALC5632 pins: | ||
| 17 | |||
| 18 | * SPK_OUTP | ||
| 19 | * SPK_OUTN | ||
| 20 | * HP_OUT_L | ||
| 21 | * HP_OUT_R | ||
| 22 | * AUX_OUT_P | ||
| 23 | * AUX_OUT_N | ||
| 24 | * LINE_IN_L | ||
| 25 | * LINE_IN_R | ||
| 26 | * PHONE_P | ||
| 27 | * PHONE_N | ||
| 28 | * MIC1_P | ||
| 29 | * MIC1_N | ||
| 30 | * MIC2_P | ||
| 31 | * MIC2_N | ||
| 32 | * MICBIAS1 | ||
| 33 | * DMICDAT | ||
| 34 | |||
| 35 | Board connectors: | ||
| 36 | 16 | ||
| 37 | * Headset Stereophone | 17 | * Headset Stereophone |
| 38 | * Int Spk | 18 | * Int Spk |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt index d130818700b2..dc6224994d69 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt | |||
| @@ -11,32 +11,12 @@ Required properties: | |||
| 11 | - nvidia,audio-routing : A list of the connections between audio components. | 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, | 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 | 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: | 14 | sinks are the RT5640's pins (as documented in its binding), and the jacks |
| 15 | 15 | on the board: | |
| 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 | 16 | ||
| 38 | * Headphones | 17 | * Headphones |
| 39 | * Speakers | 18 | * Speakers |
| 19 | * Mic Jack | ||
| 40 | 20 | ||
| 41 | - nvidia,i2s-controller : The phandle of the Tegra I2S controller that's | 21 | - nvidia,i2s-controller : The phandle of the Tegra I2S controller that's |
| 42 | connected to the CODEC. | 22 | connected to the CODEC. |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt index 3bf722deb722..4b44dfb6ca0d 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt | |||
| @@ -11,28 +11,8 @@ Required properties: | |||
| 11 | - nvidia,audio-routing : A list of the connections between audio components. | 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, | 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 | 13 | the second being the connection's source. Valid names for sources and |
| 14 | sinks are the WM8903's pins, and the jacks on the board: | 14 | sinks are the WM8903's pins (documented in the WM8903 binding document), |
| 15 | 15 | and the jacks on the board: | |
| 16 | WM8903 pins: | ||
| 17 | |||
| 18 | * IN1L | ||
| 19 | * IN1R | ||
| 20 | * IN2L | ||
| 21 | * IN2R | ||
| 22 | * IN3L | ||
| 23 | * IN3R | ||
| 24 | * DMICDAT | ||
| 25 | * HPOUTL | ||
| 26 | * HPOUTR | ||
| 27 | * LINEOUTL | ||
| 28 | * LINEOUTR | ||
| 29 | * LOP | ||
| 30 | * LON | ||
| 31 | * ROP | ||
| 32 | * RON | ||
| 33 | * MICBIAS | ||
| 34 | |||
| 35 | Board connectors: | ||
| 36 | 16 | ||
| 37 | * Headphone Jack | 17 | * Headphone Jack |
| 38 | * Int Spk | 18 | * Int Spk |
diff --git a/Documentation/devicetree/bindings/sound/pcm1792a.txt b/Documentation/devicetree/bindings/sound/pcm1792a.txt new file mode 100644 index 000000000000..970ba1ed576f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/pcm1792a.txt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | Texas Instruments pcm1792a DT bindings | ||
| 2 | |||
| 3 | This driver supports the SPI bus. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible: "ti,pcm1792a" | ||
| 8 | |||
| 9 | For required properties on SPI, please consult | ||
| 10 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
| 11 | |||
| 12 | Examples: | ||
| 13 | |||
| 14 | codec_spi: 1792a@0 { | ||
| 15 | compatible = "ti,pcm1792a"; | ||
| 16 | spi-max-frequency = <600000>; | ||
| 17 | }; | ||
| 18 | |||
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt index 005bcb24d72d..068a1141b06f 100644 --- a/Documentation/devicetree/bindings/sound/rt5640.txt +++ b/Documentation/devicetree/bindings/sound/rt5640.txt | |||
| @@ -18,6 +18,26 @@ Optional properties: | |||
| 18 | 18 | ||
| 19 | - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. | 19 | - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. |
| 20 | 20 | ||
| 21 | Pins on the device (for linking into audio routes): | ||
| 22 | |||
| 23 | * DMIC1 | ||
| 24 | * DMIC2 | ||
| 25 | * MICBIAS1 | ||
| 26 | * IN1P | ||
| 27 | * IN1R | ||
| 28 | * IN2P | ||
| 29 | * IN2R | ||
| 30 | * HPOL | ||
| 31 | * HPOR | ||
| 32 | * LOUTL | ||
| 33 | * LOUTR | ||
| 34 | * MONOP | ||
| 35 | * MONON | ||
| 36 | * SPOLP | ||
| 37 | * SPOLN | ||
| 38 | * SPORP | ||
| 39 | * SPORN | ||
| 40 | |||
| 21 | Example: | 41 | Example: |
| 22 | 42 | ||
| 23 | rt5640 { | 43 | rt5640 { |
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt index 025e66b85a43..7386d444ada1 100644 --- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt +++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt | |||
| @@ -2,7 +2,15 @@ | |||
| 2 | 2 | ||
| 3 | Required SoC Specific Properties: | 3 | Required SoC Specific Properties: |
| 4 | 4 | ||
| 5 | - compatible : "samsung,i2s-v5" | 5 | - compatible : should be one of the following. |
| 6 | - samsung,s3c6410-i2s: for 8/16/24bit stereo I2S. | ||
| 7 | - samsung,s5pv210-i2s: for 8/16/24bit multichannel(5.1) I2S with | ||
| 8 | secondary fifo, s/w reset control and internal mux for root clk src. | ||
| 9 | - samsung,exynos5420-i2s: for 8/16/24bit multichannel(7.1) I2S with | ||
| 10 | secondary fifo, s/w reset control, internal mux for root clk src and | ||
| 11 | TDM support. TDM (Time division multiplexing) is to allow transfer of | ||
| 12 | multiple channel audio data on single data line. | ||
| 13 | |||
| 6 | - reg: physical base address of the controller and length of memory mapped | 14 | - reg: physical base address of the controller and length of memory mapped |
| 7 | region. | 15 | region. |
| 8 | - dmas: list of DMA controller phandle and DMA request line ordered pairs. | 16 | - dmas: list of DMA controller phandle and DMA request line ordered pairs. |
| @@ -21,13 +29,6 @@ Required SoC Specific Properties: | |||
| 21 | 29 | ||
| 22 | Optional SoC Specific Properties: | 30 | Optional SoC Specific Properties: |
| 23 | 31 | ||
| 24 | - samsung,supports-6ch: If the I2S Primary sound source has 5.1 Channel | ||
| 25 | support, this flag is enabled. | ||
| 26 | - samsung,supports-rstclr: This flag should be set if I2S software reset bit | ||
| 27 | control is required. When this flag is set I2S software reset bit will be | ||
| 28 | enabled or disabled based on need. | ||
| 29 | - samsung,supports-secdai:If I2S block has a secondary FIFO and internal DMA, | ||
| 30 | then this flag is enabled. | ||
| 31 | - samsung,idma-addr: Internal DMA register base address of the audio | 32 | - samsung,idma-addr: Internal DMA register base address of the audio |
| 32 | sub system(used in secondary sound source). | 33 | sub system(used in secondary sound source). |
| 33 | - pinctrl-0: Should specify pin control groups used for this controller. | 34 | - pinctrl-0: Should specify pin control groups used for this controller. |
| @@ -36,7 +37,7 @@ Optional SoC Specific Properties: | |||
| 36 | Example: | 37 | Example: |
| 37 | 38 | ||
| 38 | i2s0: i2s@03830000 { | 39 | i2s0: i2s@03830000 { |
| 39 | compatible = "samsung,i2s-v5"; | 40 | compatible = "samsung,s5pv210-i2s"; |
| 40 | reg = <0x03830000 0x100>; | 41 | reg = <0x03830000 0x100>; |
| 41 | dmas = <&pdma0 10 | 42 | dmas = <&pdma0 10 |
| 42 | &pdma0 9 | 43 | &pdma0 9 |
| @@ -46,9 +47,6 @@ i2s0: i2s@03830000 { | |||
| 46 | <&clock_audss EXYNOS_I2S_BUS>, | 47 | <&clock_audss EXYNOS_I2S_BUS>, |
| 47 | <&clock_audss EXYNOS_SCLK_I2S>; | 48 | <&clock_audss EXYNOS_SCLK_I2S>; |
| 48 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; | 49 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; |
| 49 | samsung,supports-6ch; | ||
| 50 | samsung,supports-rstclr; | ||
| 51 | samsung,supports-secdai; | ||
| 52 | samsung,idma-addr = <0x03000000>; | 50 | samsung,idma-addr = <0x03000000>; |
| 53 | pinctrl-names = "default"; | 51 | pinctrl-names = "default"; |
| 54 | pinctrl-0 = <&i2s0_bus>; | 52 | pinctrl-0 = <&i2s0_bus>; |
diff --git a/Documentation/devicetree/bindings/sound/soc-ac97link.txt b/Documentation/devicetree/bindings/sound/soc-ac97link.txt new file mode 100644 index 000000000000..80152a87f239 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/soc-ac97link.txt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | AC97 link bindings | ||
| 2 | |||
| 3 | These bindings can be included within any other device node. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | - pinctrl-names: Has to contain following states to setup the correct | ||
| 7 | pinmuxing for the used gpios: | ||
| 8 | "ac97-running": AC97-link is active | ||
| 9 | "ac97-reset": AC97-link reset state | ||
| 10 | "ac97-warm-reset": AC97-link warm reset state | ||
| 11 | - ac97-gpios: List of gpio phandles with args in the order ac97-sync, | ||
| 12 | ac97-sdata, ac97-reset | ||
| 13 | |||
| 14 | |||
| 15 | Example: | ||
| 16 | |||
| 17 | ssi { | ||
| 18 | ... | ||
| 19 | |||
| 20 | pinctrl-names = "default", "ac97-running", "ac97-reset", "ac97-warm-reset"; | ||
| 21 | pinctrl-0 = <&ac97link_running>; | ||
| 22 | pinctrl-1 = <&ac97link_running>; | ||
| 23 | pinctrl-2 = <&ac97link_reset>; | ||
| 24 | pinctrl-3 = <&ac97link_warm_reset>; | ||
| 25 | ac97-gpios = <&gpio3 20 0 &gpio3 22 0 &gpio3 28 0>; | ||
| 26 | |||
| 27 | ... | ||
| 28 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm1681.txt b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt new file mode 100644 index 000000000000..4df17185ab80 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | Texas Instruments PCM1681 8-channel PWM Processor | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Should contain "ti,pcm1681". | ||
| 6 | - reg: The i2c address. Should contain <0x4c>. | ||
| 7 | |||
| 8 | Examples: | ||
| 9 | |||
| 10 | i2c_bus { | ||
| 11 | pcm1681@4c { | ||
| 12 | compatible = "ti,pcm1681"; | ||
| 13 | reg = <0x4c>; | ||
| 14 | }; | ||
| 15 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt index f47c3f589fd0..705a6b156c6c 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt | |||
| @@ -3,7 +3,14 @@ Texas Instruments - tlv320aic3x Codec module | |||
| 3 | The tlv320aic3x serial control bus communicates through I2C protocols | 3 | The tlv320aic3x serial control bus communicates through I2C protocols |
| 4 | 4 | ||
| 5 | Required properties: | 5 | Required properties: |
| 6 | - compatible - "string" - "ti,tlv320aic3x" | 6 | |
| 7 | - compatible - "string" - One of: | ||
| 8 | "ti,tlv320aic3x" - Generic TLV320AIC3x device | ||
| 9 | "ti,tlv320aic33" - TLV320AIC33 | ||
| 10 | "ti,tlv320aic3007" - TLV320AIC3007 | ||
| 11 | "ti,tlv320aic3106" - TLV320AIC3106 | ||
| 12 | |||
| 13 | |||
| 7 | - reg - <int> - I2C slave address | 14 | - reg - <int> - I2C slave address |
| 8 | 15 | ||
| 9 | 16 | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt index 15f70048469b..236690e99b87 100644 --- a/Documentation/devicetree/bindings/sound/wm8731.txt +++ b/Documentation/devicetree/bindings/sound/wm8731.txt | |||
| @@ -16,3 +16,12 @@ codec: wm8731@1a { | |||
| 16 | compatible = "wlf,wm8731"; | 16 | compatible = "wlf,wm8731"; |
| 17 | reg = <0x1a>; | 17 | reg = <0x1a>; |
| 18 | }; | 18 | }; |
| 19 | |||
| 20 | Available audio endpoints for an audio-routing table: | ||
| 21 | * LOUT: Left Channel Line Output | ||
| 22 | * ROUT: Right Channel Line Output | ||
| 23 | * LHPOUT: Left Channel Headphone Output | ||
| 24 | * RHPOUT: Right Channel Headphone Output | ||
| 25 | * LLINEIN: Left Channel Line Input | ||
| 26 | * RLINEIN: Right Channel Line Input | ||
| 27 | * MICIN: Microphone Input | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt index f102cbc42694..94ec32c194bb 100644 --- a/Documentation/devicetree/bindings/sound/wm8903.txt +++ b/Documentation/devicetree/bindings/sound/wm8903.txt | |||
| @@ -28,6 +28,25 @@ Optional properties: | |||
| 28 | performed. If any entry has the value 0xffffffff, that GPIO's | 28 | performed. If any entry has the value 0xffffffff, that GPIO's |
| 29 | configuration will not be modified. | 29 | configuration will not be modified. |
| 30 | 30 | ||
| 31 | Pins on the device (for linking into audio routes): | ||
| 32 | |||
| 33 | * IN1L | ||
| 34 | * IN1R | ||
| 35 | * IN2L | ||
| 36 | * IN2R | ||
| 37 | * IN3L | ||
| 38 | * IN3R | ||
| 39 | * DMICDAT | ||
| 40 | * HPOUTL | ||
| 41 | * HPOUTR | ||
| 42 | * LINEOUTL | ||
| 43 | * LINEOUTR | ||
| 44 | * LOP | ||
| 45 | * LON | ||
| 46 | * ROP | ||
| 47 | * RON | ||
| 48 | * MICBIAS | ||
| 49 | |||
| 31 | Example: | 50 | Example: |
| 32 | 51 | ||
| 33 | codec: wm8903@1a { | 52 | codec: wm8903@1a { |
diff --git a/MAINTAINERS b/MAINTAINERS index defc05383f83..8c54609da16b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -595,6 +595,7 @@ S: Supported | |||
| 595 | F: sound/soc/codecs/adau* | 595 | F: sound/soc/codecs/adau* |
| 596 | F: sound/soc/codecs/adav* | 596 | F: sound/soc/codecs/adav* |
| 597 | F: sound/soc/codecs/ad1* | 597 | F: sound/soc/codecs/ad1* |
| 598 | F: sound/soc/codecs/ad7* | ||
| 598 | F: sound/soc/codecs/ssm* | 599 | F: sound/soc/codecs/ssm* |
| 599 | F: sound/soc/codecs/sigmadsp.* | 600 | F: sound/soc/codecs/sigmadsp.* |
| 600 | 601 | ||
| @@ -965,6 +966,12 @@ M: Lennert Buytenhek <kernel@wantstofly.org> | |||
| 965 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 966 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 966 | S: Maintained | 967 | S: Maintained |
| 967 | 968 | ||
| 969 | ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE | ||
| 970 | M: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
| 971 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
| 972 | S: Maintained | ||
| 973 | F: arch/arm/mach-keystone/ | ||
| 974 | |||
| 968 | ARM/LOGICPD PXA270 MACHINE SUPPORT | 975 | ARM/LOGICPD PXA270 MACHINE SUPPORT |
| 969 | M: Lennert Buytenhek <kernel@wantstofly.org> | 976 | M: Lennert Buytenhek <kernel@wantstofly.org> |
| 970 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 977 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| @@ -1259,7 +1266,6 @@ F: drivers/rtc/rtc-coh901331.c | |||
| 1259 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git | 1266 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git |
| 1260 | 1267 | ||
| 1261 | ARM/Ux500 ARM ARCHITECTURE | 1268 | ARM/Ux500 ARM ARCHITECTURE |
| 1262 | M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
| 1263 | M: Linus Walleij <linus.walleij@linaro.org> | 1269 | M: Linus Walleij <linus.walleij@linaro.org> |
| 1264 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 1270 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 1265 | S: Maintained | 1271 | S: Maintained |
| @@ -5576,9 +5582,9 @@ S: Maintained | |||
| 5576 | F: drivers/media/tuners/mxl5007t.* | 5582 | F: drivers/media/tuners/mxl5007t.* |
| 5577 | 5583 | ||
| 5578 | MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) | 5584 | MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) |
| 5579 | M: Andrew Gallatin <gallatin@myri.com> | 5585 | M: Hyong-Youb Kim <hykim@myri.com> |
| 5580 | L: netdev@vger.kernel.org | 5586 | L: netdev@vger.kernel.org |
| 5581 | W: http://www.myri.com/scs/download-Myri10GE.html | 5587 | W: https://www.myricom.com/support/downloads/myri10ge.html |
| 5582 | S: Supported | 5588 | S: Supported |
| 5583 | F: drivers/net/ethernet/myricom/myri10ge/ | 5589 | F: drivers/net/ethernet/myricom/myri10ge/ |
| 5584 | 5590 | ||
| @@ -7361,7 +7367,6 @@ F: drivers/net/ethernet/sfc/ | |||
| 7361 | 7367 | ||
| 7362 | SGI GRU DRIVER | 7368 | SGI GRU DRIVER |
| 7363 | M: Dimitri Sivanich <sivanich@sgi.com> | 7369 | M: Dimitri Sivanich <sivanich@sgi.com> |
| 7364 | M: Robin Holt <holt@sgi.com> | ||
| 7365 | S: Maintained | 7370 | S: Maintained |
| 7366 | F: drivers/misc/sgi-gru/ | 7371 | F: drivers/misc/sgi-gru/ |
| 7367 | 7372 | ||
| @@ -7381,7 +7386,8 @@ S: Maintained for 2.6. | |||
| 7381 | F: Documentation/sgi-visws.txt | 7386 | F: Documentation/sgi-visws.txt |
| 7382 | 7387 | ||
| 7383 | SGI XP/XPC/XPNET DRIVER | 7388 | SGI XP/XPC/XPNET DRIVER |
| 7384 | M: Robin Holt <holt@sgi.com> | 7389 | M: Cliff Whickman <cpw@sgi.com> |
| 7390 | M: Robin Holt <robinmholt@gmail.com> | ||
| 7385 | S: Maintained | 7391 | S: Maintained |
| 7386 | F: drivers/misc/sgi-xp/ | 7392 | F: drivers/misc/sgi-xp/ |
| 7387 | 7393 | ||
| @@ -7677,6 +7683,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git | |||
| 7677 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 7683 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 7678 | W: http://alsa-project.org/main/index.php/ASoC | 7684 | W: http://alsa-project.org/main/index.php/ASoC |
| 7679 | S: Supported | 7685 | S: Supported |
| 7686 | F: Documentation/sound/alsa/soc/ | ||
| 7680 | F: sound/soc/ | 7687 | F: sound/soc/ |
| 7681 | F: include/sound/soc* | 7688 | F: include/sound/soc* |
| 7682 | 7689 | ||
| @@ -8664,6 +8671,11 @@ T: git git://git.alsa-project.org/alsa-kernel.git | |||
| 8664 | S: Maintained | 8671 | S: Maintained |
| 8665 | F: sound/usb/midi.* | 8672 | F: sound/usb/midi.* |
| 8666 | 8673 | ||
| 8674 | USB NETWORKING DRIVERS | ||
| 8675 | L: linux-usb@vger.kernel.org | ||
| 8676 | S: Odd Fixes | ||
| 8677 | F: drivers/net/usb/ | ||
| 8678 | |||
| 8667 | USB OHCI DRIVER | 8679 | USB OHCI DRIVER |
| 8668 | M: Alan Stern <stern@rowland.harvard.edu> | 8680 | M: Alan Stern <stern@rowland.harvard.edu> |
| 8669 | L: linux-usb@vger.kernel.org | 8681 | L: linux-usb@vger.kernel.org |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 11 | 2 | PATCHLEVEL = 11 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc4 | 4 | EXTRAVERSION = -rc6 |
| 5 | NAME = Linux for Workgroups | 5 | NAME = Linux for Workgroups |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/Kconfig b/arch/Kconfig index 8d2ae24b9f4a..1feb169274fe 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -407,6 +407,12 @@ config CLONE_BACKWARDS2 | |||
| 407 | help | 407 | help |
| 408 | Architecture has the first two arguments of clone(2) swapped. | 408 | Architecture has the first two arguments of clone(2) swapped. |
| 409 | 409 | ||
| 410 | config CLONE_BACKWARDS3 | ||
| 411 | bool | ||
| 412 | help | ||
| 413 | Architecture has tls passed as the 3rd argument of clone(2), | ||
| 414 | not the 5th one. | ||
| 415 | |||
| 410 | config ODD_RT_SIGACTION | 416 | config ODD_RT_SIGACTION |
| 411 | bool | 417 | bool |
| 412 | help | 418 | help |
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index ef57277fc38f..376090f07231 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi | |||
| @@ -405,7 +405,7 @@ | |||
| 405 | }; | 405 | }; |
| 406 | 406 | ||
| 407 | i2s0: i2s@03830000 { | 407 | i2s0: i2s@03830000 { |
| 408 | compatible = "samsung,i2s-v5"; | 408 | compatible = "samsung,s5pv210-i2s"; |
| 409 | reg = <0x03830000 0x100>; | 409 | reg = <0x03830000 0x100>; |
| 410 | dmas = <&pdma0 10 | 410 | dmas = <&pdma0 10 |
| 411 | &pdma0 9 | 411 | &pdma0 9 |
| @@ -415,16 +415,13 @@ | |||
| 415 | <&clock_audss EXYNOS_I2S_BUS>, | 415 | <&clock_audss EXYNOS_I2S_BUS>, |
| 416 | <&clock_audss EXYNOS_SCLK_I2S>; | 416 | <&clock_audss EXYNOS_SCLK_I2S>; |
| 417 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; | 417 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; |
| 418 | samsung,supports-6ch; | ||
| 419 | samsung,supports-rstclr; | ||
| 420 | samsung,supports-secdai; | ||
| 421 | samsung,idma-addr = <0x03000000>; | 418 | samsung,idma-addr = <0x03000000>; |
| 422 | pinctrl-names = "default"; | 419 | pinctrl-names = "default"; |
| 423 | pinctrl-0 = <&i2s0_bus>; | 420 | pinctrl-0 = <&i2s0_bus>; |
| 424 | }; | 421 | }; |
| 425 | 422 | ||
| 426 | i2s1: i2s@12D60000 { | 423 | i2s1: i2s@12D60000 { |
| 427 | compatible = "samsung,i2s-v5"; | 424 | compatible = "samsung,s3c6410-i2s"; |
| 428 | reg = <0x12D60000 0x100>; | 425 | reg = <0x12D60000 0x100>; |
| 429 | dmas = <&pdma1 12 | 426 | dmas = <&pdma1 12 |
| 430 | &pdma1 11>; | 427 | &pdma1 11>; |
| @@ -436,7 +433,7 @@ | |||
| 436 | }; | 433 | }; |
| 437 | 434 | ||
| 438 | i2s2: i2s@12D70000 { | 435 | i2s2: i2s@12D70000 { |
| 439 | compatible = "samsung,i2s-v5"; | 436 | compatible = "samsung,s3c6410-i2s"; |
| 440 | reg = <0x12D70000 0x100>; | 437 | reg = <0x12D70000 0x100>; |
| 441 | dmas = <&pdma0 12 | 438 | dmas = <&pdma0 12 |
| 442 | &pdma0 11>; | 439 | &pdma0 11>; |
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts index db2060c46540..9c1167b0459b 100644 --- a/arch/arm/boot/dts/msm8960-cdp.dts +++ b/arch/arm/boot/dts/msm8960-cdp.dts | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | cpu-offset = <0x80000>; | 26 | cpu-offset = <0x80000>; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | msmgpio: gpio@fd510000 { | 29 | msmgpio: gpio@800000 { |
| 30 | compatible = "qcom,msm-gpio"; | 30 | compatible = "qcom,msm-gpio"; |
| 31 | gpio-controller; | 31 | gpio-controller; |
| 32 | #gpio-cells = <2>; | 32 | #gpio-cells = <2>; |
| @@ -34,7 +34,7 @@ | |||
| 34 | interrupts = <0 32 0x4>; | 34 | interrupts = <0 32 0x4>; |
| 35 | interrupt-controller; | 35 | interrupt-controller; |
| 36 | #interrupt-cells = <2>; | 36 | #interrupt-cells = <2>; |
| 37 | reg = <0xfd510000 0x4000>; | 37 | reg = <0x800000 0x4000>; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | serial@16440000 { | 40 | serial@16440000 { |
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts index 08b72678abff..65d7b601651c 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/omap5-uevm.dts | |||
| @@ -235,7 +235,7 @@ | |||
| 235 | }; | 235 | }; |
| 236 | 236 | ||
| 237 | &mmc1 { | 237 | &mmc1 { |
| 238 | vmmc-supply = <&vmmcsd_fixed>; | 238 | vmmc-supply = <&ldo9_reg>; |
| 239 | bus-width = <4>; | 239 | bus-width = <4>; |
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| @@ -282,6 +282,7 @@ | |||
| 282 | 282 | ||
| 283 | regulators { | 283 | regulators { |
| 284 | smps123_reg: smps123 { | 284 | smps123_reg: smps123 { |
| 285 | /* VDD_OPP_MPU */ | ||
| 285 | regulator-name = "smps123"; | 286 | regulator-name = "smps123"; |
| 286 | regulator-min-microvolt = < 600000>; | 287 | regulator-min-microvolt = < 600000>; |
| 287 | regulator-max-microvolt = <1500000>; | 288 | regulator-max-microvolt = <1500000>; |
| @@ -290,6 +291,7 @@ | |||
| 290 | }; | 291 | }; |
| 291 | 292 | ||
| 292 | smps45_reg: smps45 { | 293 | smps45_reg: smps45 { |
| 294 | /* VDD_OPP_MM */ | ||
| 293 | regulator-name = "smps45"; | 295 | regulator-name = "smps45"; |
| 294 | regulator-min-microvolt = < 600000>; | 296 | regulator-min-microvolt = < 600000>; |
| 295 | regulator-max-microvolt = <1310000>; | 297 | regulator-max-microvolt = <1310000>; |
| @@ -298,6 +300,7 @@ | |||
| 298 | }; | 300 | }; |
| 299 | 301 | ||
| 300 | smps6_reg: smps6 { | 302 | smps6_reg: smps6 { |
| 303 | /* VDD_DDR3 - over VDD_SMPS6 */ | ||
| 301 | regulator-name = "smps6"; | 304 | regulator-name = "smps6"; |
| 302 | regulator-min-microvolt = <1200000>; | 305 | regulator-min-microvolt = <1200000>; |
| 303 | regulator-max-microvolt = <1200000>; | 306 | regulator-max-microvolt = <1200000>; |
| @@ -306,6 +309,7 @@ | |||
| 306 | }; | 309 | }; |
| 307 | 310 | ||
| 308 | smps7_reg: smps7 { | 311 | smps7_reg: smps7 { |
| 312 | /* VDDS_1v8_OMAP over VDDS_1v8_MAIN */ | ||
| 309 | regulator-name = "smps7"; | 313 | regulator-name = "smps7"; |
| 310 | regulator-min-microvolt = <1800000>; | 314 | regulator-min-microvolt = <1800000>; |
| 311 | regulator-max-microvolt = <1800000>; | 315 | regulator-max-microvolt = <1800000>; |
| @@ -314,6 +318,7 @@ | |||
| 314 | }; | 318 | }; |
| 315 | 319 | ||
| 316 | smps8_reg: smps8 { | 320 | smps8_reg: smps8 { |
| 321 | /* VDD_OPP_CORE */ | ||
| 317 | regulator-name = "smps8"; | 322 | regulator-name = "smps8"; |
| 318 | regulator-min-microvolt = < 600000>; | 323 | regulator-min-microvolt = < 600000>; |
| 319 | regulator-max-microvolt = <1310000>; | 324 | regulator-max-microvolt = <1310000>; |
| @@ -322,15 +327,15 @@ | |||
| 322 | }; | 327 | }; |
| 323 | 328 | ||
| 324 | smps9_reg: smps9 { | 329 | smps9_reg: smps9 { |
| 330 | /* VDDA_2v1_AUD over VDD_2v1 */ | ||
| 325 | regulator-name = "smps9"; | 331 | regulator-name = "smps9"; |
| 326 | regulator-min-microvolt = <2100000>; | 332 | regulator-min-microvolt = <2100000>; |
| 327 | regulator-max-microvolt = <2100000>; | 333 | regulator-max-microvolt = <2100000>; |
| 328 | regulator-always-on; | ||
| 329 | regulator-boot-on; | ||
| 330 | ti,smps-range = <0x80>; | 334 | ti,smps-range = <0x80>; |
| 331 | }; | 335 | }; |
| 332 | 336 | ||
| 333 | smps10_reg: smps10 { | 337 | smps10_reg: smps10 { |
| 338 | /* VBUS_5V_OTG */ | ||
| 334 | regulator-name = "smps10"; | 339 | regulator-name = "smps10"; |
| 335 | regulator-min-microvolt = <5000000>; | 340 | regulator-min-microvolt = <5000000>; |
| 336 | regulator-max-microvolt = <5000000>; | 341 | regulator-max-microvolt = <5000000>; |
| @@ -339,38 +344,40 @@ | |||
| 339 | }; | 344 | }; |
| 340 | 345 | ||
| 341 | ldo1_reg: ldo1 { | 346 | ldo1_reg: ldo1 { |
| 347 | /* VDDAPHY_CAM: vdda_csiport */ | ||
| 342 | regulator-name = "ldo1"; | 348 | regulator-name = "ldo1"; |
| 343 | regulator-min-microvolt = <2800000>; | 349 | regulator-min-microvolt = <1500000>; |
| 344 | regulator-max-microvolt = <2800000>; | 350 | regulator-max-microvolt = <1800000>; |
| 345 | regulator-always-on; | ||
| 346 | regulator-boot-on; | ||
| 347 | }; | 351 | }; |
| 348 | 352 | ||
| 349 | ldo2_reg: ldo2 { | 353 | ldo2_reg: ldo2 { |
| 354 | /* VCC_2V8_DISP: Does not go anywhere */ | ||
| 350 | regulator-name = "ldo2"; | 355 | regulator-name = "ldo2"; |
| 351 | regulator-min-microvolt = <2900000>; | 356 | regulator-min-microvolt = <2800000>; |
| 352 | regulator-max-microvolt = <2900000>; | 357 | regulator-max-microvolt = <2800000>; |
| 353 | regulator-always-on; | 358 | /* Unused */ |
| 354 | regulator-boot-on; | 359 | status = "disabled"; |
| 355 | }; | 360 | }; |
| 356 | 361 | ||
| 357 | ldo3_reg: ldo3 { | 362 | ldo3_reg: ldo3 { |
| 363 | /* VDDAPHY_MDM: vdda_lli */ | ||
| 358 | regulator-name = "ldo3"; | 364 | regulator-name = "ldo3"; |
| 359 | regulator-min-microvolt = <3000000>; | 365 | regulator-min-microvolt = <1500000>; |
| 360 | regulator-max-microvolt = <3000000>; | 366 | regulator-max-microvolt = <1500000>; |
| 361 | regulator-always-on; | ||
| 362 | regulator-boot-on; | 367 | regulator-boot-on; |
| 368 | /* Only if Modem is used */ | ||
| 369 | status = "disabled"; | ||
| 363 | }; | 370 | }; |
| 364 | 371 | ||
| 365 | ldo4_reg: ldo4 { | 372 | ldo4_reg: ldo4 { |
| 373 | /* VDDAPHY_DISP: vdda_dsiport/hdmi */ | ||
| 366 | regulator-name = "ldo4"; | 374 | regulator-name = "ldo4"; |
| 367 | regulator-min-microvolt = <2200000>; | 375 | regulator-min-microvolt = <1500000>; |
| 368 | regulator-max-microvolt = <2200000>; | 376 | regulator-max-microvolt = <1800000>; |
| 369 | regulator-always-on; | ||
| 370 | regulator-boot-on; | ||
| 371 | }; | 377 | }; |
| 372 | 378 | ||
| 373 | ldo5_reg: ldo5 { | 379 | ldo5_reg: ldo5 { |
| 380 | /* VDDA_1V8_PHY: usb/sata/hdmi.. */ | ||
| 374 | regulator-name = "ldo5"; | 381 | regulator-name = "ldo5"; |
| 375 | regulator-min-microvolt = <1800000>; | 382 | regulator-min-microvolt = <1800000>; |
| 376 | regulator-max-microvolt = <1800000>; | 383 | regulator-max-microvolt = <1800000>; |
| @@ -379,38 +386,43 @@ | |||
| 379 | }; | 386 | }; |
| 380 | 387 | ||
| 381 | ldo6_reg: ldo6 { | 388 | ldo6_reg: ldo6 { |
| 389 | /* VDDS_1V2_WKUP: hsic/ldo_emu_wkup */ | ||
| 382 | regulator-name = "ldo6"; | 390 | regulator-name = "ldo6"; |
| 383 | regulator-min-microvolt = <1500000>; | 391 | regulator-min-microvolt = <1200000>; |
| 384 | regulator-max-microvolt = <1500000>; | 392 | regulator-max-microvolt = <1200000>; |
| 385 | regulator-always-on; | 393 | regulator-always-on; |
| 386 | regulator-boot-on; | 394 | regulator-boot-on; |
| 387 | }; | 395 | }; |
| 388 | 396 | ||
| 389 | ldo7_reg: ldo7 { | 397 | ldo7_reg: ldo7 { |
| 398 | /* VDD_VPP: vpp1 */ | ||
| 390 | regulator-name = "ldo7"; | 399 | regulator-name = "ldo7"; |
| 391 | regulator-min-microvolt = <1500000>; | 400 | regulator-min-microvolt = <2000000>; |
| 392 | regulator-max-microvolt = <1500000>; | 401 | regulator-max-microvolt = <2000000>; |
| 393 | regulator-always-on; | 402 | /* Only for efuse reprograming! */ |
| 394 | regulator-boot-on; | 403 | status = "disabled"; |
| 395 | }; | 404 | }; |
| 396 | 405 | ||
| 397 | ldo8_reg: ldo8 { | 406 | ldo8_reg: ldo8 { |
| 407 | /* VDD_3v0: Does not go anywhere */ | ||
| 398 | regulator-name = "ldo8"; | 408 | regulator-name = "ldo8"; |
| 399 | regulator-min-microvolt = <1500000>; | 409 | regulator-min-microvolt = <3000000>; |
| 400 | regulator-max-microvolt = <1500000>; | 410 | regulator-max-microvolt = <3000000>; |
| 401 | regulator-always-on; | ||
| 402 | regulator-boot-on; | 411 | regulator-boot-on; |
| 412 | /* Unused */ | ||
| 413 | status = "disabled"; | ||
| 403 | }; | 414 | }; |
| 404 | 415 | ||
| 405 | ldo9_reg: ldo9 { | 416 | ldo9_reg: ldo9 { |
| 417 | /* VCC_DV_SDIO: vdds_sdcard */ | ||
| 406 | regulator-name = "ldo9"; | 418 | regulator-name = "ldo9"; |
| 407 | regulator-min-microvolt = <1800000>; | 419 | regulator-min-microvolt = <1800000>; |
| 408 | regulator-max-microvolt = <3300000>; | 420 | regulator-max-microvolt = <3000000>; |
| 409 | regulator-always-on; | ||
| 410 | regulator-boot-on; | 421 | regulator-boot-on; |
| 411 | }; | 422 | }; |
| 412 | 423 | ||
| 413 | ldoln_reg: ldoln { | 424 | ldoln_reg: ldoln { |
| 425 | /* VDDA_1v8_REF: vdds_osc/mm_l4per.. */ | ||
| 414 | regulator-name = "ldoln"; | 426 | regulator-name = "ldoln"; |
| 415 | regulator-min-microvolt = <1800000>; | 427 | regulator-min-microvolt = <1800000>; |
| 416 | regulator-max-microvolt = <1800000>; | 428 | regulator-max-microvolt = <1800000>; |
| @@ -419,12 +431,20 @@ | |||
| 419 | }; | 431 | }; |
| 420 | 432 | ||
| 421 | ldousb_reg: ldousb { | 433 | ldousb_reg: ldousb { |
| 434 | /* VDDA_3V_USB: VDDA_USBHS33 */ | ||
| 422 | regulator-name = "ldousb"; | 435 | regulator-name = "ldousb"; |
| 423 | regulator-min-microvolt = <3250000>; | 436 | regulator-min-microvolt = <3250000>; |
| 424 | regulator-max-microvolt = <3250000>; | 437 | regulator-max-microvolt = <3250000>; |
| 425 | regulator-always-on; | 438 | regulator-always-on; |
| 426 | regulator-boot-on; | 439 | regulator-boot-on; |
| 427 | }; | 440 | }; |
| 441 | |||
| 442 | regen3_reg: regen3 { | ||
| 443 | /* REGEN3 controls LDO9 supply to card */ | ||
| 444 | regulator-name = "regen3"; | ||
| 445 | regulator-always-on; | ||
| 446 | regulator-boot-on; | ||
| 447 | }; | ||
| 428 | }; | 448 | }; |
| 429 | }; | 449 | }; |
| 430 | }; | 450 | }; |
diff --git a/arch/arm/boot/dts/stih41x.dtsi b/arch/arm/boot/dts/stih41x.dtsi index 7321403cab8a..f5b9898d9c6e 100644 --- a/arch/arm/boot/dts/stih41x.dtsi +++ b/arch/arm/boot/dts/stih41x.dtsi | |||
| @@ -6,10 +6,12 @@ | |||
| 6 | #address-cells = <1>; | 6 | #address-cells = <1>; |
| 7 | #size-cells = <0>; | 7 | #size-cells = <0>; |
| 8 | cpu@0 { | 8 | cpu@0 { |
| 9 | device_type = "cpu"; | ||
| 9 | compatible = "arm,cortex-a9"; | 10 | compatible = "arm,cortex-a9"; |
| 10 | reg = <0>; | 11 | reg = <0>; |
| 11 | }; | 12 | }; |
| 12 | cpu@1 { | 13 | cpu@1 { |
| 14 | device_type = "cpu"; | ||
| 13 | compatible = "arm,cortex-a9"; | 15 | compatible = "arm,cortex-a9"; |
| 14 | reg = <1>; | 16 | reg = <1>; |
| 15 | }; | 17 | }; |
diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi index 2fcb3f2ca160..5592be6f2f7a 100644 --- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi +++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi | |||
| @@ -457,6 +457,7 @@ | |||
| 457 | }; | 457 | }; |
| 458 | 458 | ||
| 459 | usb-phy@c5004000 { | 459 | usb-phy@c5004000 { |
| 460 | status = "okay"; | ||
| 460 | nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) | 461 | nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) |
| 461 | GPIO_ACTIVE_LOW>; | 462 | GPIO_ACTIVE_LOW>; |
| 462 | }; | 463 | }; |
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index 6462a721ebd4..a252c0bfacf5 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h | |||
| @@ -88,4 +88,7 @@ static inline u32 mpidr_hash_size(void) | |||
| 88 | { | 88 | { |
| 89 | return 1 << mpidr_hash.bits; | 89 | return 1 << mpidr_hash.bits; |
| 90 | } | 90 | } |
| 91 | |||
| 92 | extern int platform_can_cpu_hotplug(void); | ||
| 93 | |||
| 91 | #endif | 94 | #endif |
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index f8b8965666e9..b07c09e5a0ac 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h | |||
| @@ -107,7 +107,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) | |||
| 107 | " subs %1, %0, %0, ror #16\n" | 107 | " subs %1, %0, %0, ror #16\n" |
| 108 | " addeq %0, %0, %4\n" | 108 | " addeq %0, %0, %4\n" |
| 109 | " strexeq %2, %0, [%3]" | 109 | " strexeq %2, %0, [%3]" |
| 110 | : "=&r" (slock), "=&r" (contended), "=r" (res) | 110 | : "=&r" (slock), "=&r" (contended), "=&r" (res) |
| 111 | : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) | 111 | : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) |
| 112 | : "cc"); | 112 | : "cc"); |
| 113 | } while (res); | 113 | } while (res); |
| @@ -168,17 +168,20 @@ static inline void arch_write_lock(arch_rwlock_t *rw) | |||
| 168 | 168 | ||
| 169 | static inline int arch_write_trylock(arch_rwlock_t *rw) | 169 | static inline int arch_write_trylock(arch_rwlock_t *rw) |
| 170 | { | 170 | { |
| 171 | unsigned long tmp; | 171 | unsigned long contended, res; |
| 172 | 172 | ||
| 173 | __asm__ __volatile__( | 173 | do { |
| 174 | " ldrex %0, [%1]\n" | 174 | __asm__ __volatile__( |
| 175 | " teq %0, #0\n" | 175 | " ldrex %0, [%2]\n" |
| 176 | " strexeq %0, %2, [%1]" | 176 | " mov %1, #0\n" |
| 177 | : "=&r" (tmp) | 177 | " teq %0, #0\n" |
| 178 | : "r" (&rw->lock), "r" (0x80000000) | 178 | " strexeq %1, %3, [%2]" |
| 179 | : "cc"); | 179 | : "=&r" (contended), "=&r" (res) |
| 180 | : "r" (&rw->lock), "r" (0x80000000) | ||
| 181 | : "cc"); | ||
| 182 | } while (res); | ||
| 180 | 183 | ||
| 181 | if (tmp == 0) { | 184 | if (!contended) { |
| 182 | smp_mb(); | 185 | smp_mb(); |
| 183 | return 1; | 186 | return 1; |
| 184 | } else { | 187 | } else { |
| @@ -254,18 +257,26 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) | |||
| 254 | 257 | ||
| 255 | static inline int arch_read_trylock(arch_rwlock_t *rw) | 258 | static inline int arch_read_trylock(arch_rwlock_t *rw) |
| 256 | { | 259 | { |
| 257 | unsigned long tmp, tmp2 = 1; | 260 | unsigned long contended, res; |
| 258 | 261 | ||
| 259 | __asm__ __volatile__( | 262 | do { |
| 260 | " ldrex %0, [%2]\n" | 263 | __asm__ __volatile__( |
| 261 | " adds %0, %0, #1\n" | 264 | " ldrex %0, [%2]\n" |
| 262 | " strexpl %1, %0, [%2]\n" | 265 | " mov %1, #0\n" |
| 263 | : "=&r" (tmp), "+r" (tmp2) | 266 | " adds %0, %0, #1\n" |
| 264 | : "r" (&rw->lock) | 267 | " strexpl %1, %0, [%2]" |
| 265 | : "cc"); | 268 | : "=&r" (contended), "=&r" (res) |
| 269 | : "r" (&rw->lock) | ||
| 270 | : "cc"); | ||
| 271 | } while (res); | ||
| 266 | 272 | ||
| 267 | smp_mb(); | 273 | /* If the lock is negative, then it is already held for write. */ |
| 268 | return tmp2 == 0; | 274 | if (contended < 0x80000000) { |
| 275 | smp_mb(); | ||
| 276 | return 1; | ||
| 277 | } else { | ||
| 278 | return 0; | ||
| 279 | } | ||
| 269 | } | 280 | } |
| 270 | 281 | ||
| 271 | /* read_can_lock - would read_trylock() succeed? */ | 282 | /* read_can_lock - would read_trylock() succeed? */ |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 46e7cfb3e721..0baf7f0d9394 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
| @@ -43,6 +43,7 @@ struct mmu_gather { | |||
| 43 | struct mm_struct *mm; | 43 | struct mm_struct *mm; |
| 44 | unsigned int fullmm; | 44 | unsigned int fullmm; |
| 45 | struct vm_area_struct *vma; | 45 | struct vm_area_struct *vma; |
| 46 | unsigned long start, end; | ||
| 46 | unsigned long range_start; | 47 | unsigned long range_start; |
| 47 | unsigned long range_end; | 48 | unsigned long range_end; |
| 48 | unsigned int nr; | 49 | unsigned int nr; |
| @@ -107,10 +108,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb) | |||
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | static inline void | 110 | static inline void |
| 110 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) | 111 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 111 | { | 112 | { |
| 112 | tlb->mm = mm; | 113 | tlb->mm = mm; |
| 113 | tlb->fullmm = fullmm; | 114 | tlb->fullmm = !(start | (end+1)); |
| 115 | tlb->start = start; | ||
| 116 | tlb->end = end; | ||
| 114 | tlb->vma = NULL; | 117 | tlb->vma = NULL; |
| 115 | tlb->max = ARRAY_SIZE(tlb->local); | 118 | tlb->max = ARRAY_SIZE(tlb->local); |
| 116 | tlb->pages = tlb->local; | 119 | tlb->pages = tlb->local; |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d40d0ef389db..9cbe70c8b0ef 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
| @@ -357,7 +357,8 @@ ENDPROC(__pabt_svc) | |||
| 357 | .endm | 357 | .endm |
| 358 | 358 | ||
| 359 | .macro kuser_cmpxchg_check | 359 | .macro kuser_cmpxchg_check |
| 360 | #if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) | 360 | #if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ |
| 361 | !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) | ||
| 361 | #ifndef CONFIG_MMU | 362 | #ifndef CONFIG_MMU |
| 362 | #warning "NPTL on non MMU needs fixing" | 363 | #warning "NPTL on non MMU needs fixing" |
| 363 | #else | 364 | #else |
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 25442f451148..fc7920288a3d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
| @@ -84,17 +84,13 @@ int show_fiq_list(struct seq_file *p, int prec) | |||
| 84 | 84 | ||
| 85 | void set_fiq_handler(void *start, unsigned int length) | 85 | void set_fiq_handler(void *start, unsigned int length) |
| 86 | { | 86 | { |
| 87 | #if defined(CONFIG_CPU_USE_DOMAINS) | ||
| 88 | void *base = (void *)0xffff0000; | ||
| 89 | #else | ||
| 90 | void *base = vectors_page; | 87 | void *base = vectors_page; |
| 91 | #endif | ||
| 92 | unsigned offset = FIQ_OFFSET; | 88 | unsigned offset = FIQ_OFFSET; |
| 93 | 89 | ||
| 94 | memcpy(base + offset, start, length); | 90 | memcpy(base + offset, start, length); |
| 91 | if (!cache_is_vipt_nonaliasing()) | ||
| 92 | flush_icache_range(base + offset, offset + length); | ||
| 95 | flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); | 93 | flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); |
| 96 | if (!vectors_high()) | ||
| 97 | flush_icache_range(offset, offset + length); | ||
| 98 | } | 94 | } |
| 99 | 95 | ||
| 100 | int claim_fiq(struct fiq_handler *f) | 96 | int claim_fiq(struct fiq_handler *f) |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 4fb074c446bf..d7c82df69243 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <asm/mmu_context.h> | 15 | #include <asm/mmu_context.h> |
| 16 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
| 17 | #include <asm/mach-types.h> | 17 | #include <asm/mach-types.h> |
| 18 | #include <asm/smp_plat.h> | ||
| 18 | #include <asm/system_misc.h> | 19 | #include <asm/system_misc.h> |
| 19 | 20 | ||
| 20 | extern const unsigned char relocate_new_kernel[]; | 21 | extern const unsigned char relocate_new_kernel[]; |
| @@ -39,6 +40,14 @@ int machine_kexec_prepare(struct kimage *image) | |||
| 39 | int i, err; | 40 | int i, err; |
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| 43 | * Validate that if the current HW supports SMP, then the SW supports | ||
| 44 | * and implements CPU hotplug for the current HW. If not, we won't be | ||
| 45 | * able to kexec reliably, so fail the prepare operation. | ||
| 46 | */ | ||
| 47 | if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug()) | ||
| 48 | return -EINVAL; | ||
| 49 | |||
| 50 | /* | ||
| 42 | * No segment at default ATAGs address. try to locate | 51 | * No segment at default ATAGs address. try to locate |
| 43 | * a dtb using magic. | 52 | * a dtb using magic. |
| 44 | */ | 53 | */ |
| @@ -134,10 +143,13 @@ void machine_kexec(struct kimage *image) | |||
| 134 | unsigned long reboot_code_buffer_phys; | 143 | unsigned long reboot_code_buffer_phys; |
| 135 | void *reboot_code_buffer; | 144 | void *reboot_code_buffer; |
| 136 | 145 | ||
| 137 | if (num_online_cpus() > 1) { | 146 | /* |
| 138 | pr_err("kexec: error: multiple CPUs still online\n"); | 147 | * This can only happen if machine_shutdown() failed to disable some |
| 139 | return; | 148 | * CPU, and that can only happen if the checks in |
| 140 | } | 149 | * machine_kexec_prepare() were not correct. If this fails, we can't |
| 150 | * reliably kexec anyway, so BUG_ON is appropriate. | ||
| 151 | */ | ||
| 152 | BUG_ON(num_online_cpus() > 1); | ||
| 141 | 153 | ||
| 142 | page_list = image->head & PAGE_MASK; | 154 | page_list = image->head & PAGE_MASK; |
| 143 | 155 | ||
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d9f5cd4e533f..e186ee1e63f6 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
| @@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map) | |||
| 53 | static int | 53 | static int |
| 54 | armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) | 54 | armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) |
| 55 | { | 55 | { |
| 56 | int mapping = (*event_map)[config]; | 56 | int mapping; |
| 57 | |||
| 58 | if (config >= PERF_COUNT_HW_MAX) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | mapping = (*event_map)[config]; | ||
| 57 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; | 62 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; |
| 58 | } | 63 | } |
| 59 | 64 | ||
| @@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events, | |||
| 253 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | 258 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); |
| 254 | struct pmu *leader_pmu = event->group_leader->pmu; | 259 | struct pmu *leader_pmu = event->group_leader->pmu; |
| 255 | 260 | ||
| 261 | if (is_software_event(event)) | ||
| 262 | return 1; | ||
| 263 | |||
| 256 | if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) | 264 | if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) |
| 257 | return 1; | 265 | return 1; |
| 258 | 266 | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 536c85fe72a8..94f6b05f9e24 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -462,7 +462,7 @@ int in_gate_area_no_mm(unsigned long addr) | |||
| 462 | { | 462 | { |
| 463 | return in_gate_area(NULL, addr); | 463 | return in_gate_area(NULL, addr); |
| 464 | } | 464 | } |
| 465 | #define is_gate_vma(vma) ((vma) = &gate_vma) | 465 | #define is_gate_vma(vma) ((vma) == &gate_vma) |
| 466 | #else | 466 | #else |
| 467 | #define is_gate_vma(vma) 0 | 467 | #define is_gate_vma(vma) 0 |
| 468 | #endif | 468 | #endif |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index c2b4f8f0be9a..2dc19349eb19 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
| @@ -145,6 +145,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
| 145 | return -ENOSYS; | 145 | return -ENOSYS; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | int platform_can_cpu_hotplug(void) | ||
| 149 | { | ||
| 150 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 151 | if (smp_ops.cpu_kill) | ||
| 152 | return 1; | ||
| 153 | #endif | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 148 | #ifdef CONFIG_HOTPLUG_CPU | 158 | #ifdef CONFIG_HOTPLUG_CPU |
| 149 | static void percpu_timer_stop(void); | 159 | static void percpu_timer_stop(void); |
| 150 | 160 | ||
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 00247c771313..304f069ebf50 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c | |||
| @@ -108,8 +108,8 @@ static void __init dove_clk_init(void) | |||
| 108 | orion_clkdev_add(NULL, "sdhci-dove.1", sdio1); | 108 | orion_clkdev_add(NULL, "sdhci-dove.1", sdio1); |
| 109 | orion_clkdev_add(NULL, "orion_nand", nand); | 109 | orion_clkdev_add(NULL, "orion_nand", nand); |
| 110 | orion_clkdev_add(NULL, "cafe1000-ccic.0", camera); | 110 | orion_clkdev_add(NULL, "cafe1000-ccic.0", camera); |
| 111 | orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0); | 111 | orion_clkdev_add(NULL, "mvebu-audio.0", i2s0); |
| 112 | orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1); | 112 | orion_clkdev_add(NULL, "mvebu-audio.1", i2s1); |
| 113 | orion_clkdev_add(NULL, "mv_crypto", crypto); | 113 | orion_clkdev_add(NULL, "mv_crypto", crypto); |
| 114 | orion_clkdev_add(NULL, "dove-ac97", ac97); | 114 | orion_clkdev_add(NULL, "dove-ac97", ac97); |
| 115 | orion_clkdev_add(NULL, "dove-pdma", pdma); | 115 | orion_clkdev_add(NULL, "dove-pdma", pdma); |
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index e9238b5567ee..1663de090984 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c | |||
| @@ -264,7 +264,7 @@ void __init kirkwood_clk_init(void) | |||
| 264 | orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1); | 264 | orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1); |
| 265 | orion_clkdev_add("0", "pcie", pex0); | 265 | orion_clkdev_add("0", "pcie", pex0); |
| 266 | orion_clkdev_add("1", "pcie", pex1); | 266 | orion_clkdev_add("1", "pcie", pex1); |
| 267 | orion_clkdev_add(NULL, "kirkwood-i2s", audio); | 267 | orion_clkdev_add(NULL, "mvebu-audio", audio); |
| 268 | orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit); | 268 | orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit); |
| 269 | orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit); | 269 | orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit); |
| 270 | 270 | ||
| @@ -560,7 +560,7 @@ void __init kirkwood_timer_init(void) | |||
| 560 | /***************************************************************************** | 560 | /***************************************************************************** |
| 561 | * Audio | 561 | * Audio |
| 562 | ****************************************************************************/ | 562 | ****************************************************************************/ |
| 563 | static struct resource kirkwood_i2s_resources[] = { | 563 | static struct resource kirkwood_audio_resources[] = { |
| 564 | [0] = { | 564 | [0] = { |
| 565 | .start = AUDIO_PHYS_BASE, | 565 | .start = AUDIO_PHYS_BASE, |
| 566 | .end = AUDIO_PHYS_BASE + SZ_16K - 1, | 566 | .end = AUDIO_PHYS_BASE + SZ_16K - 1, |
| @@ -573,29 +573,23 @@ static struct resource kirkwood_i2s_resources[] = { | |||
| 573 | }, | 573 | }, |
| 574 | }; | 574 | }; |
| 575 | 575 | ||
| 576 | static struct kirkwood_asoc_platform_data kirkwood_i2s_data = { | 576 | static struct kirkwood_asoc_platform_data kirkwood_audio_data = { |
| 577 | .burst = 128, | 577 | .burst = 128, |
| 578 | }; | 578 | }; |
| 579 | 579 | ||
| 580 | static struct platform_device kirkwood_i2s_device = { | 580 | static struct platform_device kirkwood_audio_device = { |
| 581 | .name = "kirkwood-i2s", | 581 | .name = "mvebu-audio", |
| 582 | .id = -1, | 582 | .id = -1, |
| 583 | .num_resources = ARRAY_SIZE(kirkwood_i2s_resources), | 583 | .num_resources = ARRAY_SIZE(kirkwood_audio_resources), |
| 584 | .resource = kirkwood_i2s_resources, | 584 | .resource = kirkwood_audio_resources, |
| 585 | .dev = { | 585 | .dev = { |
| 586 | .platform_data = &kirkwood_i2s_data, | 586 | .platform_data = &kirkwood_audio_data, |
| 587 | }, | 587 | }, |
| 588 | }; | 588 | }; |
| 589 | 589 | ||
| 590 | static struct platform_device kirkwood_pcm_device = { | ||
| 591 | .name = "kirkwood-pcm-audio", | ||
| 592 | .id = -1, | ||
| 593 | }; | ||
| 594 | |||
| 595 | void __init kirkwood_audio_init(void) | 590 | void __init kirkwood_audio_init(void) |
| 596 | { | 591 | { |
| 597 | platform_device_register(&kirkwood_i2s_device); | 592 | platform_device_register(&kirkwood_audio_device); |
| 598 | platform_device_register(&kirkwood_pcm_device); | ||
| 599 | } | 593 | } |
| 600 | 594 | ||
| 601 | /***************************************************************************** | 595 | /***************************************************************************** |
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 614e41e7881b..905efc8cac79 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig | |||
| @@ -121,8 +121,7 @@ config MSM_SMD | |||
| 121 | bool | 121 | bool |
| 122 | 122 | ||
| 123 | config MSM_GPIOMUX | 123 | config MSM_GPIOMUX |
| 124 | depends on !(ARCH_MSM8X60 || ARCH_MSM8960) | 124 | bool |
| 125 | bool "MSM V1 TLMM GPIOMUX architecture" | ||
| 126 | help | 125 | help |
| 127 | Support for MSM V1 TLMM GPIOMUX architecture. | 126 | Support for MSM V1 TLMM GPIOMUX architecture. |
| 128 | 127 | ||
diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c deleted file mode 100644 index 27de2abd7144..000000000000 --- a/arch/arm/mach-msm/gpiomux-v1.c +++ /dev/null | |||
| @@ -1,33 +0,0 @@ | |||
| 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License version 2 and | ||
| 5 | * only version 2 as published by the Free Software Foundation. | ||
| 6 | * | ||
| 7 | * This program is distributed in the hope that it will be useful, | ||
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 10 | * GNU General Public License for more details. | ||
| 11 | * | ||
| 12 | * You should have received a copy of the GNU General Public License | ||
| 13 | * along with this program; if not, write to the Free Software | ||
| 14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 15 | * 02110-1301, USA. | ||
| 16 | */ | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include "gpiomux.h" | ||
| 19 | #include "proc_comm.h" | ||
| 20 | |||
| 21 | void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) | ||
| 22 | { | ||
| 23 | unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) | | ||
| 24 | ((gpio & 0x3ff) << 4); | ||
| 25 | unsigned tlmm_disable = 0; | ||
| 26 | int rc; | ||
| 27 | |||
| 28 | rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, | ||
| 29 | &tlmm_config, &tlmm_disable); | ||
| 30 | if (rc) | ||
| 31 | pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n", | ||
| 32 | __func__, rc, tlmm_config, tlmm_disable); | ||
| 33 | } | ||
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h index 8e82f41a8923..4410d7766f93 100644 --- a/arch/arm/mach-msm/gpiomux.h +++ b/arch/arm/mach-msm/gpiomux.h | |||
| @@ -73,16 +73,6 @@ extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS]; | |||
| 73 | int msm_gpiomux_write(unsigned gpio, | 73 | int msm_gpiomux_write(unsigned gpio, |
| 74 | gpiomux_config_t active, | 74 | gpiomux_config_t active, |
| 75 | gpiomux_config_t suspended); | 75 | gpiomux_config_t suspended); |
| 76 | |||
| 77 | /* Architecture-internal function for use by the framework only. | ||
| 78 | * This function can assume the following: | ||
| 79 | * - the gpio value has passed a bounds-check | ||
| 80 | * - the gpiomux spinlock has been obtained | ||
| 81 | * | ||
| 82 | * This function is not for public consumption. External users | ||
| 83 | * should use msm_gpiomux_write. | ||
| 84 | */ | ||
| 85 | void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val); | ||
| 86 | #else | 76 | #else |
| 87 | static inline int msm_gpiomux_write(unsigned gpio, | 77 | static inline int msm_gpiomux_write(unsigned gpio, |
| 88 | gpiomux_config_t active, | 78 | gpiomux_config_t active, |
diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c index 393aeefaebb0..043e5705f2a6 100644 --- a/arch/arm/mach-omap2/dss-common.c +++ b/arch/arm/mach-omap2/dss-common.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | /* Using generic display panel */ | 43 | /* Using generic display panel */ |
| 44 | static struct tfp410_platform_data omap4_dvi_panel = { | 44 | static struct tfp410_platform_data omap4_dvi_panel = { |
| 45 | .i2c_bus_num = 3, | 45 | .i2c_bus_num = 2, |
| 46 | .power_down_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, | 46 | .power_down_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 5cc92874be7e..f99f68e1e85b 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c | |||
| @@ -129,6 +129,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) | |||
| 129 | struct device_node *node = pdev->dev.of_node; | 129 | struct device_node *node = pdev->dev.of_node; |
| 130 | const char *oh_name; | 130 | const char *oh_name; |
| 131 | int oh_cnt, i, ret = 0; | 131 | int oh_cnt, i, ret = 0; |
| 132 | bool device_active = false; | ||
| 132 | 133 | ||
| 133 | oh_cnt = of_property_count_strings(node, "ti,hwmods"); | 134 | oh_cnt = of_property_count_strings(node, "ti,hwmods"); |
| 134 | if (oh_cnt <= 0) { | 135 | if (oh_cnt <= 0) { |
| @@ -152,6 +153,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev) | |||
| 152 | goto odbfd_exit1; | 153 | goto odbfd_exit1; |
| 153 | } | 154 | } |
| 154 | hwmods[i] = oh; | 155 | hwmods[i] = oh; |
| 156 | if (oh->flags & HWMOD_INIT_NO_IDLE) | ||
| 157 | device_active = true; | ||
| 155 | } | 158 | } |
| 156 | 159 | ||
| 157 | od = omap_device_alloc(pdev, hwmods, oh_cnt); | 160 | od = omap_device_alloc(pdev, hwmods, oh_cnt); |
| @@ -172,6 +175,11 @@ static int omap_device_build_from_dt(struct platform_device *pdev) | |||
| 172 | 175 | ||
| 173 | pdev->dev.pm_domain = &omap_device_pm_domain; | 176 | pdev->dev.pm_domain = &omap_device_pm_domain; |
| 174 | 177 | ||
| 178 | if (device_active) { | ||
| 179 | omap_device_enable(pdev); | ||
| 180 | pm_runtime_set_active(&pdev->dev); | ||
| 181 | } | ||
| 182 | |||
| 175 | odbfd_exit1: | 183 | odbfd_exit1: |
| 176 | kfree(hwmods); | 184 | kfree(hwmods); |
| 177 | odbfd_exit: | 185 | odbfd_exit: |
| @@ -842,6 +850,7 @@ static int __init omap_device_late_idle(struct device *dev, void *data) | |||
| 842 | { | 850 | { |
| 843 | struct platform_device *pdev = to_platform_device(dev); | 851 | struct platform_device *pdev = to_platform_device(dev); |
| 844 | struct omap_device *od = to_omap_device(pdev); | 852 | struct omap_device *od = to_omap_device(pdev); |
| 853 | int i; | ||
| 845 | 854 | ||
| 846 | if (!od) | 855 | if (!od) |
| 847 | return 0; | 856 | return 0; |
| @@ -850,6 +859,15 @@ static int __init omap_device_late_idle(struct device *dev, void *data) | |||
| 850 | * If omap_device state is enabled, but has no driver bound, | 859 | * If omap_device state is enabled, but has no driver bound, |
| 851 | * idle it. | 860 | * idle it. |
| 852 | */ | 861 | */ |
| 862 | |||
| 863 | /* | ||
| 864 | * Some devices (like memory controllers) are always kept | ||
| 865 | * enabled, and should not be idled even with no drivers. | ||
| 866 | */ | ||
| 867 | for (i = 0; i < od->hwmods_cnt; i++) | ||
| 868 | if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE) | ||
| 869 | return 0; | ||
| 870 | |||
| 853 | if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { | 871 | if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { |
| 854 | if (od->_state == OMAP_DEVICE_STATE_ENABLED) { | 872 | if (od->_state == OMAP_DEVICE_STATE_ENABLED) { |
| 855 | dev_warn(dev, "%s: enabled but no driver. Idling\n", | 873 | dev_warn(dev, "%s: enabled but no driver. Idling\n", |
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 7341eff63f56..7f4db12b1459 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
| @@ -2386,7 +2386,7 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) | |||
| 2386 | 2386 | ||
| 2387 | np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); | 2387 | np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); |
| 2388 | if (np) | 2388 | if (np) |
| 2389 | va_start = of_iomap(np, 0); | 2389 | va_start = of_iomap(np, oh->mpu_rt_idx); |
| 2390 | } else { | 2390 | } else { |
| 2391 | va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); | 2391 | va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); |
| 2392 | } | 2392 | } |
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index aab33fd814c0..e1482a9b3bc2 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h | |||
| @@ -95,6 +95,54 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3; | |||
| 95 | #define MODULEMODE_HWCTRL 1 | 95 | #define MODULEMODE_HWCTRL 1 |
| 96 | #define MODULEMODE_SWCTRL 2 | 96 | #define MODULEMODE_SWCTRL 2 |
| 97 | 97 | ||
| 98 | #define DEBUG_OMAP2UART1_FLAGS 0 | ||
| 99 | #define DEBUG_OMAP2UART2_FLAGS 0 | ||
| 100 | #define DEBUG_OMAP2UART3_FLAGS 0 | ||
| 101 | #define DEBUG_OMAP3UART3_FLAGS 0 | ||
| 102 | #define DEBUG_OMAP3UART4_FLAGS 0 | ||
| 103 | #define DEBUG_OMAP4UART3_FLAGS 0 | ||
| 104 | #define DEBUG_OMAP4UART4_FLAGS 0 | ||
| 105 | #define DEBUG_TI81XXUART1_FLAGS 0 | ||
| 106 | #define DEBUG_TI81XXUART2_FLAGS 0 | ||
| 107 | #define DEBUG_TI81XXUART3_FLAGS 0 | ||
| 108 | #define DEBUG_AM33XXUART1_FLAGS 0 | ||
| 109 | |||
| 110 | #define DEBUG_OMAPUART_FLAGS (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET) | ||
| 111 | |||
| 112 | #if defined(CONFIG_DEBUG_OMAP2UART1) | ||
| 113 | #undef DEBUG_OMAP2UART1_FLAGS | ||
| 114 | #define DEBUG_OMAP2UART1_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 115 | #elif defined(CONFIG_DEBUG_OMAP2UART2) | ||
| 116 | #undef DEBUG_OMAP2UART2_FLAGS | ||
| 117 | #define DEBUG_OMAP2UART2_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 118 | #elif defined(CONFIG_DEBUG_OMAP2UART3) | ||
| 119 | #undef DEBUG_OMAP2UART3_FLAGS | ||
| 120 | #define DEBUG_OMAP2UART3_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 121 | #elif defined(CONFIG_DEBUG_OMAP3UART3) | ||
| 122 | #undef DEBUG_OMAP3UART3_FLAGS | ||
| 123 | #define DEBUG_OMAP3UART3_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 124 | #elif defined(CONFIG_DEBUG_OMAP3UART4) | ||
| 125 | #undef DEBUG_OMAP3UART4_FLAGS | ||
| 126 | #define DEBUG_OMAP3UART4_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 127 | #elif defined(CONFIG_DEBUG_OMAP4UART3) | ||
| 128 | #undef DEBUG_OMAP4UART3_FLAGS | ||
| 129 | #define DEBUG_OMAP4UART3_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 130 | #elif defined(CONFIG_DEBUG_OMAP4UART4) | ||
| 131 | #undef DEBUG_OMAP4UART4_FLAGS | ||
| 132 | #define DEBUG_OMAP4UART4_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 133 | #elif defined(CONFIG_DEBUG_TI81XXUART1) | ||
| 134 | #undef DEBUG_TI81XXUART1_FLAGS | ||
| 135 | #define DEBUG_TI81XXUART1_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 136 | #elif defined(CONFIG_DEBUG_TI81XXUART2) | ||
| 137 | #undef DEBUG_TI81XXUART2_FLAGS | ||
| 138 | #define DEBUG_TI81XXUART2_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 139 | #elif defined(CONFIG_DEBUG_TI81XXUART3) | ||
| 140 | #undef DEBUG_TI81XXUART3_FLAGS | ||
| 141 | #define DEBUG_TI81XXUART3_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 142 | #elif defined(CONFIG_DEBUG_AM33XXUART1) | ||
| 143 | #undef DEBUG_AM33XXUART1_FLAGS | ||
| 144 | #define DEBUG_AM33XXUART1_FLAGS DEBUG_OMAPUART_FLAGS | ||
| 145 | #endif | ||
| 98 | 146 | ||
| 99 | /** | 147 | /** |
| 100 | * struct omap_hwmod_mux_info - hwmod specific mux configuration | 148 | * struct omap_hwmod_mux_info - hwmod specific mux configuration |
| @@ -568,6 +616,7 @@ struct omap_hwmod_link { | |||
| 568 | * @voltdm: pointer to voltage domain (filled in at runtime) | 616 | * @voltdm: pointer to voltage domain (filled in at runtime) |
| 569 | * @dev_attr: arbitrary device attributes that can be passed to the driver | 617 | * @dev_attr: arbitrary device attributes that can be passed to the driver |
| 570 | * @_sysc_cache: internal-use hwmod flags | 618 | * @_sysc_cache: internal-use hwmod flags |
| 619 | * @mpu_rt_idx: index of device address space for register target (for DT boot) | ||
| 571 | * @_mpu_rt_va: cached register target start address (internal use) | 620 | * @_mpu_rt_va: cached register target start address (internal use) |
| 572 | * @_mpu_port: cached MPU register target slave (internal use) | 621 | * @_mpu_port: cached MPU register target slave (internal use) |
| 573 | * @opt_clks_cnt: number of @opt_clks | 622 | * @opt_clks_cnt: number of @opt_clks |
| @@ -617,6 +666,7 @@ struct omap_hwmod { | |||
| 617 | struct list_head node; | 666 | struct list_head node; |
| 618 | struct omap_hwmod_ocp_if *_mpu_port; | 667 | struct omap_hwmod_ocp_if *_mpu_port; |
| 619 | u16 flags; | 668 | u16 flags; |
| 669 | u8 mpu_rt_idx; | ||
| 620 | u8 response_lat; | 670 | u8 response_lat; |
| 621 | u8 rst_lines_cnt; | 671 | u8 rst_lines_cnt; |
| 622 | u8 opt_clks_cnt; | 672 | u8 opt_clks_cnt; |
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index d05fc7b54567..56cebb05509e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | |||
| @@ -512,7 +512,7 @@ struct omap_hwmod omap2xxx_uart1_hwmod = { | |||
| 512 | .mpu_irqs = omap2_uart1_mpu_irqs, | 512 | .mpu_irqs = omap2_uart1_mpu_irqs, |
| 513 | .sdma_reqs = omap2_uart1_sdma_reqs, | 513 | .sdma_reqs = omap2_uart1_sdma_reqs, |
| 514 | .main_clk = "uart1_fck", | 514 | .main_clk = "uart1_fck", |
| 515 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 515 | .flags = DEBUG_OMAP2UART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 516 | .prcm = { | 516 | .prcm = { |
| 517 | .omap2 = { | 517 | .omap2 = { |
| 518 | .module_offs = CORE_MOD, | 518 | .module_offs = CORE_MOD, |
| @@ -532,7 +532,7 @@ struct omap_hwmod omap2xxx_uart2_hwmod = { | |||
| 532 | .mpu_irqs = omap2_uart2_mpu_irqs, | 532 | .mpu_irqs = omap2_uart2_mpu_irqs, |
| 533 | .sdma_reqs = omap2_uart2_sdma_reqs, | 533 | .sdma_reqs = omap2_uart2_sdma_reqs, |
| 534 | .main_clk = "uart2_fck", | 534 | .main_clk = "uart2_fck", |
| 535 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 535 | .flags = DEBUG_OMAP2UART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 536 | .prcm = { | 536 | .prcm = { |
| 537 | .omap2 = { | 537 | .omap2 = { |
| 538 | .module_offs = CORE_MOD, | 538 | .module_offs = CORE_MOD, |
| @@ -552,7 +552,7 @@ struct omap_hwmod omap2xxx_uart3_hwmod = { | |||
| 552 | .mpu_irqs = omap2_uart3_mpu_irqs, | 552 | .mpu_irqs = omap2_uart3_mpu_irqs, |
| 553 | .sdma_reqs = omap2_uart3_sdma_reqs, | 553 | .sdma_reqs = omap2_uart3_sdma_reqs, |
| 554 | .main_clk = "uart3_fck", | 554 | .main_clk = "uart3_fck", |
| 555 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 555 | .flags = DEBUG_OMAP2UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 556 | .prcm = { | 556 | .prcm = { |
| 557 | .omap2 = { | 557 | .omap2 = { |
| 558 | .module_offs = CORE_MOD, | 558 | .module_offs = CORE_MOD, |
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 28bbd56346a9..eb2f3b93b51c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c | |||
| @@ -562,6 +562,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = { | |||
| 562 | .clkdm_name = "cpsw_125mhz_clkdm", | 562 | .clkdm_name = "cpsw_125mhz_clkdm", |
| 563 | .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), | 563 | .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), |
| 564 | .main_clk = "cpsw_125mhz_gclk", | 564 | .main_clk = "cpsw_125mhz_gclk", |
| 565 | .mpu_rt_idx = 1, | ||
| 565 | .prcm = { | 566 | .prcm = { |
| 566 | .omap4 = { | 567 | .omap4 = { |
| 567 | .clkctrl_offs = AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET, | 568 | .clkctrl_offs = AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET, |
| @@ -1512,7 +1513,7 @@ static struct omap_hwmod am33xx_uart1_hwmod = { | |||
| 1512 | .name = "uart1", | 1513 | .name = "uart1", |
| 1513 | .class = &uart_class, | 1514 | .class = &uart_class, |
| 1514 | .clkdm_name = "l4_wkup_clkdm", | 1515 | .clkdm_name = "l4_wkup_clkdm", |
| 1515 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 1516 | .flags = DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 1516 | .main_clk = "dpll_per_m2_div4_wkupdm_ck", | 1517 | .main_clk = "dpll_per_m2_div4_wkupdm_ck", |
| 1517 | .prcm = { | 1518 | .prcm = { |
| 1518 | .omap4 = { | 1519 | .omap4 = { |
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index f7a3df2fb579..0c3a427da544 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | |||
| @@ -490,7 +490,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = { | |||
| 490 | .mpu_irqs = omap2_uart1_mpu_irqs, | 490 | .mpu_irqs = omap2_uart1_mpu_irqs, |
| 491 | .sdma_reqs = omap2_uart1_sdma_reqs, | 491 | .sdma_reqs = omap2_uart1_sdma_reqs, |
| 492 | .main_clk = "uart1_fck", | 492 | .main_clk = "uart1_fck", |
| 493 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 493 | .flags = DEBUG_TI81XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 494 | .prcm = { | 494 | .prcm = { |
| 495 | .omap2 = { | 495 | .omap2 = { |
| 496 | .module_offs = CORE_MOD, | 496 | .module_offs = CORE_MOD, |
| @@ -509,7 +509,7 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = { | |||
| 509 | .mpu_irqs = omap2_uart2_mpu_irqs, | 509 | .mpu_irqs = omap2_uart2_mpu_irqs, |
| 510 | .sdma_reqs = omap2_uart2_sdma_reqs, | 510 | .sdma_reqs = omap2_uart2_sdma_reqs, |
| 511 | .main_clk = "uart2_fck", | 511 | .main_clk = "uart2_fck", |
| 512 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 512 | .flags = DEBUG_TI81XXUART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 513 | .prcm = { | 513 | .prcm = { |
| 514 | .omap2 = { | 514 | .omap2 = { |
| 515 | .module_offs = CORE_MOD, | 515 | .module_offs = CORE_MOD, |
| @@ -528,7 +528,8 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = { | |||
| 528 | .mpu_irqs = omap2_uart3_mpu_irqs, | 528 | .mpu_irqs = omap2_uart3_mpu_irqs, |
| 529 | .sdma_reqs = omap2_uart3_sdma_reqs, | 529 | .sdma_reqs = omap2_uart3_sdma_reqs, |
| 530 | .main_clk = "uart3_fck", | 530 | .main_clk = "uart3_fck", |
| 531 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 531 | .flags = DEBUG_OMAP3UART3_FLAGS | DEBUG_TI81XXUART3_FLAGS | |
| 532 | HWMOD_SWSUP_SIDLE_ACT, | ||
| 532 | .prcm = { | 533 | .prcm = { |
| 533 | .omap2 = { | 534 | .omap2 = { |
| 534 | .module_offs = OMAP3430_PER_MOD, | 535 | .module_offs = OMAP3430_PER_MOD, |
| @@ -558,7 +559,7 @@ static struct omap_hwmod omap36xx_uart4_hwmod = { | |||
| 558 | .mpu_irqs = uart4_mpu_irqs, | 559 | .mpu_irqs = uart4_mpu_irqs, |
| 559 | .sdma_reqs = uart4_sdma_reqs, | 560 | .sdma_reqs = uart4_sdma_reqs, |
| 560 | .main_clk = "uart4_fck", | 561 | .main_clk = "uart4_fck", |
| 561 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 562 | .flags = DEBUG_OMAP3UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 562 | .prcm = { | 563 | .prcm = { |
| 563 | .omap2 = { | 564 | .omap2 = { |
| 564 | .module_offs = OMAP3430_PER_MOD, | 565 | .module_offs = OMAP3430_PER_MOD, |
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index d04b5e60fdbe..9c3b504477d7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | |||
| @@ -2858,8 +2858,7 @@ static struct omap_hwmod omap44xx_uart3_hwmod = { | |||
| 2858 | .name = "uart3", | 2858 | .name = "uart3", |
| 2859 | .class = &omap44xx_uart_hwmod_class, | 2859 | .class = &omap44xx_uart_hwmod_class, |
| 2860 | .clkdm_name = "l4_per_clkdm", | 2860 | .clkdm_name = "l4_per_clkdm", |
| 2861 | .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET | | 2861 | .flags = DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 2862 | HWMOD_SWSUP_SIDLE_ACT, | ||
| 2863 | .main_clk = "func_48m_fclk", | 2862 | .main_clk = "func_48m_fclk", |
| 2864 | .prcm = { | 2863 | .prcm = { |
| 2865 | .omap4 = { | 2864 | .omap4 = { |
| @@ -2875,7 +2874,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = { | |||
| 2875 | .name = "uart4", | 2874 | .name = "uart4", |
| 2876 | .class = &omap44xx_uart_hwmod_class, | 2875 | .class = &omap44xx_uart_hwmod_class, |
| 2877 | .clkdm_name = "l4_per_clkdm", | 2876 | .clkdm_name = "l4_per_clkdm", |
| 2878 | .flags = HWMOD_SWSUP_SIDLE_ACT, | 2877 | .flags = DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT, |
| 2879 | .main_clk = "func_48m_fclk", | 2878 | .main_clk = "func_48m_fclk", |
| 2880 | .prcm = { | 2879 | .prcm = { |
| 2881 | .omap4 = { | 2880 | .omap4 = { |
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index f37ae96b70a1..3c70f5c1860f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c | |||
| @@ -1375,7 +1375,7 @@ static struct omap_hwmod omap54xx_uart3_hwmod = { | |||
| 1375 | .name = "uart3", | 1375 | .name = "uart3", |
| 1376 | .class = &omap54xx_uart_hwmod_class, | 1376 | .class = &omap54xx_uart_hwmod_class, |
| 1377 | .clkdm_name = "l4per_clkdm", | 1377 | .clkdm_name = "l4per_clkdm", |
| 1378 | .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, | 1378 | .flags = DEBUG_OMAP4UART3_FLAGS, |
| 1379 | .main_clk = "func_48m_fclk", | 1379 | .main_clk = "func_48m_fclk", |
| 1380 | .prcm = { | 1380 | .prcm = { |
| 1381 | .omap4 = { | 1381 | .omap4 = { |
| @@ -1391,6 +1391,7 @@ static struct omap_hwmod omap54xx_uart4_hwmod = { | |||
| 1391 | .name = "uart4", | 1391 | .name = "uart4", |
| 1392 | .class = &omap54xx_uart_hwmod_class, | 1392 | .class = &omap54xx_uart_hwmod_class, |
| 1393 | .clkdm_name = "l4per_clkdm", | 1393 | .clkdm_name = "l4per_clkdm", |
| 1394 | .flags = DEBUG_OMAP4UART4_FLAGS, | ||
| 1394 | .main_clk = "func_48m_fclk", | 1395 | .main_clk = "func_48m_fclk", |
| 1395 | .prcm = { | 1396 | .prcm = { |
| 1396 | .omap4 = { | 1397 | .omap4 = { |
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 3a674de6cb63..a388f8c1bcb3 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
| @@ -208,17 +208,6 @@ static int __init omap_serial_early_init(void) | |||
| 208 | pr_info("%s used as console in debug mode: uart%d clocks will not be gated", | 208 | pr_info("%s used as console in debug mode: uart%d clocks will not be gated", |
| 209 | uart_name, uart->num); | 209 | uart_name, uart->num); |
| 210 | } | 210 | } |
| 211 | |||
| 212 | /* | ||
| 213 | * omap-uart can be used for earlyprintk logs | ||
| 214 | * So if omap-uart is used as console then prevent | ||
| 215 | * uart reset and idle to get logs from omap-uart | ||
| 216 | * until uart console driver is available to take | ||
| 217 | * care for console messages. | ||
| 218 | * Idling or resetting omap-uart while printing logs | ||
| 219 | * early boot logs can stall the boot-up. | ||
| 220 | */ | ||
| 221 | oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; | ||
| 222 | } | 211 | } |
| 223 | } while (1); | 212 | } while (1); |
| 224 | 213 | ||
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index e115f6742107..c5be60d85e4b 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c | |||
| @@ -1162,9 +1162,6 @@ static void __init eva_init(void) | |||
| 1162 | gpio_request_one(61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */ | 1162 | gpio_request_one(61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */ |
| 1163 | gpio_request_one(202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */ | 1163 | gpio_request_one(202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */ |
| 1164 | 1164 | ||
| 1165 | /* Touchscreen */ | ||
| 1166 | gpio_request_one(166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */ | ||
| 1167 | |||
| 1168 | /* GETHER */ | 1165 | /* GETHER */ |
| 1169 | gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */ | 1166 | gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */ |
| 1170 | 1167 | ||
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index d5554646916c..3354a85c90f7 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c | |||
| @@ -167,7 +167,13 @@ static const struct pinctrl_map bockw_pinctrl_map[] = { | |||
| 167 | "usb1", "usb1"), | 167 | "usb1", "usb1"), |
| 168 | /* SDHI0 */ | 168 | /* SDHI0 */ |
| 169 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", | 169 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", |
| 170 | "sdhi0", "sdhi0"), | 170 | "sdhi0_data4", "sdhi0"), |
| 171 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", | ||
| 172 | "sdhi0_ctrl", "sdhi0"), | ||
| 173 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", | ||
| 174 | "sdhi0_cd", "sdhi0"), | ||
| 175 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", | ||
| 176 | "sdhi0_wp", "sdhi0"), | ||
| 171 | }; | 177 | }; |
| 172 | 178 | ||
| 173 | #define FPGA 0x18200000 | 179 | #define FPGA 0x18200000 |
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c index d73e21d3ea8a..8d6bd5c5efb9 100644 --- a/arch/arm/mach-shmobile/board-lager.c +++ b/arch/arm/mach-shmobile/board-lager.c | |||
| @@ -59,7 +59,7 @@ static __initdata struct gpio_led_platform_data lager_leds_pdata = { | |||
| 59 | #define GPIO_KEY(c, g, d, ...) \ | 59 | #define GPIO_KEY(c, g, d, ...) \ |
| 60 | { .code = c, .gpio = g, .desc = d, .active_low = 1 } | 60 | { .code = c, .gpio = g, .desc = d, .active_low = 1 } |
| 61 | 61 | ||
| 62 | static __initdata struct gpio_keys_button gpio_buttons[] = { | 62 | static struct gpio_keys_button gpio_buttons[] = { |
| 63 | GPIO_KEY(KEY_4, RCAR_GP_PIN(1, 28), "SW2-pin4"), | 63 | GPIO_KEY(KEY_4, RCAR_GP_PIN(1, 28), "SW2-pin4"), |
| 64 | GPIO_KEY(KEY_3, RCAR_GP_PIN(1, 26), "SW2-pin3"), | 64 | GPIO_KEY(KEY_3, RCAR_GP_PIN(1, 26), "SW2-pin3"), |
| 65 | GPIO_KEY(KEY_2, RCAR_GP_PIN(1, 24), "SW2-pin2"), | 65 | GPIO_KEY(KEY_2, RCAR_GP_PIN(1, 24), "SW2-pin2"), |
diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S index 78ebc7559f53..4c09bae86edf 100644 --- a/arch/arm/mach-sti/headsmp.S +++ b/arch/arm/mach-sti/headsmp.S | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | 18 | ||
| 19 | __INIT | ||
| 20 | |||
| 21 | /* | 19 | /* |
| 22 | * ST specific entry point for secondary CPUs. This provides | 20 | * ST specific entry point for secondary CPUs. This provides |
| 23 | * a "holding pen" into which all secondary cores are held until we're | 21 | * a "holding pen" into which all secondary cores are held until we're |
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 8e11e96eab5e..c83f27b6bdda 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/spi/pxa2xx_spi.h> | 31 | #include <linux/spi/pxa2xx_spi.h> |
| 32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
| 33 | #include <linux/of.h> | ||
| 34 | #include <linux/of_device.h> | ||
| 33 | 35 | ||
| 34 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
| 35 | #include <mach/hardware.h> | 37 | #include <mach/hardware.h> |
| @@ -60,6 +62,30 @@ struct ssp_device *pxa_ssp_request(int port, const char *label) | |||
| 60 | } | 62 | } |
| 61 | EXPORT_SYMBOL(pxa_ssp_request); | 63 | EXPORT_SYMBOL(pxa_ssp_request); |
| 62 | 64 | ||
| 65 | struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node, | ||
| 66 | const char *label) | ||
| 67 | { | ||
| 68 | struct ssp_device *ssp = NULL; | ||
| 69 | |||
| 70 | mutex_lock(&ssp_lock); | ||
| 71 | |||
| 72 | list_for_each_entry(ssp, &ssp_list, node) { | ||
| 73 | if (ssp->of_node == of_node && ssp->use_count == 0) { | ||
| 74 | ssp->use_count++; | ||
| 75 | ssp->label = label; | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | mutex_unlock(&ssp_lock); | ||
| 81 | |||
| 82 | if (&ssp->node == &ssp_list) | ||
| 83 | return NULL; | ||
| 84 | |||
| 85 | return ssp; | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL(pxa_ssp_request_of); | ||
| 88 | |||
| 63 | void pxa_ssp_free(struct ssp_device *ssp) | 89 | void pxa_ssp_free(struct ssp_device *ssp) |
| 64 | { | 90 | { |
| 65 | mutex_lock(&ssp_lock); | 91 | mutex_lock(&ssp_lock); |
| @@ -72,96 +98,126 @@ void pxa_ssp_free(struct ssp_device *ssp) | |||
| 72 | } | 98 | } |
| 73 | EXPORT_SYMBOL(pxa_ssp_free); | 99 | EXPORT_SYMBOL(pxa_ssp_free); |
| 74 | 100 | ||
| 101 | #ifdef CONFIG_OF | ||
| 102 | static const struct of_device_id pxa_ssp_of_ids[] = { | ||
| 103 | { .compatible = "mrvl,pxa25x-ssp", .data = (void *) PXA25x_SSP }, | ||
| 104 | { .compatible = "mvrl,pxa25x-nssp", .data = (void *) PXA25x_NSSP }, | ||
| 105 | { .compatible = "mrvl,pxa27x-ssp", .data = (void *) PXA27x_SSP }, | ||
| 106 | { .compatible = "mrvl,pxa3xx-ssp", .data = (void *) PXA3xx_SSP }, | ||
| 107 | { .compatible = "mvrl,pxa168-ssp", .data = (void *) PXA168_SSP }, | ||
| 108 | { .compatible = "mrvl,pxa910-ssp", .data = (void *) PXA910_SSP }, | ||
| 109 | { .compatible = "mrvl,ce4100-ssp", .data = (void *) CE4100_SSP }, | ||
| 110 | { .compatible = "mrvl,lpss-ssp", .data = (void *) LPSS_SSP }, | ||
| 111 | { }, | ||
| 112 | }; | ||
| 113 | MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids); | ||
| 114 | #endif | ||
| 115 | |||
| 75 | static int pxa_ssp_probe(struct platform_device *pdev) | 116 | static int pxa_ssp_probe(struct platform_device *pdev) |
| 76 | { | 117 | { |
| 77 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
| 78 | struct resource *res; | 118 | struct resource *res; |
| 79 | struct ssp_device *ssp; | 119 | struct ssp_device *ssp; |
| 80 | int ret = 0; | 120 | struct device *dev = &pdev->dev; |
| 81 | 121 | ||
| 82 | ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL); | 122 | ssp = devm_kzalloc(dev, sizeof(struct ssp_device), GFP_KERNEL); |
| 83 | if (ssp == NULL) { | 123 | if (ssp == NULL) |
| 84 | dev_err(&pdev->dev, "failed to allocate memory"); | ||
| 85 | return -ENOMEM; | 124 | return -ENOMEM; |
| 86 | } | ||
| 87 | ssp->pdev = pdev; | ||
| 88 | 125 | ||
| 89 | ssp->clk = clk_get(&pdev->dev, NULL); | 126 | ssp->pdev = pdev; |
| 90 | if (IS_ERR(ssp->clk)) { | ||
| 91 | ret = PTR_ERR(ssp->clk); | ||
| 92 | goto err_free; | ||
| 93 | } | ||
| 94 | 127 | ||
| 95 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 128 | ssp->clk = devm_clk_get(dev, NULL); |
| 96 | if (res == NULL) { | 129 | if (IS_ERR(ssp->clk)) |
| 97 | dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); | 130 | return PTR_ERR(ssp->clk); |
| 98 | ret = -ENODEV; | 131 | |
| 99 | goto err_free_clk; | 132 | if (dev->of_node) { |
| 100 | } | 133 | struct of_phandle_args dma_spec; |
| 101 | ssp->drcmr_rx = res->start; | 134 | struct device_node *np = dev->of_node; |
| 135 | |||
| 136 | /* | ||
| 137 | * FIXME: we should allocate the DMA channel from this | ||
| 138 | * context and pass the channel down to the ssp users. | ||
| 139 | * For now, we lookup the rx and tx indices manually | ||
| 140 | */ | ||
| 141 | |||
| 142 | /* rx */ | ||
| 143 | of_parse_phandle_with_args(np, "dmas", "#dma-cells", | ||
| 144 | 0, &dma_spec); | ||
| 145 | ssp->drcmr_rx = dma_spec.args[0]; | ||
| 146 | of_node_put(dma_spec.np); | ||
| 147 | |||
| 148 | /* tx */ | ||
| 149 | of_parse_phandle_with_args(np, "dmas", "#dma-cells", | ||
| 150 | 1, &dma_spec); | ||
| 151 | ssp->drcmr_tx = dma_spec.args[0]; | ||
| 152 | of_node_put(dma_spec.np); | ||
| 153 | } else { | ||
| 154 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
| 155 | if (res == NULL) { | ||
| 156 | dev_err(dev, "no SSP RX DRCMR defined\n"); | ||
| 157 | return -ENODEV; | ||
| 158 | } | ||
| 159 | ssp->drcmr_rx = res->start; | ||
| 102 | 160 | ||
| 103 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 161 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
| 104 | if (res == NULL) { | 162 | if (res == NULL) { |
| 105 | dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); | 163 | dev_err(dev, "no SSP TX DRCMR defined\n"); |
| 106 | ret = -ENODEV; | 164 | return -ENODEV; |
| 107 | goto err_free_clk; | 165 | } |
| 166 | ssp->drcmr_tx = res->start; | ||
| 108 | } | 167 | } |
| 109 | ssp->drcmr_tx = res->start; | ||
| 110 | 168 | ||
| 111 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 169 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 112 | if (res == NULL) { | 170 | if (res == NULL) { |
| 113 | dev_err(&pdev->dev, "no memory resource defined\n"); | 171 | dev_err(dev, "no memory resource defined\n"); |
| 114 | ret = -ENODEV; | 172 | return -ENODEV; |
| 115 | goto err_free_clk; | ||
| 116 | } | 173 | } |
| 117 | 174 | ||
| 118 | res = request_mem_region(res->start, resource_size(res), | 175 | res = devm_request_mem_region(dev, res->start, resource_size(res), |
| 119 | pdev->name); | 176 | pdev->name); |
| 120 | if (res == NULL) { | 177 | if (res == NULL) { |
| 121 | dev_err(&pdev->dev, "failed to request memory resource\n"); | 178 | dev_err(dev, "failed to request memory resource\n"); |
| 122 | ret = -EBUSY; | 179 | return -EBUSY; |
| 123 | goto err_free_clk; | ||
| 124 | } | 180 | } |
| 125 | 181 | ||
| 126 | ssp->phys_base = res->start; | 182 | ssp->phys_base = res->start; |
| 127 | 183 | ||
| 128 | ssp->mmio_base = ioremap(res->start, resource_size(res)); | 184 | ssp->mmio_base = devm_ioremap(dev, res->start, resource_size(res)); |
| 129 | if (ssp->mmio_base == NULL) { | 185 | if (ssp->mmio_base == NULL) { |
| 130 | dev_err(&pdev->dev, "failed to ioremap() registers\n"); | 186 | dev_err(dev, "failed to ioremap() registers\n"); |
| 131 | ret = -ENODEV; | 187 | return -ENODEV; |
| 132 | goto err_free_mem; | ||
| 133 | } | 188 | } |
| 134 | 189 | ||
| 135 | ssp->irq = platform_get_irq(pdev, 0); | 190 | ssp->irq = platform_get_irq(pdev, 0); |
| 136 | if (ssp->irq < 0) { | 191 | if (ssp->irq < 0) { |
| 137 | dev_err(&pdev->dev, "no IRQ resource defined\n"); | 192 | dev_err(dev, "no IRQ resource defined\n"); |
| 138 | ret = -ENODEV; | 193 | return -ENODEV; |
| 139 | goto err_free_io; | 194 | } |
| 195 | |||
| 196 | if (dev->of_node) { | ||
| 197 | const struct of_device_id *id = | ||
| 198 | of_match_device(of_match_ptr(pxa_ssp_of_ids), dev); | ||
| 199 | ssp->type = (int) id->data; | ||
| 200 | } else { | ||
| 201 | const struct platform_device_id *id = | ||
| 202 | platform_get_device_id(pdev); | ||
| 203 | ssp->type = (int) id->driver_data; | ||
| 204 | |||
| 205 | /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id | ||
| 206 | * starts from 0, do a translation here | ||
| 207 | */ | ||
| 208 | ssp->port_id = pdev->id + 1; | ||
| 140 | } | 209 | } |
| 141 | 210 | ||
| 142 | /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id | ||
| 143 | * starts from 0, do a translation here | ||
| 144 | */ | ||
| 145 | ssp->port_id = pdev->id + 1; | ||
| 146 | ssp->use_count = 0; | 211 | ssp->use_count = 0; |
| 147 | ssp->type = (int)id->driver_data; | 212 | ssp->of_node = dev->of_node; |
| 148 | 213 | ||
| 149 | mutex_lock(&ssp_lock); | 214 | mutex_lock(&ssp_lock); |
| 150 | list_add(&ssp->node, &ssp_list); | 215 | list_add(&ssp->node, &ssp_list); |
| 151 | mutex_unlock(&ssp_lock); | 216 | mutex_unlock(&ssp_lock); |
| 152 | 217 | ||
| 153 | platform_set_drvdata(pdev, ssp); | 218 | platform_set_drvdata(pdev, ssp); |
| 154 | return 0; | ||
| 155 | 219 | ||
| 156 | err_free_io: | 220 | return 0; |
| 157 | iounmap(ssp->mmio_base); | ||
| 158 | err_free_mem: | ||
| 159 | release_mem_region(res->start, resource_size(res)); | ||
| 160 | err_free_clk: | ||
| 161 | clk_put(ssp->clk); | ||
| 162 | err_free: | ||
| 163 | kfree(ssp); | ||
| 164 | return ret; | ||
| 165 | } | 221 | } |
| 166 | 222 | ||
| 167 | static int pxa_ssp_remove(struct platform_device *pdev) | 223 | static int pxa_ssp_remove(struct platform_device *pdev) |
| @@ -201,8 +257,9 @@ static struct platform_driver pxa_ssp_driver = { | |||
| 201 | .probe = pxa_ssp_probe, | 257 | .probe = pxa_ssp_probe, |
| 202 | .remove = pxa_ssp_remove, | 258 | .remove = pxa_ssp_remove, |
| 203 | .driver = { | 259 | .driver = { |
| 204 | .owner = THIS_MODULE, | 260 | .owner = THIS_MODULE, |
| 205 | .name = "pxa2xx-ssp", | 261 | .name = "pxa2xx-ssp", |
| 262 | .of_match_table = of_match_ptr(pxa_ssp_of_ids), | ||
| 206 | }, | 263 | }, |
| 207 | .id_table = ssp_id_table, | 264 | .id_table = ssp_id_table, |
| 208 | }; | 265 | }; |
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h index 46b3beb4b773..717031a762c2 100644 --- a/arch/arm64/include/asm/tlb.h +++ b/arch/arm64/include/asm/tlb.h | |||
| @@ -35,6 +35,7 @@ struct mmu_gather { | |||
| 35 | struct mm_struct *mm; | 35 | struct mm_struct *mm; |
| 36 | unsigned int fullmm; | 36 | unsigned int fullmm; |
| 37 | struct vm_area_struct *vma; | 37 | struct vm_area_struct *vma; |
| 38 | unsigned long start, end; | ||
| 38 | unsigned long range_start; | 39 | unsigned long range_start; |
| 39 | unsigned long range_end; | 40 | unsigned long range_end; |
| 40 | unsigned int nr; | 41 | unsigned int nr; |
| @@ -97,10 +98,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb) | |||
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | static inline void | 100 | static inline void |
| 100 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) | 101 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 101 | { | 102 | { |
| 102 | tlb->mm = mm; | 103 | tlb->mm = mm; |
| 103 | tlb->fullmm = fullmm; | 104 | tlb->fullmm = !(start | (end+1)); |
| 105 | tlb->start = start; | ||
| 106 | tlb->end = end; | ||
| 104 | tlb->vma = NULL; | 107 | tlb->vma = NULL; |
| 105 | tlb->max = ARRAY_SIZE(tlb->local); | 108 | tlb->max = ARRAY_SIZE(tlb->local); |
| 106 | tlb->pages = tlb->local; | 109 | tlb->pages = tlb->local; |
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c index f91431963452..7de083d19b7e 100644 --- a/arch/avr32/boards/atngw100/mrmt.c +++ b/arch/avr32/boards/atngw100/mrmt.c | |||
| @@ -150,7 +150,6 @@ static struct ac97c_platform_data __initdata ac97c0_data = { | |||
| 150 | static struct platform_device rmt_ts_device = { | 150 | static struct platform_device rmt_ts_device = { |
| 151 | .name = "ucb1400_ts", | 151 | .name = "ucb1400_ts", |
| 152 | .id = -1, | 152 | .id = -1, |
| 153 | } | ||
| 154 | }; | 153 | }; |
| 155 | #endif | 154 | #endif |
| 156 | 155 | ||
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 33a97929d055..77d442ab28c8 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig | |||
| @@ -158,6 +158,7 @@ source "kernel/Kconfig.hz" | |||
| 158 | endmenu | 158 | endmenu |
| 159 | 159 | ||
| 160 | source "init/Kconfig" | 160 | source "init/Kconfig" |
| 161 | source "kernel/Kconfig.freezer" | ||
| 161 | source "drivers/Kconfig" | 162 | source "drivers/Kconfig" |
| 162 | source "fs/Kconfig" | 163 | source "fs/Kconfig" |
| 163 | 164 | ||
diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h index ef3a9de01954..bc5efc7c3f3f 100644 --- a/arch/ia64/include/asm/tlb.h +++ b/arch/ia64/include/asm/tlb.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | * unmapping a portion of the virtual address space, these hooks are called according to | 22 | * unmapping a portion of the virtual address space, these hooks are called according to |
| 23 | * the following template: | 23 | * the following template: |
| 24 | * | 24 | * |
| 25 | * tlb <- tlb_gather_mmu(mm, full_mm_flush); // start unmap for address space MM | 25 | * tlb <- tlb_gather_mmu(mm, start, end); // start unmap for address space MM |
| 26 | * { | 26 | * { |
| 27 | * for each vma that needs a shootdown do { | 27 | * for each vma that needs a shootdown do { |
| 28 | * tlb_start_vma(tlb, vma); | 28 | * tlb_start_vma(tlb, vma); |
| @@ -58,6 +58,7 @@ struct mmu_gather { | |||
| 58 | unsigned int max; | 58 | unsigned int max; |
| 59 | unsigned char fullmm; /* non-zero means full mm flush */ | 59 | unsigned char fullmm; /* non-zero means full mm flush */ |
| 60 | unsigned char need_flush; /* really unmapped some PTEs? */ | 60 | unsigned char need_flush; /* really unmapped some PTEs? */ |
| 61 | unsigned long start, end; | ||
| 61 | unsigned long start_addr; | 62 | unsigned long start_addr; |
| 62 | unsigned long end_addr; | 63 | unsigned long end_addr; |
| 63 | struct page **pages; | 64 | struct page **pages; |
| @@ -155,13 +156,15 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb) | |||
| 155 | 156 | ||
| 156 | 157 | ||
| 157 | static inline void | 158 | static inline void |
| 158 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) | 159 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 159 | { | 160 | { |
| 160 | tlb->mm = mm; | 161 | tlb->mm = mm; |
| 161 | tlb->max = ARRAY_SIZE(tlb->local); | 162 | tlb->max = ARRAY_SIZE(tlb->local); |
| 162 | tlb->pages = tlb->local; | 163 | tlb->pages = tlb->local; |
| 163 | tlb->nr = 0; | 164 | tlb->nr = 0; |
| 164 | tlb->fullmm = full_mm_flush; | 165 | tlb->fullmm = !(start | (end+1)); |
| 166 | tlb->start = start; | ||
| 167 | tlb->end = end; | ||
| 165 | tlb->start_addr = ~0UL; | 168 | tlb->start_addr = ~0UL; |
| 166 | } | 169 | } |
| 167 | 170 | ||
diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c index 2291a7d69d49..fa277aecfb78 100644 --- a/arch/m68k/emu/natfeat.c +++ b/arch/m68k/emu/natfeat.c | |||
| @@ -18,9 +18,11 @@ | |||
| 18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
| 19 | #include <asm/natfeat.h> | 19 | #include <asm/natfeat.h> |
| 20 | 20 | ||
| 21 | extern long nf_get_id2(const char *feature_name); | ||
| 22 | |||
| 21 | asm("\n" | 23 | asm("\n" |
| 22 | " .global nf_get_id,nf_call\n" | 24 | " .global nf_get_id2,nf_call\n" |
| 23 | "nf_get_id:\n" | 25 | "nf_get_id2:\n" |
| 24 | " .short 0x7300\n" | 26 | " .short 0x7300\n" |
| 25 | " rts\n" | 27 | " rts\n" |
| 26 | "nf_call:\n" | 28 | "nf_call:\n" |
| @@ -29,12 +31,25 @@ asm("\n" | |||
| 29 | "1: moveq.l #0,%d0\n" | 31 | "1: moveq.l #0,%d0\n" |
| 30 | " rts\n" | 32 | " rts\n" |
| 31 | " .section __ex_table,\"a\"\n" | 33 | " .section __ex_table,\"a\"\n" |
| 32 | " .long nf_get_id,1b\n" | 34 | " .long nf_get_id2,1b\n" |
| 33 | " .long nf_call,1b\n" | 35 | " .long nf_call,1b\n" |
| 34 | " .previous"); | 36 | " .previous"); |
| 35 | EXPORT_SYMBOL_GPL(nf_get_id); | ||
| 36 | EXPORT_SYMBOL_GPL(nf_call); | 37 | EXPORT_SYMBOL_GPL(nf_call); |
| 37 | 38 | ||
| 39 | long nf_get_id(const char *feature_name) | ||
| 40 | { | ||
| 41 | /* feature_name may be in vmalloc()ed memory, so make a copy */ | ||
| 42 | char name_copy[32]; | ||
| 43 | size_t n; | ||
| 44 | |||
| 45 | n = strlcpy(name_copy, feature_name, sizeof(name_copy)); | ||
| 46 | if (n >= sizeof(name_copy)) | ||
| 47 | return 0; | ||
| 48 | |||
| 49 | return nf_get_id2(name_copy); | ||
| 50 | } | ||
| 51 | EXPORT_SYMBOL_GPL(nf_get_id); | ||
| 52 | |||
| 38 | void nfprint(const char *fmt, ...) | 53 | void nfprint(const char *fmt, ...) |
| 39 | { | 54 | { |
| 40 | static char buf[256]; | 55 | static char buf[256]; |
diff --git a/arch/m68k/include/asm/div64.h b/arch/m68k/include/asm/div64.h index 444ea8a09e9f..ef881cfbbca9 100644 --- a/arch/m68k/include/asm/div64.h +++ b/arch/m68k/include/asm/div64.h | |||
| @@ -15,16 +15,17 @@ | |||
| 15 | unsigned long long n64; \ | 15 | unsigned long long n64; \ |
| 16 | } __n; \ | 16 | } __n; \ |
| 17 | unsigned long __rem, __upper; \ | 17 | unsigned long __rem, __upper; \ |
| 18 | unsigned long __base = (base); \ | ||
| 18 | \ | 19 | \ |
| 19 | __n.n64 = (n); \ | 20 | __n.n64 = (n); \ |
| 20 | if ((__upper = __n.n32[0])) { \ | 21 | if ((__upper = __n.n32[0])) { \ |
| 21 | asm ("divul.l %2,%1:%0" \ | 22 | asm ("divul.l %2,%1:%0" \ |
| 22 | : "=d" (__n.n32[0]), "=d" (__upper) \ | 23 | : "=d" (__n.n32[0]), "=d" (__upper) \ |
| 23 | : "d" (base), "0" (__n.n32[0])); \ | 24 | : "d" (__base), "0" (__n.n32[0])); \ |
| 24 | } \ | 25 | } \ |
| 25 | asm ("divu.l %2,%1:%0" \ | 26 | asm ("divu.l %2,%1:%0" \ |
| 26 | : "=d" (__n.n32[1]), "=d" (__rem) \ | 27 | : "=d" (__n.n32[1]), "=d" (__rem) \ |
| 27 | : "d" (base), "1" (__upper), "0" (__n.n32[1])); \ | 28 | : "d" (__base), "1" (__upper), "0" (__n.n32[1])); \ |
| 28 | (n) = __n.n64; \ | 29 | (n) = __n.n64; \ |
| 29 | __rem; \ | 30 | __rem; \ |
| 30 | }) | 31 | }) |
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index d22a4ecffff4..4fab52294d98 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
| @@ -28,7 +28,7 @@ config MICROBLAZE | |||
| 28 | select GENERIC_CLOCKEVENTS | 28 | select GENERIC_CLOCKEVENTS |
| 29 | select GENERIC_IDLE_POLL_SETUP | 29 | select GENERIC_IDLE_POLL_SETUP |
| 30 | select MODULES_USE_ELF_RELA | 30 | select MODULES_USE_ELF_RELA |
| 31 | select CLONE_BACKWARDS | 31 | select CLONE_BACKWARDS3 |
| 32 | 32 | ||
| 33 | config SWAP | 33 | config SWAP |
| 34 | def_bool n | 34 | def_bool n |
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 1dc086087a72..fa44f3ec5302 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #define current_cpu_type() current_cpu_data.cputype | 17 | #define current_cpu_type() current_cpu_data.cputype |
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | #define boot_cpu_type() cpu_data[0].cputype | ||
| 21 | |||
| 20 | /* | 22 | /* |
| 21 | * SMP assumption: Options of CPU 0 are a superset of all processors. | 23 | * SMP assumption: Options of CPU 0 are a superset of all processors. |
| 22 | * This is true for all known MIPS systems. | 24 | * This is true for all known MIPS systems. |
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 159abc8842d2..126da74d4c55 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c | |||
| @@ -66,6 +66,8 @@ static void __init bmips_smp_setup(void) | |||
| 66 | int i, cpu = 1, boot_cpu = 0; | 66 | int i, cpu = 1, boot_cpu = 0; |
| 67 | 67 | ||
| 68 | #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) | 68 | #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) |
| 69 | int cpu_hw_intr; | ||
| 70 | |||
| 69 | /* arbitration priority */ | 71 | /* arbitration priority */ |
| 70 | clear_c0_brcm_cmt_ctrl(0x30); | 72 | clear_c0_brcm_cmt_ctrl(0x30); |
| 71 | 73 | ||
| @@ -80,8 +82,12 @@ static void __init bmips_smp_setup(void) | |||
| 80 | * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output | 82 | * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output |
| 81 | * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output | 83 | * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output |
| 82 | */ | 84 | */ |
| 83 | change_c0_brcm_cmt_intr(0xf8018000, | 85 | if (boot_cpu == 0) |
| 84 | (0x02 << 27) | (0x03 << 15)); | 86 | cpu_hw_intr = 0x02; |
| 87 | else | ||
| 88 | cpu_hw_intr = 0x1d; | ||
| 89 | |||
| 90 | change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15)); | ||
| 85 | 91 | ||
| 86 | /* single core, 2 threads (2 pipelines) */ | 92 | /* single core, 2 threads (2 pipelines) */ |
| 87 | max_cpus = 2; | 93 | max_cpus = 2; |
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index e4b1140cdae0..3a2b6e9f25cf 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c | |||
| @@ -166,7 +166,7 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr) | |||
| 166 | reg.control[i] |= M_PERFCTL_USER; | 166 | reg.control[i] |= M_PERFCTL_USER; |
| 167 | if (ctr[i].exl) | 167 | if (ctr[i].exl) |
| 168 | reg.control[i] |= M_PERFCTL_EXL; | 168 | reg.control[i] |= M_PERFCTL_EXL; |
| 169 | if (current_cpu_type() == CPU_XLR) | 169 | if (boot_cpu_type() == CPU_XLR) |
| 170 | reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS; | 170 | reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS; |
| 171 | reg.counter[i] = 0x80000000 - ctr[i].count; | 171 | reg.counter[i] = 0x80000000 - ctr[i].count; |
| 172 | } | 172 | } |
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index d22dc0d6f289..2b7e837dc2e2 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c | |||
| @@ -206,11 +206,13 @@ static struct resource pnx833x_ethernet_resources[] = { | |||
| 206 | .end = PNX8335_IP3902_PORTS_END, | 206 | .end = PNX8335_IP3902_PORTS_END, |
| 207 | .flags = IORESOURCE_MEM, | 207 | .flags = IORESOURCE_MEM, |
| 208 | }, | 208 | }, |
| 209 | #ifdef CONFIG_SOC_PNX8335 | ||
| 209 | [1] = { | 210 | [1] = { |
| 210 | .start = PNX8335_PIC_ETHERNET_INT, | 211 | .start = PNX8335_PIC_ETHERNET_INT, |
| 211 | .end = PNX8335_PIC_ETHERNET_INT, | 212 | .end = PNX8335_PIC_ETHERNET_INT, |
| 212 | .flags = IORESOURCE_IRQ, | 213 | .flags = IORESOURCE_IRQ, |
| 213 | }, | 214 | }, |
| 215 | #endif | ||
| 214 | }; | 216 | }; |
| 215 | 217 | ||
| 216 | static struct platform_device pnx833x_ethernet_device = { | 218 | static struct platform_device pnx833x_ethernet_device = { |
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 99dbab1c59ac..d60bf98fa5cf 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
| @@ -55,6 +55,7 @@ config GENERIC_CSUM | |||
| 55 | 55 | ||
| 56 | source "init/Kconfig" | 56 | source "init/Kconfig" |
| 57 | 57 | ||
| 58 | source "kernel/Kconfig.freezer" | ||
| 58 | 59 | ||
| 59 | menu "Processor type and features" | 60 | menu "Processor type and features" |
| 60 | 61 | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 3bf72cd2c8fc..dbd9d3c991e8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -566,7 +566,7 @@ config SCHED_SMT | |||
| 566 | config PPC_DENORMALISATION | 566 | config PPC_DENORMALISATION |
| 567 | bool "PowerPC denormalisation exception handling" | 567 | bool "PowerPC denormalisation exception handling" |
| 568 | depends on PPC_BOOK3S_64 | 568 | depends on PPC_BOOK3S_64 |
| 569 | default "n" | 569 | default "y" if PPC_POWERNV |
| 570 | ---help--- | 570 | ---help--- |
| 571 | Add support for handling denormalisation of single precision | 571 | Add support for handling denormalisation of single precision |
| 572 | values. Useful for bare metal only. If unsure say Y here. | 572 | values. Useful for bare metal only. If unsure say Y here. |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 47a35b08b963..e378cccfca55 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
| @@ -247,6 +247,10 @@ struct thread_struct { | |||
| 247 | unsigned long tm_orig_msr; /* Thread's MSR on ctx switch */ | 247 | unsigned long tm_orig_msr; /* Thread's MSR on ctx switch */ |
| 248 | struct pt_regs ckpt_regs; /* Checkpointed registers */ | 248 | struct pt_regs ckpt_regs; /* Checkpointed registers */ |
| 249 | 249 | ||
| 250 | unsigned long tm_tar; | ||
| 251 | unsigned long tm_ppr; | ||
| 252 | unsigned long tm_dscr; | ||
| 253 | |||
| 250 | /* | 254 | /* |
| 251 | * Transactional FP and VSX 0-31 register set. | 255 | * Transactional FP and VSX 0-31 register set. |
| 252 | * NOTE: the sense of these is the opposite of the integer ckpt_regs! | 256 | * NOTE: the sense of these is the opposite of the integer ckpt_regs! |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index a6840e4e24f7..99222e27f173 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
| @@ -254,19 +254,28 @@ | |||
| 254 | #define SPRN_HRMOR 0x139 /* Real mode offset register */ | 254 | #define SPRN_HRMOR 0x139 /* Real mode offset register */ |
| 255 | #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ | 255 | #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ |
| 256 | #define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ | 256 | #define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ |
| 257 | /* HFSCR and FSCR bit numbers are the same */ | ||
| 258 | #define FSCR_TAR_LG 8 /* Enable Target Address Register */ | ||
| 259 | #define FSCR_EBB_LG 7 /* Enable Event Based Branching */ | ||
| 260 | #define FSCR_TM_LG 5 /* Enable Transactional Memory */ | ||
| 261 | #define FSCR_PM_LG 4 /* Enable prob/priv access to PMU SPRs */ | ||
| 262 | #define FSCR_BHRB_LG 3 /* Enable Branch History Rolling Buffer*/ | ||
| 263 | #define FSCR_DSCR_LG 2 /* Enable Data Stream Control Register */ | ||
| 264 | #define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */ | ||
| 265 | #define FSCR_FP_LG 0 /* Enable Floating Point */ | ||
| 257 | #define SPRN_FSCR 0x099 /* Facility Status & Control Register */ | 266 | #define SPRN_FSCR 0x099 /* Facility Status & Control Register */ |
| 258 | #define FSCR_TAR (1 << (63-55)) /* Enable Target Address Register */ | 267 | #define FSCR_TAR __MASK(FSCR_TAR_LG) |
| 259 | #define FSCR_EBB (1 << (63-56)) /* Enable Event Based Branching */ | 268 | #define FSCR_EBB __MASK(FSCR_EBB_LG) |
| 260 | #define FSCR_DSCR (1 << (63-61)) /* Enable Data Stream Control Register */ | 269 | #define FSCR_DSCR __MASK(FSCR_DSCR_LG) |
| 261 | #define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */ | 270 | #define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */ |
| 262 | #define HFSCR_TAR (1 << (63-55)) /* Enable Target Address Register */ | 271 | #define HFSCR_TAR __MASK(FSCR_TAR_LG) |
| 263 | #define HFSCR_EBB (1 << (63-56)) /* Enable Event Based Branching */ | 272 | #define HFSCR_EBB __MASK(FSCR_EBB_LG) |
| 264 | #define HFSCR_TM (1 << (63-58)) /* Enable Transactional Memory */ | 273 | #define HFSCR_TM __MASK(FSCR_TM_LG) |
| 265 | #define HFSCR_PM (1 << (63-60)) /* Enable prob/priv access to PMU SPRs */ | 274 | #define HFSCR_PM __MASK(FSCR_PM_LG) |
| 266 | #define HFSCR_BHRB (1 << (63-59)) /* Enable Branch History Rolling Buffer*/ | 275 | #define HFSCR_BHRB __MASK(FSCR_BHRB_LG) |
| 267 | #define HFSCR_DSCR (1 << (63-61)) /* Enable Data Stream Control Register */ | 276 | #define HFSCR_DSCR __MASK(FSCR_DSCR_LG) |
| 268 | #define HFSCR_VECVSX (1 << (63-62)) /* Enable VMX/VSX */ | 277 | #define HFSCR_VECVSX __MASK(FSCR_VECVSX_LG) |
| 269 | #define HFSCR_FP (1 << (63-63)) /* Enable Floating Point */ | 278 | #define HFSCR_FP __MASK(FSCR_FP_LG) |
| 270 | #define SPRN_TAR 0x32f /* Target Address Register */ | 279 | #define SPRN_TAR 0x32f /* Target Address Register */ |
| 271 | #define SPRN_LPCR 0x13E /* LPAR Control Register */ | 280 | #define SPRN_LPCR 0x13E /* LPAR Control Register */ |
| 272 | #define LPCR_VPM0 (1ul << (63-0)) | 281 | #define LPCR_VPM0 (1ul << (63-0)) |
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h index 49a13e0ef234..294c2cedcf7a 100644 --- a/arch/powerpc/include/asm/switch_to.h +++ b/arch/powerpc/include/asm/switch_to.h | |||
| @@ -15,6 +15,15 @@ extern struct task_struct *__switch_to(struct task_struct *, | |||
| 15 | struct thread_struct; | 15 | struct thread_struct; |
| 16 | extern struct task_struct *_switch(struct thread_struct *prev, | 16 | extern struct task_struct *_switch(struct thread_struct *prev, |
| 17 | struct thread_struct *next); | 17 | struct thread_struct *next); |
| 18 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 19 | static inline void save_tar(struct thread_struct *prev) | ||
| 20 | { | ||
| 21 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
| 22 | prev->tar = mfspr(SPRN_TAR); | ||
| 23 | } | ||
| 24 | #else | ||
| 25 | static inline void save_tar(struct thread_struct *prev) {} | ||
| 26 | #endif | ||
| 18 | 27 | ||
| 19 | extern void giveup_fpu(struct task_struct *); | 28 | extern void giveup_fpu(struct task_struct *); |
| 20 | extern void load_up_fpu(void); | 29 | extern void load_up_fpu(void); |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index c7e8afc2ead0..8207459efe56 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -138,6 +138,9 @@ int main(void) | |||
| 138 | DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar)); | 138 | DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar)); |
| 139 | DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr)); | 139 | DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr)); |
| 140 | DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar)); | 140 | DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar)); |
| 141 | DEFINE(THREAD_TM_TAR, offsetof(struct thread_struct, tm_tar)); | ||
| 142 | DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); | ||
| 143 | DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); | ||
| 141 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); | 144 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); |
| 142 | DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, | 145 | DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, |
| 143 | transact_vr[0])); | 146 | transact_vr[0])); |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index ea9414c8088d..55593ee2d5aa 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
| @@ -1061,7 +1061,7 @@ static const struct file_operations proc_eeh_operations = { | |||
| 1061 | 1061 | ||
| 1062 | static int __init eeh_init_proc(void) | 1062 | static int __init eeh_init_proc(void) |
| 1063 | { | 1063 | { |
| 1064 | if (machine_is(pseries)) | 1064 | if (machine_is(pseries) || machine_is(powernv)) |
| 1065 | proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations); | 1065 | proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations); |
| 1066 | return 0; | 1066 | return 0; |
| 1067 | } | 1067 | } |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ab15b8d057ad..2bd0b885b0fe 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -449,15 +449,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR) | |||
| 449 | 449 | ||
| 450 | #ifdef CONFIG_PPC_BOOK3S_64 | 450 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 451 | BEGIN_FTR_SECTION | 451 | BEGIN_FTR_SECTION |
| 452 | /* | ||
| 453 | * Back up the TAR across context switches. Note that the TAR is not | ||
| 454 | * available for use in the kernel. (To provide this, the TAR should | ||
| 455 | * be backed up/restored on exception entry/exit instead, and be in | ||
| 456 | * pt_regs. FIXME, this should be in pt_regs anyway (for debug).) | ||
| 457 | */ | ||
| 458 | mfspr r0,SPRN_TAR | ||
| 459 | std r0,THREAD_TAR(r3) | ||
| 460 | |||
| 461 | /* Event based branch registers */ | 452 | /* Event based branch registers */ |
| 462 | mfspr r0, SPRN_BESCR | 453 | mfspr r0, SPRN_BESCR |
| 463 | std r0, THREAD_BESCR(r3) | 454 | std r0, THREAD_BESCR(r3) |
| @@ -584,9 +575,34 @@ BEGIN_FTR_SECTION | |||
| 584 | ld r7,DSCR_DEFAULT@toc(2) | 575 | ld r7,DSCR_DEFAULT@toc(2) |
| 585 | ld r0,THREAD_DSCR(r4) | 576 | ld r0,THREAD_DSCR(r4) |
| 586 | cmpwi r6,0 | 577 | cmpwi r6,0 |
| 578 | li r8, FSCR_DSCR | ||
| 587 | bne 1f | 579 | bne 1f |
| 588 | ld r0,0(r7) | 580 | ld r0,0(r7) |
| 589 | 1: cmpd r0,r25 | 581 | b 3f |
| 582 | 1: | ||
| 583 | BEGIN_FTR_SECTION_NESTED(70) | ||
| 584 | mfspr r6, SPRN_FSCR | ||
| 585 | or r6, r6, r8 | ||
| 586 | mtspr SPRN_FSCR, r6 | ||
| 587 | BEGIN_FTR_SECTION_NESTED(69) | ||
| 588 | mfspr r6, SPRN_HFSCR | ||
| 589 | or r6, r6, r8 | ||
| 590 | mtspr SPRN_HFSCR, r6 | ||
| 591 | END_FTR_SECTION_NESTED(CPU_FTR_HVMODE, CPU_FTR_HVMODE, 69) | ||
| 592 | b 4f | ||
| 593 | END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70) | ||
| 594 | 3: | ||
| 595 | BEGIN_FTR_SECTION_NESTED(70) | ||
| 596 | mfspr r6, SPRN_FSCR | ||
| 597 | andc r6, r6, r8 | ||
| 598 | mtspr SPRN_FSCR, r6 | ||
| 599 | BEGIN_FTR_SECTION_NESTED(69) | ||
| 600 | mfspr r6, SPRN_HFSCR | ||
| 601 | andc r6, r6, r8 | ||
| 602 | mtspr SPRN_HFSCR, r6 | ||
| 603 | END_FTR_SECTION_NESTED(CPU_FTR_HVMODE, CPU_FTR_HVMODE, 69) | ||
| 604 | END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70) | ||
| 605 | 4: cmpd r0,r25 | ||
| 590 | beq 2f | 606 | beq 2f |
| 591 | mtspr SPRN_DSCR,r0 | 607 | mtspr SPRN_DSCR,r0 |
| 592 | 2: | 608 | 2: |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 4e00d223b2e3..902ca3c6b4b6 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -848,7 +848,7 @@ hv_facility_unavailable_relon_trampoline: | |||
| 848 | . = 0x4f80 | 848 | . = 0x4f80 |
| 849 | SET_SCRATCH0(r13) | 849 | SET_SCRATCH0(r13) |
| 850 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 850 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
| 851 | b facility_unavailable_relon_hv | 851 | b hv_facility_unavailable_relon_hv |
| 852 | 852 | ||
| 853 | STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint) | 853 | STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint) |
| 854 | #ifdef CONFIG_PPC_DENORMALISATION | 854 | #ifdef CONFIG_PPC_DENORMALISATION |
| @@ -1175,6 +1175,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
| 1175 | b .ret_from_except | 1175 | b .ret_from_except |
| 1176 | 1176 | ||
| 1177 | STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception) | 1177 | STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception) |
| 1178 | STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, .facility_unavailable_exception) | ||
| 1178 | 1179 | ||
| 1179 | .align 7 | 1180 | .align 7 |
| 1180 | .globl __end_handlers | 1181 | .globl __end_handlers |
| @@ -1188,7 +1189,7 @@ __end_handlers: | |||
| 1188 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable) | 1189 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable) |
| 1189 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable) | 1190 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable) |
| 1190 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable) | 1191 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable) |
| 1191 | STD_RELON_EXCEPTION_HV_OOL(0xf80, facility_unavailable) | 1192 | STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable) |
| 1192 | 1193 | ||
| 1193 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 1194 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
| 1194 | /* | 1195 | /* |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index c517dbe705fd..8083be20fe5e 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -600,6 +600,16 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 600 | struct ppc64_tlb_batch *batch; | 600 | struct ppc64_tlb_batch *batch; |
| 601 | #endif | 601 | #endif |
| 602 | 602 | ||
| 603 | /* Back up the TAR across context switches. | ||
| 604 | * Note that the TAR is not available for use in the kernel. (To | ||
| 605 | * provide this, the TAR should be backed up/restored on exception | ||
| 606 | * entry/exit instead, and be in pt_regs. FIXME, this should be in | ||
| 607 | * pt_regs anyway (for debug).) | ||
| 608 | * Save the TAR here before we do treclaim/trecheckpoint as these | ||
| 609 | * will change the TAR. | ||
| 610 | */ | ||
| 611 | save_tar(&prev->thread); | ||
| 612 | |||
| 603 | __switch_to_tm(prev); | 613 | __switch_to_tm(prev); |
| 604 | 614 | ||
| 605 | #ifdef CONFIG_SMP | 615 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 51be8fb24803..0554d1f6d70d 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
| @@ -233,6 +233,16 @@ dont_backup_fp: | |||
| 233 | std r5, _CCR(r7) | 233 | std r5, _CCR(r7) |
| 234 | std r6, _XER(r7) | 234 | std r6, _XER(r7) |
| 235 | 235 | ||
| 236 | |||
| 237 | /* ******************** TAR, PPR, DSCR ********** */ | ||
| 238 | mfspr r3, SPRN_TAR | ||
| 239 | mfspr r4, SPRN_PPR | ||
| 240 | mfspr r5, SPRN_DSCR | ||
| 241 | |||
| 242 | std r3, THREAD_TM_TAR(r12) | ||
| 243 | std r4, THREAD_TM_PPR(r12) | ||
| 244 | std r5, THREAD_TM_DSCR(r12) | ||
| 245 | |||
| 236 | /* MSR and flags: We don't change CRs, and we don't need to alter | 246 | /* MSR and flags: We don't change CRs, and we don't need to alter |
| 237 | * MSR. | 247 | * MSR. |
| 238 | */ | 248 | */ |
| @@ -347,6 +357,16 @@ dont_restore_fp: | |||
| 347 | mtmsr r6 /* FP/Vec off again! */ | 357 | mtmsr r6 /* FP/Vec off again! */ |
| 348 | 358 | ||
| 349 | restore_gprs: | 359 | restore_gprs: |
| 360 | |||
| 361 | /* ******************** TAR, PPR, DSCR ********** */ | ||
| 362 | ld r4, THREAD_TM_TAR(r3) | ||
| 363 | ld r5, THREAD_TM_PPR(r3) | ||
| 364 | ld r6, THREAD_TM_DSCR(r3) | ||
| 365 | |||
| 366 | mtspr SPRN_TAR, r4 | ||
| 367 | mtspr SPRN_PPR, r5 | ||
| 368 | mtspr SPRN_DSCR, r6 | ||
| 369 | |||
| 350 | /* ******************** CR,LR,CCR,MSR ********** */ | 370 | /* ******************** CR,LR,CCR,MSR ********** */ |
| 351 | ld r3, _CTR(r7) | 371 | ld r3, _CTR(r7) |
| 352 | ld r4, _LINK(r7) | 372 | ld r4, _LINK(r7) |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index bf33c22e38a4..e435bc089ea3 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -44,9 +44,7 @@ | |||
| 44 | #include <asm/machdep.h> | 44 | #include <asm/machdep.h> |
| 45 | #include <asm/rtas.h> | 45 | #include <asm/rtas.h> |
| 46 | #include <asm/pmc.h> | 46 | #include <asm/pmc.h> |
| 47 | #ifdef CONFIG_PPC32 | ||
| 48 | #include <asm/reg.h> | 47 | #include <asm/reg.h> |
| 49 | #endif | ||
| 50 | #ifdef CONFIG_PMAC_BACKLIGHT | 48 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 51 | #include <asm/backlight.h> | 49 | #include <asm/backlight.h> |
| 52 | #endif | 50 | #endif |
| @@ -1296,43 +1294,54 @@ void vsx_unavailable_exception(struct pt_regs *regs) | |||
| 1296 | die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); | 1294 | die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); |
| 1297 | } | 1295 | } |
| 1298 | 1296 | ||
| 1297 | #ifdef CONFIG_PPC64 | ||
| 1299 | void facility_unavailable_exception(struct pt_regs *regs) | 1298 | void facility_unavailable_exception(struct pt_regs *regs) |
| 1300 | { | 1299 | { |
| 1301 | static char *facility_strings[] = { | 1300 | static char *facility_strings[] = { |
| 1302 | "FPU", | 1301 | [FSCR_FP_LG] = "FPU", |
| 1303 | "VMX/VSX", | 1302 | [FSCR_VECVSX_LG] = "VMX/VSX", |
| 1304 | "DSCR", | 1303 | [FSCR_DSCR_LG] = "DSCR", |
| 1305 | "PMU SPRs", | 1304 | [FSCR_PM_LG] = "PMU SPRs", |
| 1306 | "BHRB", | 1305 | [FSCR_BHRB_LG] = "BHRB", |
| 1307 | "TM", | 1306 | [FSCR_TM_LG] = "TM", |
| 1308 | "AT", | 1307 | [FSCR_EBB_LG] = "EBB", |
| 1309 | "EBB", | 1308 | [FSCR_TAR_LG] = "TAR", |
| 1310 | "TAR", | ||
| 1311 | }; | 1309 | }; |
| 1312 | char *facility, *prefix; | 1310 | char *facility = "unknown"; |
| 1313 | u64 value; | 1311 | u64 value; |
| 1312 | u8 status; | ||
| 1313 | bool hv; | ||
| 1314 | 1314 | ||
| 1315 | if (regs->trap == 0xf60) { | 1315 | hv = (regs->trap == 0xf80); |
| 1316 | value = mfspr(SPRN_FSCR); | 1316 | if (hv) |
| 1317 | prefix = ""; | ||
| 1318 | } else { | ||
| 1319 | value = mfspr(SPRN_HFSCR); | 1317 | value = mfspr(SPRN_HFSCR); |
| 1320 | prefix = "Hypervisor "; | 1318 | else |
| 1319 | value = mfspr(SPRN_FSCR); | ||
| 1320 | |||
| 1321 | status = value >> 56; | ||
| 1322 | if (status == FSCR_DSCR_LG) { | ||
| 1323 | /* User is acessing the DSCR. Set the inherit bit and allow | ||
| 1324 | * the user to set it directly in future by setting via the | ||
| 1325 | * H/FSCR DSCR bit. | ||
| 1326 | */ | ||
| 1327 | current->thread.dscr_inherit = 1; | ||
| 1328 | if (hv) | ||
| 1329 | mtspr(SPRN_HFSCR, value | HFSCR_DSCR); | ||
| 1330 | else | ||
| 1331 | mtspr(SPRN_FSCR, value | FSCR_DSCR); | ||
| 1332 | return; | ||
| 1321 | } | 1333 | } |
| 1322 | 1334 | ||
| 1323 | value = value >> 56; | 1335 | if ((status < ARRAY_SIZE(facility_strings)) && |
| 1336 | facility_strings[status]) | ||
| 1337 | facility = facility_strings[status]; | ||
| 1324 | 1338 | ||
| 1325 | /* We restore the interrupt state now */ | 1339 | /* We restore the interrupt state now */ |
| 1326 | if (!arch_irq_disabled_regs(regs)) | 1340 | if (!arch_irq_disabled_regs(regs)) |
| 1327 | local_irq_enable(); | 1341 | local_irq_enable(); |
| 1328 | 1342 | ||
| 1329 | if (value < ARRAY_SIZE(facility_strings)) | ||
| 1330 | facility = facility_strings[value]; | ||
| 1331 | else | ||
| 1332 | facility = "unknown"; | ||
| 1333 | |||
| 1334 | pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", | 1343 | pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", |
| 1335 | prefix, facility, regs->nip, regs->msr); | 1344 | hv ? "Hypervisor " : "", facility, regs->nip, regs->msr); |
| 1336 | 1345 | ||
| 1337 | if (user_mode(regs)) { | 1346 | if (user_mode(regs)) { |
| 1338 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | 1347 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); |
| @@ -1341,6 +1350,7 @@ void facility_unavailable_exception(struct pt_regs *regs) | |||
| 1341 | 1350 | ||
| 1342 | die("Unexpected facility unavailable exception", regs, SIGABRT); | 1351 | die("Unexpected facility unavailable exception", regs, SIGABRT); |
| 1343 | } | 1352 | } |
| 1353 | #endif | ||
| 1344 | 1354 | ||
| 1345 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1355 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 1346 | 1356 | ||
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 2efa9dde741a..7629cd3eb91a 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
| @@ -1809,7 +1809,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
| 1809 | rma_size <<= PAGE_SHIFT; | 1809 | rma_size <<= PAGE_SHIFT; |
| 1810 | rmls = lpcr_rmls(rma_size); | 1810 | rmls = lpcr_rmls(rma_size); |
| 1811 | err = -EINVAL; | 1811 | err = -EINVAL; |
| 1812 | if (rmls < 0) { | 1812 | if ((long)rmls < 0) { |
| 1813 | pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size); | 1813 | pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size); |
| 1814 | goto out_srcu; | 1814 | goto out_srcu; |
| 1815 | } | 1815 | } |
| @@ -1874,7 +1874,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
| 1874 | /* Allocate the guest's logical partition ID */ | 1874 | /* Allocate the guest's logical partition ID */ |
| 1875 | 1875 | ||
| 1876 | lpid = kvmppc_alloc_lpid(); | 1876 | lpid = kvmppc_alloc_lpid(); |
| 1877 | if (lpid < 0) | 1877 | if ((long)lpid < 0) |
| 1878 | return -ENOMEM; | 1878 | return -ENOMEM; |
| 1879 | kvm->arch.lpid = lpid; | 1879 | kvm->arch.lpid = lpid; |
| 1880 | 1880 | ||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 19498a567a81..c6e13d9a9e15 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
| @@ -1047,11 +1047,12 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
| 1047 | if (err) | 1047 | if (err) |
| 1048 | goto free_shadow_vcpu; | 1048 | goto free_shadow_vcpu; |
| 1049 | 1049 | ||
| 1050 | err = -ENOMEM; | ||
| 1050 | p = __get_free_page(GFP_KERNEL|__GFP_ZERO); | 1051 | p = __get_free_page(GFP_KERNEL|__GFP_ZERO); |
| 1051 | /* the real shared page fills the last 4k of our page */ | ||
| 1052 | vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096); | ||
| 1053 | if (!p) | 1052 | if (!p) |
| 1054 | goto uninit_vcpu; | 1053 | goto uninit_vcpu; |
| 1054 | /* the real shared page fills the last 4k of our page */ | ||
| 1055 | vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096); | ||
| 1055 | 1056 | ||
| 1056 | #ifdef CONFIG_PPC_BOOK3S_64 | 1057 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1057 | /* default to book3s_64 (970fx) */ | 1058 | /* default to book3s_64 (970fx) */ |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 9f8671a44551..6a5f2b1f32ca 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
| @@ -569,35 +569,6 @@ error: | |||
| 569 | return ret; | 569 | return ret; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static int unzip_oops(char *oops_buf, char *big_buf) | ||
| 573 | { | ||
| 574 | struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; | ||
| 575 | u64 timestamp = oops_hdr->timestamp; | ||
| 576 | char *big_oops_data = NULL; | ||
| 577 | char *oops_data_buf = NULL; | ||
| 578 | size_t big_oops_data_sz; | ||
| 579 | int unzipped_len; | ||
| 580 | |||
| 581 | big_oops_data = big_buf + sizeof(struct oops_log_info); | ||
| 582 | big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info); | ||
| 583 | oops_data_buf = oops_buf + sizeof(struct oops_log_info); | ||
| 584 | |||
| 585 | unzipped_len = nvram_decompress(oops_data_buf, big_oops_data, | ||
| 586 | oops_hdr->report_length, | ||
| 587 | big_oops_data_sz); | ||
| 588 | |||
| 589 | if (unzipped_len < 0) { | ||
| 590 | pr_err("nvram: decompression failed; returned %d\n", | ||
| 591 | unzipped_len); | ||
| 592 | return -1; | ||
| 593 | } | ||
| 594 | oops_hdr = (struct oops_log_info *)big_buf; | ||
| 595 | oops_hdr->version = OOPS_HDR_VERSION; | ||
| 596 | oops_hdr->report_length = (u16) unzipped_len; | ||
| 597 | oops_hdr->timestamp = timestamp; | ||
| 598 | return 0; | ||
| 599 | } | ||
| 600 | |||
| 601 | static int nvram_pstore_open(struct pstore_info *psi) | 572 | static int nvram_pstore_open(struct pstore_info *psi) |
| 602 | { | 573 | { |
| 603 | /* Reset the iterator to start reading partitions again */ | 574 | /* Reset the iterator to start reading partitions again */ |
| @@ -685,10 +656,9 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
| 685 | unsigned int err_type, id_no, size = 0; | 656 | unsigned int err_type, id_no, size = 0; |
| 686 | struct nvram_os_partition *part = NULL; | 657 | struct nvram_os_partition *part = NULL; |
| 687 | char *buff = NULL, *big_buff = NULL; | 658 | char *buff = NULL, *big_buff = NULL; |
| 688 | int rc, sig = 0; | 659 | int sig = 0; |
| 689 | loff_t p; | 660 | loff_t p; |
| 690 | 661 | ||
| 691 | read_partition: | ||
| 692 | read_type++; | 662 | read_type++; |
| 693 | 663 | ||
| 694 | switch (nvram_type_ids[read_type]) { | 664 | switch (nvram_type_ids[read_type]) { |
| @@ -749,30 +719,46 @@ read_partition: | |||
| 749 | *id = id_no; | 719 | *id = id_no; |
| 750 | 720 | ||
| 751 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { | 721 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { |
| 722 | int length, unzipped_len; | ||
| 723 | size_t hdr_size; | ||
| 724 | |||
| 752 | oops_hdr = (struct oops_log_info *)buff; | 725 | oops_hdr = (struct oops_log_info *)buff; |
| 753 | *buf = buff + sizeof(*oops_hdr); | 726 | if (oops_hdr->version < OOPS_HDR_VERSION) { |
| 727 | /* Old format oops header had 2-byte record size */ | ||
| 728 | hdr_size = sizeof(u16); | ||
| 729 | length = oops_hdr->version; | ||
| 730 | time->tv_sec = 0; | ||
| 731 | time->tv_nsec = 0; | ||
| 732 | } else { | ||
| 733 | hdr_size = sizeof(*oops_hdr); | ||
| 734 | length = oops_hdr->report_length; | ||
| 735 | time->tv_sec = oops_hdr->timestamp; | ||
| 736 | time->tv_nsec = 0; | ||
| 737 | } | ||
| 738 | *buf = kmalloc(length, GFP_KERNEL); | ||
| 739 | if (*buf == NULL) | ||
| 740 | return -ENOMEM; | ||
| 741 | memcpy(*buf, buff + hdr_size, length); | ||
| 742 | kfree(buff); | ||
| 754 | 743 | ||
| 755 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { | 744 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { |
| 756 | big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); | 745 | big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); |
| 757 | if (!big_buff) | 746 | if (!big_buff) |
| 758 | return -ENOMEM; | 747 | return -ENOMEM; |
| 759 | 748 | ||
| 760 | rc = unzip_oops(buff, big_buff); | 749 | unzipped_len = nvram_decompress(*buf, big_buff, |
| 750 | length, big_oops_buf_sz); | ||
| 761 | 751 | ||
| 762 | if (rc != 0) { | 752 | if (unzipped_len < 0) { |
| 763 | kfree(buff); | 753 | pr_err("nvram: decompression failed, returned " |
| 754 | "rc %d\n", unzipped_len); | ||
| 764 | kfree(big_buff); | 755 | kfree(big_buff); |
| 765 | goto read_partition; | 756 | } else { |
| 757 | *buf = big_buff; | ||
| 758 | length = unzipped_len; | ||
| 766 | } | 759 | } |
| 767 | |||
| 768 | oops_hdr = (struct oops_log_info *)big_buff; | ||
| 769 | *buf = big_buff + sizeof(*oops_hdr); | ||
| 770 | kfree(buff); | ||
| 771 | } | 760 | } |
| 772 | 761 | return length; | |
| 773 | time->tv_sec = oops_hdr->timestamp; | ||
| 774 | time->tv_nsec = 0; | ||
| 775 | return oops_hdr->report_length; | ||
| 776 | } | 762 | } |
| 777 | 763 | ||
| 778 | *buf = buff; | 764 | *buf = buff; |
| @@ -816,6 +802,7 @@ static int nvram_pstore_init(void) | |||
| 816 | static void __init nvram_init_oops_partition(int rtas_partition_exists) | 802 | static void __init nvram_init_oops_partition(int rtas_partition_exists) |
| 817 | { | 803 | { |
| 818 | int rc; | 804 | int rc; |
| 805 | size_t size; | ||
| 819 | 806 | ||
| 820 | rc = pseries_nvram_init_os_partition(&oops_log_partition); | 807 | rc = pseries_nvram_init_os_partition(&oops_log_partition); |
| 821 | if (rc != 0) { | 808 | if (rc != 0) { |
| @@ -844,8 +831,9 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists) | |||
| 844 | big_oops_buf_sz = (oops_data_sz * 100) / 45; | 831 | big_oops_buf_sz = (oops_data_sz * 100) / 45; |
| 845 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); | 832 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); |
| 846 | if (big_oops_buf) { | 833 | if (big_oops_buf) { |
| 847 | stream.workspace = kmalloc(zlib_deflate_workspacesize( | 834 | size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), |
| 848 | WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); | 835 | zlib_inflate_workspacesize()); |
| 836 | stream.workspace = kmalloc(size, GFP_KERNEL); | ||
| 849 | if (!stream.workspace) { | 837 | if (!stream.workspace) { |
| 850 | pr_err("nvram: No memory for compression workspace; " | 838 | pr_err("nvram: No memory for compression workspace; " |
| 851 | "skipping compression of %s partition data\n", | 839 | "skipping compression of %s partition data\n", |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 22f75b504f7f..8a4cae78f03c 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -118,6 +118,7 @@ config S390 | |||
| 118 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 118 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
| 119 | select HAVE_KERNEL_BZIP2 | 119 | select HAVE_KERNEL_BZIP2 |
| 120 | select HAVE_KERNEL_GZIP | 120 | select HAVE_KERNEL_GZIP |
| 121 | select HAVE_KERNEL_LZ4 | ||
| 121 | select HAVE_KERNEL_LZMA | 122 | select HAVE_KERNEL_LZMA |
| 122 | select HAVE_KERNEL_LZO | 123 | select HAVE_KERNEL_LZO |
| 123 | select HAVE_KERNEL_XZ | 124 | select HAVE_KERNEL_XZ |
| @@ -227,11 +228,12 @@ config MARCH_Z196 | |||
| 227 | not work on older machines. | 228 | not work on older machines. |
| 228 | 229 | ||
| 229 | config MARCH_ZEC12 | 230 | config MARCH_ZEC12 |
| 230 | bool "IBM zEC12" | 231 | bool "IBM zBC12 and zEC12" |
| 231 | select HAVE_MARCH_ZEC12_FEATURES if 64BIT | 232 | select HAVE_MARCH_ZEC12_FEATURES if 64BIT |
| 232 | help | 233 | help |
| 233 | Select this to enable optimizations for IBM zEC12 (2827 series). The | 234 | Select this to enable optimizations for IBM zBC12 and zEC12 (2828 and |
| 234 | kernel will be slightly faster but will not work on older machines. | 235 | 2827 series). The kernel will be slightly faster but will not work on |
| 236 | older machines. | ||
| 235 | 237 | ||
| 236 | endchoice | 238 | endchoice |
| 237 | 239 | ||
| @@ -709,6 +711,7 @@ config S390_GUEST | |||
| 709 | def_bool y | 711 | def_bool y |
| 710 | prompt "s390 support for virtio devices" | 712 | prompt "s390 support for virtio devices" |
| 711 | depends on 64BIT | 713 | depends on 64BIT |
| 714 | select TTY | ||
| 712 | select VIRTUALIZATION | 715 | select VIRTUALIZATION |
| 713 | select VIRTIO | 716 | select VIRTIO |
| 714 | select VIRTIO_CONSOLE | 717 | select VIRTIO_CONSOLE |
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index 3ad8f61c9985..866ecbe670e4 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | BITS := $(if $(CONFIG_64BIT),64,31) | 7 | BITS := $(if $(CONFIG_64BIT),64,31) |
| 8 | 8 | ||
| 9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ | 9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 |
| 10 | vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \ | 10 | targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 |
| 11 | sizes.h head$(BITS).o | 11 | targets += misc.o piggy.o sizes.h head$(BITS).o |
| 12 | 12 | ||
| 13 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 | 13 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 |
| 14 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING | 14 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING |
| @@ -48,6 +48,7 @@ vmlinux.bin.all-y := $(obj)/vmlinux.bin | |||
| 48 | 48 | ||
| 49 | suffix-$(CONFIG_KERNEL_GZIP) := gz | 49 | suffix-$(CONFIG_KERNEL_GZIP) := gz |
| 50 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 | 50 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 |
| 51 | suffix-$(CONFIG_KERNEL_LZ4) := lz4 | ||
| 51 | suffix-$(CONFIG_KERNEL_LZMA) := lzma | 52 | suffix-$(CONFIG_KERNEL_LZMA) := lzma |
| 52 | suffix-$(CONFIG_KERNEL_LZO) := lzo | 53 | suffix-$(CONFIG_KERNEL_LZO) := lzo |
| 53 | suffix-$(CONFIG_KERNEL_XZ) := xz | 54 | suffix-$(CONFIG_KERNEL_XZ) := xz |
| @@ -56,6 +57,8 @@ $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) | |||
| 56 | $(call if_changed,gzip) | 57 | $(call if_changed,gzip) |
| 57 | $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) | 58 | $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) |
| 58 | $(call if_changed,bzip2) | 59 | $(call if_changed,bzip2) |
| 60 | $(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) | ||
| 61 | $(call if_changed,lz4) | ||
| 59 | $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) | 62 | $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) |
| 60 | $(call if_changed,lzma) | 63 | $(call if_changed,lzma) |
| 61 | $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) | 64 | $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) |
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index c4c6a1cf221b..57cbaff1f397 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c | |||
| @@ -47,6 +47,10 @@ static unsigned long free_mem_end_ptr; | |||
| 47 | #include "../../../../lib/decompress_bunzip2.c" | 47 | #include "../../../../lib/decompress_bunzip2.c" |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | #ifdef CONFIG_KERNEL_LZ4 | ||
| 51 | #include "../../../../lib/decompress_unlz4.c" | ||
| 52 | #endif | ||
| 53 | |||
| 50 | #ifdef CONFIG_KERNEL_LZMA | 54 | #ifdef CONFIG_KERNEL_LZMA |
| 51 | #include "../../../../lib/decompress_unlzma.c" | 55 | #include "../../../../lib/decompress_unlzma.c" |
| 52 | #endif | 56 | #endif |
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 4d8604e311f3..7d4676758733 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h | |||
| @@ -693,7 +693,7 @@ static inline int find_next_bit_left(const unsigned long *addr, | |||
| 693 | size -= offset; | 693 | size -= offset; |
| 694 | p = addr + offset / BITS_PER_LONG; | 694 | p = addr + offset / BITS_PER_LONG; |
| 695 | if (bit) { | 695 | if (bit) { |
| 696 | set = __flo_word(0, *p & (~0UL << bit)); | 696 | set = __flo_word(0, *p & (~0UL >> bit)); |
| 697 | if (set >= size) | 697 | if (set >= size) |
| 698 | return size + offset; | 698 | return size + offset; |
| 699 | if (set < BITS_PER_LONG) | 699 | if (set < BITS_PER_LONG) |
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index b75d7d686684..6d6d92b4ea11 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h | |||
| @@ -32,6 +32,7 @@ struct mmu_gather { | |||
| 32 | struct mm_struct *mm; | 32 | struct mm_struct *mm; |
| 33 | struct mmu_table_batch *batch; | 33 | struct mmu_table_batch *batch; |
| 34 | unsigned int fullmm; | 34 | unsigned int fullmm; |
| 35 | unsigned long start, end; | ||
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 37 | struct mmu_table_batch { | 38 | struct mmu_table_batch { |
| @@ -48,10 +49,13 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table); | |||
| 48 | 49 | ||
| 49 | static inline void tlb_gather_mmu(struct mmu_gather *tlb, | 50 | static inline void tlb_gather_mmu(struct mmu_gather *tlb, |
| 50 | struct mm_struct *mm, | 51 | struct mm_struct *mm, |
| 51 | unsigned int full_mm_flush) | 52 | unsigned long start, |
| 53 | unsigned long end) | ||
| 52 | { | 54 | { |
| 53 | tlb->mm = mm; | 55 | tlb->mm = mm; |
| 54 | tlb->fullmm = full_mm_flush; | 56 | tlb->start = start; |
| 57 | tlb->end = end; | ||
| 58 | tlb->fullmm = !(start | (end+1)); | ||
| 55 | tlb->batch = NULL; | 59 | tlb->batch = NULL; |
| 56 | if (tlb->fullmm) | 60 | if (tlb->fullmm) |
| 57 | __tlb_flush_mm(mm); | 61 | __tlb_flush_mm(mm); |
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index a6fc037671b1..500aa1029bcb 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c | |||
| @@ -52,12 +52,13 @@ static struct kvm_s390_sie_block *sie_block(struct pt_regs *regs) | |||
| 52 | 52 | ||
| 53 | static bool is_in_guest(struct pt_regs *regs) | 53 | static bool is_in_guest(struct pt_regs *regs) |
| 54 | { | 54 | { |
| 55 | unsigned long ip = instruction_pointer(regs); | ||
| 56 | |||
| 57 | if (user_mode(regs)) | 55 | if (user_mode(regs)) |
| 58 | return false; | 56 | return false; |
| 59 | 57 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | |
| 60 | return ip == (unsigned long) &sie_exit; | 58 | return instruction_pointer(regs) == (unsigned long) &sie_exit; |
| 59 | #else | ||
| 60 | return false; | ||
| 61 | #endif | ||
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | static unsigned long guest_is_user_mode(struct pt_regs *regs) | 64 | static unsigned long guest_is_user_mode(struct pt_regs *regs) |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 497451ec5e26..aeed8a61fa0d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -994,6 +994,7 @@ static void __init setup_hwcaps(void) | |||
| 994 | strcpy(elf_platform, "z196"); | 994 | strcpy(elf_platform, "z196"); |
| 995 | break; | 995 | break; |
| 996 | case 0x2827: | 996 | case 0x2827: |
| 997 | case 0x2828: | ||
| 997 | strcpy(elf_platform, "zEC12"); | 998 | strcpy(elf_platform, "zEC12"); |
| 998 | break; | 999 | break; |
| 999 | } | 1000 | } |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ba694d2ba51e..34c1c9a90be2 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -702,14 +702,25 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
| 702 | return rc; | 702 | return rc; |
| 703 | 703 | ||
| 704 | vcpu->arch.sie_block->icptcode = 0; | 704 | vcpu->arch.sie_block->icptcode = 0; |
| 705 | preempt_disable(); | ||
| 706 | kvm_guest_enter(); | ||
| 707 | preempt_enable(); | ||
| 708 | VCPU_EVENT(vcpu, 6, "entering sie flags %x", | 705 | VCPU_EVENT(vcpu, 6, "entering sie flags %x", |
| 709 | atomic_read(&vcpu->arch.sie_block->cpuflags)); | 706 | atomic_read(&vcpu->arch.sie_block->cpuflags)); |
| 710 | trace_kvm_s390_sie_enter(vcpu, | 707 | trace_kvm_s390_sie_enter(vcpu, |
| 711 | atomic_read(&vcpu->arch.sie_block->cpuflags)); | 708 | atomic_read(&vcpu->arch.sie_block->cpuflags)); |
| 709 | |||
| 710 | /* | ||
| 711 | * As PF_VCPU will be used in fault handler, between guest_enter | ||
| 712 | * and guest_exit should be no uaccess. | ||
| 713 | */ | ||
| 714 | preempt_disable(); | ||
| 715 | kvm_guest_enter(); | ||
| 716 | preempt_enable(); | ||
| 712 | rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs); | 717 | rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs); |
| 718 | kvm_guest_exit(); | ||
| 719 | |||
| 720 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", | ||
| 721 | vcpu->arch.sie_block->icptcode); | ||
| 722 | trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); | ||
| 723 | |||
| 713 | if (rc > 0) | 724 | if (rc > 0) |
| 714 | rc = 0; | 725 | rc = 0; |
| 715 | if (rc < 0) { | 726 | if (rc < 0) { |
| @@ -721,10 +732,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
| 721 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 732 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
| 722 | } | 733 | } |
| 723 | } | 734 | } |
| 724 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", | ||
| 725 | vcpu->arch.sie_block->icptcode); | ||
| 726 | trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); | ||
| 727 | kvm_guest_exit(); | ||
| 728 | 735 | ||
| 729 | memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); | 736 | memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); |
| 730 | return rc; | 737 | return rc; |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 0da3e6eb6be6..4cdc54e63ebc 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
| 17 | #include <linux/compat.h> | 17 | #include <linux/compat.h> |
| 18 | #include <asm/asm-offsets.h> | 18 | #include <asm/asm-offsets.h> |
| 19 | #include <asm/facility.h> | ||
| 19 | #include <asm/current.h> | 20 | #include <asm/current.h> |
| 20 | #include <asm/debug.h> | 21 | #include <asm/debug.h> |
| 21 | #include <asm/ebcdic.h> | 22 | #include <asm/ebcdic.h> |
| @@ -532,8 +533,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) | |||
| 532 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 533 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
| 533 | 534 | ||
| 534 | /* Only provide non-quiescing support if the host supports it */ | 535 | /* Only provide non-quiescing support if the host supports it */ |
| 535 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && | 536 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14)) |
| 536 | S390_lowcore.stfl_fac_list & 0x00020000) | ||
| 537 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 537 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
| 538 | 538 | ||
| 539 | /* No support for conditional-SSKE */ | 539 | /* No support for conditional-SSKE */ |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index ce36ea80e4f9..ad446b0c55b6 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
| @@ -69,6 +69,7 @@ static void __init setup_zero_pages(void) | |||
| 69 | order = 2; | 69 | order = 2; |
| 70 | break; | 70 | break; |
| 71 | case 0x2827: /* zEC12 */ | 71 | case 0x2827: /* zEC12 */ |
| 72 | case 0x2828: /* zEC12 */ | ||
| 72 | default: | 73 | default: |
| 73 | order = 5; | 74 | order = 5; |
| 74 | break; | 75 | break; |
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index ffeb17ce7f31..930783d2c99b 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c | |||
| @@ -440,7 +440,7 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops) | |||
| 440 | switch (id.machine) { | 440 | switch (id.machine) { |
| 441 | case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break; | 441 | case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break; |
| 442 | case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break; | 442 | case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break; |
| 443 | case 0x2827: ops->cpu_type = "s390/zEC12"; break; | 443 | case 0x2827: case 0x2828: ops->cpu_type = "s390/zEC12"; break; |
| 444 | default: return -ENODEV; | 444 | default: return -ENODEV; |
| 445 | } | 445 | } |
| 446 | } | 446 | } |
diff --git a/arch/score/Kconfig b/arch/score/Kconfig index c8def8bc9020..5fc237581caf 100644 --- a/arch/score/Kconfig +++ b/arch/score/Kconfig | |||
| @@ -87,6 +87,8 @@ config STACKTRACE_SUPPORT | |||
| 87 | 87 | ||
| 88 | source "init/Kconfig" | 88 | source "init/Kconfig" |
| 89 | 89 | ||
| 90 | source "kernel/Kconfig.freezer" | ||
| 91 | |||
| 90 | config MMU | 92 | config MMU |
| 91 | def_bool y | 93 | def_bool y |
| 92 | 94 | ||
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index e61d43d9f689..362192ed12fe 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h | |||
| @@ -36,10 +36,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static inline void | 38 | static inline void |
| 39 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) | 39 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 40 | { | 40 | { |
| 41 | tlb->mm = mm; | 41 | tlb->mm = mm; |
| 42 | tlb->fullmm = full_mm_flush; | 42 | tlb->start = start; |
| 43 | tlb->end = end; | ||
| 44 | tlb->fullmm = !(start | (end+1)); | ||
| 43 | 45 | ||
| 44 | init_tlb_gather(tlb); | 46 | init_tlb_gather(tlb); |
| 45 | } | 47 | } |
diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h index 4febacd1a8a1..29b0301c18aa 100644 --- a/arch/um/include/asm/tlb.h +++ b/arch/um/include/asm/tlb.h | |||
| @@ -45,10 +45,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | static inline void | 47 | static inline void |
| 48 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) | 48 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 49 | { | 49 | { |
| 50 | tlb->mm = mm; | 50 | tlb->mm = mm; |
| 51 | tlb->fullmm = full_mm_flush; | 51 | tlb->start = start; |
| 52 | tlb->end = end; | ||
| 53 | tlb->fullmm = !(start | (end+1)); | ||
| 52 | 54 | ||
| 53 | init_tlb_gather(tlb); | 55 | init_tlb_gather(tlb); |
| 54 | } | 56 | } |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index d606463aa6d6..b7388a425f09 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
| @@ -225,7 +225,7 @@ static void low_free(unsigned long size, unsigned long addr) | |||
| 225 | unsigned long nr_pages; | 225 | unsigned long nr_pages; |
| 226 | 226 | ||
| 227 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | 227 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; |
| 228 | efi_call_phys2(sys_table->boottime->free_pages, addr, size); | 228 | efi_call_phys2(sys_table->boottime->free_pages, addr, nr_pages); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) | 231 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) |
diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h index f2b489cf1602..3bf2dd0cf61f 100644 --- a/arch/x86/include/asm/pgtable-2level.h +++ b/arch/x86/include/asm/pgtable-2level.h | |||
| @@ -55,9 +55,53 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) | |||
| 55 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) | 55 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | #ifdef CONFIG_MEM_SOFT_DIRTY | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE, _PAGE_BIT_SOFT_DIRTY and | ||
| 62 | * _PAGE_BIT_PROTNONE are taken, split up the 28 bits of offset | ||
| 63 | * into this range. | ||
| 64 | */ | ||
| 65 | #define PTE_FILE_MAX_BITS 28 | ||
| 66 | #define PTE_FILE_SHIFT1 (_PAGE_BIT_PRESENT + 1) | ||
| 67 | #define PTE_FILE_SHIFT2 (_PAGE_BIT_FILE + 1) | ||
| 68 | #define PTE_FILE_SHIFT3 (_PAGE_BIT_PROTNONE + 1) | ||
| 69 | #define PTE_FILE_SHIFT4 (_PAGE_BIT_SOFT_DIRTY + 1) | ||
| 70 | #define PTE_FILE_BITS1 (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1) | ||
| 71 | #define PTE_FILE_BITS2 (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1) | ||
| 72 | #define PTE_FILE_BITS3 (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1) | ||
| 73 | |||
| 74 | #define pte_to_pgoff(pte) \ | ||
| 75 | ((((pte).pte_low >> (PTE_FILE_SHIFT1)) \ | ||
| 76 | & ((1U << PTE_FILE_BITS1) - 1))) \ | ||
| 77 | + ((((pte).pte_low >> (PTE_FILE_SHIFT2)) \ | ||
| 78 | & ((1U << PTE_FILE_BITS2) - 1)) \ | ||
| 79 | << (PTE_FILE_BITS1)) \ | ||
| 80 | + ((((pte).pte_low >> (PTE_FILE_SHIFT3)) \ | ||
| 81 | & ((1U << PTE_FILE_BITS3) - 1)) \ | ||
| 82 | << (PTE_FILE_BITS1 + PTE_FILE_BITS2)) \ | ||
| 83 | + ((((pte).pte_low >> (PTE_FILE_SHIFT4))) \ | ||
| 84 | << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)) | ||
| 85 | |||
| 86 | #define pgoff_to_pte(off) \ | ||
| 87 | ((pte_t) { .pte_low = \ | ||
| 88 | ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1) \ | ||
| 89 | + ((((off) >> PTE_FILE_BITS1) \ | ||
| 90 | & ((1U << PTE_FILE_BITS2) - 1)) \ | ||
| 91 | << PTE_FILE_SHIFT2) \ | ||
| 92 | + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2)) \ | ||
| 93 | & ((1U << PTE_FILE_BITS3) - 1)) \ | ||
| 94 | << PTE_FILE_SHIFT3) \ | ||
| 95 | + ((((off) >> \ | ||
| 96 | (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))) \ | ||
| 97 | << PTE_FILE_SHIFT4) \ | ||
| 98 | + _PAGE_FILE }) | ||
| 99 | |||
| 100 | #else /* CONFIG_MEM_SOFT_DIRTY */ | ||
| 101 | |||
| 58 | /* | 102 | /* |
| 59 | * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken, | 103 | * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken, |
| 60 | * split up the 29 bits of offset into this range: | 104 | * split up the 29 bits of offset into this range. |
| 61 | */ | 105 | */ |
| 62 | #define PTE_FILE_MAX_BITS 29 | 106 | #define PTE_FILE_MAX_BITS 29 |
| 63 | #define PTE_FILE_SHIFT1 (_PAGE_BIT_PRESENT + 1) | 107 | #define PTE_FILE_SHIFT1 (_PAGE_BIT_PRESENT + 1) |
| @@ -88,6 +132,8 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) | |||
| 88 | << PTE_FILE_SHIFT3) \ | 132 | << PTE_FILE_SHIFT3) \ |
| 89 | + _PAGE_FILE }) | 133 | + _PAGE_FILE }) |
| 90 | 134 | ||
| 135 | #endif /* CONFIG_MEM_SOFT_DIRTY */ | ||
| 136 | |||
| 91 | /* Encode and de-code a swap entry */ | 137 | /* Encode and de-code a swap entry */ |
| 92 | #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE | 138 | #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE |
| 93 | #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1) | 139 | #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1) |
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 4cc9f2b7cdc3..81bb91b49a88 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h | |||
| @@ -179,6 +179,9 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp) | |||
| 179 | /* | 179 | /* |
| 180 | * Bits 0, 6 and 7 are taken in the low part of the pte, | 180 | * Bits 0, 6 and 7 are taken in the low part of the pte, |
| 181 | * put the 32 bits of offset into the high part. | 181 | * put the 32 bits of offset into the high part. |
| 182 | * | ||
| 183 | * For soft-dirty tracking 11 bit is taken from | ||
| 184 | * the low part of pte as well. | ||
| 182 | */ | 185 | */ |
| 183 | #define pte_to_pgoff(pte) ((pte).pte_high) | 186 | #define pte_to_pgoff(pte) ((pte).pte_high) |
| 184 | #define pgoff_to_pte(off) \ | 187 | #define pgoff_to_pte(off) \ |
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 7dc305a46058..1c00631164c2 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
| @@ -314,6 +314,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd) | |||
| 314 | return pmd_set_flags(pmd, _PAGE_SOFT_DIRTY); | 314 | return pmd_set_flags(pmd, _PAGE_SOFT_DIRTY); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | static inline pte_t pte_swp_mksoft_dirty(pte_t pte) | ||
| 318 | { | ||
| 319 | return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY); | ||
| 320 | } | ||
| 321 | |||
| 322 | static inline int pte_swp_soft_dirty(pte_t pte) | ||
| 323 | { | ||
| 324 | return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY; | ||
| 325 | } | ||
| 326 | |||
| 327 | static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) | ||
| 328 | { | ||
| 329 | return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY); | ||
| 330 | } | ||
| 331 | |||
| 332 | static inline pte_t pte_file_clear_soft_dirty(pte_t pte) | ||
| 333 | { | ||
| 334 | return pte_clear_flags(pte, _PAGE_SOFT_DIRTY); | ||
| 335 | } | ||
| 336 | |||
| 337 | static inline pte_t pte_file_mksoft_dirty(pte_t pte) | ||
| 338 | { | ||
| 339 | return pte_set_flags(pte, _PAGE_SOFT_DIRTY); | ||
| 340 | } | ||
| 341 | |||
| 342 | static inline int pte_file_soft_dirty(pte_t pte) | ||
| 343 | { | ||
| 344 | return pte_flags(pte) & _PAGE_SOFT_DIRTY; | ||
| 345 | } | ||
| 346 | |||
| 317 | /* | 347 | /* |
| 318 | * Mask out unsupported bits in a present pgprot. Non-present pgprots | 348 | * Mask out unsupported bits in a present pgprot. Non-present pgprots |
| 319 | * can use those bits for other purposes, so leave them be. | 349 | * can use those bits for other purposes, so leave them be. |
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index c98ac63aae48..f4843e031131 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
| @@ -61,12 +61,27 @@ | |||
| 61 | * they do not conflict with each other. | 61 | * they do not conflict with each other. |
| 62 | */ | 62 | */ |
| 63 | 63 | ||
| 64 | #define _PAGE_BIT_SOFT_DIRTY _PAGE_BIT_HIDDEN | ||
| 65 | |||
| 64 | #ifdef CONFIG_MEM_SOFT_DIRTY | 66 | #ifdef CONFIG_MEM_SOFT_DIRTY |
| 65 | #define _PAGE_SOFT_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN) | 67 | #define _PAGE_SOFT_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_SOFT_DIRTY) |
| 66 | #else | 68 | #else |
| 67 | #define _PAGE_SOFT_DIRTY (_AT(pteval_t, 0)) | 69 | #define _PAGE_SOFT_DIRTY (_AT(pteval_t, 0)) |
| 68 | #endif | 70 | #endif |
| 69 | 71 | ||
| 72 | /* | ||
| 73 | * Tracking soft dirty bit when a page goes to a swap is tricky. | ||
| 74 | * We need a bit which can be stored in pte _and_ not conflict | ||
| 75 | * with swap entry format. On x86 bits 6 and 7 are *not* involved | ||
| 76 | * into swap entry computation, but bit 6 is used for nonlinear | ||
| 77 | * file mapping, so we borrow bit 7 for soft dirty tracking. | ||
| 78 | */ | ||
| 79 | #ifdef CONFIG_MEM_SOFT_DIRTY | ||
| 80 | #define _PAGE_SWP_SOFT_DIRTY _PAGE_PSE | ||
| 81 | #else | ||
| 82 | #define _PAGE_SWP_SOFT_DIRTY (_AT(pteval_t, 0)) | ||
| 83 | #endif | ||
| 84 | |||
| 70 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | 85 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) |
| 71 | #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) | 86 | #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) |
| 72 | #else | 87 | #else |
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index 33692eaabab5..e3ddd7db723f 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h | |||
| @@ -233,8 +233,4 @@ static inline void arch_write_unlock(arch_rwlock_t *rw) | |||
| 233 | #define arch_read_relax(lock) cpu_relax() | 233 | #define arch_read_relax(lock) cpu_relax() |
| 234 | #define arch_write_relax(lock) cpu_relax() | 234 | #define arch_write_relax(lock) cpu_relax() |
| 235 | 235 | ||
| 236 | /* The {read|write|spin}_lock() on x86 are full memory barriers. */ | ||
| 237 | static inline void smp_mb__after_lock(void) { } | ||
| 238 | #define ARCH_HAS_SMP_MB_AFTER_LOCK | ||
| 239 | |||
| 240 | #endif /* _ASM_X86_SPINLOCK_H */ | 236 | #endif /* _ASM_X86_SPINLOCK_H */ |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index fbc9210b45bc..a45d8d4ace10 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
| @@ -2270,6 +2270,7 @@ __init int intel_pmu_init(void) | |||
| 2270 | case 70: | 2270 | case 70: |
| 2271 | case 71: | 2271 | case 71: |
| 2272 | case 63: | 2272 | case 63: |
| 2273 | case 69: | ||
| 2273 | x86_pmu.late_ack = true; | 2274 | x86_pmu.late_ack = true; |
| 2274 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); | 2275 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); |
| 2275 | memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs)); | 2276 | memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs)); |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index cad791dbde95..1fb6c72717bd 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
| @@ -314,8 +314,8 @@ static struct uncore_event_desc snbep_uncore_imc_events[] = { | |||
| 314 | static struct uncore_event_desc snbep_uncore_qpi_events[] = { | 314 | static struct uncore_event_desc snbep_uncore_qpi_events[] = { |
| 315 | INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x14"), | 315 | INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x14"), |
| 316 | INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"), | 316 | INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"), |
| 317 | INTEL_UNCORE_EVENT_DESC(drs_data, "event=0x02,umask=0x08"), | 317 | INTEL_UNCORE_EVENT_DESC(drs_data, "event=0x102,umask=0x08"), |
| 318 | INTEL_UNCORE_EVENT_DESC(ncb_data, "event=0x03,umask=0x04"), | 318 | INTEL_UNCORE_EVENT_DESC(ncb_data, "event=0x103,umask=0x04"), |
| 319 | { /* end: all zeroes */ }, | 319 | { /* end: all zeroes */ }, |
| 320 | }; | 320 | }; |
| 321 | 321 | ||
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 94ab6b90dd3f..63bdb29b2549 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c | |||
| @@ -196,15 +196,23 @@ static void __init ati_bugs_contd(int num, int slot, int func) | |||
| 196 | static void __init intel_remapping_check(int num, int slot, int func) | 196 | static void __init intel_remapping_check(int num, int slot, int func) |
| 197 | { | 197 | { |
| 198 | u8 revision; | 198 | u8 revision; |
| 199 | u16 device; | ||
| 199 | 200 | ||
| 201 | device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); | ||
| 200 | revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); | 202 | revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); |
| 201 | 203 | ||
| 202 | /* | 204 | /* |
| 203 | * Revision 0x13 of this chipset supports irq remapping | 205 | * Revision 13 of all triggering devices id in this quirk have |
| 204 | * but has an erratum that breaks its behavior, flag it as such | 206 | * a problem draining interrupts when irq remapping is enabled, |
| 207 | * and should be flagged as broken. Additionally revisions 0x12 | ||
| 208 | * and 0x22 of device id 0x3405 has this problem. | ||
| 205 | */ | 209 | */ |
| 206 | if (revision == 0x13) | 210 | if (revision == 0x13) |
| 207 | set_irq_remapping_broken(); | 211 | set_irq_remapping_broken(); |
| 212 | else if ((device == 0x3405) && | ||
| 213 | ((revision == 0x12) || | ||
| 214 | (revision == 0x22))) | ||
| 215 | set_irq_remapping_broken(); | ||
| 208 | 216 | ||
| 209 | } | 217 | } |
| 210 | 218 | ||
| @@ -239,6 +247,8 @@ static struct chipset early_qrk[] __initdata = { | |||
| 239 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, | 247 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, |
| 240 | { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, | 248 | { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, |
| 241 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | 249 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, |
| 250 | { PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST, | ||
| 251 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | ||
| 242 | { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, | 252 | { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, |
| 243 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | 253 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, |
| 244 | {} | 254 | {} |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 202d24f0f7e7..5d576ab34403 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -116,7 +116,7 @@ static void mxcsr_feature_mask_init(void) | |||
| 116 | 116 | ||
| 117 | if (cpu_has_fxsr) { | 117 | if (cpu_has_fxsr) { |
| 118 | memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); | 118 | memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); |
| 119 | asm volatile("fxsave %0" : : "m" (fx_scratch)); | 119 | asm volatile("fxsave %0" : "+m" (fx_scratch)); |
| 120 | mask = fx_scratch.mxcsr_mask; | 120 | mask = fx_scratch.mxcsr_mask; |
| 121 | if (mask == 0) | 121 | if (mask == 0) |
| 122 | mask = 0x0000ffbf; | 122 | mask = 0x0000ffbf; |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 47ebb1dbfbcb..7a0adb7ee433 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -220,12 +220,13 @@ int apply_microcode_amd(int cpu) | |||
| 220 | return 0; | 220 | return 0; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | if (__apply_microcode_amd(mc_amd)) | 223 | if (__apply_microcode_amd(mc_amd)) { |
| 224 | pr_err("CPU%d: update failed for patch_level=0x%08x\n", | 224 | pr_err("CPU%d: update failed for patch_level=0x%08x\n", |
| 225 | cpu, mc_amd->hdr.patch_id); | 225 | cpu, mc_amd->hdr.patch_id); |
| 226 | else | 226 | return -1; |
| 227 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, | 227 | } |
| 228 | mc_amd->hdr.patch_id); | 228 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, |
| 229 | mc_amd->hdr.patch_id); | ||
| 229 | 230 | ||
| 230 | uci->cpu_sig.rev = mc_amd->hdr.patch_id; | 231 | uci->cpu_sig.rev = mc_amd->hdr.patch_id; |
| 231 | c->microcode = mc_amd->hdr.patch_id; | 232 | c->microcode = mc_amd->hdr.patch_id; |
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index dbded5aedb81..48f8375e4c6b 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c | |||
| @@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin, | |||
| 101 | *begin = new_begin; | 101 | *begin = new_begin; |
| 102 | } | 102 | } |
| 103 | } else { | 103 | } else { |
| 104 | *begin = TASK_UNMAPPED_BASE; | 104 | *begin = mmap_legacy_base(); |
| 105 | *end = TASK_SIZE; | 105 | *end = TASK_SIZE; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 62c29a5bfe26..f63778cb2363 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c | |||
| @@ -98,7 +98,7 @@ static unsigned long mmap_base(void) | |||
| 98 | * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 | 98 | * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 |
| 99 | * does, but not when emulating X86_32 | 99 | * does, but not when emulating X86_32 |
| 100 | */ | 100 | */ |
| 101 | static unsigned long mmap_legacy_base(void) | 101 | unsigned long mmap_legacy_base(void) |
| 102 | { | 102 | { |
| 103 | if (mmap_is_ia32()) | 103 | if (mmap_is_ia32()) |
| 104 | return TASK_UNMAPPED_BASE; | 104 | return TASK_UNMAPPED_BASE; |
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index fd6c51cc3acb..5a74a9c1e42c 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c | |||
| @@ -451,7 +451,6 @@ static void acpi_processor_remove(struct acpi_device *device) | |||
| 451 | /* Clean up. */ | 451 | /* Clean up. */ |
| 452 | per_cpu(processor_device_array, pr->id) = NULL; | 452 | per_cpu(processor_device_array, pr->id) = NULL; |
| 453 | per_cpu(processors, pr->id) = NULL; | 453 | per_cpu(processors, pr->id) = NULL; |
| 454 | try_offline_node(cpu_to_node(pr->id)); | ||
| 455 | 454 | ||
| 456 | /* Remove the CPU. */ | 455 | /* Remove the CPU. */ |
| 457 | get_online_cpus(); | 456 | get_online_cpus(); |
| @@ -459,6 +458,8 @@ static void acpi_processor_remove(struct acpi_device *device) | |||
| 459 | acpi_unmap_lsapic(pr->id); | 458 | acpi_unmap_lsapic(pr->id); |
| 460 | put_online_cpus(); | 459 | put_online_cpus(); |
| 461 | 460 | ||
| 461 | try_offline_node(cpu_to_node(pr->id)); | ||
| 462 | |||
| 462 | out: | 463 | out: |
| 463 | free_cpumask_var(pr->throttling.shared_cpu_map); | 464 | free_cpumask_var(pr->throttling.shared_cpu_map); |
| 464 | kfree(pr); | 465 | kfree(pr); |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index f68095756fb7..408f6b2a5fa8 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -31,6 +31,7 @@ static LIST_HEAD(bus_type_list); | |||
| 31 | static DECLARE_RWSEM(bus_type_sem); | 31 | static DECLARE_RWSEM(bus_type_sem); |
| 32 | 32 | ||
| 33 | #define PHYSICAL_NODE_STRING "physical_node" | 33 | #define PHYSICAL_NODE_STRING "physical_node" |
| 34 | #define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10) | ||
| 34 | 35 | ||
| 35 | int register_acpi_bus_type(struct acpi_bus_type *type) | 36 | int register_acpi_bus_type(struct acpi_bus_type *type) |
| 36 | { | 37 | { |
| @@ -78,41 +79,108 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) | |||
| 78 | return ret; | 79 | return ret; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, | 82 | static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, |
| 82 | void *addr_p, void **ret_p) | 83 | void *not_used, void **ret_p) |
| 83 | { | 84 | { |
| 84 | unsigned long long addr, sta; | 85 | struct acpi_device *adev = NULL; |
| 85 | acpi_status status; | ||
| 86 | 86 | ||
| 87 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); | 87 | acpi_bus_get_device(handle, &adev); |
| 88 | if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) { | 88 | if (adev) { |
| 89 | *ret_p = handle; | 89 | *ret_p = handle; |
| 90 | status = acpi_bus_get_status_handle(handle, &sta); | 90 | return AE_CTRL_TERMINATE; |
| 91 | if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED)) | ||
| 92 | return AE_CTRL_TERMINATE; | ||
| 93 | } | 91 | } |
| 94 | return AE_OK; | 92 | return AE_OK; |
| 95 | } | 93 | } |
| 96 | 94 | ||
| 97 | acpi_handle acpi_get_child(acpi_handle parent, u64 address) | 95 | static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) |
| 98 | { | 96 | { |
| 99 | void *ret = NULL; | 97 | unsigned long long sta; |
| 98 | acpi_status status; | ||
| 99 | |||
| 100 | status = acpi_bus_get_status_handle(handle, &sta); | ||
| 101 | if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) | ||
| 102 | return false; | ||
| 103 | |||
| 104 | if (is_bridge) { | ||
| 105 | void *test = NULL; | ||
| 106 | |||
| 107 | /* Check if this object has at least one child device. */ | ||
| 108 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
| 109 | acpi_dev_present, NULL, NULL, &test); | ||
| 110 | return !!test; | ||
| 111 | } | ||
| 112 | return true; | ||
| 113 | } | ||
| 114 | |||
| 115 | struct find_child_context { | ||
| 116 | u64 addr; | ||
| 117 | bool is_bridge; | ||
| 118 | acpi_handle ret; | ||
| 119 | bool ret_checked; | ||
| 120 | }; | ||
| 121 | |||
| 122 | static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, | ||
| 123 | void *data, void **not_used) | ||
| 124 | { | ||
| 125 | struct find_child_context *context = data; | ||
| 126 | unsigned long long addr; | ||
| 127 | acpi_status status; | ||
| 100 | 128 | ||
| 101 | if (!parent) | 129 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); |
| 102 | return NULL; | 130 | if (ACPI_FAILURE(status) || addr != context->addr) |
| 131 | return AE_OK; | ||
| 103 | 132 | ||
| 104 | acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL, | 133 | if (!context->ret) { |
| 105 | do_acpi_find_child, &address, &ret); | 134 | /* This is the first matching object. Save its handle. */ |
| 106 | return (acpi_handle)ret; | 135 | context->ret = handle; |
| 136 | return AE_OK; | ||
| 137 | } | ||
| 138 | /* | ||
| 139 | * There is more than one matching object with the same _ADR value. | ||
| 140 | * That really is unexpected, so we are kind of beyond the scope of the | ||
| 141 | * spec here. We have to choose which one to return, though. | ||
| 142 | * | ||
| 143 | * First, check if the previously found object is good enough and return | ||
| 144 | * its handle if so. Second, check the same for the object that we've | ||
| 145 | * just found. | ||
| 146 | */ | ||
| 147 | if (!context->ret_checked) { | ||
| 148 | if (acpi_extra_checks_passed(context->ret, context->is_bridge)) | ||
| 149 | return AE_CTRL_TERMINATE; | ||
| 150 | else | ||
| 151 | context->ret_checked = true; | ||
| 152 | } | ||
| 153 | if (acpi_extra_checks_passed(handle, context->is_bridge)) { | ||
| 154 | context->ret = handle; | ||
| 155 | return AE_CTRL_TERMINATE; | ||
| 156 | } | ||
| 157 | return AE_OK; | ||
| 107 | } | 158 | } |
| 108 | EXPORT_SYMBOL(acpi_get_child); | 159 | |
| 160 | acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge) | ||
| 161 | { | ||
| 162 | if (parent) { | ||
| 163 | struct find_child_context context = { | ||
| 164 | .addr = addr, | ||
| 165 | .is_bridge = is_bridge, | ||
| 166 | }; | ||
| 167 | |||
| 168 | acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child, | ||
| 169 | NULL, &context, NULL); | ||
| 170 | return context.ret; | ||
| 171 | } | ||
| 172 | return NULL; | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL_GPL(acpi_find_child); | ||
| 109 | 175 | ||
| 110 | int acpi_bind_one(struct device *dev, acpi_handle handle) | 176 | int acpi_bind_one(struct device *dev, acpi_handle handle) |
| 111 | { | 177 | { |
| 112 | struct acpi_device *acpi_dev; | 178 | struct acpi_device *acpi_dev; |
| 113 | acpi_status status; | 179 | acpi_status status; |
| 114 | struct acpi_device_physical_node *physical_node, *pn; | 180 | struct acpi_device_physical_node *physical_node, *pn; |
| 115 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; | 181 | char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; |
| 182 | struct list_head *physnode_list; | ||
| 183 | unsigned int node_id; | ||
| 116 | int retval = -EINVAL; | 184 | int retval = -EINVAL; |
| 117 | 185 | ||
| 118 | if (ACPI_HANDLE(dev)) { | 186 | if (ACPI_HANDLE(dev)) { |
| @@ -139,25 +207,27 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
| 139 | 207 | ||
| 140 | mutex_lock(&acpi_dev->physical_node_lock); | 208 | mutex_lock(&acpi_dev->physical_node_lock); |
| 141 | 209 | ||
| 142 | /* Sanity check. */ | 210 | /* |
| 143 | list_for_each_entry(pn, &acpi_dev->physical_node_list, node) | 211 | * Keep the list sorted by node_id so that the IDs of removed nodes can |
| 212 | * be recycled easily. | ||
| 213 | */ | ||
| 214 | physnode_list = &acpi_dev->physical_node_list; | ||
| 215 | node_id = 0; | ||
| 216 | list_for_each_entry(pn, &acpi_dev->physical_node_list, node) { | ||
| 217 | /* Sanity check. */ | ||
| 144 | if (pn->dev == dev) { | 218 | if (pn->dev == dev) { |
| 145 | dev_warn(dev, "Already associated with ACPI node\n"); | 219 | dev_warn(dev, "Already associated with ACPI node\n"); |
| 146 | goto err_free; | 220 | goto err_free; |
| 147 | } | 221 | } |
| 148 | 222 | if (pn->node_id == node_id) { | |
| 149 | /* allocate physical node id according to physical_node_id_bitmap */ | 223 | physnode_list = &pn->node; |
| 150 | physical_node->node_id = | 224 | node_id++; |
| 151 | find_first_zero_bit(acpi_dev->physical_node_id_bitmap, | 225 | } |
| 152 | ACPI_MAX_PHYSICAL_NODE); | ||
| 153 | if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { | ||
| 154 | retval = -ENOSPC; | ||
| 155 | goto err_free; | ||
| 156 | } | 226 | } |
| 157 | 227 | ||
| 158 | set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); | 228 | physical_node->node_id = node_id; |
| 159 | physical_node->dev = dev; | 229 | physical_node->dev = dev; |
| 160 | list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); | 230 | list_add(&physical_node->node, physnode_list); |
| 161 | acpi_dev->physical_node_count++; | 231 | acpi_dev->physical_node_count++; |
| 162 | 232 | ||
| 163 | mutex_unlock(&acpi_dev->physical_node_lock); | 233 | mutex_unlock(&acpi_dev->physical_node_lock); |
| @@ -208,7 +278,7 @@ int acpi_unbind_one(struct device *dev) | |||
| 208 | 278 | ||
| 209 | mutex_lock(&acpi_dev->physical_node_lock); | 279 | mutex_lock(&acpi_dev->physical_node_lock); |
| 210 | list_for_each_safe(node, next, &acpi_dev->physical_node_list) { | 280 | list_for_each_safe(node, next, &acpi_dev->physical_node_list) { |
| 211 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; | 281 | char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; |
| 212 | 282 | ||
| 213 | entry = list_entry(node, struct acpi_device_physical_node, | 283 | entry = list_entry(node, struct acpi_device_physical_node, |
| 214 | node); | 284 | node); |
| @@ -216,7 +286,6 @@ int acpi_unbind_one(struct device *dev) | |||
| 216 | continue; | 286 | continue; |
| 217 | 287 | ||
| 218 | list_del(node); | 288 | list_del(node); |
| 219 | clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap); | ||
| 220 | 289 | ||
| 221 | acpi_dev->physical_node_count--; | 290 | acpi_dev->physical_node_count--; |
| 222 | 291 | ||
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index aa1227a7e3f2..04a13784dd20 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
| @@ -311,6 +311,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 311 | dev->pnp.bus_id, | 311 | dev->pnp.bus_id, |
| 312 | (u32) dev->wakeup.sleep_state); | 312 | (u32) dev->wakeup.sleep_state); |
| 313 | 313 | ||
| 314 | mutex_lock(&dev->physical_node_lock); | ||
| 315 | |||
| 314 | if (!dev->physical_node_count) { | 316 | if (!dev->physical_node_count) { |
| 315 | seq_printf(seq, "%c%-8s\n", | 317 | seq_printf(seq, "%c%-8s\n", |
| 316 | dev->wakeup.flags.run_wake ? '*' : ' ', | 318 | dev->wakeup.flags.run_wake ? '*' : ' ', |
| @@ -338,6 +340,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 338 | put_device(ldev); | 340 | put_device(ldev); |
| 339 | } | 341 | } |
| 340 | } | 342 | } |
| 343 | |||
| 344 | mutex_unlock(&dev->physical_node_lock); | ||
| 341 | } | 345 | } |
| 342 | mutex_unlock(&acpi_device_lock); | 346 | mutex_unlock(&acpi_device_lock); |
| 343 | return 0; | 347 | return 0; |
| @@ -347,12 +351,16 @@ static void physical_device_enable_wakeup(struct acpi_device *adev) | |||
| 347 | { | 351 | { |
| 348 | struct acpi_device_physical_node *entry; | 352 | struct acpi_device_physical_node *entry; |
| 349 | 353 | ||
| 354 | mutex_lock(&adev->physical_node_lock); | ||
| 355 | |||
| 350 | list_for_each_entry(entry, | 356 | list_for_each_entry(entry, |
| 351 | &adev->physical_node_list, node) | 357 | &adev->physical_node_list, node) |
| 352 | if (entry->dev && device_can_wakeup(entry->dev)) { | 358 | if (entry->dev && device_can_wakeup(entry->dev)) { |
| 353 | bool enable = !device_may_wakeup(entry->dev); | 359 | bool enable = !device_may_wakeup(entry->dev); |
| 354 | device_set_wakeup_enable(entry->dev, enable); | 360 | device_set_wakeup_enable(entry->dev, enable); |
| 355 | } | 361 | } |
| 362 | |||
| 363 | mutex_unlock(&adev->physical_node_lock); | ||
| 356 | } | 364 | } |
| 357 | 365 | ||
| 358 | static ssize_t | 366 | static ssize_t |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 0ec434d2586d..e1284b8dc6ee 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -689,7 +689,7 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device, | |||
| 689 | * Some systems always report current brightness level as maximum | 689 | * Some systems always report current brightness level as maximum |
| 690 | * through _BQC, we need to test another value for them. | 690 | * through _BQC, we need to test another value for them. |
| 691 | */ | 691 | */ |
| 692 | test_level = current_level == max_level ? br->levels[2] : max_level; | 692 | test_level = current_level == max_level ? br->levels[3] : max_level; |
| 693 | 693 | ||
| 694 | result = acpi_video_device_lcd_set_level(device, test_level); | 694 | result = acpi_video_device_lcd_set_level(device, test_level); |
| 695 | if (result) | 695 | if (result) |
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 4ec7c04b3f82..26386f0b89a8 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c | |||
| @@ -237,6 +237,7 @@ static const struct of_device_id imx_pata_dt_ids[] = { | |||
| 237 | /* sentinel */ | 237 | /* sentinel */ |
| 238 | } | 238 | } |
| 239 | }; | 239 | }; |
| 240 | MODULE_DEVICE_TABLE(of, imx_pata_dt_ids); | ||
| 240 | 241 | ||
| 241 | static struct platform_driver pata_imx_driver = { | 242 | static struct platform_driver pata_imx_driver = { |
| 242 | .probe = pata_imx_probe, | 243 | .probe = pata_imx_probe, |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index e69102696533..3455f833e473 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
| @@ -719,7 +719,8 @@ static int regcache_sync_block_raw(struct regmap *map, void *block, | |||
| 719 | } | 719 | } |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | return regcache_sync_block_raw_flush(map, &data, base, regtmp); | 722 | return regcache_sync_block_raw_flush(map, &data, base, regtmp + |
| 723 | map->reg_stride); | ||
| 723 | } | 724 | } |
| 724 | 725 | ||
| 725 | int regcache_sync_block(struct regmap *map, void *block, | 726 | int regcache_sync_block(struct regmap *map, void *block, |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 99cb944a002d..4d45dba7fb8f 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
| @@ -906,16 +906,10 @@ bio_pageinc(struct bio *bio) | |||
| 906 | int i; | 906 | int i; |
| 907 | 907 | ||
| 908 | bio_for_each_segment(bv, bio, i) { | 908 | bio_for_each_segment(bv, bio, i) { |
| 909 | page = bv->bv_page; | ||
| 910 | /* Non-zero page count for non-head members of | 909 | /* Non-zero page count for non-head members of |
| 911 | * compound pages is no longer allowed by the kernel, | 910 | * compound pages is no longer allowed by the kernel. |
| 912 | * but this has never been seen here. | ||
| 913 | */ | 911 | */ |
| 914 | if (unlikely(PageCompound(page))) | 912 | page = compound_trans_head(bv->bv_page); |
| 915 | if (compound_trans_head(page) != page) { | ||
| 916 | pr_crit("page tail used for block I/O\n"); | ||
| 917 | BUG(); | ||
| 918 | } | ||
| 919 | atomic_inc(&page->_count); | 913 | atomic_inc(&page->_count); |
| 920 | } | 914 | } |
| 921 | } | 915 | } |
| @@ -924,10 +918,13 @@ static void | |||
| 924 | bio_pagedec(struct bio *bio) | 918 | bio_pagedec(struct bio *bio) |
| 925 | { | 919 | { |
| 926 | struct bio_vec *bv; | 920 | struct bio_vec *bv; |
| 921 | struct page *page; | ||
| 927 | int i; | 922 | int i; |
| 928 | 923 | ||
| 929 | bio_for_each_segment(bv, bio, i) | 924 | bio_for_each_segment(bv, bio, i) { |
| 930 | atomic_dec(&bv->bv_page->_count); | 925 | page = compound_trans_head(bv->bv_page); |
| 926 | atomic_dec(&page->_count); | ||
| 927 | } | ||
| 931 | } | 928 | } |
| 932 | 929 | ||
| 933 | static void | 930 | static void |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 1b456fe9b87a..fc45567ad3ac 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -272,9 +272,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, | |||
| 272 | unsigned long flags; | 272 | unsigned long flags; |
| 273 | 273 | ||
| 274 | spin_lock_irqsave(&portdev->ports_lock, flags); | 274 | spin_lock_irqsave(&portdev->ports_lock, flags); |
| 275 | list_for_each_entry(port, &portdev->ports, list) | 275 | list_for_each_entry(port, &portdev->ports, list) { |
| 276 | if (port->cdev->dev == dev) | 276 | if (port->cdev->dev == dev) { |
| 277 | kref_get(&port->kref); | ||
| 277 | goto out; | 278 | goto out; |
| 279 | } | ||
| 280 | } | ||
| 278 | port = NULL; | 281 | port = NULL; |
| 279 | out: | 282 | out: |
| 280 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | 283 | spin_unlock_irqrestore(&portdev->ports_lock, flags); |
| @@ -746,6 +749,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
| 746 | 749 | ||
| 747 | port = filp->private_data; | 750 | port = filp->private_data; |
| 748 | 751 | ||
| 752 | /* Port is hot-unplugged. */ | ||
| 753 | if (!port->guest_connected) | ||
| 754 | return -ENODEV; | ||
| 755 | |||
| 749 | if (!port_has_data(port)) { | 756 | if (!port_has_data(port)) { |
| 750 | /* | 757 | /* |
| 751 | * If nothing's connected on the host just return 0 in | 758 | * If nothing's connected on the host just return 0 in |
| @@ -762,7 +769,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
| 762 | if (ret < 0) | 769 | if (ret < 0) |
| 763 | return ret; | 770 | return ret; |
| 764 | } | 771 | } |
| 765 | /* Port got hot-unplugged. */ | 772 | /* Port got hot-unplugged while we were waiting above. */ |
| 766 | if (!port->guest_connected) | 773 | if (!port->guest_connected) |
| 767 | return -ENODEV; | 774 | return -ENODEV; |
| 768 | /* | 775 | /* |
| @@ -932,13 +939,25 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
| 932 | if (is_rproc_serial(port->out_vq->vdev)) | 939 | if (is_rproc_serial(port->out_vq->vdev)) |
| 933 | return -EINVAL; | 940 | return -EINVAL; |
| 934 | 941 | ||
| 942 | /* | ||
| 943 | * pipe->nrbufs == 0 means there are no data to transfer, | ||
| 944 | * so this returns just 0 for no data. | ||
| 945 | */ | ||
| 946 | pipe_lock(pipe); | ||
| 947 | if (!pipe->nrbufs) { | ||
| 948 | ret = 0; | ||
| 949 | goto error_out; | ||
| 950 | } | ||
| 951 | |||
| 935 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); | 952 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); |
| 936 | if (ret < 0) | 953 | if (ret < 0) |
| 937 | return ret; | 954 | goto error_out; |
| 938 | 955 | ||
| 939 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); | 956 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); |
| 940 | if (!buf) | 957 | if (!buf) { |
| 941 | return -ENOMEM; | 958 | ret = -ENOMEM; |
| 959 | goto error_out; | ||
| 960 | } | ||
| 942 | 961 | ||
| 943 | sgl.n = 0; | 962 | sgl.n = 0; |
| 944 | sgl.len = 0; | 963 | sgl.len = 0; |
| @@ -946,12 +965,17 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
| 946 | sgl.sg = buf->sg; | 965 | sgl.sg = buf->sg; |
| 947 | sg_init_table(sgl.sg, sgl.size); | 966 | sg_init_table(sgl.sg, sgl.size); |
| 948 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | 967 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); |
| 968 | pipe_unlock(pipe); | ||
| 949 | if (likely(ret > 0)) | 969 | if (likely(ret > 0)) |
| 950 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); | 970 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); |
| 951 | 971 | ||
| 952 | if (unlikely(ret <= 0)) | 972 | if (unlikely(ret <= 0)) |
| 953 | free_buf(buf, true); | 973 | free_buf(buf, true); |
| 954 | return ret; | 974 | return ret; |
| 975 | |||
| 976 | error_out: | ||
| 977 | pipe_unlock(pipe); | ||
| 978 | return ret; | ||
| 955 | } | 979 | } |
| 956 | 980 | ||
| 957 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | 981 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) |
| @@ -1019,14 +1043,14 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
| 1019 | struct port *port; | 1043 | struct port *port; |
| 1020 | int ret; | 1044 | int ret; |
| 1021 | 1045 | ||
| 1046 | /* We get the port with a kref here */ | ||
| 1022 | port = find_port_by_devt(cdev->dev); | 1047 | port = find_port_by_devt(cdev->dev); |
| 1048 | if (!port) { | ||
| 1049 | /* Port was unplugged before we could proceed */ | ||
| 1050 | return -ENXIO; | ||
| 1051 | } | ||
| 1023 | filp->private_data = port; | 1052 | filp->private_data = port; |
| 1024 | 1053 | ||
| 1025 | /* Prevent against a port getting hot-unplugged at the same time */ | ||
| 1026 | spin_lock_irq(&port->portdev->ports_lock); | ||
| 1027 | kref_get(&port->kref); | ||
| 1028 | spin_unlock_irq(&port->portdev->ports_lock); | ||
| 1029 | |||
| 1030 | /* | 1054 | /* |
| 1031 | * Don't allow opening of console port devices -- that's done | 1055 | * Don't allow opening of console port devices -- that's done |
| 1032 | * via /dev/hvc | 1056 | * via /dev/hvc |
| @@ -1498,14 +1522,6 @@ static void remove_port(struct kref *kref) | |||
| 1498 | 1522 | ||
| 1499 | port = container_of(kref, struct port, kref); | 1523 | port = container_of(kref, struct port, kref); |
| 1500 | 1524 | ||
| 1501 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
| 1502 | device_destroy(pdrvdata.class, port->dev->devt); | ||
| 1503 | cdev_del(port->cdev); | ||
| 1504 | |||
| 1505 | kfree(port->name); | ||
| 1506 | |||
| 1507 | debugfs_remove(port->debugfs_file); | ||
| 1508 | |||
| 1509 | kfree(port); | 1525 | kfree(port); |
| 1510 | } | 1526 | } |
| 1511 | 1527 | ||
| @@ -1539,12 +1555,14 @@ static void unplug_port(struct port *port) | |||
| 1539 | spin_unlock_irq(&port->portdev->ports_lock); | 1555 | spin_unlock_irq(&port->portdev->ports_lock); |
| 1540 | 1556 | ||
| 1541 | if (port->guest_connected) { | 1557 | if (port->guest_connected) { |
| 1558 | /* Let the app know the port is going down. */ | ||
| 1559 | send_sigio_to_port(port); | ||
| 1560 | |||
| 1561 | /* Do this after sigio is actually sent */ | ||
| 1542 | port->guest_connected = false; | 1562 | port->guest_connected = false; |
| 1543 | port->host_connected = false; | 1563 | port->host_connected = false; |
| 1544 | wake_up_interruptible(&port->waitqueue); | ||
| 1545 | 1564 | ||
| 1546 | /* Let the app know the port is going down. */ | 1565 | wake_up_interruptible(&port->waitqueue); |
| 1547 | send_sigio_to_port(port); | ||
| 1548 | } | 1566 | } |
| 1549 | 1567 | ||
| 1550 | if (is_console_port(port)) { | 1568 | if (is_console_port(port)) { |
| @@ -1563,6 +1581,14 @@ static void unplug_port(struct port *port) | |||
| 1563 | */ | 1581 | */ |
| 1564 | port->portdev = NULL; | 1582 | port->portdev = NULL; |
| 1565 | 1583 | ||
| 1584 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
| 1585 | device_destroy(pdrvdata.class, port->dev->devt); | ||
| 1586 | cdev_del(port->cdev); | ||
| 1587 | |||
| 1588 | kfree(port->name); | ||
| 1589 | |||
| 1590 | debugfs_remove(port->debugfs_file); | ||
| 1591 | |||
| 1566 | /* | 1592 | /* |
| 1567 | * Locks around here are not necessary - a port can't be | 1593 | * Locks around here are not necessary - a port can't be |
| 1568 | * opened after we removed the port struct from ports_list | 1594 | * opened after we removed the port struct from ports_list |
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 1bdb882c845b..4e5739773c33 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c | |||
| @@ -581,11 +581,15 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = { | |||
| 581 | DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4), | 581 | DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4), |
| 582 | DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8), | 582 | DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8), |
| 583 | DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4), | 583 | DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4), |
| 584 | DIV(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3), | 584 | DIV_F(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3, |
| 585 | DIV(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3), | 585 | CLK_GET_RATE_NOCACHE, 0), |
| 586 | DIV_F(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3, | ||
| 587 | CLK_GET_RATE_NOCACHE, 0), | ||
| 586 | DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), | 588 | DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), |
| 587 | DIV(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3), | 589 | DIV_F(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, |
| 588 | DIV(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3), | 590 | 4, 3, CLK_GET_RATE_NOCACHE, 0), |
| 591 | DIV_F(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, | ||
| 592 | 8, 3, CLK_GET_RATE_NOCACHE, 0), | ||
| 589 | DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), | 593 | DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), |
| 590 | }; | 594 | }; |
| 591 | 595 | ||
| @@ -863,57 +867,57 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { | |||
| 863 | GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100", | 867 | GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100", |
| 864 | E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"), | 868 | E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"), |
| 865 | GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0, | 869 | GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0, |
| 866 | CLK_IGNORE_UNUSED, 0), | 870 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 867 | GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1, | 871 | GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1, |
| 868 | CLK_IGNORE_UNUSED, 0), | 872 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 869 | GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2, | 873 | GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2, |
| 870 | CLK_IGNORE_UNUSED, 0), | 874 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 871 | GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, | 875 | GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, |
| 872 | CLK_IGNORE_UNUSED, 0), | 876 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 873 | GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, | 877 | GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, |
| 874 | CLK_IGNORE_UNUSED, 0), | 878 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 875 | GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, | 879 | GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, |
| 876 | CLK_IGNORE_UNUSED, 0), | 880 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 877 | GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, | 881 | GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, |
| 878 | CLK_IGNORE_UNUSED, 0), | 882 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 879 | GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, | 883 | GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, |
| 880 | CLK_IGNORE_UNUSED, 0), | 884 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 881 | GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, | 885 | GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, |
| 882 | CLK_IGNORE_UNUSED, 0), | 886 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 883 | GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, | 887 | GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, |
| 884 | CLK_IGNORE_UNUSED, 0), | 888 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 885 | GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, | 889 | GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, |
| 886 | CLK_IGNORE_UNUSED, 0), | 890 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 887 | GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, | 891 | GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, |
| 888 | CLK_IGNORE_UNUSED, 0), | 892 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 889 | GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, | 893 | GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, |
| 890 | CLK_IGNORE_UNUSED, 0), | 894 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 891 | GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21, | 895 | GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21, |
| 892 | CLK_IGNORE_UNUSED, 0), | 896 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 893 | GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23, | 897 | GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23, |
| 894 | CLK_IGNORE_UNUSED, 0), | 898 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 895 | GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24, | 899 | GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24, |
| 896 | CLK_IGNORE_UNUSED, 0), | 900 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 897 | GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25, | 901 | GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25, |
| 898 | CLK_IGNORE_UNUSED, 0), | 902 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 899 | GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26, | 903 | GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26, |
| 900 | CLK_IGNORE_UNUSED, 0), | 904 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 901 | GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27, | 905 | GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27, |
| 902 | CLK_IGNORE_UNUSED, 0), | 906 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 903 | GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, | 907 | GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, |
| 904 | CLK_IGNORE_UNUSED, 0), | 908 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 905 | GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, | 909 | GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, |
| 906 | CLK_IGNORE_UNUSED, 0), | 910 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 907 | GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31, | 911 | GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31, |
| 908 | CLK_IGNORE_UNUSED, 0), | 912 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 909 | GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0, | 913 | GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0, |
| 910 | CLK_IGNORE_UNUSED, 0), | 914 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 911 | GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4, | 915 | GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4, |
| 912 | CLK_IGNORE_UNUSED, 0), | 916 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 913 | GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12, | 917 | GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12, |
| 914 | CLK_IGNORE_UNUSED, 0), | 918 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 915 | GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, | 919 | GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, |
| 916 | CLK_IGNORE_UNUSED, 0), | 920 | CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), |
| 917 | GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), | 921 | GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), |
| 918 | }; | 922 | }; |
| 919 | 923 | ||
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index 5c205b60a82a..089d3e30e221 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c | |||
| @@ -71,6 +71,7 @@ static DEFINE_SPINLOCK(armpll_lock); | |||
| 71 | static DEFINE_SPINLOCK(ddrpll_lock); | 71 | static DEFINE_SPINLOCK(ddrpll_lock); |
| 72 | static DEFINE_SPINLOCK(iopll_lock); | 72 | static DEFINE_SPINLOCK(iopll_lock); |
| 73 | static DEFINE_SPINLOCK(armclk_lock); | 73 | static DEFINE_SPINLOCK(armclk_lock); |
| 74 | static DEFINE_SPINLOCK(swdtclk_lock); | ||
| 74 | static DEFINE_SPINLOCK(ddrclk_lock); | 75 | static DEFINE_SPINLOCK(ddrclk_lock); |
| 75 | static DEFINE_SPINLOCK(dciclk_lock); | 76 | static DEFINE_SPINLOCK(dciclk_lock); |
| 76 | static DEFINE_SPINLOCK(gem0clk_lock); | 77 | static DEFINE_SPINLOCK(gem0clk_lock); |
| @@ -293,7 +294,7 @@ static void __init zynq_clk_setup(struct device_node *np) | |||
| 293 | } | 294 | } |
| 294 | clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt], | 295 | clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt], |
| 295 | swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT, | 296 | swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT, |
| 296 | SLCR_SWDT_CLK_SEL, 0, 1, 0, &gem0clk_lock); | 297 | SLCR_SWDT_CLK_SEL, 0, 1, 0, &swdtclk_lock); |
| 297 | 298 | ||
| 298 | /* DDR clocks */ | 299 | /* DDR clocks */ |
| 299 | clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0, | 300 | clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0, |
| @@ -364,8 +365,9 @@ static void __init zynq_clk_setup(struct device_node *np) | |||
| 364 | CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6, | 365 | CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6, |
| 365 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, | 366 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, |
| 366 | &gem0clk_lock); | 367 | &gem0clk_lock); |
| 367 | clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, 0, | 368 | clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, |
| 368 | SLCR_GEM0_CLK_CTRL, 6, 1, 0, &gem0clk_lock); | 369 | CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0, |
| 370 | &gem0clk_lock); | ||
| 369 | clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0], | 371 | clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0], |
| 370 | "gem0_emio_mux", CLK_SET_RATE_PARENT, | 372 | "gem0_emio_mux", CLK_SET_RATE_PARENT, |
| 371 | SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock); | 373 | SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock); |
| @@ -386,8 +388,9 @@ static void __init zynq_clk_setup(struct device_node *np) | |||
| 386 | CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6, | 388 | CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6, |
| 387 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, | 389 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, |
| 388 | &gem1clk_lock); | 390 | &gem1clk_lock); |
| 389 | clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, 0, | 391 | clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, |
| 390 | SLCR_GEM1_CLK_CTRL, 6, 1, 0, &gem1clk_lock); | 392 | CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0, |
| 393 | &gem1clk_lock); | ||
| 391 | clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1], | 394 | clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1], |
| 392 | "gem1_emio_mux", CLK_SET_RATE_PARENT, | 395 | "gem1_emio_mux", CLK_SET_RATE_PARENT, |
| 393 | SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock); | 396 | SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock); |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 0ceb2eff5a7e..f97cb3d8c5a2 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
| @@ -221,8 +221,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, | |||
| 221 | return count; | 221 | return count; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | 224 | static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, |
| 225 | size_t count) | 225 | const char *buf, size_t count) |
| 226 | { | 226 | { |
| 227 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; | 227 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; |
| 228 | unsigned int input, j; | 228 | unsigned int input, j; |
| @@ -235,10 +235,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | |||
| 235 | if (input > 1) | 235 | if (input > 1) |
| 236 | input = 1; | 236 | input = 1; |
| 237 | 237 | ||
| 238 | if (input == cs_tuners->ignore_nice) /* nothing to do */ | 238 | if (input == cs_tuners->ignore_nice_load) /* nothing to do */ |
| 239 | return count; | 239 | return count; |
| 240 | 240 | ||
| 241 | cs_tuners->ignore_nice = input; | 241 | cs_tuners->ignore_nice_load = input; |
| 242 | 242 | ||
| 243 | /* we need to re-evaluate prev_cpu_idle */ | 243 | /* we need to re-evaluate prev_cpu_idle */ |
| 244 | for_each_online_cpu(j) { | 244 | for_each_online_cpu(j) { |
| @@ -246,7 +246,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | |||
| 246 | dbs_info = &per_cpu(cs_cpu_dbs_info, j); | 246 | dbs_info = &per_cpu(cs_cpu_dbs_info, j); |
| 247 | dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, | 247 | dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, |
| 248 | &dbs_info->cdbs.prev_cpu_wall, 0); | 248 | &dbs_info->cdbs.prev_cpu_wall, 0); |
| 249 | if (cs_tuners->ignore_nice) | 249 | if (cs_tuners->ignore_nice_load) |
| 250 | dbs_info->cdbs.prev_cpu_nice = | 250 | dbs_info->cdbs.prev_cpu_nice = |
| 251 | kcpustat_cpu(j).cpustat[CPUTIME_NICE]; | 251 | kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
| 252 | } | 252 | } |
| @@ -279,7 +279,7 @@ show_store_one(cs, sampling_rate); | |||
| 279 | show_store_one(cs, sampling_down_factor); | 279 | show_store_one(cs, sampling_down_factor); |
| 280 | show_store_one(cs, up_threshold); | 280 | show_store_one(cs, up_threshold); |
| 281 | show_store_one(cs, down_threshold); | 281 | show_store_one(cs, down_threshold); |
| 282 | show_store_one(cs, ignore_nice); | 282 | show_store_one(cs, ignore_nice_load); |
| 283 | show_store_one(cs, freq_step); | 283 | show_store_one(cs, freq_step); |
| 284 | declare_show_sampling_rate_min(cs); | 284 | declare_show_sampling_rate_min(cs); |
| 285 | 285 | ||
| @@ -287,7 +287,7 @@ gov_sys_pol_attr_rw(sampling_rate); | |||
| 287 | gov_sys_pol_attr_rw(sampling_down_factor); | 287 | gov_sys_pol_attr_rw(sampling_down_factor); |
| 288 | gov_sys_pol_attr_rw(up_threshold); | 288 | gov_sys_pol_attr_rw(up_threshold); |
| 289 | gov_sys_pol_attr_rw(down_threshold); | 289 | gov_sys_pol_attr_rw(down_threshold); |
| 290 | gov_sys_pol_attr_rw(ignore_nice); | 290 | gov_sys_pol_attr_rw(ignore_nice_load); |
| 291 | gov_sys_pol_attr_rw(freq_step); | 291 | gov_sys_pol_attr_rw(freq_step); |
| 292 | gov_sys_pol_attr_ro(sampling_rate_min); | 292 | gov_sys_pol_attr_ro(sampling_rate_min); |
| 293 | 293 | ||
| @@ -297,7 +297,7 @@ static struct attribute *dbs_attributes_gov_sys[] = { | |||
| 297 | &sampling_down_factor_gov_sys.attr, | 297 | &sampling_down_factor_gov_sys.attr, |
| 298 | &up_threshold_gov_sys.attr, | 298 | &up_threshold_gov_sys.attr, |
| 299 | &down_threshold_gov_sys.attr, | 299 | &down_threshold_gov_sys.attr, |
| 300 | &ignore_nice_gov_sys.attr, | 300 | &ignore_nice_load_gov_sys.attr, |
| 301 | &freq_step_gov_sys.attr, | 301 | &freq_step_gov_sys.attr, |
| 302 | NULL | 302 | NULL |
| 303 | }; | 303 | }; |
| @@ -313,7 +313,7 @@ static struct attribute *dbs_attributes_gov_pol[] = { | |||
| 313 | &sampling_down_factor_gov_pol.attr, | 313 | &sampling_down_factor_gov_pol.attr, |
| 314 | &up_threshold_gov_pol.attr, | 314 | &up_threshold_gov_pol.attr, |
| 315 | &down_threshold_gov_pol.attr, | 315 | &down_threshold_gov_pol.attr, |
| 316 | &ignore_nice_gov_pol.attr, | 316 | &ignore_nice_load_gov_pol.attr, |
| 317 | &freq_step_gov_pol.attr, | 317 | &freq_step_gov_pol.attr, |
| 318 | NULL | 318 | NULL |
| 319 | }; | 319 | }; |
| @@ -338,7 +338,7 @@ static int cs_init(struct dbs_data *dbs_data) | |||
| 338 | tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; | 338 | tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; |
| 339 | tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; | 339 | tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; |
| 340 | tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; | 340 | tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; |
| 341 | tuners->ignore_nice = 0; | 341 | tuners->ignore_nice_load = 0; |
| 342 | tuners->freq_step = DEF_FREQUENCY_STEP; | 342 | tuners->freq_step = DEF_FREQUENCY_STEP; |
| 343 | 343 | ||
| 344 | dbs_data->tuners = tuners; | 344 | dbs_data->tuners = tuners; |
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 7b839a8db2a7..e59afaa9da23 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c | |||
| @@ -47,9 +47,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) | |||
| 47 | unsigned int j; | 47 | unsigned int j; |
| 48 | 48 | ||
| 49 | if (dbs_data->cdata->governor == GOV_ONDEMAND) | 49 | if (dbs_data->cdata->governor == GOV_ONDEMAND) |
| 50 | ignore_nice = od_tuners->ignore_nice; | 50 | ignore_nice = od_tuners->ignore_nice_load; |
| 51 | else | 51 | else |
| 52 | ignore_nice = cs_tuners->ignore_nice; | 52 | ignore_nice = cs_tuners->ignore_nice_load; |
| 53 | 53 | ||
| 54 | policy = cdbs->cur_policy; | 54 | policy = cdbs->cur_policy; |
| 55 | 55 | ||
| @@ -298,12 +298,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 298 | cs_tuners = dbs_data->tuners; | 298 | cs_tuners = dbs_data->tuners; |
| 299 | cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); | 299 | cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); |
| 300 | sampling_rate = cs_tuners->sampling_rate; | 300 | sampling_rate = cs_tuners->sampling_rate; |
| 301 | ignore_nice = cs_tuners->ignore_nice; | 301 | ignore_nice = cs_tuners->ignore_nice_load; |
| 302 | } else { | 302 | } else { |
| 303 | od_tuners = dbs_data->tuners; | 303 | od_tuners = dbs_data->tuners; |
| 304 | od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); | 304 | od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); |
| 305 | sampling_rate = od_tuners->sampling_rate; | 305 | sampling_rate = od_tuners->sampling_rate; |
| 306 | ignore_nice = od_tuners->ignore_nice; | 306 | ignore_nice = od_tuners->ignore_nice_load; |
| 307 | od_ops = dbs_data->cdata->gov_ops; | 307 | od_ops = dbs_data->cdata->gov_ops; |
| 308 | io_busy = od_tuners->io_is_busy; | 308 | io_busy = od_tuners->io_is_busy; |
| 309 | } | 309 | } |
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 6663ec3b3056..d5f12b4b11b8 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h | |||
| @@ -165,7 +165,7 @@ struct cs_cpu_dbs_info_s { | |||
| 165 | 165 | ||
| 166 | /* Per policy Governers sysfs tunables */ | 166 | /* Per policy Governers sysfs tunables */ |
| 167 | struct od_dbs_tuners { | 167 | struct od_dbs_tuners { |
| 168 | unsigned int ignore_nice; | 168 | unsigned int ignore_nice_load; |
| 169 | unsigned int sampling_rate; | 169 | unsigned int sampling_rate; |
| 170 | unsigned int sampling_down_factor; | 170 | unsigned int sampling_down_factor; |
| 171 | unsigned int up_threshold; | 171 | unsigned int up_threshold; |
| @@ -175,7 +175,7 @@ struct od_dbs_tuners { | |||
| 175 | }; | 175 | }; |
| 176 | 176 | ||
| 177 | struct cs_dbs_tuners { | 177 | struct cs_dbs_tuners { |
| 178 | unsigned int ignore_nice; | 178 | unsigned int ignore_nice_load; |
| 179 | unsigned int sampling_rate; | 179 | unsigned int sampling_rate; |
| 180 | unsigned int sampling_down_factor; | 180 | unsigned int sampling_down_factor; |
| 181 | unsigned int up_threshold; | 181 | unsigned int up_threshold; |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 93eb5cbcc1f6..c087347d6688 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -403,8 +403,8 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, | |||
| 403 | return count; | 403 | return count; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | 406 | static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, |
| 407 | size_t count) | 407 | const char *buf, size_t count) |
| 408 | { | 408 | { |
| 409 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; | 409 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; |
| 410 | unsigned int input; | 410 | unsigned int input; |
| @@ -419,10 +419,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | |||
| 419 | if (input > 1) | 419 | if (input > 1) |
| 420 | input = 1; | 420 | input = 1; |
| 421 | 421 | ||
| 422 | if (input == od_tuners->ignore_nice) { /* nothing to do */ | 422 | if (input == od_tuners->ignore_nice_load) { /* nothing to do */ |
| 423 | return count; | 423 | return count; |
| 424 | } | 424 | } |
| 425 | od_tuners->ignore_nice = input; | 425 | od_tuners->ignore_nice_load = input; |
| 426 | 426 | ||
| 427 | /* we need to re-evaluate prev_cpu_idle */ | 427 | /* we need to re-evaluate prev_cpu_idle */ |
| 428 | for_each_online_cpu(j) { | 428 | for_each_online_cpu(j) { |
| @@ -430,7 +430,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf, | |||
| 430 | dbs_info = &per_cpu(od_cpu_dbs_info, j); | 430 | dbs_info = &per_cpu(od_cpu_dbs_info, j); |
| 431 | dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, | 431 | dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, |
| 432 | &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); | 432 | &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); |
| 433 | if (od_tuners->ignore_nice) | 433 | if (od_tuners->ignore_nice_load) |
| 434 | dbs_info->cdbs.prev_cpu_nice = | 434 | dbs_info->cdbs.prev_cpu_nice = |
| 435 | kcpustat_cpu(j).cpustat[CPUTIME_NICE]; | 435 | kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
| 436 | 436 | ||
| @@ -461,7 +461,7 @@ show_store_one(od, sampling_rate); | |||
| 461 | show_store_one(od, io_is_busy); | 461 | show_store_one(od, io_is_busy); |
| 462 | show_store_one(od, up_threshold); | 462 | show_store_one(od, up_threshold); |
| 463 | show_store_one(od, sampling_down_factor); | 463 | show_store_one(od, sampling_down_factor); |
| 464 | show_store_one(od, ignore_nice); | 464 | show_store_one(od, ignore_nice_load); |
| 465 | show_store_one(od, powersave_bias); | 465 | show_store_one(od, powersave_bias); |
| 466 | declare_show_sampling_rate_min(od); | 466 | declare_show_sampling_rate_min(od); |
| 467 | 467 | ||
| @@ -469,7 +469,7 @@ gov_sys_pol_attr_rw(sampling_rate); | |||
| 469 | gov_sys_pol_attr_rw(io_is_busy); | 469 | gov_sys_pol_attr_rw(io_is_busy); |
| 470 | gov_sys_pol_attr_rw(up_threshold); | 470 | gov_sys_pol_attr_rw(up_threshold); |
| 471 | gov_sys_pol_attr_rw(sampling_down_factor); | 471 | gov_sys_pol_attr_rw(sampling_down_factor); |
| 472 | gov_sys_pol_attr_rw(ignore_nice); | 472 | gov_sys_pol_attr_rw(ignore_nice_load); |
| 473 | gov_sys_pol_attr_rw(powersave_bias); | 473 | gov_sys_pol_attr_rw(powersave_bias); |
| 474 | gov_sys_pol_attr_ro(sampling_rate_min); | 474 | gov_sys_pol_attr_ro(sampling_rate_min); |
| 475 | 475 | ||
| @@ -478,7 +478,7 @@ static struct attribute *dbs_attributes_gov_sys[] = { | |||
| 478 | &sampling_rate_gov_sys.attr, | 478 | &sampling_rate_gov_sys.attr, |
| 479 | &up_threshold_gov_sys.attr, | 479 | &up_threshold_gov_sys.attr, |
| 480 | &sampling_down_factor_gov_sys.attr, | 480 | &sampling_down_factor_gov_sys.attr, |
| 481 | &ignore_nice_gov_sys.attr, | 481 | &ignore_nice_load_gov_sys.attr, |
| 482 | &powersave_bias_gov_sys.attr, | 482 | &powersave_bias_gov_sys.attr, |
| 483 | &io_is_busy_gov_sys.attr, | 483 | &io_is_busy_gov_sys.attr, |
| 484 | NULL | 484 | NULL |
| @@ -494,7 +494,7 @@ static struct attribute *dbs_attributes_gov_pol[] = { | |||
| 494 | &sampling_rate_gov_pol.attr, | 494 | &sampling_rate_gov_pol.attr, |
| 495 | &up_threshold_gov_pol.attr, | 495 | &up_threshold_gov_pol.attr, |
| 496 | &sampling_down_factor_gov_pol.attr, | 496 | &sampling_down_factor_gov_pol.attr, |
| 497 | &ignore_nice_gov_pol.attr, | 497 | &ignore_nice_load_gov_pol.attr, |
| 498 | &powersave_bias_gov_pol.attr, | 498 | &powersave_bias_gov_pol.attr, |
| 499 | &io_is_busy_gov_pol.attr, | 499 | &io_is_busy_gov_pol.attr, |
| 500 | NULL | 500 | NULL |
| @@ -544,7 +544,7 @@ static int od_init(struct dbs_data *dbs_data) | |||
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; | 546 | tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; |
| 547 | tuners->ignore_nice = 0; | 547 | tuners->ignore_nice_load = 0; |
| 548 | tuners->powersave_bias = default_powersave_bias; | 548 | tuners->powersave_bias = default_powersave_bias; |
| 549 | tuners->io_is_busy = should_io_be_busy(); | 549 | tuners->io_is_busy = should_io_be_busy(); |
| 550 | 550 | ||
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index bb838b985077..9536852c504a 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c | |||
| @@ -118,11 +118,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 118 | clk_put(cpuclk); | 118 | clk_put(cpuclk); |
| 119 | return -EINVAL; | 119 | return -EINVAL; |
| 120 | } | 120 | } |
| 121 | ret = clk_set_rate(cpuclk, rate); | ||
| 122 | if (ret) { | ||
| 123 | clk_put(cpuclk); | ||
| 124 | return ret; | ||
| 125 | } | ||
| 126 | 121 | ||
| 127 | /* clock table init */ | 122 | /* clock table init */ |
| 128 | for (i = 2; | 123 | for (i = 2; |
| @@ -130,6 +125,12 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 130 | i++) | 125 | i++) |
| 131 | loongson2_clockmod_table[i].frequency = (rate * i) / 8; | 126 | loongson2_clockmod_table[i].frequency = (rate * i) / 8; |
| 132 | 127 | ||
| 128 | ret = clk_set_rate(cpuclk, rate); | ||
| 129 | if (ret) { | ||
| 130 | clk_put(cpuclk); | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 133 | policy->cur = loongson2_cpufreq_get(policy->cpu); | 134 | policy->cur = loongson2_cpufreq_get(policy->cpu); |
| 134 | 135 | ||
| 135 | cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0], | 136 | cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0], |
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index b67f45f5c271..5039fbc88254 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c | |||
| @@ -400,8 +400,8 @@ static size_t sh_dmae_get_partial(struct shdma_chan *schan, | |||
| 400 | shdma_chan); | 400 | shdma_chan); |
| 401 | struct sh_dmae_desc *sh_desc = container_of(sdesc, | 401 | struct sh_dmae_desc *sh_desc = container_of(sdesc, |
| 402 | struct sh_dmae_desc, shdma_desc); | 402 | struct sh_dmae_desc, shdma_desc); |
| 403 | return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) << | 403 | return sh_desc->hw.tcr - |
| 404 | sh_chan->xmit_shift; | 404 | (sh_dmae_readl(sh_chan, TCR) << sh_chan->xmit_shift); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | /* Called from error IRQ or NMI */ | 407 | /* Called from error IRQ or NMI */ |
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 98d670825a1a..6e8887fe6c1b 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c | |||
| @@ -323,6 +323,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align, | |||
| 323 | 323 | ||
| 324 | astbo->gem.driver_private = NULL; | 324 | astbo->gem.driver_private = NULL; |
| 325 | astbo->bo.bdev = &ast->ttm.bdev; | 325 | astbo->bo.bdev = &ast->ttm.bdev; |
| 326 | astbo->bo.bdev->dev_mapping = dev->dev_mapping; | ||
| 326 | 327 | ||
| 327 | ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); | 328 | ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); |
| 328 | 329 | ||
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index 0047012045c2..69fd8f1ac8df 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c | |||
| @@ -328,6 +328,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align, | |||
| 328 | 328 | ||
| 329 | cirrusbo->gem.driver_private = NULL; | 329 | cirrusbo->gem.driver_private = NULL; |
| 330 | cirrusbo->bo.bdev = &cirrus->ttm.bdev; | 330 | cirrusbo->bo.bdev = &cirrus->ttm.bdev; |
| 331 | cirrusbo->bo.bdev->dev_mapping = dev->dev_mapping; | ||
| 331 | 332 | ||
| 332 | cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); | 333 | cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); |
| 333 | 334 | ||
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 8bcce7866d36..f92da0a32f0d 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -708,7 +708,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, | |||
| 708 | /* Subtract time delta from raw timestamp to get final | 708 | /* Subtract time delta from raw timestamp to get final |
| 709 | * vblank_time timestamp for end of vblank. | 709 | * vblank_time timestamp for end of vblank. |
| 710 | */ | 710 | */ |
| 711 | etime = ktime_sub_ns(etime, delta_ns); | 711 | if (delta_ns < 0) |
| 712 | etime = ktime_add_ns(etime, -delta_ns); | ||
| 713 | else | ||
| 714 | etime = ktime_sub_ns(etime, delta_ns); | ||
| 712 | *vblank_time = ktime_to_timeval(etime); | 715 | *vblank_time = ktime_to_timeval(etime); |
| 713 | 716 | ||
| 714 | DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", | 717 | DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f2326fc60ac9..6f514297c483 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -1856,10 +1856,16 @@ | |||
| 1856 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) | 1856 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) |
| 1857 | 1857 | ||
| 1858 | #define PORT_HOTPLUG_STAT (dev_priv->info->display_mmio_offset + 0x61114) | 1858 | #define PORT_HOTPLUG_STAT (dev_priv->info->display_mmio_offset + 0x61114) |
| 1859 | /* HDMI/DP bits are gen4+ */ | 1859 | /* |
| 1860 | #define PORTB_HOTPLUG_LIVE_STATUS (1 << 29) | 1860 | * HDMI/DP bits are gen4+ |
| 1861 | * | ||
| 1862 | * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused. | ||
| 1863 | * Please check the detailed lore in the commit message for for experimental | ||
| 1864 | * evidence. | ||
| 1865 | */ | ||
| 1866 | #define PORTD_HOTPLUG_LIVE_STATUS (1 << 29) | ||
| 1861 | #define PORTC_HOTPLUG_LIVE_STATUS (1 << 28) | 1867 | #define PORTC_HOTPLUG_LIVE_STATUS (1 << 28) |
| 1862 | #define PORTD_HOTPLUG_LIVE_STATUS (1 << 27) | 1868 | #define PORTB_HOTPLUG_LIVE_STATUS (1 << 27) |
| 1863 | #define PORTD_HOTPLUG_INT_STATUS (3 << 21) | 1869 | #define PORTD_HOTPLUG_INT_STATUS (3 << 21) |
| 1864 | #define PORTC_HOTPLUG_INT_STATUS (3 << 19) | 1870 | #define PORTC_HOTPLUG_INT_STATUS (3 << 19) |
| 1865 | #define PORTB_HOTPLUG_INT_STATUS (3 << 17) | 1871 | #define PORTB_HOTPLUG_INT_STATUS (3 << 17) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5fb305840db8..e38b45786653 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -8269,9 +8269,11 @@ check_crtc_state(struct drm_device *dev) | |||
| 8269 | 8269 | ||
| 8270 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, | 8270 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, |
| 8271 | base.head) { | 8271 | base.head) { |
| 8272 | enum pipe pipe; | ||
| 8272 | if (encoder->base.crtc != &crtc->base) | 8273 | if (encoder->base.crtc != &crtc->base) |
| 8273 | continue; | 8274 | continue; |
| 8274 | if (encoder->get_config) | 8275 | if (encoder->get_config && |
| 8276 | encoder->get_hw_state(encoder, &pipe)) | ||
| 8275 | encoder->get_config(encoder, &pipe_config); | 8277 | encoder->get_config(encoder, &pipe_config); |
| 8276 | } | 8278 | } |
| 8277 | 8279 | ||
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 67e2c1f1c9a8..5950888ae1d0 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -497,8 +497,11 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) | |||
| 497 | goto out; | 497 | goto out; |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | /* scale to hardware */ | 500 | /* scale to hardware, but be careful to not overflow */ |
| 501 | level = level * freq / max; | 501 | if (freq < max) |
| 502 | level = level * freq / max; | ||
| 503 | else | ||
| 504 | level = freq / max * level; | ||
| 502 | 505 | ||
| 503 | dev_priv->backlight.level = level; | 506 | dev_priv->backlight.level = level; |
| 504 | if (dev_priv->backlight.device) | 507 | if (dev_priv->backlight.device) |
| @@ -515,6 +518,17 @@ void intel_panel_disable_backlight(struct drm_device *dev) | |||
| 515 | struct drm_i915_private *dev_priv = dev->dev_private; | 518 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 516 | unsigned long flags; | 519 | unsigned long flags; |
| 517 | 520 | ||
| 521 | /* | ||
| 522 | * Do not disable backlight on the vgaswitcheroo path. When switching | ||
| 523 | * away from i915, the other client may depend on i915 to handle the | ||
| 524 | * backlight. This will leave the backlight on unnecessarily when | ||
| 525 | * another client is not activated. | ||
| 526 | */ | ||
| 527 | if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { | ||
| 528 | DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); | ||
| 529 | return; | ||
| 530 | } | ||
| 531 | |||
| 518 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); | 532 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
| 519 | 533 | ||
| 520 | dev_priv->backlight.enabled = false; | 534 | dev_priv->backlight.enabled = false; |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f895d1508df8..b0e4a0bd1313 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -5063,8 +5063,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) | |||
| 5063 | } | 5063 | } |
| 5064 | } else { | 5064 | } else { |
| 5065 | if (enable_requested) { | 5065 | if (enable_requested) { |
| 5066 | unsigned long irqflags; | ||
| 5067 | enum pipe p; | ||
| 5068 | |||
| 5066 | I915_WRITE(HSW_PWR_WELL_DRIVER, 0); | 5069 | I915_WRITE(HSW_PWR_WELL_DRIVER, 0); |
| 5070 | POSTING_READ(HSW_PWR_WELL_DRIVER); | ||
| 5067 | DRM_DEBUG_KMS("Requesting to disable the power well\n"); | 5071 | DRM_DEBUG_KMS("Requesting to disable the power well\n"); |
| 5072 | |||
| 5073 | /* | ||
| 5074 | * After this, the registers on the pipes that are part | ||
| 5075 | * of the power well will become zero, so we have to | ||
| 5076 | * adjust our counters according to that. | ||
| 5077 | * | ||
| 5078 | * FIXME: Should we do this in general in | ||
| 5079 | * drm_vblank_post_modeset? | ||
| 5080 | */ | ||
| 5081 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | ||
| 5082 | for_each_pipe(p) | ||
| 5083 | if (p != PIPE_A) | ||
| 5084 | dev->last_vblank[p] = 0; | ||
| 5085 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
| 5068 | } | 5086 | } |
| 5069 | } | 5087 | } |
| 5070 | } | 5088 | } |
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 13878d5de063..d70e4a92773b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c | |||
| @@ -323,6 +323,7 @@ int mgag200_bo_create(struct drm_device *dev, int size, int align, | |||
| 323 | 323 | ||
| 324 | mgabo->gem.driver_private = NULL; | 324 | mgabo->gem.driver_private = NULL; |
| 325 | mgabo->bo.bdev = &mdev->ttm.bdev; | 325 | mgabo->bo.bdev = &mdev->ttm.bdev; |
| 326 | mgabo->bo.bdev->dev_mapping = dev->dev_mapping; | ||
| 326 | 327 | ||
| 327 | mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); | 328 | mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); |
| 328 | 329 | ||
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 0bfd55e08820..9953e1fbc46d 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c | |||
| @@ -2548,9 +2548,6 @@ int btc_dpm_init(struct radeon_device *rdev) | |||
| 2548 | { | 2548 | { |
| 2549 | struct rv7xx_power_info *pi; | 2549 | struct rv7xx_power_info *pi; |
| 2550 | struct evergreen_power_info *eg_pi; | 2550 | struct evergreen_power_info *eg_pi; |
| 2551 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
| 2552 | u16 data_offset, size; | ||
| 2553 | u8 frev, crev; | ||
| 2554 | struct atom_clock_dividers dividers; | 2551 | struct atom_clock_dividers dividers; |
| 2555 | int ret; | 2552 | int ret; |
| 2556 | 2553 | ||
| @@ -2633,16 +2630,7 @@ int btc_dpm_init(struct radeon_device *rdev) | |||
| 2633 | eg_pi->vddci_control = | 2630 | eg_pi->vddci_control = |
| 2634 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); | 2631 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); |
| 2635 | 2632 | ||
| 2636 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 2633 | rv770_get_engine_memory_ss(rdev); |
| 2637 | &frev, &crev, &data_offset)) { | ||
| 2638 | pi->sclk_ss = true; | ||
| 2639 | pi->mclk_ss = true; | ||
| 2640 | pi->dynamic_ss = true; | ||
| 2641 | } else { | ||
| 2642 | pi->sclk_ss = false; | ||
| 2643 | pi->mclk_ss = false; | ||
| 2644 | pi->dynamic_ss = true; | ||
| 2645 | } | ||
| 2646 | 2634 | ||
| 2647 | pi->asi = RV770_ASI_DFLT; | 2635 | pi->asi = RV770_ASI_DFLT; |
| 2648 | pi->pasi = CYPRESS_HASI_DFLT; | 2636 | pi->pasi = CYPRESS_HASI_DFLT; |
| @@ -2659,8 +2647,7 @@ int btc_dpm_init(struct radeon_device *rdev) | |||
| 2659 | 2647 | ||
| 2660 | pi->dynamic_pcie_gen2 = true; | 2648 | pi->dynamic_pcie_gen2 = true; |
| 2661 | 2649 | ||
| 2662 | if (pi->gfx_clock_gating && | 2650 | if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE) |
| 2663 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
| 2664 | pi->thermal_protection = true; | 2651 | pi->thermal_protection = true; |
| 2665 | else | 2652 | else |
| 2666 | pi->thermal_protection = false; | 2653 | pi->thermal_protection = false; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dacec4e2090..8928bd109c16 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -2587,9 +2587,11 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev, | |||
| 2587 | if (rdev->wb.enabled) { | 2587 | if (rdev->wb.enabled) { |
| 2588 | rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); | 2588 | rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); |
| 2589 | } else { | 2589 | } else { |
| 2590 | mutex_lock(&rdev->srbm_mutex); | ||
| 2590 | cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); | 2591 | cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); |
| 2591 | rptr = RREG32(CP_HQD_PQ_RPTR); | 2592 | rptr = RREG32(CP_HQD_PQ_RPTR); |
| 2592 | cik_srbm_select(rdev, 0, 0, 0, 0); | 2593 | cik_srbm_select(rdev, 0, 0, 0, 0); |
| 2594 | mutex_unlock(&rdev->srbm_mutex); | ||
| 2593 | } | 2595 | } |
| 2594 | rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; | 2596 | rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; |
| 2595 | 2597 | ||
| @@ -2604,9 +2606,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev, | |||
| 2604 | if (rdev->wb.enabled) { | 2606 | if (rdev->wb.enabled) { |
| 2605 | wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]); | 2607 | wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]); |
| 2606 | } else { | 2608 | } else { |
| 2609 | mutex_lock(&rdev->srbm_mutex); | ||
| 2607 | cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); | 2610 | cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); |
| 2608 | wptr = RREG32(CP_HQD_PQ_WPTR); | 2611 | wptr = RREG32(CP_HQD_PQ_WPTR); |
| 2609 | cik_srbm_select(rdev, 0, 0, 0, 0); | 2612 | cik_srbm_select(rdev, 0, 0, 0, 0); |
| 2613 | mutex_unlock(&rdev->srbm_mutex); | ||
| 2610 | } | 2614 | } |
| 2611 | wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; | 2615 | wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; |
| 2612 | 2616 | ||
| @@ -2897,6 +2901,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) | |||
| 2897 | WREG32(CP_CPF_DEBUG, tmp); | 2901 | WREG32(CP_CPF_DEBUG, tmp); |
| 2898 | 2902 | ||
| 2899 | /* init the pipes */ | 2903 | /* init the pipes */ |
| 2904 | mutex_lock(&rdev->srbm_mutex); | ||
| 2900 | for (i = 0; i < (rdev->mec.num_pipe * rdev->mec.num_mec); i++) { | 2905 | for (i = 0; i < (rdev->mec.num_pipe * rdev->mec.num_mec); i++) { |
| 2901 | int me = (i < 4) ? 1 : 2; | 2906 | int me = (i < 4) ? 1 : 2; |
| 2902 | int pipe = (i < 4) ? i : (i - 4); | 2907 | int pipe = (i < 4) ? i : (i - 4); |
| @@ -2919,6 +2924,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) | |||
| 2919 | WREG32(CP_HPD_EOP_CONTROL, tmp); | 2924 | WREG32(CP_HPD_EOP_CONTROL, tmp); |
| 2920 | } | 2925 | } |
| 2921 | cik_srbm_select(rdev, 0, 0, 0, 0); | 2926 | cik_srbm_select(rdev, 0, 0, 0, 0); |
| 2927 | mutex_unlock(&rdev->srbm_mutex); | ||
| 2922 | 2928 | ||
| 2923 | /* init the queues. Just two for now. */ | 2929 | /* init the queues. Just two for now. */ |
| 2924 | for (i = 0; i < 2; i++) { | 2930 | for (i = 0; i < 2; i++) { |
| @@ -2972,6 +2978,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) | |||
| 2972 | mqd->static_thread_mgmt23[0] = 0xffffffff; | 2978 | mqd->static_thread_mgmt23[0] = 0xffffffff; |
| 2973 | mqd->static_thread_mgmt23[1] = 0xffffffff; | 2979 | mqd->static_thread_mgmt23[1] = 0xffffffff; |
| 2974 | 2980 | ||
| 2981 | mutex_lock(&rdev->srbm_mutex); | ||
| 2975 | cik_srbm_select(rdev, rdev->ring[idx].me, | 2982 | cik_srbm_select(rdev, rdev->ring[idx].me, |
| 2976 | rdev->ring[idx].pipe, | 2983 | rdev->ring[idx].pipe, |
| 2977 | rdev->ring[idx].queue, 0); | 2984 | rdev->ring[idx].queue, 0); |
| @@ -3099,6 +3106,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) | |||
| 3099 | WREG32(CP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); | 3106 | WREG32(CP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); |
| 3100 | 3107 | ||
| 3101 | cik_srbm_select(rdev, 0, 0, 0, 0); | 3108 | cik_srbm_select(rdev, 0, 0, 0, 0); |
| 3109 | mutex_unlock(&rdev->srbm_mutex); | ||
| 3102 | 3110 | ||
| 3103 | radeon_bo_kunmap(rdev->ring[idx].mqd_obj); | 3111 | radeon_bo_kunmap(rdev->ring[idx].mqd_obj); |
| 3104 | radeon_bo_unreserve(rdev->ring[idx].mqd_obj); | 3112 | radeon_bo_unreserve(rdev->ring[idx].mqd_obj); |
| @@ -4320,6 +4328,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) | |||
| 4320 | 4328 | ||
| 4321 | /* XXX SH_MEM regs */ | 4329 | /* XXX SH_MEM regs */ |
| 4322 | /* where to put LDS, scratch, GPUVM in FSA64 space */ | 4330 | /* where to put LDS, scratch, GPUVM in FSA64 space */ |
| 4331 | mutex_lock(&rdev->srbm_mutex); | ||
| 4323 | for (i = 0; i < 16; i++) { | 4332 | for (i = 0; i < 16; i++) { |
| 4324 | cik_srbm_select(rdev, 0, 0, 0, i); | 4333 | cik_srbm_select(rdev, 0, 0, 0, i); |
| 4325 | /* CP and shaders */ | 4334 | /* CP and shaders */ |
| @@ -4335,6 +4344,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) | |||
| 4335 | /* XXX SDMA RLC - todo */ | 4344 | /* XXX SDMA RLC - todo */ |
| 4336 | } | 4345 | } |
| 4337 | cik_srbm_select(rdev, 0, 0, 0, 0); | 4346 | cik_srbm_select(rdev, 0, 0, 0, 0); |
| 4347 | mutex_unlock(&rdev->srbm_mutex); | ||
| 4338 | 4348 | ||
| 4339 | cik_pcie_gart_tlb_flush(rdev); | 4349 | cik_pcie_gart_tlb_flush(rdev); |
| 4340 | DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", | 4350 | DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", |
| @@ -5954,6 +5964,8 @@ static int cik_startup(struct radeon_device *rdev) | |||
| 5954 | struct radeon_ring *ring; | 5964 | struct radeon_ring *ring; |
| 5955 | int r; | 5965 | int r; |
| 5956 | 5966 | ||
| 5967 | cik_mc_program(rdev); | ||
| 5968 | |||
| 5957 | if (rdev->flags & RADEON_IS_IGP) { | 5969 | if (rdev->flags & RADEON_IS_IGP) { |
| 5958 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || | 5970 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || |
| 5959 | !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) { | 5971 | !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) { |
| @@ -5985,7 +5997,6 @@ static int cik_startup(struct radeon_device *rdev) | |||
| 5985 | if (r) | 5997 | if (r) |
| 5986 | return r; | 5998 | return r; |
| 5987 | 5999 | ||
| 5988 | cik_mc_program(rdev); | ||
| 5989 | r = cik_pcie_gart_enable(rdev); | 6000 | r = cik_pcie_gart_enable(rdev); |
| 5990 | if (r) | 6001 | if (r) |
| 5991 | return r; | 6002 | return r; |
| @@ -6194,7 +6205,7 @@ int cik_suspend(struct radeon_device *rdev) | |||
| 6194 | radeon_vm_manager_fini(rdev); | 6205 | radeon_vm_manager_fini(rdev); |
| 6195 | cik_cp_enable(rdev, false); | 6206 | cik_cp_enable(rdev, false); |
| 6196 | cik_sdma_enable(rdev, false); | 6207 | cik_sdma_enable(rdev, false); |
| 6197 | r600_uvd_rbc_stop(rdev); | 6208 | r600_uvd_stop(rdev); |
| 6198 | radeon_uvd_suspend(rdev); | 6209 | radeon_uvd_suspend(rdev); |
| 6199 | cik_irq_suspend(rdev); | 6210 | cik_irq_suspend(rdev); |
| 6200 | radeon_wb_disable(rdev); | 6211 | radeon_wb_disable(rdev); |
| @@ -6358,6 +6369,7 @@ void cik_fini(struct radeon_device *rdev) | |||
| 6358 | radeon_vm_manager_fini(rdev); | 6369 | radeon_vm_manager_fini(rdev); |
| 6359 | radeon_ib_pool_fini(rdev); | 6370 | radeon_ib_pool_fini(rdev); |
| 6360 | radeon_irq_kms_fini(rdev); | 6371 | radeon_irq_kms_fini(rdev); |
| 6372 | r600_uvd_stop(rdev); | ||
| 6361 | radeon_uvd_fini(rdev); | 6373 | radeon_uvd_fini(rdev); |
| 6362 | cik_pcie_gart_fini(rdev); | 6374 | cik_pcie_gart_fini(rdev); |
| 6363 | r600_vram_scratch_fini(rdev); | 6375 | r600_vram_scratch_fini(rdev); |
| @@ -6978,7 +6990,7 @@ int cik_uvd_resume(struct radeon_device *rdev) | |||
| 6978 | 6990 | ||
| 6979 | /* programm the VCPU memory controller bits 0-27 */ | 6991 | /* programm the VCPU memory controller bits 0-27 */ |
| 6980 | addr = rdev->uvd.gpu_addr >> 3; | 6992 | addr = rdev->uvd.gpu_addr >> 3; |
| 6981 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3; | 6993 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; |
| 6982 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); | 6994 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); |
| 6983 | WREG32(UVD_VCPU_CACHE_SIZE0, size); | 6995 | WREG32(UVD_VCPU_CACHE_SIZE0, size); |
| 6984 | 6996 | ||
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 9bcdd174780f..7e5d0b570a30 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c | |||
| @@ -2038,9 +2038,6 @@ int cypress_dpm_init(struct radeon_device *rdev) | |||
| 2038 | { | 2038 | { |
| 2039 | struct rv7xx_power_info *pi; | 2039 | struct rv7xx_power_info *pi; |
| 2040 | struct evergreen_power_info *eg_pi; | 2040 | struct evergreen_power_info *eg_pi; |
| 2041 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
| 2042 | uint16_t data_offset, size; | ||
| 2043 | uint8_t frev, crev; | ||
| 2044 | struct atom_clock_dividers dividers; | 2041 | struct atom_clock_dividers dividers; |
| 2045 | int ret; | 2042 | int ret; |
| 2046 | 2043 | ||
| @@ -2092,16 +2089,7 @@ int cypress_dpm_init(struct radeon_device *rdev) | |||
| 2092 | eg_pi->vddci_control = | 2089 | eg_pi->vddci_control = |
| 2093 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); | 2090 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); |
| 2094 | 2091 | ||
| 2095 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 2092 | rv770_get_engine_memory_ss(rdev); |
| 2096 | &frev, &crev, &data_offset)) { | ||
| 2097 | pi->sclk_ss = true; | ||
| 2098 | pi->mclk_ss = true; | ||
| 2099 | pi->dynamic_ss = true; | ||
| 2100 | } else { | ||
| 2101 | pi->sclk_ss = false; | ||
| 2102 | pi->mclk_ss = false; | ||
| 2103 | pi->dynamic_ss = true; | ||
| 2104 | } | ||
| 2105 | 2093 | ||
| 2106 | pi->asi = RV770_ASI_DFLT; | 2094 | pi->asi = RV770_ASI_DFLT; |
| 2107 | pi->pasi = CYPRESS_HASI_DFLT; | 2095 | pi->pasi = CYPRESS_HASI_DFLT; |
| @@ -2122,8 +2110,7 @@ int cypress_dpm_init(struct radeon_device *rdev) | |||
| 2122 | 2110 | ||
| 2123 | pi->dynamic_pcie_gen2 = true; | 2111 | pi->dynamic_pcie_gen2 = true; |
| 2124 | 2112 | ||
| 2125 | if (pi->gfx_clock_gating && | 2113 | if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE) |
| 2126 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
| 2127 | pi->thermal_protection = true; | 2114 | pi->thermal_protection = true; |
| 2128 | else | 2115 | else |
| 2129 | pi->thermal_protection = false; | 2116 | pi->thermal_protection = false; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 038dcac7670c..d5b49e33315e 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -5106,6 +5106,8 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
| 5106 | /* enable aspm */ | 5106 | /* enable aspm */ |
| 5107 | evergreen_program_aspm(rdev); | 5107 | evergreen_program_aspm(rdev); |
| 5108 | 5108 | ||
| 5109 | evergreen_mc_program(rdev); | ||
| 5110 | |||
| 5109 | if (ASIC_IS_DCE5(rdev)) { | 5111 | if (ASIC_IS_DCE5(rdev)) { |
| 5110 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { | 5112 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { |
| 5111 | r = ni_init_microcode(rdev); | 5113 | r = ni_init_microcode(rdev); |
| @@ -5133,7 +5135,6 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
| 5133 | if (r) | 5135 | if (r) |
| 5134 | return r; | 5136 | return r; |
| 5135 | 5137 | ||
| 5136 | evergreen_mc_program(rdev); | ||
| 5137 | if (rdev->flags & RADEON_IS_AGP) { | 5138 | if (rdev->flags & RADEON_IS_AGP) { |
| 5138 | evergreen_agp_enable(rdev); | 5139 | evergreen_agp_enable(rdev); |
| 5139 | } else { | 5140 | } else { |
| @@ -5291,10 +5292,10 @@ int evergreen_resume(struct radeon_device *rdev) | |||
| 5291 | int evergreen_suspend(struct radeon_device *rdev) | 5292 | int evergreen_suspend(struct radeon_device *rdev) |
| 5292 | { | 5293 | { |
| 5293 | r600_audio_fini(rdev); | 5294 | r600_audio_fini(rdev); |
| 5295 | r600_uvd_stop(rdev); | ||
| 5294 | radeon_uvd_suspend(rdev); | 5296 | radeon_uvd_suspend(rdev); |
| 5295 | r700_cp_stop(rdev); | 5297 | r700_cp_stop(rdev); |
| 5296 | r600_dma_stop(rdev); | 5298 | r600_dma_stop(rdev); |
| 5297 | r600_uvd_rbc_stop(rdev); | ||
| 5298 | evergreen_irq_suspend(rdev); | 5299 | evergreen_irq_suspend(rdev); |
| 5299 | radeon_wb_disable(rdev); | 5300 | radeon_wb_disable(rdev); |
| 5300 | evergreen_pcie_gart_disable(rdev); | 5301 | evergreen_pcie_gart_disable(rdev); |
| @@ -5429,6 +5430,7 @@ void evergreen_fini(struct radeon_device *rdev) | |||
| 5429 | radeon_ib_pool_fini(rdev); | 5430 | radeon_ib_pool_fini(rdev); |
| 5430 | radeon_irq_kms_fini(rdev); | 5431 | radeon_irq_kms_fini(rdev); |
| 5431 | evergreen_pcie_gart_fini(rdev); | 5432 | evergreen_pcie_gart_fini(rdev); |
| 5433 | r600_uvd_stop(rdev); | ||
| 5432 | radeon_uvd_fini(rdev); | 5434 | radeon_uvd_fini(rdev); |
| 5433 | r600_vram_scratch_fini(rdev); | 5435 | r600_vram_scratch_fini(rdev); |
| 5434 | radeon_gem_fini(rdev); | 5436 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index bb9ea3641312..b0e280058b9b 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c | |||
| @@ -148,18 +148,40 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
| 148 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 148 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 149 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | 149 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
| 150 | u32 base_rate = 24000; | 150 | u32 base_rate = 24000; |
| 151 | u32 max_ratio = clock / base_rate; | ||
| 152 | u32 dto_phase; | ||
| 153 | u32 dto_modulo = clock; | ||
| 154 | u32 wallclock_ratio; | ||
| 155 | u32 dto_cntl; | ||
| 151 | 156 | ||
| 152 | if (!dig || !dig->afmt) | 157 | if (!dig || !dig->afmt) |
| 153 | return; | 158 | return; |
| 154 | 159 | ||
| 160 | if (max_ratio >= 8) { | ||
| 161 | dto_phase = 192 * 1000; | ||
| 162 | wallclock_ratio = 3; | ||
| 163 | } else if (max_ratio >= 4) { | ||
| 164 | dto_phase = 96 * 1000; | ||
| 165 | wallclock_ratio = 2; | ||
| 166 | } else if (max_ratio >= 2) { | ||
| 167 | dto_phase = 48 * 1000; | ||
| 168 | wallclock_ratio = 1; | ||
| 169 | } else { | ||
| 170 | dto_phase = 24 * 1000; | ||
| 171 | wallclock_ratio = 0; | ||
| 172 | } | ||
| 173 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 174 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 175 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
| 176 | |||
| 155 | /* XXX two dtos; generally use dto0 for hdmi */ | 177 | /* XXX two dtos; generally use dto0 for hdmi */ |
| 156 | /* Express [24MHz / target pixel clock] as an exact rational | 178 | /* Express [24MHz / target pixel clock] as an exact rational |
| 157 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE | 179 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
| 158 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator | 180 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
| 159 | */ | 181 | */ |
| 160 | WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id)); | 182 | WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id)); |
| 161 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); | 183 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); |
| 162 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); | 184 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); |
| 163 | } | 185 | } |
| 164 | 186 | ||
| 165 | 187 | ||
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index a7baf67aef6c..0d582ac1dc31 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
| @@ -497,6 +497,9 @@ | |||
| 497 | #define DCCG_AUDIO_DTO0_MODULE 0x05b4 | 497 | #define DCCG_AUDIO_DTO0_MODULE 0x05b4 |
| 498 | #define DCCG_AUDIO_DTO0_LOAD 0x05b8 | 498 | #define DCCG_AUDIO_DTO0_LOAD 0x05b8 |
| 499 | #define DCCG_AUDIO_DTO0_CNTL 0x05bc | 499 | #define DCCG_AUDIO_DTO0_CNTL 0x05bc |
| 500 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO(x) (((x) & 7) << 0) | ||
| 501 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK 7 | ||
| 502 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_SHIFT 0 | ||
| 500 | 503 | ||
| 501 | #define DCCG_AUDIO_DTO1_PHASE 0x05c0 | 504 | #define DCCG_AUDIO_DTO1_PHASE 0x05c0 |
| 502 | #define DCCG_AUDIO_DTO1_MODULE 0x05c4 | 505 | #define DCCG_AUDIO_DTO1_MODULE 0x05c4 |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 56bd4f3be4fe..ccb4f8b54852 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -794,9 +794,13 @@ int ni_init_microcode(struct radeon_device *rdev) | |||
| 794 | if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) { | 794 | if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) { |
| 795 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); | 795 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); |
| 796 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); | 796 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); |
| 797 | if (err) | 797 | if (err) { |
| 798 | goto out; | 798 | printk(KERN_ERR |
| 799 | if (rdev->smc_fw->size != smc_req_size) { | 799 | "smc: error loading firmware \"%s\"\n", |
| 800 | fw_name); | ||
| 801 | release_firmware(rdev->smc_fw); | ||
| 802 | rdev->smc_fw = NULL; | ||
| 803 | } else if (rdev->smc_fw->size != smc_req_size) { | ||
| 800 | printk(KERN_ERR | 804 | printk(KERN_ERR |
| 801 | "ni_mc: Bogus length %zu in firmware \"%s\"\n", | 805 | "ni_mc: Bogus length %zu in firmware \"%s\"\n", |
| 802 | rdev->mc_fw->size, fw_name); | 806 | rdev->mc_fw->size, fw_name); |
| @@ -2079,6 +2083,8 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 2079 | /* enable aspm */ | 2083 | /* enable aspm */ |
| 2080 | evergreen_program_aspm(rdev); | 2084 | evergreen_program_aspm(rdev); |
| 2081 | 2085 | ||
| 2086 | evergreen_mc_program(rdev); | ||
| 2087 | |||
| 2082 | if (rdev->flags & RADEON_IS_IGP) { | 2088 | if (rdev->flags & RADEON_IS_IGP) { |
| 2083 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | 2089 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { |
| 2084 | r = ni_init_microcode(rdev); | 2090 | r = ni_init_microcode(rdev); |
| @@ -2107,7 +2113,6 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 2107 | if (r) | 2113 | if (r) |
| 2108 | return r; | 2114 | return r; |
| 2109 | 2115 | ||
| 2110 | evergreen_mc_program(rdev); | ||
| 2111 | r = cayman_pcie_gart_enable(rdev); | 2116 | r = cayman_pcie_gart_enable(rdev); |
| 2112 | if (r) | 2117 | if (r) |
| 2113 | return r; | 2118 | return r; |
| @@ -2286,7 +2291,7 @@ int cayman_suspend(struct radeon_device *rdev) | |||
| 2286 | radeon_vm_manager_fini(rdev); | 2291 | radeon_vm_manager_fini(rdev); |
| 2287 | cayman_cp_enable(rdev, false); | 2292 | cayman_cp_enable(rdev, false); |
| 2288 | cayman_dma_stop(rdev); | 2293 | cayman_dma_stop(rdev); |
| 2289 | r600_uvd_rbc_stop(rdev); | 2294 | r600_uvd_stop(rdev); |
| 2290 | radeon_uvd_suspend(rdev); | 2295 | radeon_uvd_suspend(rdev); |
| 2291 | evergreen_irq_suspend(rdev); | 2296 | evergreen_irq_suspend(rdev); |
| 2292 | radeon_wb_disable(rdev); | 2297 | radeon_wb_disable(rdev); |
| @@ -2418,6 +2423,7 @@ void cayman_fini(struct radeon_device *rdev) | |||
| 2418 | radeon_vm_manager_fini(rdev); | 2423 | radeon_vm_manager_fini(rdev); |
| 2419 | radeon_ib_pool_fini(rdev); | 2424 | radeon_ib_pool_fini(rdev); |
| 2420 | radeon_irq_kms_fini(rdev); | 2425 | radeon_irq_kms_fini(rdev); |
| 2426 | r600_uvd_stop(rdev); | ||
| 2421 | radeon_uvd_fini(rdev); | 2427 | radeon_uvd_fini(rdev); |
| 2422 | cayman_pcie_gart_fini(rdev); | 2428 | cayman_pcie_gart_fini(rdev); |
| 2423 | r600_vram_scratch_fini(rdev); | 2429 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 4f9b9bc20daa..f0f5f748938a 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c | |||
| @@ -4067,9 +4067,6 @@ int ni_dpm_init(struct radeon_device *rdev) | |||
| 4067 | struct rv7xx_power_info *pi; | 4067 | struct rv7xx_power_info *pi; |
| 4068 | struct evergreen_power_info *eg_pi; | 4068 | struct evergreen_power_info *eg_pi; |
| 4069 | struct ni_power_info *ni_pi; | 4069 | struct ni_power_info *ni_pi; |
| 4070 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
| 4071 | u16 data_offset, size; | ||
| 4072 | u8 frev, crev; | ||
| 4073 | struct atom_clock_dividers dividers; | 4070 | struct atom_clock_dividers dividers; |
| 4074 | int ret; | 4071 | int ret; |
| 4075 | 4072 | ||
| @@ -4162,16 +4159,7 @@ int ni_dpm_init(struct radeon_device *rdev) | |||
| 4162 | eg_pi->vddci_control = | 4159 | eg_pi->vddci_control = |
| 4163 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); | 4160 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0); |
| 4164 | 4161 | ||
| 4165 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 4162 | rv770_get_engine_memory_ss(rdev); |
| 4166 | &frev, &crev, &data_offset)) { | ||
| 4167 | pi->sclk_ss = true; | ||
| 4168 | pi->mclk_ss = true; | ||
| 4169 | pi->dynamic_ss = true; | ||
| 4170 | } else { | ||
| 4171 | pi->sclk_ss = false; | ||
| 4172 | pi->mclk_ss = false; | ||
| 4173 | pi->dynamic_ss = true; | ||
| 4174 | } | ||
| 4175 | 4163 | ||
| 4176 | pi->asi = RV770_ASI_DFLT; | 4164 | pi->asi = RV770_ASI_DFLT; |
| 4177 | pi->pasi = CYPRESS_HASI_DFLT; | 4165 | pi->pasi = CYPRESS_HASI_DFLT; |
| @@ -4188,8 +4176,7 @@ int ni_dpm_init(struct radeon_device *rdev) | |||
| 4188 | 4176 | ||
| 4189 | pi->dynamic_pcie_gen2 = true; | 4177 | pi->dynamic_pcie_gen2 = true; |
| 4190 | 4178 | ||
| 4191 | if (pi->gfx_clock_gating && | 4179 | if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE) |
| 4192 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
| 4193 | pi->thermal_protection = true; | 4180 | pi->thermal_protection = true; |
| 4194 | else | 4181 | else |
| 4195 | pi->thermal_protection = false; | 4182 | pi->thermal_protection = false; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 10f712e37003..e66e72077350 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -2299,9 +2299,13 @@ int r600_init_microcode(struct radeon_device *rdev) | |||
| 2299 | if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) { | 2299 | if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) { |
| 2300 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); | 2300 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); |
| 2301 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); | 2301 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); |
| 2302 | if (err) | 2302 | if (err) { |
| 2303 | goto out; | 2303 | printk(KERN_ERR |
| 2304 | if (rdev->smc_fw->size != smc_req_size) { | 2304 | "smc: error loading firmware \"%s\"\n", |
| 2305 | fw_name); | ||
| 2306 | release_firmware(rdev->smc_fw); | ||
| 2307 | rdev->smc_fw = NULL; | ||
| 2308 | } else if (rdev->smc_fw->size != smc_req_size) { | ||
| 2305 | printk(KERN_ERR | 2309 | printk(KERN_ERR |
| 2306 | "smc: Bogus length %zu in firmware \"%s\"\n", | 2310 | "smc: Bogus length %zu in firmware \"%s\"\n", |
| 2307 | rdev->smc_fw->size, fw_name); | 2311 | rdev->smc_fw->size, fw_name); |
| @@ -2697,12 +2701,29 @@ int r600_uvd_rbc_start(struct radeon_device *rdev) | |||
| 2697 | return 0; | 2701 | return 0; |
| 2698 | } | 2702 | } |
| 2699 | 2703 | ||
| 2700 | void r600_uvd_rbc_stop(struct radeon_device *rdev) | 2704 | void r600_uvd_stop(struct radeon_device *rdev) |
| 2701 | { | 2705 | { |
| 2702 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | 2706 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; |
| 2703 | 2707 | ||
| 2704 | /* force RBC into idle state */ | 2708 | /* force RBC into idle state */ |
| 2705 | WREG32(UVD_RBC_RB_CNTL, 0x11010101); | 2709 | WREG32(UVD_RBC_RB_CNTL, 0x11010101); |
| 2710 | |||
| 2711 | /* Stall UMC and register bus before resetting VCPU */ | ||
| 2712 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
| 2713 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
| 2714 | mdelay(1); | ||
| 2715 | |||
| 2716 | /* put VCPU into reset */ | ||
| 2717 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); | ||
| 2718 | mdelay(5); | ||
| 2719 | |||
| 2720 | /* disable VCPU clock */ | ||
| 2721 | WREG32(UVD_VCPU_CNTL, 0x0); | ||
| 2722 | |||
| 2723 | /* Unstall UMC and register bus */ | ||
| 2724 | WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8)); | ||
| 2725 | WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3)); | ||
| 2726 | |||
| 2706 | ring->ready = false; | 2727 | ring->ready = false; |
| 2707 | } | 2728 | } |
| 2708 | 2729 | ||
| @@ -2722,6 +2743,11 @@ int r600_uvd_init(struct radeon_device *rdev) | |||
| 2722 | /* disable interupt */ | 2743 | /* disable interupt */ |
| 2723 | WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1)); | 2744 | WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1)); |
| 2724 | 2745 | ||
| 2746 | /* Stall UMC and register bus before resetting VCPU */ | ||
| 2747 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
| 2748 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
| 2749 | mdelay(1); | ||
| 2750 | |||
| 2725 | /* put LMI, VCPU, RBC etc... into reset */ | 2751 | /* put LMI, VCPU, RBC etc... into reset */ |
| 2726 | WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET | | 2752 | WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET | |
| 2727 | LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET | | 2753 | LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET | |
| @@ -2751,10 +2777,6 @@ int r600_uvd_init(struct radeon_device *rdev) | |||
| 2751 | WREG32(UVD_MPC_SET_ALU, 0); | 2777 | WREG32(UVD_MPC_SET_ALU, 0); |
| 2752 | WREG32(UVD_MPC_SET_MUX, 0x88); | 2778 | WREG32(UVD_MPC_SET_MUX, 0x88); |
| 2753 | 2779 | ||
| 2754 | /* Stall UMC */ | ||
| 2755 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
| 2756 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
| 2757 | |||
| 2758 | /* take all subblocks out of reset, except VCPU */ | 2780 | /* take all subblocks out of reset, except VCPU */ |
| 2759 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); | 2781 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); |
| 2760 | mdelay(5); | 2782 | mdelay(5); |
| @@ -3312,6 +3334,8 @@ static int r600_startup(struct radeon_device *rdev) | |||
| 3312 | /* enable pcie gen2 link */ | 3334 | /* enable pcie gen2 link */ |
| 3313 | r600_pcie_gen2_enable(rdev); | 3335 | r600_pcie_gen2_enable(rdev); |
| 3314 | 3336 | ||
| 3337 | r600_mc_program(rdev); | ||
| 3338 | |||
| 3315 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | 3339 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { |
| 3316 | r = r600_init_microcode(rdev); | 3340 | r = r600_init_microcode(rdev); |
| 3317 | if (r) { | 3341 | if (r) { |
| @@ -3324,7 +3348,6 @@ static int r600_startup(struct radeon_device *rdev) | |||
| 3324 | if (r) | 3348 | if (r) |
| 3325 | return r; | 3349 | return r; |
| 3326 | 3350 | ||
| 3327 | r600_mc_program(rdev); | ||
| 3328 | if (rdev->flags & RADEON_IS_AGP) { | 3351 | if (rdev->flags & RADEON_IS_AGP) { |
| 3329 | r600_agp_enable(rdev); | 3352 | r600_agp_enable(rdev); |
| 3330 | } else { | 3353 | } else { |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index f48240bb8c56..f264df5470f7 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
| @@ -226,10 +226,29 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
| 226 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 226 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 227 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 227 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 228 | u32 base_rate = 24000; | 228 | u32 base_rate = 24000; |
| 229 | u32 max_ratio = clock / base_rate; | ||
| 230 | u32 dto_phase; | ||
| 231 | u32 dto_modulo = clock; | ||
| 232 | u32 wallclock_ratio; | ||
| 233 | u32 dto_cntl; | ||
| 229 | 234 | ||
| 230 | if (!dig || !dig->afmt) | 235 | if (!dig || !dig->afmt) |
| 231 | return; | 236 | return; |
| 232 | 237 | ||
| 238 | if (max_ratio >= 8) { | ||
| 239 | dto_phase = 192 * 1000; | ||
| 240 | wallclock_ratio = 3; | ||
| 241 | } else if (max_ratio >= 4) { | ||
| 242 | dto_phase = 96 * 1000; | ||
| 243 | wallclock_ratio = 2; | ||
| 244 | } else if (max_ratio >= 2) { | ||
| 245 | dto_phase = 48 * 1000; | ||
| 246 | wallclock_ratio = 1; | ||
| 247 | } else { | ||
| 248 | dto_phase = 24 * 1000; | ||
| 249 | wallclock_ratio = 0; | ||
| 250 | } | ||
| 251 | |||
| 233 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. | 252 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. |
| 234 | * doesn't matter which one you use. Just use the first one. | 253 | * doesn't matter which one you use. Just use the first one. |
| 235 | */ | 254 | */ |
| @@ -242,9 +261,21 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
| 242 | /* according to the reg specs, this should DCE3.2 only, but in | 261 | /* according to the reg specs, this should DCE3.2 only, but in |
| 243 | * practice it seems to cover DCE3.0 as well. | 262 | * practice it seems to cover DCE3.0 as well. |
| 244 | */ | 263 | */ |
| 245 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); | 264 | if (dig->dig_encoder == 0) { |
| 246 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); | 265 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
| 247 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | 266 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); |
| 267 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
| 268 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); | ||
| 269 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); | ||
| 270 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
| 271 | } else { | ||
| 272 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 273 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 274 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); | ||
| 275 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); | ||
| 276 | WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); | ||
| 277 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
| 278 | } | ||
| 248 | } else { | 279 | } else { |
| 249 | /* according to the reg specs, this should be DCE2.0 and DCE3.0 */ | 280 | /* according to the reg specs, this should be DCE2.0 and DCE3.0 */ |
| 250 | WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) | | 281 | WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) | |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 8e3fe815edab..7c780839a7f4 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
| @@ -933,6 +933,9 @@ | |||
| 933 | #define DCCG_AUDIO_DTO0_LOAD 0x051c | 933 | #define DCCG_AUDIO_DTO0_LOAD 0x051c |
| 934 | # define DTO_LOAD (1 << 31) | 934 | # define DTO_LOAD (1 << 31) |
| 935 | #define DCCG_AUDIO_DTO0_CNTL 0x0520 | 935 | #define DCCG_AUDIO_DTO0_CNTL 0x0520 |
| 936 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO(x) (((x) & 7) << 0) | ||
| 937 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK 7 | ||
| 938 | # define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_SHIFT 0 | ||
| 936 | 939 | ||
| 937 | #define DCCG_AUDIO_DTO1_PHASE 0x0524 | 940 | #define DCCG_AUDIO_DTO1_PHASE 0x0524 |
| 938 | #define DCCG_AUDIO_DTO1_MODULE 0x0528 | 941 | #define DCCG_AUDIO_DTO1_MODULE 0x0528 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 2f08219c39b6..274b8e1b889f 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -1468,7 +1468,6 @@ struct radeon_uvd { | |||
| 1468 | void *cpu_addr; | 1468 | void *cpu_addr; |
| 1469 | uint64_t gpu_addr; | 1469 | uint64_t gpu_addr; |
| 1470 | void *saved_bo; | 1470 | void *saved_bo; |
| 1471 | unsigned fw_size; | ||
| 1472 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; | 1471 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; |
| 1473 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; | 1472 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; |
| 1474 | struct delayed_work idle_work; | 1473 | struct delayed_work idle_work; |
| @@ -2066,6 +2065,7 @@ struct radeon_device { | |||
| 2066 | const struct firmware *mec_fw; /* CIK MEC firmware */ | 2065 | const struct firmware *mec_fw; /* CIK MEC firmware */ |
| 2067 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ | 2066 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ |
| 2068 | const struct firmware *smc_fw; /* SMC firmware */ | 2067 | const struct firmware *smc_fw; /* SMC firmware */ |
| 2068 | const struct firmware *uvd_fw; /* UVD firmware */ | ||
| 2069 | struct r600_blit r600_blit; | 2069 | struct r600_blit r600_blit; |
| 2070 | struct r600_vram_scratch vram_scratch; | 2070 | struct r600_vram_scratch vram_scratch; |
| 2071 | int msi_enabled; /* msi enabled */ | 2071 | int msi_enabled; /* msi enabled */ |
| @@ -2095,6 +2095,8 @@ struct radeon_device { | |||
| 2095 | /* ACPI interface */ | 2095 | /* ACPI interface */ |
| 2096 | struct radeon_atif atif; | 2096 | struct radeon_atif atif; |
| 2097 | struct radeon_atcs atcs; | 2097 | struct radeon_atcs atcs; |
| 2098 | /* srbm instance registers */ | ||
| 2099 | struct mutex srbm_mutex; | ||
| 2098 | }; | 2100 | }; |
| 2099 | 2101 | ||
| 2100 | int radeon_device_init(struct radeon_device *rdev, | 2102 | int radeon_device_init(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 902479fa737f..3d61d5aac18f 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -441,7 +441,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde | |||
| 441 | /* uvd */ | 441 | /* uvd */ |
| 442 | int r600_uvd_init(struct radeon_device *rdev); | 442 | int r600_uvd_init(struct radeon_device *rdev); |
| 443 | int r600_uvd_rbc_start(struct radeon_device *rdev); | 443 | int r600_uvd_rbc_start(struct radeon_device *rdev); |
| 444 | void r600_uvd_rbc_stop(struct radeon_device *rdev); | 444 | void r600_uvd_stop(struct radeon_device *rdev); |
| 445 | int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); | 445 | int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); |
| 446 | void r600_uvd_fence_emit(struct radeon_device *rdev, | 446 | void r600_uvd_fence_emit(struct radeon_device *rdev, |
| 447 | struct radeon_fence *fence); | 447 | struct radeon_fence *fence); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 82335e38ec4f..63398ae1dbf5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1163,6 +1163,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 1163 | mutex_init(&rdev->gem.mutex); | 1163 | mutex_init(&rdev->gem.mutex); |
| 1164 | mutex_init(&rdev->pm.mutex); | 1164 | mutex_init(&rdev->pm.mutex); |
| 1165 | mutex_init(&rdev->gpu_clock_mutex); | 1165 | mutex_init(&rdev->gpu_clock_mutex); |
| 1166 | mutex_init(&rdev->srbm_mutex); | ||
| 1166 | init_rwsem(&rdev->pm.mclk_lock); | 1167 | init_rwsem(&rdev->pm.mclk_lock); |
| 1167 | init_rwsem(&rdev->exclusive_lock); | 1168 | init_rwsem(&rdev->exclusive_lock); |
| 1168 | init_waitqueue_head(&rdev->irq.vblank_queue); | 1169 | init_waitqueue_head(&rdev->irq.vblank_queue); |
| @@ -1519,6 +1520,7 @@ int radeon_gpu_reset(struct radeon_device *rdev) | |||
| 1519 | radeon_save_bios_scratch_regs(rdev); | 1520 | radeon_save_bios_scratch_regs(rdev); |
| 1520 | /* block TTM */ | 1521 | /* block TTM */ |
| 1521 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); | 1522 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); |
| 1523 | radeon_pm_suspend(rdev); | ||
| 1522 | radeon_suspend(rdev); | 1524 | radeon_suspend(rdev); |
| 1523 | 1525 | ||
| 1524 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1526 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| @@ -1564,6 +1566,7 @@ retry: | |||
| 1564 | } | 1566 | } |
| 1565 | } | 1567 | } |
| 1566 | 1568 | ||
| 1569 | radeon_pm_resume(rdev); | ||
| 1567 | drm_helper_resume_force_mode(rdev->ddev); | 1570 | drm_helper_resume_force_mode(rdev->ddev); |
| 1568 | 1571 | ||
| 1569 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 1572 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7ddb0efe2408..ddb8f8e04eb5 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | |||
| 782 | 782 | ||
| 783 | } else { | 783 | } else { |
| 784 | /* put fence directly behind firmware */ | 784 | /* put fence directly behind firmware */ |
| 785 | index = ALIGN(rdev->uvd.fw_size, 8); | 785 | index = ALIGN(rdev->uvd_fw->size, 8); |
| 786 | rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index; | 786 | rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index; |
| 787 | rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index; | 787 | rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index; |
| 788 | } | 788 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 6a51d943ccf4..b990b1a2bd50 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -207,7 +207,6 @@ void radeon_gart_table_vram_free(struct radeon_device *rdev) | |||
| 207 | if (rdev->gart.robj == NULL) { | 207 | if (rdev->gart.robj == NULL) { |
| 208 | return; | 208 | return; |
| 209 | } | 209 | } |
| 210 | radeon_gart_table_vram_unpin(rdev); | ||
| 211 | radeon_bo_unref(&rdev->gart.robj); | 210 | radeon_bo_unref(&rdev->gart.robj); |
| 212 | } | 211 | } |
| 213 | 212 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f374c467aaca..c557850cd345 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -1176,7 +1176,14 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
| 1176 | case CHIP_VERDE: | 1176 | case CHIP_VERDE: |
| 1177 | case CHIP_OLAND: | 1177 | case CHIP_OLAND: |
| 1178 | case CHIP_HAINAN: | 1178 | case CHIP_HAINAN: |
| 1179 | if (radeon_dpm == 1) | 1179 | /* DPM requires the RLC, RV770+ dGPU requires SMC */ |
| 1180 | if (!rdev->rlc_fw) | ||
| 1181 | rdev->pm.pm_method = PM_METHOD_PROFILE; | ||
| 1182 | else if ((rdev->family >= CHIP_RV770) && | ||
| 1183 | (!(rdev->flags & RADEON_IS_IGP)) && | ||
| 1184 | (!rdev->smc_fw)) | ||
| 1185 | rdev->pm.pm_method = PM_METHOD_PROFILE; | ||
| 1186 | else if (radeon_dpm == 1) | ||
| 1180 | rdev->pm.pm_method = PM_METHOD_DPM; | 1187 | rdev->pm.pm_method = PM_METHOD_DPM; |
| 1181 | else | 1188 | else |
| 1182 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1189 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 414fd145d20e..f1c15754e73c 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c | |||
| @@ -56,7 +56,6 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work); | |||
| 56 | 56 | ||
| 57 | int radeon_uvd_init(struct radeon_device *rdev) | 57 | int radeon_uvd_init(struct radeon_device *rdev) |
| 58 | { | 58 | { |
| 59 | const struct firmware *fw; | ||
| 60 | unsigned long bo_size; | 59 | unsigned long bo_size; |
| 61 | const char *fw_name; | 60 | const char *fw_name; |
| 62 | int i, r; | 61 | int i, r; |
| @@ -105,14 +104,14 @@ int radeon_uvd_init(struct radeon_device *rdev) | |||
| 105 | return -EINVAL; | 104 | return -EINVAL; |
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | r = request_firmware(&fw, fw_name, rdev->dev); | 107 | r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev); |
| 109 | if (r) { | 108 | if (r) { |
| 110 | dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", | 109 | dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", |
| 111 | fw_name); | 110 | fw_name); |
| 112 | return r; | 111 | return r; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) + | 114 | bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + |
| 116 | RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; | 115 | RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; |
| 117 | r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, | 116 | r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, |
| 118 | RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); | 117 | RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); |
| @@ -145,12 +144,6 @@ int radeon_uvd_init(struct radeon_device *rdev) | |||
| 145 | 144 | ||
| 146 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); | 145 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); |
| 147 | 146 | ||
| 148 | rdev->uvd.fw_size = fw->size; | ||
| 149 | memset(rdev->uvd.cpu_addr, 0, bo_size); | ||
| 150 | memcpy(rdev->uvd.cpu_addr, fw->data, fw->size); | ||
| 151 | |||
| 152 | release_firmware(fw); | ||
| 153 | |||
| 154 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | 147 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
| 155 | atomic_set(&rdev->uvd.handles[i], 0); | 148 | atomic_set(&rdev->uvd.handles[i], 0); |
| 156 | rdev->uvd.filp[i] = NULL; | 149 | rdev->uvd.filp[i] = NULL; |
| @@ -174,33 +167,60 @@ void radeon_uvd_fini(struct radeon_device *rdev) | |||
| 174 | } | 167 | } |
| 175 | 168 | ||
| 176 | radeon_bo_unref(&rdev->uvd.vcpu_bo); | 169 | radeon_bo_unref(&rdev->uvd.vcpu_bo); |
| 170 | |||
| 171 | release_firmware(rdev->uvd_fw); | ||
| 177 | } | 172 | } |
| 178 | 173 | ||
| 179 | int radeon_uvd_suspend(struct radeon_device *rdev) | 174 | int radeon_uvd_suspend(struct radeon_device *rdev) |
| 180 | { | 175 | { |
| 181 | unsigned size; | 176 | unsigned size; |
| 177 | void *ptr; | ||
| 178 | int i; | ||
| 182 | 179 | ||
| 183 | if (rdev->uvd.vcpu_bo == NULL) | 180 | if (rdev->uvd.vcpu_bo == NULL) |
| 184 | return 0; | 181 | return 0; |
| 185 | 182 | ||
| 183 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) | ||
| 184 | if (atomic_read(&rdev->uvd.handles[i])) | ||
| 185 | break; | ||
| 186 | |||
| 187 | if (i == RADEON_MAX_UVD_HANDLES) | ||
| 188 | return 0; | ||
| 189 | |||
| 186 | size = radeon_bo_size(rdev->uvd.vcpu_bo); | 190 | size = radeon_bo_size(rdev->uvd.vcpu_bo); |
| 191 | size -= rdev->uvd_fw->size; | ||
| 192 | |||
| 193 | ptr = rdev->uvd.cpu_addr; | ||
| 194 | ptr += rdev->uvd_fw->size; | ||
| 195 | |||
| 187 | rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); | 196 | rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); |
| 188 | memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size); | 197 | memcpy(rdev->uvd.saved_bo, ptr, size); |
| 189 | 198 | ||
| 190 | return 0; | 199 | return 0; |
| 191 | } | 200 | } |
| 192 | 201 | ||
| 193 | int radeon_uvd_resume(struct radeon_device *rdev) | 202 | int radeon_uvd_resume(struct radeon_device *rdev) |
| 194 | { | 203 | { |
| 204 | unsigned size; | ||
| 205 | void *ptr; | ||
| 206 | |||
| 195 | if (rdev->uvd.vcpu_bo == NULL) | 207 | if (rdev->uvd.vcpu_bo == NULL) |
| 196 | return -EINVAL; | 208 | return -EINVAL; |
| 197 | 209 | ||
| 210 | memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size); | ||
| 211 | |||
| 212 | size = radeon_bo_size(rdev->uvd.vcpu_bo); | ||
| 213 | size -= rdev->uvd_fw->size; | ||
| 214 | |||
| 215 | ptr = rdev->uvd.cpu_addr; | ||
| 216 | ptr += rdev->uvd_fw->size; | ||
| 217 | |||
| 198 | if (rdev->uvd.saved_bo != NULL) { | 218 | if (rdev->uvd.saved_bo != NULL) { |
| 199 | unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo); | 219 | memcpy(ptr, rdev->uvd.saved_bo, size); |
| 200 | memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size); | ||
| 201 | kfree(rdev->uvd.saved_bo); | 220 | kfree(rdev->uvd.saved_bo); |
| 202 | rdev->uvd.saved_bo = NULL; | 221 | rdev->uvd.saved_bo = NULL; |
| 203 | } | 222 | } else |
| 223 | memset(ptr, 0, size); | ||
| 204 | 224 | ||
| 205 | return 0; | 225 | return 0; |
| 206 | } | 226 | } |
| @@ -215,8 +235,8 @@ void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp) | |||
| 215 | { | 235 | { |
| 216 | int i, r; | 236 | int i, r; |
| 217 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | 237 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
| 218 | if (rdev->uvd.filp[i] == filp) { | 238 | uint32_t handle = atomic_read(&rdev->uvd.handles[i]); |
| 219 | uint32_t handle = atomic_read(&rdev->uvd.handles[i]); | 239 | if (handle != 0 && rdev->uvd.filp[i] == filp) { |
| 220 | struct radeon_fence *fence; | 240 | struct radeon_fence *fence; |
| 221 | 241 | ||
| 222 | r = radeon_uvd_get_destroy_msg(rdev, | 242 | r = radeon_uvd_get_destroy_msg(rdev, |
| @@ -337,8 +357,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, | |||
| 337 | } | 357 | } |
| 338 | 358 | ||
| 339 | r = radeon_bo_kmap(bo, &ptr); | 359 | r = radeon_bo_kmap(bo, &ptr); |
| 340 | if (r) | 360 | if (r) { |
| 361 | DRM_ERROR("Failed mapping the UVD message (%d)!\n", r); | ||
| 341 | return r; | 362 | return r; |
| 363 | } | ||
| 342 | 364 | ||
| 343 | msg = ptr + offset; | 365 | msg = ptr + offset; |
| 344 | 366 | ||
| @@ -364,8 +386,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, | |||
| 364 | radeon_bo_kunmap(bo); | 386 | radeon_bo_kunmap(bo); |
| 365 | return 0; | 387 | return 0; |
| 366 | } else { | 388 | } else { |
| 367 | /* it's a create msg, no special handling needed */ | ||
| 368 | radeon_bo_kunmap(bo); | 389 | radeon_bo_kunmap(bo); |
| 390 | |||
| 391 | if (msg_type != 0) { | ||
| 392 | DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); | ||
| 393 | return -EINVAL; | ||
| 394 | } | ||
| 395 | |||
| 396 | /* it's a create msg, no special handling needed */ | ||
| 369 | } | 397 | } |
| 370 | 398 | ||
| 371 | /* create or decode, validate the handle */ | 399 | /* create or decode, validate the handle */ |
| @@ -388,7 +416,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, | |||
| 388 | 416 | ||
| 389 | static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, | 417 | static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, |
| 390 | int data0, int data1, | 418 | int data0, int data1, |
| 391 | unsigned buf_sizes[]) | 419 | unsigned buf_sizes[], bool *has_msg_cmd) |
| 392 | { | 420 | { |
| 393 | struct radeon_cs_chunk *relocs_chunk; | 421 | struct radeon_cs_chunk *relocs_chunk; |
| 394 | struct radeon_cs_reloc *reloc; | 422 | struct radeon_cs_reloc *reloc; |
| @@ -417,7 +445,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, | |||
| 417 | 445 | ||
| 418 | if (cmd < 0x4) { | 446 | if (cmd < 0x4) { |
| 419 | if ((end - start) < buf_sizes[cmd]) { | 447 | if ((end - start) < buf_sizes[cmd]) { |
| 420 | DRM_ERROR("buffer to small (%d / %d)!\n", | 448 | DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd, |
| 421 | (unsigned)(end - start), buf_sizes[cmd]); | 449 | (unsigned)(end - start), buf_sizes[cmd]); |
| 422 | return -EINVAL; | 450 | return -EINVAL; |
| 423 | } | 451 | } |
| @@ -442,9 +470,17 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, | |||
| 442 | } | 470 | } |
| 443 | 471 | ||
| 444 | if (cmd == 0) { | 472 | if (cmd == 0) { |
| 473 | if (*has_msg_cmd) { | ||
| 474 | DRM_ERROR("More than one message in a UVD-IB!\n"); | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | *has_msg_cmd = true; | ||
| 445 | r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes); | 478 | r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes); |
| 446 | if (r) | 479 | if (r) |
| 447 | return r; | 480 | return r; |
| 481 | } else if (!*has_msg_cmd) { | ||
| 482 | DRM_ERROR("Message needed before other commands are send!\n"); | ||
| 483 | return -EINVAL; | ||
| 448 | } | 484 | } |
| 449 | 485 | ||
| 450 | return 0; | 486 | return 0; |
| @@ -453,7 +489,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, | |||
| 453 | static int radeon_uvd_cs_reg(struct radeon_cs_parser *p, | 489 | static int radeon_uvd_cs_reg(struct radeon_cs_parser *p, |
| 454 | struct radeon_cs_packet *pkt, | 490 | struct radeon_cs_packet *pkt, |
| 455 | int *data0, int *data1, | 491 | int *data0, int *data1, |
| 456 | unsigned buf_sizes[]) | 492 | unsigned buf_sizes[], |
| 493 | bool *has_msg_cmd) | ||
| 457 | { | 494 | { |
| 458 | int i, r; | 495 | int i, r; |
| 459 | 496 | ||
| @@ -467,7 +504,8 @@ static int radeon_uvd_cs_reg(struct radeon_cs_parser *p, | |||
| 467 | *data1 = p->idx; | 504 | *data1 = p->idx; |
| 468 | break; | 505 | break; |
| 469 | case UVD_GPCOM_VCPU_CMD: | 506 | case UVD_GPCOM_VCPU_CMD: |
| 470 | r = radeon_uvd_cs_reloc(p, *data0, *data1, buf_sizes); | 507 | r = radeon_uvd_cs_reloc(p, *data0, *data1, |
| 508 | buf_sizes, has_msg_cmd); | ||
| 471 | if (r) | 509 | if (r) |
| 472 | return r; | 510 | return r; |
| 473 | break; | 511 | break; |
| @@ -488,6 +526,9 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p) | |||
| 488 | struct radeon_cs_packet pkt; | 526 | struct radeon_cs_packet pkt; |
| 489 | int r, data0 = 0, data1 = 0; | 527 | int r, data0 = 0, data1 = 0; |
| 490 | 528 | ||
| 529 | /* does the IB has a msg command */ | ||
| 530 | bool has_msg_cmd = false; | ||
| 531 | |||
| 491 | /* minimum buffer sizes */ | 532 | /* minimum buffer sizes */ |
| 492 | unsigned buf_sizes[] = { | 533 | unsigned buf_sizes[] = { |
| 493 | [0x00000000] = 2048, | 534 | [0x00000000] = 2048, |
| @@ -514,8 +555,8 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p) | |||
| 514 | return r; | 555 | return r; |
| 515 | switch (pkt.type) { | 556 | switch (pkt.type) { |
| 516 | case RADEON_PACKET_TYPE0: | 557 | case RADEON_PACKET_TYPE0: |
| 517 | r = radeon_uvd_cs_reg(p, &pkt, &data0, | 558 | r = radeon_uvd_cs_reg(p, &pkt, &data0, &data1, |
| 518 | &data1, buf_sizes); | 559 | buf_sizes, &has_msg_cmd); |
| 519 | if (r) | 560 | if (r) |
| 520 | return r; | 561 | return r; |
| 521 | break; | 562 | break; |
| @@ -527,6 +568,12 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p) | |||
| 527 | return -EINVAL; | 568 | return -EINVAL; |
| 528 | } | 569 | } |
| 529 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); | 570 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); |
| 571 | |||
| 572 | if (!has_msg_cmd) { | ||
| 573 | DRM_ERROR("UVD-IBs need a msg command!\n"); | ||
| 574 | return -EINVAL; | ||
| 575 | } | ||
| 576 | |||
| 530 | return 0; | 577 | return 0; |
| 531 | } | 578 | } |
| 532 | 579 | ||
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index 363018c60412..bdd888b4db2b 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c | |||
| @@ -1944,9 +1944,7 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev) | |||
| 1944 | 1944 | ||
| 1945 | int rv6xx_dpm_init(struct radeon_device *rdev) | 1945 | int rv6xx_dpm_init(struct radeon_device *rdev) |
| 1946 | { | 1946 | { |
| 1947 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | 1947 | struct radeon_atom_ss ss; |
| 1948 | uint16_t data_offset, size; | ||
| 1949 | uint8_t frev, crev; | ||
| 1950 | struct atom_clock_dividers dividers; | 1948 | struct atom_clock_dividers dividers; |
| 1951 | struct rv6xx_power_info *pi; | 1949 | struct rv6xx_power_info *pi; |
| 1952 | int ret; | 1950 | int ret; |
| @@ -1989,16 +1987,18 @@ int rv6xx_dpm_init(struct radeon_device *rdev) | |||
| 1989 | 1987 | ||
| 1990 | pi->gfx_clock_gating = true; | 1988 | pi->gfx_clock_gating = true; |
| 1991 | 1989 | ||
| 1992 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 1990 | pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, |
| 1993 | &frev, &crev, &data_offset)) { | 1991 | ASIC_INTERNAL_ENGINE_SS, 0); |
| 1994 | pi->sclk_ss = true; | 1992 | pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, |
| 1995 | pi->mclk_ss = true; | 1993 | ASIC_INTERNAL_MEMORY_SS, 0); |
| 1994 | |||
| 1995 | /* Disable sclk ss, causes hangs on a lot of systems */ | ||
| 1996 | pi->sclk_ss = false; | ||
| 1997 | |||
| 1998 | if (pi->sclk_ss || pi->mclk_ss) | ||
| 1996 | pi->dynamic_ss = true; | 1999 | pi->dynamic_ss = true; |
| 1997 | } else { | 2000 | else |
| 1998 | pi->sclk_ss = false; | ||
| 1999 | pi->mclk_ss = false; | ||
| 2000 | pi->dynamic_ss = false; | 2001 | pi->dynamic_ss = false; |
| 2001 | } | ||
| 2002 | 2002 | ||
| 2003 | pi->dynamic_pcie_gen2 = true; | 2003 | pi->dynamic_pcie_gen2 = true; |
| 2004 | 2004 | ||
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 30ea14e8854c..bcc68ec204ad 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev) | |||
| 813 | 813 | ||
| 814 | /* programm the VCPU memory controller bits 0-27 */ | 814 | /* programm the VCPU memory controller bits 0-27 */ |
| 815 | addr = rdev->uvd.gpu_addr >> 3; | 815 | addr = rdev->uvd.gpu_addr >> 3; |
| 816 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3; | 816 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; |
| 817 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); | 817 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); |
| 818 | WREG32(UVD_VCPU_CACHE_SIZE0, size); | 818 | WREG32(UVD_VCPU_CACHE_SIZE0, size); |
| 819 | 819 | ||
| @@ -1829,6 +1829,8 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 1829 | /* enable pcie gen2 link */ | 1829 | /* enable pcie gen2 link */ |
| 1830 | rv770_pcie_gen2_enable(rdev); | 1830 | rv770_pcie_gen2_enable(rdev); |
| 1831 | 1831 | ||
| 1832 | rv770_mc_program(rdev); | ||
| 1833 | |||
| 1832 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | 1834 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { |
| 1833 | r = r600_init_microcode(rdev); | 1835 | r = r600_init_microcode(rdev); |
| 1834 | if (r) { | 1836 | if (r) { |
| @@ -1841,7 +1843,6 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 1841 | if (r) | 1843 | if (r) |
| 1842 | return r; | 1844 | return r; |
| 1843 | 1845 | ||
| 1844 | rv770_mc_program(rdev); | ||
| 1845 | if (rdev->flags & RADEON_IS_AGP) { | 1846 | if (rdev->flags & RADEON_IS_AGP) { |
| 1846 | rv770_agp_enable(rdev); | 1847 | rv770_agp_enable(rdev); |
| 1847 | } else { | 1848 | } else { |
| @@ -1983,6 +1984,7 @@ int rv770_resume(struct radeon_device *rdev) | |||
| 1983 | int rv770_suspend(struct radeon_device *rdev) | 1984 | int rv770_suspend(struct radeon_device *rdev) |
| 1984 | { | 1985 | { |
| 1985 | r600_audio_fini(rdev); | 1986 | r600_audio_fini(rdev); |
| 1987 | r600_uvd_stop(rdev); | ||
| 1986 | radeon_uvd_suspend(rdev); | 1988 | radeon_uvd_suspend(rdev); |
| 1987 | r700_cp_stop(rdev); | 1989 | r700_cp_stop(rdev); |
| 1988 | r600_dma_stop(rdev); | 1990 | r600_dma_stop(rdev); |
| @@ -2098,6 +2100,7 @@ void rv770_fini(struct radeon_device *rdev) | |||
| 2098 | radeon_ib_pool_fini(rdev); | 2100 | radeon_ib_pool_fini(rdev); |
| 2099 | radeon_irq_kms_fini(rdev); | 2101 | radeon_irq_kms_fini(rdev); |
| 2100 | rv770_pcie_gart_fini(rdev); | 2102 | rv770_pcie_gart_fini(rdev); |
| 2103 | r600_uvd_stop(rdev); | ||
| 2101 | radeon_uvd_fini(rdev); | 2104 | radeon_uvd_fini(rdev); |
| 2102 | r600_vram_scratch_fini(rdev); | 2105 | r600_vram_scratch_fini(rdev); |
| 2103 | radeon_gem_fini(rdev); | 2106 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 2d347925f77d..094c67a29d0d 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c | |||
| @@ -2319,12 +2319,25 @@ int rv7xx_parse_power_table(struct radeon_device *rdev) | |||
| 2319 | return 0; | 2319 | return 0; |
| 2320 | } | 2320 | } |
| 2321 | 2321 | ||
| 2322 | void rv770_get_engine_memory_ss(struct radeon_device *rdev) | ||
| 2323 | { | ||
| 2324 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
| 2325 | struct radeon_atom_ss ss; | ||
| 2326 | |||
| 2327 | pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
| 2328 | ASIC_INTERNAL_ENGINE_SS, 0); | ||
| 2329 | pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
| 2330 | ASIC_INTERNAL_MEMORY_SS, 0); | ||
| 2331 | |||
| 2332 | if (pi->sclk_ss || pi->mclk_ss) | ||
| 2333 | pi->dynamic_ss = true; | ||
| 2334 | else | ||
| 2335 | pi->dynamic_ss = false; | ||
| 2336 | } | ||
| 2337 | |||
| 2322 | int rv770_dpm_init(struct radeon_device *rdev) | 2338 | int rv770_dpm_init(struct radeon_device *rdev) |
| 2323 | { | 2339 | { |
| 2324 | struct rv7xx_power_info *pi; | 2340 | struct rv7xx_power_info *pi; |
| 2325 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
| 2326 | uint16_t data_offset, size; | ||
| 2327 | uint8_t frev, crev; | ||
| 2328 | struct atom_clock_dividers dividers; | 2341 | struct atom_clock_dividers dividers; |
| 2329 | int ret; | 2342 | int ret; |
| 2330 | 2343 | ||
| @@ -2369,16 +2382,7 @@ int rv770_dpm_init(struct radeon_device *rdev) | |||
| 2369 | pi->mvdd_control = | 2382 | pi->mvdd_control = |
| 2370 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0); | 2383 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0); |
| 2371 | 2384 | ||
| 2372 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 2385 | rv770_get_engine_memory_ss(rdev); |
| 2373 | &frev, &crev, &data_offset)) { | ||
| 2374 | pi->sclk_ss = true; | ||
| 2375 | pi->mclk_ss = true; | ||
| 2376 | pi->dynamic_ss = true; | ||
| 2377 | } else { | ||
| 2378 | pi->sclk_ss = false; | ||
| 2379 | pi->mclk_ss = false; | ||
| 2380 | pi->dynamic_ss = false; | ||
| 2381 | } | ||
| 2382 | 2386 | ||
| 2383 | pi->asi = RV770_ASI_DFLT; | 2387 | pi->asi = RV770_ASI_DFLT; |
| 2384 | pi->pasi = RV770_HASI_DFLT; | 2388 | pi->pasi = RV770_HASI_DFLT; |
| @@ -2393,8 +2397,7 @@ int rv770_dpm_init(struct radeon_device *rdev) | |||
| 2393 | 2397 | ||
| 2394 | pi->dynamic_pcie_gen2 = true; | 2398 | pi->dynamic_pcie_gen2 = true; |
| 2395 | 2399 | ||
| 2396 | if (pi->gfx_clock_gating && | 2400 | if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE) |
| 2397 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
| 2398 | pi->thermal_protection = true; | 2401 | pi->thermal_protection = true; |
| 2399 | else | 2402 | else |
| 2400 | pi->thermal_protection = false; | 2403 | pi->thermal_protection = false; |
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.h b/drivers/gpu/drm/radeon/rv770_dpm.h index 96b1b2a62a8a..9244effc6b59 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.h +++ b/drivers/gpu/drm/radeon/rv770_dpm.h | |||
| @@ -275,6 +275,7 @@ void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, | |||
| 275 | void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, | 275 | void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, |
| 276 | struct radeon_ps *new_ps, | 276 | struct radeon_ps *new_ps, |
| 277 | struct radeon_ps *old_ps); | 277 | struct radeon_ps *old_ps); |
| 278 | void rv770_get_engine_memory_ss(struct radeon_device *rdev); | ||
| 278 | 279 | ||
| 279 | /* smc */ | 280 | /* smc */ |
| 280 | int rv770_read_smc_soft_register(struct radeon_device *rdev, | 281 | int rv770_read_smc_soft_register(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6ca904673a4f..daa8d2df8ec5 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -1663,9 +1663,13 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1663 | 1663 | ||
| 1664 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); | 1664 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); |
| 1665 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); | 1665 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); |
| 1666 | if (err) | 1666 | if (err) { |
| 1667 | goto out; | 1667 | printk(KERN_ERR |
| 1668 | if (rdev->smc_fw->size != smc_req_size) { | 1668 | "smc: error loading firmware \"%s\"\n", |
| 1669 | fw_name); | ||
| 1670 | release_firmware(rdev->smc_fw); | ||
| 1671 | rdev->smc_fw = NULL; | ||
| 1672 | } else if (rdev->smc_fw->size != smc_req_size) { | ||
| 1669 | printk(KERN_ERR | 1673 | printk(KERN_ERR |
| 1670 | "si_smc: Bogus length %zu in firmware \"%s\"\n", | 1674 | "si_smc: Bogus length %zu in firmware \"%s\"\n", |
| 1671 | rdev->smc_fw->size, fw_name); | 1675 | rdev->smc_fw->size, fw_name); |
| @@ -6418,6 +6422,8 @@ static int si_startup(struct radeon_device *rdev) | |||
| 6418 | /* enable aspm */ | 6422 | /* enable aspm */ |
| 6419 | si_program_aspm(rdev); | 6423 | si_program_aspm(rdev); |
| 6420 | 6424 | ||
| 6425 | si_mc_program(rdev); | ||
| 6426 | |||
| 6421 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || | 6427 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || |
| 6422 | !rdev->rlc_fw || !rdev->mc_fw) { | 6428 | !rdev->rlc_fw || !rdev->mc_fw) { |
| 6423 | r = si_init_microcode(rdev); | 6429 | r = si_init_microcode(rdev); |
| @@ -6437,7 +6443,6 @@ static int si_startup(struct radeon_device *rdev) | |||
| 6437 | if (r) | 6443 | if (r) |
| 6438 | return r; | 6444 | return r; |
| 6439 | 6445 | ||
| 6440 | si_mc_program(rdev); | ||
| 6441 | r = si_pcie_gart_enable(rdev); | 6446 | r = si_pcie_gart_enable(rdev); |
| 6442 | if (r) | 6447 | if (r) |
| 6443 | return r; | 6448 | return r; |
| @@ -6621,7 +6626,7 @@ int si_suspend(struct radeon_device *rdev) | |||
| 6621 | si_cp_enable(rdev, false); | 6626 | si_cp_enable(rdev, false); |
| 6622 | cayman_dma_stop(rdev); | 6627 | cayman_dma_stop(rdev); |
| 6623 | if (rdev->has_uvd) { | 6628 | if (rdev->has_uvd) { |
| 6624 | r600_uvd_rbc_stop(rdev); | 6629 | r600_uvd_stop(rdev); |
| 6625 | radeon_uvd_suspend(rdev); | 6630 | radeon_uvd_suspend(rdev); |
| 6626 | } | 6631 | } |
| 6627 | si_irq_suspend(rdev); | 6632 | si_irq_suspend(rdev); |
| @@ -6763,8 +6768,10 @@ void si_fini(struct radeon_device *rdev) | |||
| 6763 | radeon_vm_manager_fini(rdev); | 6768 | radeon_vm_manager_fini(rdev); |
| 6764 | radeon_ib_pool_fini(rdev); | 6769 | radeon_ib_pool_fini(rdev); |
| 6765 | radeon_irq_kms_fini(rdev); | 6770 | radeon_irq_kms_fini(rdev); |
| 6766 | if (rdev->has_uvd) | 6771 | if (rdev->has_uvd) { |
| 6772 | r600_uvd_stop(rdev); | ||
| 6767 | radeon_uvd_fini(rdev); | 6773 | radeon_uvd_fini(rdev); |
| 6774 | } | ||
| 6768 | si_pcie_gart_fini(rdev); | 6775 | si_pcie_gart_fini(rdev); |
| 6769 | r600_vram_scratch_fini(rdev); | 6776 | r600_vram_scratch_fini(rdev); |
| 6770 | radeon_gem_fini(rdev); | 6777 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 41825575b403..88699e3cd868 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -2903,7 +2903,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2903 | { | 2903 | { |
| 2904 | struct ni_ps *ps = ni_get_ps(rps); | 2904 | struct ni_ps *ps = ni_get_ps(rps); |
| 2905 | struct radeon_clock_and_voltage_limits *max_limits; | 2905 | struct radeon_clock_and_voltage_limits *max_limits; |
| 2906 | bool disable_mclk_switching; | 2906 | bool disable_mclk_switching = false; |
| 2907 | bool disable_sclk_switching = false; | ||
| 2907 | u32 mclk, sclk; | 2908 | u32 mclk, sclk; |
| 2908 | u16 vddc, vddci; | 2909 | u16 vddc, vddci; |
| 2909 | int i; | 2910 | int i; |
| @@ -2911,8 +2912,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2911 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || | 2912 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || |
| 2912 | ni_dpm_vblank_too_short(rdev)) | 2913 | ni_dpm_vblank_too_short(rdev)) |
| 2913 | disable_mclk_switching = true; | 2914 | disable_mclk_switching = true; |
| 2914 | else | 2915 | |
| 2915 | disable_mclk_switching = false; | 2916 | if (rps->vclk || rps->dclk) { |
| 2917 | disable_mclk_switching = true; | ||
| 2918 | disable_sclk_switching = true; | ||
| 2919 | } | ||
| 2916 | 2920 | ||
| 2917 | if (rdev->pm.dpm.ac_power) | 2921 | if (rdev->pm.dpm.ac_power) |
| 2918 | max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; | 2922 | max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; |
| @@ -2940,27 +2944,43 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2940 | 2944 | ||
| 2941 | if (disable_mclk_switching) { | 2945 | if (disable_mclk_switching) { |
| 2942 | mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; | 2946 | mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; |
| 2943 | sclk = ps->performance_levels[0].sclk; | ||
| 2944 | vddc = ps->performance_levels[0].vddc; | ||
| 2945 | vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; | 2947 | vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; |
| 2946 | } else { | 2948 | } else { |
| 2947 | sclk = ps->performance_levels[0].sclk; | ||
| 2948 | mclk = ps->performance_levels[0].mclk; | 2949 | mclk = ps->performance_levels[0].mclk; |
| 2949 | vddc = ps->performance_levels[0].vddc; | ||
| 2950 | vddci = ps->performance_levels[0].vddci; | 2950 | vddci = ps->performance_levels[0].vddci; |
| 2951 | } | 2951 | } |
| 2952 | 2952 | ||
| 2953 | if (disable_sclk_switching) { | ||
| 2954 | sclk = ps->performance_levels[ps->performance_level_count - 1].sclk; | ||
| 2955 | vddc = ps->performance_levels[ps->performance_level_count - 1].vddc; | ||
| 2956 | } else { | ||
| 2957 | sclk = ps->performance_levels[0].sclk; | ||
| 2958 | vddc = ps->performance_levels[0].vddc; | ||
| 2959 | } | ||
| 2960 | |||
| 2953 | /* adjusted low state */ | 2961 | /* adjusted low state */ |
| 2954 | ps->performance_levels[0].sclk = sclk; | 2962 | ps->performance_levels[0].sclk = sclk; |
| 2955 | ps->performance_levels[0].mclk = mclk; | 2963 | ps->performance_levels[0].mclk = mclk; |
| 2956 | ps->performance_levels[0].vddc = vddc; | 2964 | ps->performance_levels[0].vddc = vddc; |
| 2957 | ps->performance_levels[0].vddci = vddci; | 2965 | ps->performance_levels[0].vddci = vddci; |
| 2958 | 2966 | ||
| 2959 | for (i = 1; i < ps->performance_level_count; i++) { | 2967 | if (disable_sclk_switching) { |
| 2960 | if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk) | 2968 | sclk = ps->performance_levels[0].sclk; |
| 2961 | ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk; | 2969 | for (i = 1; i < ps->performance_level_count; i++) { |
| 2962 | if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc) | 2970 | if (sclk < ps->performance_levels[i].sclk) |
| 2963 | ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; | 2971 | sclk = ps->performance_levels[i].sclk; |
| 2972 | } | ||
| 2973 | for (i = 0; i < ps->performance_level_count; i++) { | ||
| 2974 | ps->performance_levels[i].sclk = sclk; | ||
| 2975 | ps->performance_levels[i].vddc = vddc; | ||
| 2976 | } | ||
| 2977 | } else { | ||
| 2978 | for (i = 1; i < ps->performance_level_count; i++) { | ||
| 2979 | if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk) | ||
| 2980 | ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk; | ||
| 2981 | if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc) | ||
| 2982 | ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; | ||
| 2983 | } | ||
| 2964 | } | 2984 | } |
| 2965 | 2985 | ||
| 2966 | if (disable_mclk_switching) { | 2986 | if (disable_mclk_switching) { |
| @@ -6253,9 +6273,6 @@ int si_dpm_init(struct radeon_device *rdev) | |||
| 6253 | struct evergreen_power_info *eg_pi; | 6273 | struct evergreen_power_info *eg_pi; |
| 6254 | struct ni_power_info *ni_pi; | 6274 | struct ni_power_info *ni_pi; |
| 6255 | struct si_power_info *si_pi; | 6275 | struct si_power_info *si_pi; |
| 6256 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
| 6257 | u16 data_offset, size; | ||
| 6258 | u8 frev, crev; | ||
| 6259 | struct atom_clock_dividers dividers; | 6276 | struct atom_clock_dividers dividers; |
| 6260 | int ret; | 6277 | int ret; |
| 6261 | u32 mask; | 6278 | u32 mask; |
| @@ -6346,16 +6363,7 @@ int si_dpm_init(struct radeon_device *rdev) | |||
| 6346 | si_pi->vddc_phase_shed_control = | 6363 | si_pi->vddc_phase_shed_control = |
| 6347 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT); | 6364 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT); |
| 6348 | 6365 | ||
| 6349 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | 6366 | rv770_get_engine_memory_ss(rdev); |
| 6350 | &frev, &crev, &data_offset)) { | ||
| 6351 | pi->sclk_ss = true; | ||
| 6352 | pi->mclk_ss = true; | ||
| 6353 | pi->dynamic_ss = true; | ||
| 6354 | } else { | ||
| 6355 | pi->sclk_ss = false; | ||
| 6356 | pi->mclk_ss = false; | ||
| 6357 | pi->dynamic_ss = true; | ||
| 6358 | } | ||
| 6359 | 6367 | ||
| 6360 | pi->asi = RV770_ASI_DFLT; | 6368 | pi->asi = RV770_ASI_DFLT; |
| 6361 | pi->pasi = CYPRESS_HASI_DFLT; | 6369 | pi->pasi = CYPRESS_HASI_DFLT; |
| @@ -6366,8 +6374,7 @@ int si_dpm_init(struct radeon_device *rdev) | |||
| 6366 | eg_pi->sclk_deep_sleep = true; | 6374 | eg_pi->sclk_deep_sleep = true; |
| 6367 | si_pi->sclk_deep_sleep_above_low = false; | 6375 | si_pi->sclk_deep_sleep_above_low = false; |
| 6368 | 6376 | ||
| 6369 | if (pi->gfx_clock_gating && | 6377 | if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE) |
| 6370 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
| 6371 | pi->thermal_protection = true; | 6378 | pi->thermal_protection = true; |
| 6372 | else | 6379 | else |
| 6373 | pi->thermal_protection = false; | 6380 | pi->thermal_protection = false; |
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 7a5764843bfb..cd33084c7860 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
| @@ -488,8 +488,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | |||
| 488 | if (djrcv_dev->querying_devices) | 488 | if (djrcv_dev->querying_devices) |
| 489 | return 0; | 489 | return 0; |
| 490 | 490 | ||
| 491 | djrcv_dev->querying_devices = true; | ||
| 492 | |||
| 493 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); | 491 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); |
| 494 | if (!dj_report) | 492 | if (!dj_report) |
| 495 | return -ENOMEM; | 493 | return -ENOMEM; |
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 0f34bca9f5e5..6099f50b28aa 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c | |||
| @@ -215,7 +215,7 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, | |||
| 215 | u16 value) | 215 | u16 value) |
| 216 | { | 216 | { |
| 217 | return i2c_smbus_write_byte_data(client, reg, value & 0xFF) | 217 | return i2c_smbus_write_byte_data(client, reg, value & 0xFF) |
| 218 | && i2c_smbus_write_byte_data(client, reg + 1, value >> 8); | 218 | || i2c_smbus_write_byte_data(client, reg + 1, value >> 8); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | static void adt7470_init_client(struct i2c_client *client) | 221 | static void adt7470_init_client(struct i2c_client *client) |
diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index ccec916bc3eb..af8f65fb1c05 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c | |||
| @@ -246,9 +246,9 @@ static void kempld_i2c_device_init(struct kempld_i2c_data *i2c) | |||
| 246 | bus_frequency = KEMPLD_I2C_FREQ_MAX; | 246 | bus_frequency = KEMPLD_I2C_FREQ_MAX; |
| 247 | 247 | ||
| 248 | if (pld->info.spec_major == 1) | 248 | if (pld->info.spec_major == 1) |
| 249 | prescale = pld->pld_clock / bus_frequency * 5 - 1000; | 249 | prescale = pld->pld_clock / (bus_frequency * 5) - 1000; |
| 250 | else | 250 | else |
| 251 | prescale = pld->pld_clock / bus_frequency * 4 - 3000; | 251 | prescale = pld->pld_clock / (bus_frequency * 4) - 3000; |
| 252 | 252 | ||
| 253 | if (prescale < 0) | 253 | if (prescale < 0) |
| 254 | prescale = 0; | 254 | prescale = 0; |
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index df8ff5aea5b5..e2e9a0dade96 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
| @@ -493,7 +493,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 493 | * based on this empirical measurement and a lot of previous frobbing. | 493 | * based on this empirical measurement and a lot of previous frobbing. |
| 494 | */ | 494 | */ |
| 495 | i2c->cmd_err = 0; | 495 | i2c->cmd_err = 0; |
| 496 | if (msg->len < 8) { | 496 | if (0) { /* disable PIO mode until a proper fix is made */ |
| 497 | ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); | 497 | ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); |
| 498 | if (ret) | 498 | if (ret) |
| 499 | mxs_i2c_reset(i2c); | 499 | mxs_i2c_reset(i2c); |
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 0ad208a69c29..3ceac3e91dde 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c | |||
| @@ -60,7 +60,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) | |||
| 60 | { | 60 | { |
| 61 | unsigned int stepconfig; | 61 | unsigned int stepconfig; |
| 62 | int i, steps; | 62 | int i, steps; |
| 63 | u32 step_en; | ||
| 64 | 63 | ||
| 65 | /* | 64 | /* |
| 66 | * There are 16 configurable steps and 8 analog input | 65 | * There are 16 configurable steps and 8 analog input |
| @@ -86,8 +85,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) | |||
| 86 | adc_dev->channel_step[i] = steps; | 85 | adc_dev->channel_step[i] = steps; |
| 87 | steps++; | 86 | steps++; |
| 88 | } | 87 | } |
| 89 | step_en = get_adc_step_mask(adc_dev); | 88 | |
| 90 | am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); | ||
| 91 | } | 89 | } |
| 92 | 90 | ||
| 93 | static const char * const chan_name_ain[] = { | 91 | static const char * const chan_name_ain[] = { |
| @@ -142,10 +140,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, | |||
| 142 | int *val, int *val2, long mask) | 140 | int *val, int *val2, long mask) |
| 143 | { | 141 | { |
| 144 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | 142 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
| 145 | int i; | 143 | int i, map_val; |
| 146 | unsigned int fifo1count, read; | 144 | unsigned int fifo1count, read, stepid; |
| 147 | u32 step = UINT_MAX; | 145 | u32 step = UINT_MAX; |
| 148 | bool found = false; | 146 | bool found = false; |
| 147 | u32 step_en; | ||
| 148 | unsigned long timeout = jiffies + usecs_to_jiffies | ||
| 149 | (IDLE_TIMEOUT * adc_dev->channels); | ||
| 150 | step_en = get_adc_step_mask(adc_dev); | ||
| 151 | am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); | ||
| 152 | |||
| 153 | /* Wait for ADC sequencer to complete sampling */ | ||
| 154 | while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { | ||
| 155 | if (time_after(jiffies, timeout)) | ||
| 156 | return -EAGAIN; | ||
| 157 | } | ||
| 158 | map_val = chan->channel + TOTAL_CHANNELS; | ||
| 149 | 159 | ||
| 150 | /* | 160 | /* |
| 151 | * When the sub-system is first enabled, | 161 | * When the sub-system is first enabled, |
| @@ -170,12 +180,16 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, | |||
| 170 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | 180 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); |
| 171 | for (i = 0; i < fifo1count; i++) { | 181 | for (i = 0; i < fifo1count; i++) { |
| 172 | read = tiadc_readl(adc_dev, REG_FIFO1); | 182 | read = tiadc_readl(adc_dev, REG_FIFO1); |
| 173 | if (read >> 16 == step) { | 183 | stepid = read & FIFOREAD_CHNLID_MASK; |
| 174 | *val = read & 0xfff; | 184 | stepid = stepid >> 0x10; |
| 185 | |||
| 186 | if (stepid == map_val) { | ||
| 187 | read = read & FIFOREAD_DATA_MASK; | ||
| 175 | found = true; | 188 | found = true; |
| 189 | *val = read; | ||
| 176 | } | 190 | } |
| 177 | } | 191 | } |
| 178 | am335x_tsc_se_update(adc_dev->mfd_tscadc); | 192 | |
| 179 | if (found == false) | 193 | if (found == false) |
| 180 | return -EBUSY; | 194 | return -EBUSY; |
| 181 | return IIO_VAL_INT; | 195 | return IIO_VAL_INT; |
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ea8a4146620d..0dd9bb873130 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c | |||
| @@ -127,12 +127,17 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, | |||
| 127 | void iio_trigger_poll(struct iio_trigger *trig, s64 time) | 127 | void iio_trigger_poll(struct iio_trigger *trig, s64 time) |
| 128 | { | 128 | { |
| 129 | int i; | 129 | int i; |
| 130 | if (!trig->use_count) | 130 | |
| 131 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | 131 | if (!atomic_read(&trig->use_count)) { |
| 132 | if (trig->subirqs[i].enabled) { | 132 | atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER); |
| 133 | trig->use_count++; | 133 | |
| 134 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
| 135 | if (trig->subirqs[i].enabled) | ||
| 134 | generic_handle_irq(trig->subirq_base + i); | 136 | generic_handle_irq(trig->subirq_base + i); |
| 135 | } | 137 | else |
| 138 | iio_trigger_notify_done(trig); | ||
| 139 | } | ||
| 140 | } | ||
| 136 | } | 141 | } |
| 137 | EXPORT_SYMBOL(iio_trigger_poll); | 142 | EXPORT_SYMBOL(iio_trigger_poll); |
| 138 | 143 | ||
| @@ -146,19 +151,24 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); | |||
| 146 | void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) | 151 | void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) |
| 147 | { | 152 | { |
| 148 | int i; | 153 | int i; |
| 149 | if (!trig->use_count) | 154 | |
| 150 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | 155 | if (!atomic_read(&trig->use_count)) { |
| 151 | if (trig->subirqs[i].enabled) { | 156 | atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER); |
| 152 | trig->use_count++; | 157 | |
| 158 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
| 159 | if (trig->subirqs[i].enabled) | ||
| 153 | handle_nested_irq(trig->subirq_base + i); | 160 | handle_nested_irq(trig->subirq_base + i); |
| 154 | } | 161 | else |
| 162 | iio_trigger_notify_done(trig); | ||
| 163 | } | ||
| 164 | } | ||
| 155 | } | 165 | } |
| 156 | EXPORT_SYMBOL(iio_trigger_poll_chained); | 166 | EXPORT_SYMBOL(iio_trigger_poll_chained); |
| 157 | 167 | ||
| 158 | void iio_trigger_notify_done(struct iio_trigger *trig) | 168 | void iio_trigger_notify_done(struct iio_trigger *trig) |
| 159 | { | 169 | { |
| 160 | trig->use_count--; | 170 | if (atomic_dec_and_test(&trig->use_count) && trig->ops && |
| 161 | if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) | 171 | trig->ops->try_reenable) |
| 162 | if (trig->ops->try_reenable(trig)) | 172 | if (trig->ops->try_reenable(trig)) |
| 163 | /* Missed an interrupt so launch new poll now */ | 173 | /* Missed an interrupt so launch new poll now */ |
| 164 | iio_trigger_poll(trig, 0); | 174 | iio_trigger_poll(trig, 0); |
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index efdc873e58d1..a9857022f71d 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c | |||
| @@ -117,7 +117,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) | |||
| 117 | { | 117 | { |
| 118 | struct v4l2_subdev *sd = to_sd(ctrl); | 118 | struct v4l2_subdev *sd = to_sd(ctrl); |
| 119 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 119 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 120 | int ret; | 120 | int ret = -EINVAL; |
| 121 | 121 | ||
| 122 | switch (ctrl->id) { | 122 | switch (ctrl->id) { |
| 123 | case V4L2_CID_BRIGHTNESS: | 123 | case V4L2_CID_BRIGHTNESS: |
| @@ -157,7 +157,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) | |||
| 157 | break; | 157 | break; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | return 0; | 160 | return ret; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) | 163 | static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index df4ada880e42..bd9405df1bd6 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
| @@ -1987,7 +1987,7 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids); | |||
| 1987 | 1987 | ||
| 1988 | #ifdef CONFIG_OF | 1988 | #ifdef CONFIG_OF |
| 1989 | static const struct of_device_id coda_dt_ids[] = { | 1989 | static const struct of_device_id coda_dt_ids[] = { |
| 1990 | { .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] }, | 1990 | { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, |
| 1991 | { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, | 1991 | { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, |
| 1992 | { /* sentinel */ } | 1992 | { /* sentinel */ } |
| 1993 | }; | 1993 | }; |
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 553d87e5ceab..fd6289d60cde 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c | |||
| @@ -784,6 +784,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
| 784 | } | 784 | } |
| 785 | *vfd = g2d_videodev; | 785 | *vfd = g2d_videodev; |
| 786 | vfd->lock = &dev->mutex; | 786 | vfd->lock = &dev->mutex; |
| 787 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
| 787 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | 788 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); |
| 788 | if (ret) { | 789 | if (ret) { |
| 789 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | 790 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 5296385153d5..4f6dd42c9adb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
| @@ -344,7 +344,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 344 | pix_mp->num_planes = 2; | 344 | pix_mp->num_planes = 2; |
| 345 | /* Set pixelformat to the format in which MFC | 345 | /* Set pixelformat to the format in which MFC |
| 346 | outputs the decoded frame */ | 346 | outputs the decoded frame */ |
| 347 | pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT; | 347 | pix_mp->pixelformat = ctx->dst_fmt->fourcc; |
| 348 | pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; | 348 | pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; |
| 349 | pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; | 349 | pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; |
| 350 | pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; | 350 | pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; |
| @@ -382,10 +382,16 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 382 | mfc_err("Unsupported format for source.\n"); | 382 | mfc_err("Unsupported format for source.\n"); |
| 383 | return -EINVAL; | 383 | return -EINVAL; |
| 384 | } | 384 | } |
| 385 | if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | 385 | if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) { |
| 386 | mfc_err("Not supported format.\n"); | 386 | mfc_err("Unknown codec\n"); |
| 387 | return -EINVAL; | 387 | return -EINVAL; |
| 388 | } | 388 | } |
| 389 | if (!IS_MFCV6(dev)) { | ||
| 390 | if (fmt->fourcc == V4L2_PIX_FMT_VP8) { | ||
| 391 | mfc_err("Not supported format.\n"); | ||
| 392 | return -EINVAL; | ||
| 393 | } | ||
| 394 | } | ||
| 389 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 395 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
| 390 | fmt = find_format(f, MFC_FMT_RAW); | 396 | fmt = find_format(f, MFC_FMT_RAW); |
| 391 | if (!fmt) { | 397 | if (!fmt) { |
| @@ -411,7 +417,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 411 | struct s5p_mfc_dev *dev = video_drvdata(file); | 417 | struct s5p_mfc_dev *dev = video_drvdata(file); |
| 412 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | 418 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
| 413 | int ret = 0; | 419 | int ret = 0; |
| 414 | struct s5p_mfc_fmt *fmt; | ||
| 415 | struct v4l2_pix_format_mplane *pix_mp; | 420 | struct v4l2_pix_format_mplane *pix_mp; |
| 416 | 421 | ||
| 417 | mfc_debug_enter(); | 422 | mfc_debug_enter(); |
| @@ -425,54 +430,32 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 425 | goto out; | 430 | goto out; |
| 426 | } | 431 | } |
| 427 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 432 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
| 428 | fmt = find_format(f, MFC_FMT_RAW); | 433 | /* dst_fmt is validated by call to vidioc_try_fmt */ |
| 429 | if (!fmt) { | 434 | ctx->dst_fmt = find_format(f, MFC_FMT_RAW); |
| 430 | mfc_err("Unsupported format for source.\n"); | 435 | ret = 0; |
| 431 | return -EINVAL; | ||
| 432 | } | ||
| 433 | if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | ||
| 434 | mfc_err("Not supported format.\n"); | ||
| 435 | return -EINVAL; | ||
| 436 | } else if (IS_MFCV6(dev) && | ||
| 437 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
| 438 | mfc_err("Not supported format.\n"); | ||
| 439 | return -EINVAL; | ||
| 440 | } | ||
| 441 | ctx->dst_fmt = fmt; | ||
| 442 | mfc_debug_leave(); | ||
| 443 | return ret; | ||
| 444 | } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
| 445 | mfc_err("Wrong type error for S_FMT : %d", f->type); | ||
| 446 | return -EINVAL; | ||
| 447 | } | ||
| 448 | fmt = find_format(f, MFC_FMT_DEC); | ||
| 449 | if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) { | ||
| 450 | mfc_err("Unknown codec\n"); | ||
| 451 | ret = -EINVAL; | ||
| 452 | goto out; | 436 | goto out; |
| 453 | } | 437 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| 454 | if (fmt->type != MFC_FMT_DEC) { | 438 | /* src_fmt is validated by call to vidioc_try_fmt */ |
| 455 | mfc_err("Wrong format selected, you should choose " | 439 | ctx->src_fmt = find_format(f, MFC_FMT_DEC); |
| 456 | "format for decoding\n"); | 440 | ctx->codec_mode = ctx->src_fmt->codec_mode; |
| 441 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | ||
| 442 | pix_mp->height = 0; | ||
| 443 | pix_mp->width = 0; | ||
| 444 | if (pix_mp->plane_fmt[0].sizeimage) | ||
| 445 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | ||
| 446 | else | ||
| 447 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = | ||
| 448 | DEF_CPB_SIZE; | ||
| 449 | pix_mp->plane_fmt[0].bytesperline = 0; | ||
| 450 | ctx->state = MFCINST_INIT; | ||
| 451 | ret = 0; | ||
| 452 | goto out; | ||
| 453 | } else { | ||
| 454 | mfc_err("Wrong type error for S_FMT : %d", f->type); | ||
| 457 | ret = -EINVAL; | 455 | ret = -EINVAL; |
| 458 | goto out; | 456 | goto out; |
| 459 | } | 457 | } |
| 460 | if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | 458 | |
| 461 | mfc_err("Not supported format.\n"); | ||
| 462 | return -EINVAL; | ||
| 463 | } | ||
| 464 | ctx->src_fmt = fmt; | ||
| 465 | ctx->codec_mode = fmt->codec_mode; | ||
| 466 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | ||
| 467 | pix_mp->height = 0; | ||
| 468 | pix_mp->width = 0; | ||
| 469 | if (pix_mp->plane_fmt[0].sizeimage) | ||
| 470 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | ||
| 471 | else | ||
| 472 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = | ||
| 473 | DEF_CPB_SIZE; | ||
| 474 | pix_mp->plane_fmt[0].bytesperline = 0; | ||
| 475 | ctx->state = MFCINST_INIT; | ||
| 476 | out: | 459 | out: |
| 477 | mfc_debug_leave(); | 460 | mfc_debug_leave(); |
| 478 | return ret; | 461 | return ret; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 2549967b2f85..59e56f4c8ce3 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
| @@ -906,6 +906,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 906 | 906 | ||
| 907 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | 907 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) |
| 908 | { | 908 | { |
| 909 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
| 909 | struct s5p_mfc_fmt *fmt; | 910 | struct s5p_mfc_fmt *fmt; |
| 910 | struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; | 911 | struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; |
| 911 | 912 | ||
| @@ -930,6 +931,18 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 930 | return -EINVAL; | 931 | return -EINVAL; |
| 931 | } | 932 | } |
| 932 | 933 | ||
| 934 | if (!IS_MFCV6(dev)) { | ||
| 935 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { | ||
| 936 | mfc_err("Not supported format.\n"); | ||
| 937 | return -EINVAL; | ||
| 938 | } | ||
| 939 | } else if (IS_MFCV6(dev)) { | ||
| 940 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | ||
| 941 | mfc_err("Not supported format.\n"); | ||
| 942 | return -EINVAL; | ||
| 943 | } | ||
| 944 | } | ||
| 945 | |||
| 933 | if (fmt->num_planes != pix_fmt_mp->num_planes) { | 946 | if (fmt->num_planes != pix_fmt_mp->num_planes) { |
| 934 | mfc_err("failed to try output format\n"); | 947 | mfc_err("failed to try output format\n"); |
| 935 | return -EINVAL; | 948 | return -EINVAL; |
| @@ -947,7 +960,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 947 | { | 960 | { |
| 948 | struct s5p_mfc_dev *dev = video_drvdata(file); | 961 | struct s5p_mfc_dev *dev = video_drvdata(file); |
| 949 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | 962 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
| 950 | struct s5p_mfc_fmt *fmt; | ||
| 951 | struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; | 963 | struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; |
| 952 | int ret = 0; | 964 | int ret = 0; |
| 953 | 965 | ||
| @@ -960,13 +972,9 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 960 | goto out; | 972 | goto out; |
| 961 | } | 973 | } |
| 962 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | 974 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
| 963 | fmt = find_format(f, MFC_FMT_ENC); | 975 | /* dst_fmt is validated by call to vidioc_try_fmt */ |
| 964 | if (!fmt) { | 976 | ctx->dst_fmt = find_format(f, MFC_FMT_ENC); |
| 965 | mfc_err("failed to set capture format\n"); | ||
| 966 | return -EINVAL; | ||
| 967 | } | ||
| 968 | ctx->state = MFCINST_INIT; | 977 | ctx->state = MFCINST_INIT; |
| 969 | ctx->dst_fmt = fmt; | ||
| 970 | ctx->codec_mode = ctx->dst_fmt->codec_mode; | 978 | ctx->codec_mode = ctx->dst_fmt->codec_mode; |
| 971 | ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage; | 979 | ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage; |
| 972 | pix_fmt_mp->plane_fmt[0].bytesperline = 0; | 980 | pix_fmt_mp->plane_fmt[0].bytesperline = 0; |
| @@ -987,28 +995,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 987 | } | 995 | } |
| 988 | mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | 996 | mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); |
| 989 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | 997 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| 990 | fmt = find_format(f, MFC_FMT_RAW); | 998 | /* src_fmt is validated by call to vidioc_try_fmt */ |
| 991 | if (!fmt) { | 999 | ctx->src_fmt = find_format(f, MFC_FMT_RAW); |
| 992 | mfc_err("failed to set output format\n"); | ||
| 993 | return -EINVAL; | ||
| 994 | } | ||
| 995 | |||
| 996 | if (!IS_MFCV6(dev) && | ||
| 997 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) { | ||
| 998 | mfc_err("Not supported format.\n"); | ||
| 999 | return -EINVAL; | ||
| 1000 | } else if (IS_MFCV6(dev) && | ||
| 1001 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
| 1002 | mfc_err("Not supported format.\n"); | ||
| 1003 | return -EINVAL; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | if (fmt->num_planes != pix_fmt_mp->num_planes) { | ||
| 1007 | mfc_err("failed to set output format\n"); | ||
| 1008 | ret = -EINVAL; | ||
| 1009 | goto out; | ||
| 1010 | } | ||
| 1011 | ctx->src_fmt = fmt; | ||
| 1012 | ctx->img_width = pix_fmt_mp->width; | 1000 | ctx->img_width = pix_fmt_mp->width; |
| 1013 | ctx->img_height = pix_fmt_mp->height; | 1001 | ctx->img_height = pix_fmt_mp->height; |
| 1014 | mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode); | 1002 | mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode); |
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 4851cc2e4a4d..c4ff9739a7ae 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c | |||
| @@ -726,7 +726,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus, | |||
| 726 | 726 | ||
| 727 | *eedata = data; | 727 | *eedata = data; |
| 728 | *eedata_len = len; | 728 | *eedata_len = len; |
| 729 | dev_config = (void *)eedata; | 729 | dev_config = (void *)*eedata; |
| 730 | 730 | ||
| 731 | switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) { | 731 | switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) { |
| 732 | case 0: | 732 | case 0: |
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index cb694055ba7d..6e5070774dc2 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c | |||
| @@ -303,6 +303,11 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
| 303 | 303 | ||
| 304 | dev->workqueue = 0; | 304 | dev->workqueue = 0; |
| 305 | 305 | ||
| 306 | /* init video transfer queues first of all */ | ||
| 307 | /* to prevent oops in hdpvr_delete() on error paths */ | ||
| 308 | INIT_LIST_HEAD(&dev->free_buff_list); | ||
| 309 | INIT_LIST_HEAD(&dev->rec_buff_list); | ||
| 310 | |||
| 306 | /* register v4l2_device early so it can be used for printks */ | 311 | /* register v4l2_device early so it can be used for printks */ |
| 307 | if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { | 312 | if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { |
| 308 | dev_err(&interface->dev, "v4l2_device_register failed\n"); | 313 | dev_err(&interface->dev, "v4l2_device_register failed\n"); |
| @@ -325,10 +330,6 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
| 325 | if (!dev->workqueue) | 330 | if (!dev->workqueue) |
| 326 | goto error; | 331 | goto error; |
| 327 | 332 | ||
| 328 | /* init video transfer queues */ | ||
| 329 | INIT_LIST_HEAD(&dev->free_buff_list); | ||
| 330 | INIT_LIST_HEAD(&dev->rec_buff_list); | ||
| 331 | |||
| 332 | dev->options = hdpvr_default_options; | 333 | dev->options = hdpvr_default_options; |
| 333 | 334 | ||
| 334 | if (default_video_input < HDPVR_VIDEO_INPUTS) | 335 | if (default_video_input < HDPVR_VIDEO_INPUTS) |
| @@ -405,7 +406,7 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
| 405 | video_nr[atomic_inc_return(&dev_nr)]); | 406 | video_nr[atomic_inc_return(&dev_nr)]); |
| 406 | if (retval < 0) { | 407 | if (retval < 0) { |
| 407 | v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); | 408 | v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); |
| 408 | goto error; | 409 | goto reg_fail; |
| 409 | } | 410 | } |
| 410 | 411 | ||
| 411 | /* let the user know what node this device is now attached to */ | 412 | /* let the user know what node this device is now attached to */ |
diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig index 8864436464bf..7c5b86006ee6 100644 --- a/drivers/media/usb/usbtv/Kconfig +++ b/drivers/media/usb/usbtv/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config VIDEO_USBTV | 1 | config VIDEO_USBTV |
| 2 | tristate "USBTV007 video capture support" | 2 | tristate "USBTV007 video capture support" |
| 3 | depends on VIDEO_DEV | 3 | depends on VIDEO_V4L2 |
| 4 | select VIDEOBUF2_VMALLOC | 4 | select VIDEOBUF2_VMALLOC |
| 5 | 5 | ||
| 6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index bf43f874685e..91650173941a 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | #define USBTV_CHUNK_SIZE 256 | 57 | #define USBTV_CHUNK_SIZE 256 |
| 58 | #define USBTV_CHUNK 240 | 58 | #define USBTV_CHUNK 240 |
| 59 | #define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ | 59 | #define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ |
| 60 | / 2 / USBTV_CHUNK) | 60 | / 4 / USBTV_CHUNK) |
| 61 | 61 | ||
| 62 | /* Chunk header. */ | 62 | /* Chunk header. */ |
| 63 | #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ | 63 | #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ |
| @@ -89,6 +89,7 @@ struct usbtv { | |||
| 89 | /* Number of currently processed frame, useful find | 89 | /* Number of currently processed frame, useful find |
| 90 | * out when a new one begins. */ | 90 | * out when a new one begins. */ |
| 91 | u32 frame_id; | 91 | u32 frame_id; |
| 92 | int chunks_done; | ||
| 92 | 93 | ||
| 93 | int iso_size; | 94 | int iso_size; |
| 94 | unsigned int sequence; | 95 | unsigned int sequence; |
| @@ -202,6 +203,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv) | |||
| 202 | return 0; | 203 | return 0; |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 206 | /* Copy data from chunk into a frame buffer, deinterlacing the data | ||
| 207 | * into every second line. Unfortunately, they don't align nicely into | ||
| 208 | * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels. | ||
| 209 | * Therefore, we break down the chunk into two halves before copyting, | ||
| 210 | * so that we can interleave a line if needed. */ | ||
| 211 | static void usbtv_chunk_to_vbuf(u32 *frame, u32 *src, int chunk_no, int odd) | ||
| 212 | { | ||
| 213 | int half; | ||
| 214 | |||
| 215 | for (half = 0; half < 2; half++) { | ||
| 216 | int part_no = chunk_no * 2 + half; | ||
| 217 | int line = part_no / 3; | ||
| 218 | int part_index = (line * 2 + !odd) * 3 + (part_no % 3); | ||
| 219 | |||
| 220 | u32 *dst = &frame[part_index * USBTV_CHUNK/2]; | ||
| 221 | memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src)); | ||
| 222 | src += USBTV_CHUNK/2; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 205 | /* Called for each 256-byte image chunk. | 226 | /* Called for each 256-byte image chunk. |
| 206 | * First word identifies the chunk, followed by 240 words of image | 227 | * First word identifies the chunk, followed by 240 words of image |
| 207 | * data and padding. */ | 228 | * data and padding. */ |
| @@ -218,17 +239,17 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
| 218 | frame_id = USBTV_FRAME_ID(chunk); | 239 | frame_id = USBTV_FRAME_ID(chunk); |
| 219 | odd = USBTV_ODD(chunk); | 240 | odd = USBTV_ODD(chunk); |
| 220 | chunk_no = USBTV_CHUNK_NO(chunk); | 241 | chunk_no = USBTV_CHUNK_NO(chunk); |
| 221 | |||
| 222 | /* Deinterlace. TODO: Use interlaced frame format. */ | ||
| 223 | chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3; | ||
| 224 | chunk_no += !odd * 3; | ||
| 225 | |||
| 226 | if (chunk_no >= USBTV_CHUNKS) | 242 | if (chunk_no >= USBTV_CHUNKS) |
| 227 | return; | 243 | return; |
| 228 | 244 | ||
| 229 | /* Beginning of a frame. */ | 245 | /* Beginning of a frame. */ |
| 230 | if (chunk_no == 0) | 246 | if (chunk_no == 0) { |
| 231 | usbtv->frame_id = frame_id; | 247 | usbtv->frame_id = frame_id; |
| 248 | usbtv->chunks_done = 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (usbtv->frame_id != frame_id) | ||
| 252 | return; | ||
| 232 | 253 | ||
| 233 | spin_lock_irqsave(&usbtv->buflock, flags); | 254 | spin_lock_irqsave(&usbtv->buflock, flags); |
| 234 | if (list_empty(&usbtv->bufs)) { | 255 | if (list_empty(&usbtv->bufs)) { |
| @@ -241,19 +262,23 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
| 241 | buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); | 262 | buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); |
| 242 | frame = vb2_plane_vaddr(&buf->vb, 0); | 263 | frame = vb2_plane_vaddr(&buf->vb, 0); |
| 243 | 264 | ||
| 244 | /* Copy the chunk. */ | 265 | /* Copy the chunk data. */ |
| 245 | memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], | 266 | usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); |
| 246 | USBTV_CHUNK * sizeof(chunk[1])); | 267 | usbtv->chunks_done++; |
| 247 | 268 | ||
| 248 | /* Last chunk in a frame, signalling an end */ | 269 | /* Last chunk in a frame, signalling an end */ |
| 249 | if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) { | 270 | if (odd && chunk_no == USBTV_CHUNKS-1) { |
| 250 | int size = vb2_plane_size(&buf->vb, 0); | 271 | int size = vb2_plane_size(&buf->vb, 0); |
| 272 | enum vb2_buffer_state state = usbtv->chunks_done == | ||
| 273 | USBTV_CHUNKS ? | ||
| 274 | VB2_BUF_STATE_DONE : | ||
| 275 | VB2_BUF_STATE_ERROR; | ||
| 251 | 276 | ||
| 252 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; | 277 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
| 253 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; | 278 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; |
| 254 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); | 279 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
| 255 | vb2_set_plane_payload(&buf->vb, 0, size); | 280 | vb2_set_plane_payload(&buf->vb, 0, size); |
| 256 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); | 281 | vb2_buffer_done(&buf->vb, state); |
| 257 | list_del(&buf->list); | 282 | list_del(&buf->list); |
| 258 | } | 283 | } |
| 259 | 284 | ||
| @@ -518,7 +543,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq, | |||
| 518 | if (*nbuffers < 2) | 543 | if (*nbuffers < 2) |
| 519 | *nbuffers = 2; | 544 | *nbuffers = 2; |
| 520 | *nplanes = 1; | 545 | *nplanes = 1; |
| 521 | sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); | 546 | sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); |
| 522 | 547 | ||
| 523 | return 0; | 548 | return 0; |
| 524 | } | 549 | } |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 07f257d44a1e..e48cb339c0c6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -3714,11 +3714,17 @@ static int bond_neigh_init(struct neighbour *n) | |||
| 3714 | * The bonding ndo_neigh_setup is called at init time beofre any | 3714 | * The bonding ndo_neigh_setup is called at init time beofre any |
| 3715 | * slave exists. So we must declare proxy setup function which will | 3715 | * slave exists. So we must declare proxy setup function which will |
| 3716 | * be used at run time to resolve the actual slave neigh param setup. | 3716 | * be used at run time to resolve the actual slave neigh param setup. |
| 3717 | * | ||
| 3718 | * It's also called by master devices (such as vlans) to setup their | ||
| 3719 | * underlying devices. In that case - do nothing, we're already set up from | ||
| 3720 | * our init. | ||
| 3717 | */ | 3721 | */ |
| 3718 | static int bond_neigh_setup(struct net_device *dev, | 3722 | static int bond_neigh_setup(struct net_device *dev, |
| 3719 | struct neigh_parms *parms) | 3723 | struct neigh_parms *parms) |
| 3720 | { | 3724 | { |
| 3721 | parms->neigh_setup = bond_neigh_init; | 3725 | /* modify only our neigh_parms */ |
| 3726 | if (parms->dev == dev) | ||
| 3727 | parms->neigh_setup = bond_neigh_init; | ||
| 3722 | 3728 | ||
| 3723 | return 0; | 3729 | return 0; |
| 3724 | } | 3730 | } |
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 25723d8ee201..925ab8ec9329 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c | |||
| @@ -649,7 +649,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) | |||
| 649 | if ((mc->ptr + rec_len) > mc->end) | 649 | if ((mc->ptr + rec_len) > mc->end) |
| 650 | goto decode_failed; | 650 | goto decode_failed; |
| 651 | 651 | ||
| 652 | memcpy(cf->data, mc->ptr, rec_len); | 652 | memcpy(cf->data, mc->ptr, cf->can_dlc); |
| 653 | mc->ptr += rec_len; | 653 | mc->ptr += rec_len; |
| 654 | } | 654 | } |
| 655 | 655 | ||
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index f1b121ee5525..55d79cb53a79 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c | |||
| @@ -199,7 +199,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget) | |||
| 199 | struct arc_emac_priv *priv = netdev_priv(ndev); | 199 | struct arc_emac_priv *priv = netdev_priv(ndev); |
| 200 | unsigned int work_done; | 200 | unsigned int work_done; |
| 201 | 201 | ||
| 202 | for (work_done = 0; work_done <= budget; work_done++) { | 202 | for (work_done = 0; work_done < budget; work_done++) { |
| 203 | unsigned int *last_rx_bd = &priv->last_rx_bd; | 203 | unsigned int *last_rx_bd = &priv->last_rx_bd; |
| 204 | struct net_device_stats *stats = &priv->stats; | 204 | struct net_device_stats *stats = &priv->stats; |
| 205 | struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd]; | 205 | struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd]; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index d80e34b8285f..ce9b387b5a19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
| @@ -1502,6 +1502,7 @@ struct bnx2x { | |||
| 1502 | #define BC_SUPPORTS_DCBX_MSG_NON_PMF (1 << 21) | 1502 | #define BC_SUPPORTS_DCBX_MSG_NON_PMF (1 << 21) |
| 1503 | #define IS_VF_FLAG (1 << 22) | 1503 | #define IS_VF_FLAG (1 << 22) |
| 1504 | #define INTERRUPTS_ENABLED_FLAG (1 << 23) | 1504 | #define INTERRUPTS_ENABLED_FLAG (1 << 23) |
| 1505 | #define BC_SUPPORTS_RMMOD_CMD (1 << 24) | ||
| 1505 | 1506 | ||
| 1506 | #define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG) | 1507 | #define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG) |
| 1507 | 1508 | ||
| @@ -1830,6 +1831,8 @@ struct bnx2x { | |||
| 1830 | 1831 | ||
| 1831 | int fp_array_size; | 1832 | int fp_array_size; |
| 1832 | u32 dump_preset_idx; | 1833 | u32 dump_preset_idx; |
| 1834 | bool stats_started; | ||
| 1835 | struct semaphore stats_sema; | ||
| 1833 | }; | 1836 | }; |
| 1834 | 1837 | ||
| 1835 | /* Tx queues may be less or equal to Rx queues */ | 1838 | /* Tx queues may be less or equal to Rx queues */ |
| @@ -2451,4 +2454,6 @@ enum bnx2x_pci_bus_speed { | |||
| 2451 | BNX2X_PCI_LINK_SPEED_5000 = 5000, | 2454 | BNX2X_PCI_LINK_SPEED_5000 = 5000, |
| 2452 | BNX2X_PCI_LINK_SPEED_8000 = 8000 | 2455 | BNX2X_PCI_LINK_SPEED_8000 = 8000 |
| 2453 | }; | 2456 | }; |
| 2457 | |||
| 2458 | void bnx2x_set_local_cmng(struct bnx2x *bp); | ||
| 2454 | #endif /* bnx2x.h */ | 2459 | #endif /* bnx2x.h */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 0c94df47e0e8..f9122f2d6b65 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | |||
| @@ -753,6 +753,10 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) | |||
| 753 | bnx2x_pfc_set_pfc(bp); | 753 | bnx2x_pfc_set_pfc(bp); |
| 754 | 754 | ||
| 755 | bnx2x_dcbx_update_ets_params(bp); | 755 | bnx2x_dcbx_update_ets_params(bp); |
| 756 | |||
| 757 | /* ets may affect cmng configuration: reinit it in hw */ | ||
| 758 | bnx2x_set_local_cmng(bp); | ||
| 759 | |||
| 756 | bnx2x_dcbx_resume_hw_tx(bp); | 760 | bnx2x_dcbx_resume_hw_tx(bp); |
| 757 | 761 | ||
| 758 | return; | 762 | return; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 5018e52ae2ad..32767f6aa33f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | |||
| @@ -1300,6 +1300,9 @@ struct drv_func_mb { | |||
| 1300 | 1300 | ||
| 1301 | #define DRV_MSG_CODE_EEE_RESULTS_ACK 0xda000000 | 1301 | #define DRV_MSG_CODE_EEE_RESULTS_ACK 0xda000000 |
| 1302 | 1302 | ||
| 1303 | #define DRV_MSG_CODE_RMMOD 0xdb000000 | ||
| 1304 | #define REQ_BC_VER_4_RMMOD_CMD 0x0007080f | ||
| 1305 | |||
| 1303 | #define DRV_MSG_CODE_SET_MF_BW 0xe0000000 | 1306 | #define DRV_MSG_CODE_SET_MF_BW 0xe0000000 |
| 1304 | #define REQ_BC_VER_4_SET_MF_BW 0x00060202 | 1307 | #define REQ_BC_VER_4_SET_MF_BW 0x00060202 |
| 1305 | #define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000 | 1308 | #define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000 |
| @@ -1372,6 +1375,8 @@ struct drv_func_mb { | |||
| 1372 | 1375 | ||
| 1373 | #define FW_MSG_CODE_EEE_RESULS_ACK 0xda100000 | 1376 | #define FW_MSG_CODE_EEE_RESULS_ACK 0xda100000 |
| 1374 | 1377 | ||
| 1378 | #define FW_MSG_CODE_RMMOD_ACK 0xdb100000 | ||
| 1379 | |||
| 1375 | #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000 | 1380 | #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000 |
| 1376 | #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000 | 1381 | #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000 |
| 1377 | 1382 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index e06186c305d8..955d6cfd9cb7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
| @@ -2476,7 +2476,7 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) | |||
| 2476 | 2476 | ||
| 2477 | input.port_rate = bp->link_vars.line_speed; | 2477 | input.port_rate = bp->link_vars.line_speed; |
| 2478 | 2478 | ||
| 2479 | if (cmng_type == CMNG_FNS_MINMAX) { | 2479 | if (cmng_type == CMNG_FNS_MINMAX && input.port_rate) { |
| 2480 | int vn; | 2480 | int vn; |
| 2481 | 2481 | ||
| 2482 | /* read mf conf from shmem */ | 2482 | /* read mf conf from shmem */ |
| @@ -2533,6 +2533,21 @@ static void storm_memset_cmng(struct bnx2x *bp, | |||
| 2533 | } | 2533 | } |
| 2534 | } | 2534 | } |
| 2535 | 2535 | ||
| 2536 | /* init cmng mode in HW according to local configuration */ | ||
| 2537 | void bnx2x_set_local_cmng(struct bnx2x *bp) | ||
| 2538 | { | ||
| 2539 | int cmng_fns = bnx2x_get_cmng_fns_mode(bp); | ||
| 2540 | |||
| 2541 | if (cmng_fns != CMNG_FNS_NONE) { | ||
| 2542 | bnx2x_cmng_fns_init(bp, false, cmng_fns); | ||
| 2543 | storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp)); | ||
| 2544 | } else { | ||
| 2545 | /* rate shaping and fairness are disabled */ | ||
| 2546 | DP(NETIF_MSG_IFUP, | ||
| 2547 | "single function mode without fairness\n"); | ||
| 2548 | } | ||
| 2549 | } | ||
| 2550 | |||
| 2536 | /* This function is called upon link interrupt */ | 2551 | /* This function is called upon link interrupt */ |
| 2537 | static void bnx2x_link_attn(struct bnx2x *bp) | 2552 | static void bnx2x_link_attn(struct bnx2x *bp) |
| 2538 | { | 2553 | { |
| @@ -2568,17 +2583,8 @@ static void bnx2x_link_attn(struct bnx2x *bp) | |||
| 2568 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); | 2583 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); |
| 2569 | } | 2584 | } |
| 2570 | 2585 | ||
| 2571 | if (bp->link_vars.link_up && bp->link_vars.line_speed) { | 2586 | if (bp->link_vars.link_up && bp->link_vars.line_speed) |
| 2572 | int cmng_fns = bnx2x_get_cmng_fns_mode(bp); | 2587 | bnx2x_set_local_cmng(bp); |
| 2573 | |||
| 2574 | if (cmng_fns != CMNG_FNS_NONE) { | ||
| 2575 | bnx2x_cmng_fns_init(bp, false, cmng_fns); | ||
| 2576 | storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp)); | ||
| 2577 | } else | ||
| 2578 | /* rate shaping and fairness are disabled */ | ||
| 2579 | DP(NETIF_MSG_IFUP, | ||
| 2580 | "single function mode without fairness\n"); | ||
| 2581 | } | ||
| 2582 | 2588 | ||
| 2583 | __bnx2x_link_report(bp); | 2589 | __bnx2x_link_report(bp); |
| 2584 | 2590 | ||
| @@ -10362,6 +10368,10 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp) | |||
| 10362 | 10368 | ||
| 10363 | bp->flags |= (val >= REQ_BC_VER_4_DCBX_ADMIN_MSG_NON_PMF) ? | 10369 | bp->flags |= (val >= REQ_BC_VER_4_DCBX_ADMIN_MSG_NON_PMF) ? |
| 10364 | BC_SUPPORTS_DCBX_MSG_NON_PMF : 0; | 10370 | BC_SUPPORTS_DCBX_MSG_NON_PMF : 0; |
| 10371 | |||
| 10372 | bp->flags |= (val >= REQ_BC_VER_4_RMMOD_CMD) ? | ||
| 10373 | BC_SUPPORTS_RMMOD_CMD : 0; | ||
| 10374 | |||
| 10365 | boot_mode = SHMEM_RD(bp, | 10375 | boot_mode = SHMEM_RD(bp, |
| 10366 | dev_info.port_feature_config[BP_PORT(bp)].mba_config) & | 10376 | dev_info.port_feature_config[BP_PORT(bp)].mba_config) & |
| 10367 | PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK; | 10377 | PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK; |
| @@ -11524,6 +11534,7 @@ static int bnx2x_init_bp(struct bnx2x *bp) | |||
| 11524 | mutex_init(&bp->port.phy_mutex); | 11534 | mutex_init(&bp->port.phy_mutex); |
| 11525 | mutex_init(&bp->fw_mb_mutex); | 11535 | mutex_init(&bp->fw_mb_mutex); |
| 11526 | spin_lock_init(&bp->stats_lock); | 11536 | spin_lock_init(&bp->stats_lock); |
| 11537 | sema_init(&bp->stats_sema, 1); | ||
| 11527 | 11538 | ||
| 11528 | INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); | 11539 | INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); |
| 11529 | INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); | 11540 | INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); |
| @@ -12817,13 +12828,17 @@ static void __bnx2x_remove(struct pci_dev *pdev, | |||
| 12817 | bnx2x_dcbnl_update_applist(bp, true); | 12828 | bnx2x_dcbnl_update_applist(bp, true); |
| 12818 | #endif | 12829 | #endif |
| 12819 | 12830 | ||
| 12831 | if (IS_PF(bp) && | ||
| 12832 | !BP_NOMCP(bp) && | ||
| 12833 | (bp->flags & BC_SUPPORTS_RMMOD_CMD)) | ||
| 12834 | bnx2x_fw_command(bp, DRV_MSG_CODE_RMMOD, 0); | ||
| 12835 | |||
| 12820 | /* Close the interface - either directly or implicitly */ | 12836 | /* Close the interface - either directly or implicitly */ |
| 12821 | if (remove_netdev) { | 12837 | if (remove_netdev) { |
| 12822 | unregister_netdev(dev); | 12838 | unregister_netdev(dev); |
| 12823 | } else { | 12839 | } else { |
| 12824 | rtnl_lock(); | 12840 | rtnl_lock(); |
| 12825 | if (netif_running(dev)) | 12841 | dev_close(dev); |
| 12826 | bnx2x_close(dev); | ||
| 12827 | rtnl_unlock(); | 12842 | rtnl_unlock(); |
| 12828 | } | 12843 | } |
| 12829 | 12844 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 95861efb5051..44104fb27947 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
| @@ -3463,7 +3463,7 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp) | |||
| 3463 | alloc_mem_err: | 3463 | alloc_mem_err: |
| 3464 | BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, | 3464 | BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, |
| 3465 | sizeof(struct bnx2x_vf_mbx_msg)); | 3465 | sizeof(struct bnx2x_vf_mbx_msg)); |
| 3466 | BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, | 3466 | BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, |
| 3467 | sizeof(union pf_vf_bulletin)); | 3467 | sizeof(union pf_vf_bulletin)); |
| 3468 | return -ENOMEM; | 3468 | return -ENOMEM; |
| 3469 | } | 3469 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 98366abd02bd..d63d1327b051 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | |||
| @@ -221,7 +221,8 @@ static int bnx2x_stats_comp(struct bnx2x *bp) | |||
| 221 | * Statistics service functions | 221 | * Statistics service functions |
| 222 | */ | 222 | */ |
| 223 | 223 | ||
| 224 | static void bnx2x_stats_pmf_update(struct bnx2x *bp) | 224 | /* should be called under stats_sema */ |
| 225 | static void __bnx2x_stats_pmf_update(struct bnx2x *bp) | ||
| 225 | { | 226 | { |
| 226 | struct dmae_command *dmae; | 227 | struct dmae_command *dmae; |
| 227 | u32 opcode; | 228 | u32 opcode; |
| @@ -518,7 +519,8 @@ static void bnx2x_func_stats_init(struct bnx2x *bp) | |||
| 518 | *stats_comp = 0; | 519 | *stats_comp = 0; |
| 519 | } | 520 | } |
| 520 | 521 | ||
| 521 | static void bnx2x_stats_start(struct bnx2x *bp) | 522 | /* should be called under stats_sema */ |
| 523 | static void __bnx2x_stats_start(struct bnx2x *bp) | ||
| 522 | { | 524 | { |
| 523 | /* vfs travel through here as part of the statistics FSM, but no action | 525 | /* vfs travel through here as part of the statistics FSM, but no action |
| 524 | * is required | 526 | * is required |
| @@ -534,13 +536,34 @@ static void bnx2x_stats_start(struct bnx2x *bp) | |||
| 534 | 536 | ||
| 535 | bnx2x_hw_stats_post(bp); | 537 | bnx2x_hw_stats_post(bp); |
| 536 | bnx2x_storm_stats_post(bp); | 538 | bnx2x_storm_stats_post(bp); |
| 539 | |||
| 540 | bp->stats_started = true; | ||
| 541 | } | ||
| 542 | |||
| 543 | static void bnx2x_stats_start(struct bnx2x *bp) | ||
| 544 | { | ||
| 545 | if (down_timeout(&bp->stats_sema, HZ/10)) | ||
| 546 | BNX2X_ERR("Unable to acquire stats lock\n"); | ||
| 547 | __bnx2x_stats_start(bp); | ||
| 548 | up(&bp->stats_sema); | ||
| 537 | } | 549 | } |
| 538 | 550 | ||
| 539 | static void bnx2x_stats_pmf_start(struct bnx2x *bp) | 551 | static void bnx2x_stats_pmf_start(struct bnx2x *bp) |
| 540 | { | 552 | { |
| 553 | if (down_timeout(&bp->stats_sema, HZ/10)) | ||
| 554 | BNX2X_ERR("Unable to acquire stats lock\n"); | ||
| 541 | bnx2x_stats_comp(bp); | 555 | bnx2x_stats_comp(bp); |
| 542 | bnx2x_stats_pmf_update(bp); | 556 | __bnx2x_stats_pmf_update(bp); |
| 543 | bnx2x_stats_start(bp); | 557 | __bnx2x_stats_start(bp); |
| 558 | up(&bp->stats_sema); | ||
| 559 | } | ||
| 560 | |||
| 561 | static void bnx2x_stats_pmf_update(struct bnx2x *bp) | ||
| 562 | { | ||
| 563 | if (down_timeout(&bp->stats_sema, HZ/10)) | ||
| 564 | BNX2X_ERR("Unable to acquire stats lock\n"); | ||
| 565 | __bnx2x_stats_pmf_update(bp); | ||
| 566 | up(&bp->stats_sema); | ||
| 544 | } | 567 | } |
| 545 | 568 | ||
| 546 | static void bnx2x_stats_restart(struct bnx2x *bp) | 569 | static void bnx2x_stats_restart(struct bnx2x *bp) |
| @@ -550,8 +573,11 @@ static void bnx2x_stats_restart(struct bnx2x *bp) | |||
| 550 | */ | 573 | */ |
| 551 | if (IS_VF(bp)) | 574 | if (IS_VF(bp)) |
| 552 | return; | 575 | return; |
| 576 | if (down_timeout(&bp->stats_sema, HZ/10)) | ||
| 577 | BNX2X_ERR("Unable to acquire stats lock\n"); | ||
| 553 | bnx2x_stats_comp(bp); | 578 | bnx2x_stats_comp(bp); |
| 554 | bnx2x_stats_start(bp); | 579 | __bnx2x_stats_start(bp); |
| 580 | up(&bp->stats_sema); | ||
| 555 | } | 581 | } |
| 556 | 582 | ||
| 557 | static void bnx2x_bmac_stats_update(struct bnx2x *bp) | 583 | static void bnx2x_bmac_stats_update(struct bnx2x *bp) |
| @@ -888,9 +914,7 @@ static int bnx2x_storm_stats_validate_counters(struct bnx2x *bp) | |||
| 888 | /* Make sure we use the value of the counter | 914 | /* Make sure we use the value of the counter |
| 889 | * used for sending the last stats ramrod. | 915 | * used for sending the last stats ramrod. |
| 890 | */ | 916 | */ |
| 891 | spin_lock_bh(&bp->stats_lock); | ||
| 892 | cur_stats_counter = bp->stats_counter - 1; | 917 | cur_stats_counter = bp->stats_counter - 1; |
| 893 | spin_unlock_bh(&bp->stats_lock); | ||
| 894 | 918 | ||
| 895 | /* are storm stats valid? */ | 919 | /* are storm stats valid? */ |
| 896 | if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) { | 920 | if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) { |
| @@ -1227,12 +1251,18 @@ static void bnx2x_stats_update(struct bnx2x *bp) | |||
| 1227 | { | 1251 | { |
| 1228 | u32 *stats_comp = bnx2x_sp(bp, stats_comp); | 1252 | u32 *stats_comp = bnx2x_sp(bp, stats_comp); |
| 1229 | 1253 | ||
| 1230 | if (bnx2x_edebug_stats_stopped(bp)) | 1254 | /* we run update from timer context, so give up |
| 1255 | * if somebody is in the middle of transition | ||
| 1256 | */ | ||
| 1257 | if (down_trylock(&bp->stats_sema)) | ||
| 1231 | return; | 1258 | return; |
| 1232 | 1259 | ||
| 1260 | if (bnx2x_edebug_stats_stopped(bp) || !bp->stats_started) | ||
| 1261 | goto out; | ||
| 1262 | |||
| 1233 | if (IS_PF(bp)) { | 1263 | if (IS_PF(bp)) { |
| 1234 | if (*stats_comp != DMAE_COMP_VAL) | 1264 | if (*stats_comp != DMAE_COMP_VAL) |
| 1235 | return; | 1265 | goto out; |
| 1236 | 1266 | ||
| 1237 | if (bp->port.pmf) | 1267 | if (bp->port.pmf) |
| 1238 | bnx2x_hw_stats_update(bp); | 1268 | bnx2x_hw_stats_update(bp); |
| @@ -1242,7 +1272,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) | |||
| 1242 | BNX2X_ERR("storm stats were not updated for 3 times\n"); | 1272 | BNX2X_ERR("storm stats were not updated for 3 times\n"); |
| 1243 | bnx2x_panic(); | 1273 | bnx2x_panic(); |
| 1244 | } | 1274 | } |
| 1245 | return; | 1275 | goto out; |
| 1246 | } | 1276 | } |
| 1247 | } else { | 1277 | } else { |
| 1248 | /* vf doesn't collect HW statistics, and doesn't get completions | 1278 | /* vf doesn't collect HW statistics, and doesn't get completions |
| @@ -1256,7 +1286,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) | |||
| 1256 | 1286 | ||
| 1257 | /* vf is done */ | 1287 | /* vf is done */ |
| 1258 | if (IS_VF(bp)) | 1288 | if (IS_VF(bp)) |
| 1259 | return; | 1289 | goto out; |
| 1260 | 1290 | ||
| 1261 | if (netif_msg_timer(bp)) { | 1291 | if (netif_msg_timer(bp)) { |
| 1262 | struct bnx2x_eth_stats *estats = &bp->eth_stats; | 1292 | struct bnx2x_eth_stats *estats = &bp->eth_stats; |
| @@ -1267,6 +1297,9 @@ static void bnx2x_stats_update(struct bnx2x *bp) | |||
| 1267 | 1297 | ||
| 1268 | bnx2x_hw_stats_post(bp); | 1298 | bnx2x_hw_stats_post(bp); |
| 1269 | bnx2x_storm_stats_post(bp); | 1299 | bnx2x_storm_stats_post(bp); |
| 1300 | |||
| 1301 | out: | ||
| 1302 | up(&bp->stats_sema); | ||
| 1270 | } | 1303 | } |
| 1271 | 1304 | ||
| 1272 | static void bnx2x_port_stats_stop(struct bnx2x *bp) | 1305 | static void bnx2x_port_stats_stop(struct bnx2x *bp) |
| @@ -1332,6 +1365,11 @@ static void bnx2x_stats_stop(struct bnx2x *bp) | |||
| 1332 | { | 1365 | { |
| 1333 | int update = 0; | 1366 | int update = 0; |
| 1334 | 1367 | ||
| 1368 | if (down_timeout(&bp->stats_sema, HZ/10)) | ||
| 1369 | BNX2X_ERR("Unable to acquire stats lock\n"); | ||
| 1370 | |||
| 1371 | bp->stats_started = false; | ||
| 1372 | |||
| 1335 | bnx2x_stats_comp(bp); | 1373 | bnx2x_stats_comp(bp); |
| 1336 | 1374 | ||
| 1337 | if (bp->port.pmf) | 1375 | if (bp->port.pmf) |
| @@ -1348,6 +1386,8 @@ static void bnx2x_stats_stop(struct bnx2x *bp) | |||
| 1348 | bnx2x_hw_stats_post(bp); | 1386 | bnx2x_hw_stats_post(bp); |
| 1349 | bnx2x_stats_comp(bp); | 1387 | bnx2x_stats_comp(bp); |
| 1350 | } | 1388 | } |
| 1389 | |||
| 1390 | up(&bp->stats_sema); | ||
| 1351 | } | 1391 | } |
| 1352 | 1392 | ||
| 1353 | static void bnx2x_stats_do_nothing(struct bnx2x *bp) | 1393 | static void bnx2x_stats_do_nothing(struct bnx2x *bp) |
| @@ -1376,15 +1416,17 @@ static const struct { | |||
| 1376 | void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) | 1416 | void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) |
| 1377 | { | 1417 | { |
| 1378 | enum bnx2x_stats_state state; | 1418 | enum bnx2x_stats_state state; |
| 1419 | void (*action)(struct bnx2x *bp); | ||
| 1379 | if (unlikely(bp->panic)) | 1420 | if (unlikely(bp->panic)) |
| 1380 | return; | 1421 | return; |
| 1381 | 1422 | ||
| 1382 | spin_lock_bh(&bp->stats_lock); | 1423 | spin_lock_bh(&bp->stats_lock); |
| 1383 | state = bp->stats_state; | 1424 | state = bp->stats_state; |
| 1384 | bp->stats_state = bnx2x_stats_stm[state][event].next_state; | 1425 | bp->stats_state = bnx2x_stats_stm[state][event].next_state; |
| 1426 | action = bnx2x_stats_stm[state][event].action; | ||
| 1385 | spin_unlock_bh(&bp->stats_lock); | 1427 | spin_unlock_bh(&bp->stats_lock); |
| 1386 | 1428 | ||
| 1387 | bnx2x_stats_stm[state][event].action(bp); | 1429 | action(bp); |
| 1388 | 1430 | ||
| 1389 | if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) | 1431 | if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) |
| 1390 | DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", | 1432 | DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ddebc7a5dda0..0da2214ef1b9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
| @@ -17796,8 +17796,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, | |||
| 17796 | 17796 | ||
| 17797 | done: | 17797 | done: |
| 17798 | if (state == pci_channel_io_perm_failure) { | 17798 | if (state == pci_channel_io_perm_failure) { |
| 17799 | tg3_napi_enable(tp); | 17799 | if (netdev) { |
| 17800 | dev_close(netdev); | 17800 | tg3_napi_enable(tp); |
| 17801 | dev_close(netdev); | ||
| 17802 | } | ||
| 17801 | err = PCI_ERS_RESULT_DISCONNECT; | 17803 | err = PCI_ERS_RESULT_DISCONNECT; |
| 17802 | } else { | 17804 | } else { |
| 17803 | pci_disable_device(pdev); | 17805 | pci_disable_device(pdev); |
| @@ -17827,7 +17829,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) | |||
| 17827 | rtnl_lock(); | 17829 | rtnl_lock(); |
| 17828 | 17830 | ||
| 17829 | if (pci_enable_device(pdev)) { | 17831 | if (pci_enable_device(pdev)) { |
| 17830 | netdev_err(netdev, "Cannot re-enable PCI device after reset.\n"); | 17832 | dev_err(&pdev->dev, |
| 17833 | "Cannot re-enable PCI device after reset.\n"); | ||
| 17831 | goto done; | 17834 | goto done; |
| 17832 | } | 17835 | } |
| 17833 | 17836 | ||
| @@ -17835,7 +17838,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) | |||
| 17835 | pci_restore_state(pdev); | 17838 | pci_restore_state(pdev); |
| 17836 | pci_save_state(pdev); | 17839 | pci_save_state(pdev); |
| 17837 | 17840 | ||
| 17838 | if (!netif_running(netdev)) { | 17841 | if (!netdev || !netif_running(netdev)) { |
| 17839 | rc = PCI_ERS_RESULT_RECOVERED; | 17842 | rc = PCI_ERS_RESULT_RECOVERED; |
| 17840 | goto done; | 17843 | goto done; |
| 17841 | } | 17844 | } |
| @@ -17847,7 +17850,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) | |||
| 17847 | rc = PCI_ERS_RESULT_RECOVERED; | 17850 | rc = PCI_ERS_RESULT_RECOVERED; |
| 17848 | 17851 | ||
| 17849 | done: | 17852 | done: |
| 17850 | if (rc != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) { | 17853 | if (rc != PCI_ERS_RESULT_RECOVERED && netdev && netif_running(netdev)) { |
| 17851 | tg3_napi_enable(tp); | 17854 | tg3_napi_enable(tp); |
| 17852 | dev_close(netdev); | 17855 | dev_close(netdev); |
| 17853 | } | 17856 | } |
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 687ec4a8bb48..9c89dc8fe105 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c | |||
| @@ -455,11 +455,6 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q, | |||
| 455 | q->pg_chunk.offset = 0; | 455 | q->pg_chunk.offset = 0; |
| 456 | mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, | 456 | mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, |
| 457 | 0, q->alloc_size, PCI_DMA_FROMDEVICE); | 457 | 0, q->alloc_size, PCI_DMA_FROMDEVICE); |
| 458 | if (unlikely(pci_dma_mapping_error(adapter->pdev, mapping))) { | ||
| 459 | __free_pages(q->pg_chunk.page, order); | ||
| 460 | q->pg_chunk.page = NULL; | ||
| 461 | return -EIO; | ||
| 462 | } | ||
| 463 | q->pg_chunk.mapping = mapping; | 458 | q->pg_chunk.mapping = mapping; |
| 464 | } | 459 | } |
| 465 | sd->pg_chunk = q->pg_chunk; | 460 | sd->pg_chunk = q->pg_chunk; |
| @@ -954,75 +949,40 @@ static inline unsigned int calc_tx_descs(const struct sk_buff *skb) | |||
| 954 | return flits_to_desc(flits); | 949 | return flits_to_desc(flits); |
| 955 | } | 950 | } |
| 956 | 951 | ||
| 957 | |||
| 958 | /* map_skb - map a packet main body and its page fragments | ||
| 959 | * @pdev: the PCI device | ||
| 960 | * @skb: the packet | ||
| 961 | * @addr: placeholder to save the mapped addresses | ||
| 962 | * | ||
| 963 | * map the main body of an sk_buff and its page fragments, if any. | ||
| 964 | */ | ||
| 965 | static int map_skb(struct pci_dev *pdev, const struct sk_buff *skb, | ||
| 966 | dma_addr_t *addr) | ||
| 967 | { | ||
| 968 | const skb_frag_t *fp, *end; | ||
| 969 | const struct skb_shared_info *si; | ||
| 970 | |||
| 971 | *addr = pci_map_single(pdev, skb->data, skb_headlen(skb), | ||
| 972 | PCI_DMA_TODEVICE); | ||
| 973 | if (pci_dma_mapping_error(pdev, *addr)) | ||
| 974 | goto out_err; | ||
| 975 | |||
| 976 | si = skb_shinfo(skb); | ||
| 977 | end = &si->frags[si->nr_frags]; | ||
| 978 | |||
| 979 | for (fp = si->frags; fp < end; fp++) { | ||
| 980 | *++addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp), | ||
| 981 | DMA_TO_DEVICE); | ||
| 982 | if (pci_dma_mapping_error(pdev, *addr)) | ||
| 983 | goto unwind; | ||
| 984 | } | ||
| 985 | return 0; | ||
| 986 | |||
| 987 | unwind: | ||
| 988 | while (fp-- > si->frags) | ||
| 989 | dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp), | ||
| 990 | DMA_TO_DEVICE); | ||
| 991 | |||
| 992 | pci_unmap_single(pdev, addr[-1], skb_headlen(skb), PCI_DMA_TODEVICE); | ||
| 993 | out_err: | ||
| 994 | return -ENOMEM; | ||
| 995 | } | ||
| 996 | |||
| 997 | /** | 952 | /** |
| 998 | * write_sgl - populate a scatter/gather list for a packet | 953 | * make_sgl - populate a scatter/gather list for a packet |
| 999 | * @skb: the packet | 954 | * @skb: the packet |
| 1000 | * @sgp: the SGL to populate | 955 | * @sgp: the SGL to populate |
| 1001 | * @start: start address of skb main body data to include in the SGL | 956 | * @start: start address of skb main body data to include in the SGL |
| 1002 | * @len: length of skb main body data to include in the SGL | 957 | * @len: length of skb main body data to include in the SGL |
| 1003 | * @addr: the list of the mapped addresses | 958 | * @pdev: the PCI device |
| 1004 | * | 959 | * |
| 1005 | * Copies the scatter/gather list for the buffers that make up a packet | 960 | * Generates a scatter/gather list for the buffers that make up a packet |
| 1006 | * and returns the SGL size in 8-byte words. The caller must size the SGL | 961 | * and returns the SGL size in 8-byte words. The caller must size the SGL |
| 1007 | * appropriately. | 962 | * appropriately. |
| 1008 | */ | 963 | */ |
| 1009 | static inline unsigned int write_sgl(const struct sk_buff *skb, | 964 | static inline unsigned int make_sgl(const struct sk_buff *skb, |
| 1010 | struct sg_ent *sgp, unsigned char *start, | 965 | struct sg_ent *sgp, unsigned char *start, |
| 1011 | unsigned int len, const dma_addr_t *addr) | 966 | unsigned int len, struct pci_dev *pdev) |
| 1012 | { | 967 | { |
| 1013 | unsigned int i, j = 0, k = 0, nfrags; | 968 | dma_addr_t mapping; |
| 969 | unsigned int i, j = 0, nfrags; | ||
| 1014 | 970 | ||
| 1015 | if (len) { | 971 | if (len) { |
| 972 | mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE); | ||
| 1016 | sgp->len[0] = cpu_to_be32(len); | 973 | sgp->len[0] = cpu_to_be32(len); |
| 1017 | sgp->addr[j++] = cpu_to_be64(addr[k++]); | 974 | sgp->addr[0] = cpu_to_be64(mapping); |
| 975 | j = 1; | ||
| 1018 | } | 976 | } |
| 1019 | 977 | ||
| 1020 | nfrags = skb_shinfo(skb)->nr_frags; | 978 | nfrags = skb_shinfo(skb)->nr_frags; |
| 1021 | for (i = 0; i < nfrags; i++) { | 979 | for (i = 0; i < nfrags; i++) { |
| 1022 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 980 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
| 1023 | 981 | ||
| 982 | mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), | ||
| 983 | DMA_TO_DEVICE); | ||
| 1024 | sgp->len[j] = cpu_to_be32(skb_frag_size(frag)); | 984 | sgp->len[j] = cpu_to_be32(skb_frag_size(frag)); |
| 1025 | sgp->addr[j] = cpu_to_be64(addr[k++]); | 985 | sgp->addr[j] = cpu_to_be64(mapping); |
| 1026 | j ^= 1; | 986 | j ^= 1; |
| 1027 | if (j == 0) | 987 | if (j == 0) |
| 1028 | ++sgp; | 988 | ++sgp; |
| @@ -1178,7 +1138,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, | |||
| 1178 | const struct port_info *pi, | 1138 | const struct port_info *pi, |
| 1179 | unsigned int pidx, unsigned int gen, | 1139 | unsigned int pidx, unsigned int gen, |
| 1180 | struct sge_txq *q, unsigned int ndesc, | 1140 | struct sge_txq *q, unsigned int ndesc, |
| 1181 | unsigned int compl, const dma_addr_t *addr) | 1141 | unsigned int compl) |
| 1182 | { | 1142 | { |
| 1183 | unsigned int flits, sgl_flits, cntrl, tso_info; | 1143 | unsigned int flits, sgl_flits, cntrl, tso_info; |
| 1184 | struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1]; | 1144 | struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1]; |
| @@ -1236,7 +1196,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, | |||
| 1236 | } | 1196 | } |
| 1237 | 1197 | ||
| 1238 | sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; | 1198 | sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; |
| 1239 | sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr); | 1199 | sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev); |
| 1240 | 1200 | ||
| 1241 | write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen, | 1201 | write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen, |
| 1242 | htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl), | 1202 | htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl), |
| @@ -1267,7 +1227,6 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1267 | struct netdev_queue *txq; | 1227 | struct netdev_queue *txq; |
| 1268 | struct sge_qset *qs; | 1228 | struct sge_qset *qs; |
| 1269 | struct sge_txq *q; | 1229 | struct sge_txq *q; |
| 1270 | dma_addr_t addr[MAX_SKB_FRAGS + 1]; | ||
| 1271 | 1230 | ||
| 1272 | /* | 1231 | /* |
| 1273 | * The chip min packet length is 9 octets but play safe and reject | 1232 | * The chip min packet length is 9 octets but play safe and reject |
| @@ -1296,11 +1255,6 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1296 | return NETDEV_TX_BUSY; | 1255 | return NETDEV_TX_BUSY; |
| 1297 | } | 1256 | } |
| 1298 | 1257 | ||
| 1299 | if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) { | ||
| 1300 | dev_kfree_skb(skb); | ||
| 1301 | return NETDEV_TX_OK; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | q->in_use += ndesc; | 1258 | q->in_use += ndesc; |
| 1305 | if (unlikely(credits - ndesc < q->stop_thres)) { | 1259 | if (unlikely(credits - ndesc < q->stop_thres)) { |
| 1306 | t3_stop_tx_queue(txq, qs, q); | 1260 | t3_stop_tx_queue(txq, qs, q); |
| @@ -1358,7 +1312,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1358 | if (likely(!skb_shared(skb))) | 1312 | if (likely(!skb_shared(skb))) |
| 1359 | skb_orphan(skb); | 1313 | skb_orphan(skb); |
| 1360 | 1314 | ||
| 1361 | write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr); | 1315 | write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl); |
| 1362 | check_ring_tx_db(adap, q); | 1316 | check_ring_tx_db(adap, q); |
| 1363 | return NETDEV_TX_OK; | 1317 | return NETDEV_TX_OK; |
| 1364 | } | 1318 | } |
| @@ -1623,8 +1577,7 @@ static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev, | |||
| 1623 | */ | 1577 | */ |
| 1624 | static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, | 1578 | static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, |
| 1625 | struct sge_txq *q, unsigned int pidx, | 1579 | struct sge_txq *q, unsigned int pidx, |
| 1626 | unsigned int gen, unsigned int ndesc, | 1580 | unsigned int gen, unsigned int ndesc) |
| 1627 | const dma_addr_t *addr) | ||
| 1628 | { | 1581 | { |
| 1629 | unsigned int sgl_flits, flits; | 1582 | unsigned int sgl_flits, flits; |
| 1630 | struct work_request_hdr *from; | 1583 | struct work_request_hdr *from; |
| @@ -1645,9 +1598,9 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, | |||
| 1645 | 1598 | ||
| 1646 | flits = skb_transport_offset(skb) / 8; | 1599 | flits = skb_transport_offset(skb) / 8; |
| 1647 | sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; | 1600 | sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; |
| 1648 | sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb), | 1601 | sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb), |
| 1649 | skb_tail_pointer(skb) - | 1602 | skb->tail - skb->transport_header, |
| 1650 | skb_transport_header(skb), addr); | 1603 | adap->pdev); |
| 1651 | if (need_skb_unmap()) { | 1604 | if (need_skb_unmap()) { |
| 1652 | setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); | 1605 | setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); |
| 1653 | skb->destructor = deferred_unmap_destructor; | 1606 | skb->destructor = deferred_unmap_destructor; |
| @@ -1705,11 +1658,6 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | |||
| 1705 | goto again; | 1658 | goto again; |
| 1706 | } | 1659 | } |
| 1707 | 1660 | ||
| 1708 | if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) { | ||
| 1709 | spin_unlock(&q->lock); | ||
| 1710 | return NET_XMIT_SUCCESS; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | gen = q->gen; | 1661 | gen = q->gen; |
| 1714 | q->in_use += ndesc; | 1662 | q->in_use += ndesc; |
| 1715 | pidx = q->pidx; | 1663 | pidx = q->pidx; |
| @@ -1720,7 +1668,7 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | |||
| 1720 | } | 1668 | } |
| 1721 | spin_unlock(&q->lock); | 1669 | spin_unlock(&q->lock); |
| 1722 | 1670 | ||
| 1723 | write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head); | 1671 | write_ofld_wr(adap, skb, q, pidx, gen, ndesc); |
| 1724 | check_ring_tx_db(adap, q); | 1672 | check_ring_tx_db(adap, q); |
| 1725 | return NET_XMIT_SUCCESS; | 1673 | return NET_XMIT_SUCCESS; |
| 1726 | } | 1674 | } |
| @@ -1738,7 +1686,6 @@ static void restart_offloadq(unsigned long data) | |||
| 1738 | struct sge_txq *q = &qs->txq[TXQ_OFLD]; | 1686 | struct sge_txq *q = &qs->txq[TXQ_OFLD]; |
| 1739 | const struct port_info *pi = netdev_priv(qs->netdev); | 1687 | const struct port_info *pi = netdev_priv(qs->netdev); |
| 1740 | struct adapter *adap = pi->adapter; | 1688 | struct adapter *adap = pi->adapter; |
| 1741 | unsigned int written = 0; | ||
| 1742 | 1689 | ||
| 1743 | spin_lock(&q->lock); | 1690 | spin_lock(&q->lock); |
| 1744 | again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | 1691 | again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); |
| @@ -1758,14 +1705,10 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | |||
| 1758 | break; | 1705 | break; |
| 1759 | } | 1706 | } |
| 1760 | 1707 | ||
| 1761 | if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) | ||
| 1762 | break; | ||
| 1763 | |||
| 1764 | gen = q->gen; | 1708 | gen = q->gen; |
| 1765 | q->in_use += ndesc; | 1709 | q->in_use += ndesc; |
| 1766 | pidx = q->pidx; | 1710 | pidx = q->pidx; |
| 1767 | q->pidx += ndesc; | 1711 | q->pidx += ndesc; |
| 1768 | written += ndesc; | ||
| 1769 | if (q->pidx >= q->size) { | 1712 | if (q->pidx >= q->size) { |
| 1770 | q->pidx -= q->size; | 1713 | q->pidx -= q->size; |
| 1771 | q->gen ^= 1; | 1714 | q->gen ^= 1; |
| @@ -1773,8 +1716,7 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | |||
| 1773 | __skb_unlink(skb, &q->sendq); | 1716 | __skb_unlink(skb, &q->sendq); |
| 1774 | spin_unlock(&q->lock); | 1717 | spin_unlock(&q->lock); |
| 1775 | 1718 | ||
| 1776 | write_ofld_wr(adap, skb, q, pidx, gen, ndesc, | 1719 | write_ofld_wr(adap, skb, q, pidx, gen, ndesc); |
| 1777 | (dma_addr_t *)skb->head); | ||
| 1778 | spin_lock(&q->lock); | 1720 | spin_lock(&q->lock); |
| 1779 | } | 1721 | } |
| 1780 | spin_unlock(&q->lock); | 1722 | spin_unlock(&q->lock); |
| @@ -1784,9 +1726,8 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); | |||
| 1784 | set_bit(TXQ_LAST_PKT_DB, &q->flags); | 1726 | set_bit(TXQ_LAST_PKT_DB, &q->flags); |
| 1785 | #endif | 1727 | #endif |
| 1786 | wmb(); | 1728 | wmb(); |
| 1787 | if (likely(written)) | 1729 | t3_write_reg(adap, A_SG_KDOORBELL, |
| 1788 | t3_write_reg(adap, A_SG_KDOORBELL, | 1730 | F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); |
| 1789 | F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); | ||
| 1790 | } | 1731 | } |
| 1791 | 1732 | ||
| 1792 | /** | 1733 | /** |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 6e6e0a117ee2..8ec5d74ad44d 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
| @@ -3048,6 +3048,9 @@ int be_cmd_get_func_config(struct be_adapter *adapter) | |||
| 3048 | 3048 | ||
| 3049 | adapter->max_event_queues = le16_to_cpu(desc->eq_count); | 3049 | adapter->max_event_queues = le16_to_cpu(desc->eq_count); |
| 3050 | adapter->if_cap_flags = le32_to_cpu(desc->cap_flags); | 3050 | adapter->if_cap_flags = le32_to_cpu(desc->cap_flags); |
| 3051 | |||
| 3052 | /* Clear flags that driver is not interested in */ | ||
| 3053 | adapter->if_cap_flags &= BE_IF_CAP_FLAGS_WANT; | ||
| 3051 | } | 3054 | } |
| 3052 | err: | 3055 | err: |
| 3053 | mutex_unlock(&adapter->mbox_lock); | 3056 | mutex_unlock(&adapter->mbox_lock); |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 5228d88c5a02..1b3b9e886412 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
| @@ -563,6 +563,12 @@ enum be_if_flags { | |||
| 563 | BE_IF_FLAGS_MULTICAST = 0x1000 | 563 | BE_IF_FLAGS_MULTICAST = 0x1000 |
| 564 | }; | 564 | }; |
| 565 | 565 | ||
| 566 | #define BE_IF_CAP_FLAGS_WANT (BE_IF_FLAGS_RSS | BE_IF_FLAGS_PROMISCUOUS |\ | ||
| 567 | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_VLAN_PROMISCUOUS |\ | ||
| 568 | BE_IF_FLAGS_VLAN | BE_IF_FLAGS_MCAST_PROMISCUOUS |\ | ||
| 569 | BE_IF_FLAGS_PASS_L3L4_ERRORS | BE_IF_FLAGS_MULTICAST |\ | ||
| 570 | BE_IF_FLAGS_UNTAGGED) | ||
| 571 | |||
| 566 | /* An RX interface is an object with one or more MAC addresses and | 572 | /* An RX interface is an object with one or more MAC addresses and |
| 567 | * filtering capabilities. */ | 573 | * filtering capabilities. */ |
| 568 | struct be_cmd_req_if_create { | 574 | struct be_cmd_req_if_create { |
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index c896079728e1..ef94a591f9e5 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c | |||
| @@ -931,17 +931,20 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) | |||
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | /* Allocate and setup a new buffer for receiving */ | 933 | /* Allocate and setup a new buffer for receiving */ |
| 934 | static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, | 934 | static int skge_rx_setup(struct skge_port *skge, struct skge_element *e, |
| 935 | struct sk_buff *skb, unsigned int bufsize) | 935 | struct sk_buff *skb, unsigned int bufsize) |
| 936 | { | 936 | { |
| 937 | struct skge_rx_desc *rd = e->desc; | 937 | struct skge_rx_desc *rd = e->desc; |
| 938 | u64 map; | 938 | dma_addr_t map; |
| 939 | 939 | ||
| 940 | map = pci_map_single(skge->hw->pdev, skb->data, bufsize, | 940 | map = pci_map_single(skge->hw->pdev, skb->data, bufsize, |
| 941 | PCI_DMA_FROMDEVICE); | 941 | PCI_DMA_FROMDEVICE); |
| 942 | 942 | ||
| 943 | rd->dma_lo = map; | 943 | if (pci_dma_mapping_error(skge->hw->pdev, map)) |
| 944 | rd->dma_hi = map >> 32; | 944 | return -1; |
| 945 | |||
| 946 | rd->dma_lo = lower_32_bits(map); | ||
| 947 | rd->dma_hi = upper_32_bits(map); | ||
| 945 | e->skb = skb; | 948 | e->skb = skb; |
| 946 | rd->csum1_start = ETH_HLEN; | 949 | rd->csum1_start = ETH_HLEN; |
| 947 | rd->csum2_start = ETH_HLEN; | 950 | rd->csum2_start = ETH_HLEN; |
| @@ -953,6 +956,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, | |||
| 953 | rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; | 956 | rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; |
| 954 | dma_unmap_addr_set(e, mapaddr, map); | 957 | dma_unmap_addr_set(e, mapaddr, map); |
| 955 | dma_unmap_len_set(e, maplen, bufsize); | 958 | dma_unmap_len_set(e, maplen, bufsize); |
| 959 | return 0; | ||
| 956 | } | 960 | } |
| 957 | 961 | ||
| 958 | /* Resume receiving using existing skb, | 962 | /* Resume receiving using existing skb, |
| @@ -1014,7 +1018,10 @@ static int skge_rx_fill(struct net_device *dev) | |||
| 1014 | return -ENOMEM; | 1018 | return -ENOMEM; |
| 1015 | 1019 | ||
| 1016 | skb_reserve(skb, NET_IP_ALIGN); | 1020 | skb_reserve(skb, NET_IP_ALIGN); |
| 1017 | skge_rx_setup(skge, e, skb, skge->rx_buf_size); | 1021 | if (skge_rx_setup(skge, e, skb, skge->rx_buf_size) < 0) { |
| 1022 | dev_kfree_skb(skb); | ||
| 1023 | return -EIO; | ||
| 1024 | } | ||
| 1018 | } while ((e = e->next) != ring->start); | 1025 | } while ((e = e->next) != ring->start); |
| 1019 | 1026 | ||
| 1020 | ring->to_clean = ring->start; | 1027 | ring->to_clean = ring->start; |
| @@ -2544,7 +2551,7 @@ static int skge_up(struct net_device *dev) | |||
| 2544 | 2551 | ||
| 2545 | BUG_ON(skge->dma & 7); | 2552 | BUG_ON(skge->dma & 7); |
| 2546 | 2553 | ||
| 2547 | if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) { | 2554 | if (upper_32_bits(skge->dma) != upper_32_bits(skge->dma + skge->mem_size)) { |
| 2548 | dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n"); | 2555 | dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n"); |
| 2549 | err = -EINVAL; | 2556 | err = -EINVAL; |
| 2550 | goto free_pci_mem; | 2557 | goto free_pci_mem; |
| @@ -2729,7 +2736,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, | |||
| 2729 | struct skge_tx_desc *td; | 2736 | struct skge_tx_desc *td; |
| 2730 | int i; | 2737 | int i; |
| 2731 | u32 control, len; | 2738 | u32 control, len; |
| 2732 | u64 map; | 2739 | dma_addr_t map; |
| 2733 | 2740 | ||
| 2734 | if (skb_padto(skb, ETH_ZLEN)) | 2741 | if (skb_padto(skb, ETH_ZLEN)) |
| 2735 | return NETDEV_TX_OK; | 2742 | return NETDEV_TX_OK; |
| @@ -2743,11 +2750,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, | |||
| 2743 | e->skb = skb; | 2750 | e->skb = skb; |
| 2744 | len = skb_headlen(skb); | 2751 | len = skb_headlen(skb); |
| 2745 | map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | 2752 | map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); |
| 2753 | if (pci_dma_mapping_error(hw->pdev, map)) | ||
| 2754 | goto mapping_error; | ||
| 2755 | |||
| 2746 | dma_unmap_addr_set(e, mapaddr, map); | 2756 | dma_unmap_addr_set(e, mapaddr, map); |
| 2747 | dma_unmap_len_set(e, maplen, len); | 2757 | dma_unmap_len_set(e, maplen, len); |
| 2748 | 2758 | ||
| 2749 | td->dma_lo = map; | 2759 | td->dma_lo = lower_32_bits(map); |
| 2750 | td->dma_hi = map >> 32; | 2760 | td->dma_hi = upper_32_bits(map); |
| 2751 | 2761 | ||
| 2752 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 2762 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 2753 | const int offset = skb_checksum_start_offset(skb); | 2763 | const int offset = skb_checksum_start_offset(skb); |
| @@ -2778,14 +2788,16 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, | |||
| 2778 | 2788 | ||
| 2779 | map = skb_frag_dma_map(&hw->pdev->dev, frag, 0, | 2789 | map = skb_frag_dma_map(&hw->pdev->dev, frag, 0, |
| 2780 | skb_frag_size(frag), DMA_TO_DEVICE); | 2790 | skb_frag_size(frag), DMA_TO_DEVICE); |
| 2791 | if (dma_mapping_error(&hw->pdev->dev, map)) | ||
| 2792 | goto mapping_unwind; | ||
| 2781 | 2793 | ||
| 2782 | e = e->next; | 2794 | e = e->next; |
| 2783 | e->skb = skb; | 2795 | e->skb = skb; |
| 2784 | tf = e->desc; | 2796 | tf = e->desc; |
| 2785 | BUG_ON(tf->control & BMU_OWN); | 2797 | BUG_ON(tf->control & BMU_OWN); |
| 2786 | 2798 | ||
| 2787 | tf->dma_lo = map; | 2799 | tf->dma_lo = lower_32_bits(map); |
| 2788 | tf->dma_hi = (u64) map >> 32; | 2800 | tf->dma_hi = upper_32_bits(map); |
| 2789 | dma_unmap_addr_set(e, mapaddr, map); | 2801 | dma_unmap_addr_set(e, mapaddr, map); |
| 2790 | dma_unmap_len_set(e, maplen, skb_frag_size(frag)); | 2802 | dma_unmap_len_set(e, maplen, skb_frag_size(frag)); |
| 2791 | 2803 | ||
| @@ -2815,6 +2827,26 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, | |||
| 2815 | } | 2827 | } |
| 2816 | 2828 | ||
| 2817 | return NETDEV_TX_OK; | 2829 | return NETDEV_TX_OK; |
| 2830 | |||
| 2831 | mapping_unwind: | ||
| 2832 | e = skge->tx_ring.to_use; | ||
| 2833 | pci_unmap_single(hw->pdev, | ||
| 2834 | dma_unmap_addr(e, mapaddr), | ||
| 2835 | dma_unmap_len(e, maplen), | ||
| 2836 | PCI_DMA_TODEVICE); | ||
| 2837 | while (i-- > 0) { | ||
| 2838 | e = e->next; | ||
| 2839 | pci_unmap_page(hw->pdev, | ||
| 2840 | dma_unmap_addr(e, mapaddr), | ||
| 2841 | dma_unmap_len(e, maplen), | ||
| 2842 | PCI_DMA_TODEVICE); | ||
| 2843 | } | ||
| 2844 | |||
| 2845 | mapping_error: | ||
| 2846 | if (net_ratelimit()) | ||
| 2847 | dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); | ||
| 2848 | dev_kfree_skb(skb); | ||
| 2849 | return NETDEV_TX_OK; | ||
| 2818 | } | 2850 | } |
| 2819 | 2851 | ||
| 2820 | 2852 | ||
| @@ -3045,11 +3077,13 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, | |||
| 3045 | 3077 | ||
| 3046 | pci_dma_sync_single_for_cpu(skge->hw->pdev, | 3078 | pci_dma_sync_single_for_cpu(skge->hw->pdev, |
| 3047 | dma_unmap_addr(e, mapaddr), | 3079 | dma_unmap_addr(e, mapaddr), |
| 3048 | len, PCI_DMA_FROMDEVICE); | 3080 | dma_unmap_len(e, maplen), |
| 3081 | PCI_DMA_FROMDEVICE); | ||
| 3049 | skb_copy_from_linear_data(e->skb, skb->data, len); | 3082 | skb_copy_from_linear_data(e->skb, skb->data, len); |
| 3050 | pci_dma_sync_single_for_device(skge->hw->pdev, | 3083 | pci_dma_sync_single_for_device(skge->hw->pdev, |
| 3051 | dma_unmap_addr(e, mapaddr), | 3084 | dma_unmap_addr(e, mapaddr), |
| 3052 | len, PCI_DMA_FROMDEVICE); | 3085 | dma_unmap_len(e, maplen), |
| 3086 | PCI_DMA_FROMDEVICE); | ||
| 3053 | skge_rx_reuse(e, skge->rx_buf_size); | 3087 | skge_rx_reuse(e, skge->rx_buf_size); |
| 3054 | } else { | 3088 | } else { |
| 3055 | struct sk_buff *nskb; | 3089 | struct sk_buff *nskb; |
| @@ -3058,13 +3092,17 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, | |||
| 3058 | if (!nskb) | 3092 | if (!nskb) |
| 3059 | goto resubmit; | 3093 | goto resubmit; |
| 3060 | 3094 | ||
| 3095 | if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) { | ||
| 3096 | dev_kfree_skb(nskb); | ||
| 3097 | goto resubmit; | ||
| 3098 | } | ||
| 3099 | |||
| 3061 | pci_unmap_single(skge->hw->pdev, | 3100 | pci_unmap_single(skge->hw->pdev, |
| 3062 | dma_unmap_addr(e, mapaddr), | 3101 | dma_unmap_addr(e, mapaddr), |
| 3063 | dma_unmap_len(e, maplen), | 3102 | dma_unmap_len(e, maplen), |
| 3064 | PCI_DMA_FROMDEVICE); | 3103 | PCI_DMA_FROMDEVICE); |
| 3065 | skb = e->skb; | 3104 | skb = e->skb; |
| 3066 | prefetch(skb->data); | 3105 | prefetch(skb->data); |
| 3067 | skge_rx_setup(skge, e, nskb, skge->rx_buf_size); | ||
| 3068 | } | 3106 | } |
| 3069 | 3107 | ||
| 3070 | skb_put(skb, len); | 3108 | skb_put(skb, len); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index c571de85d0f9..5472cbd34028 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | #include "mlx5_core.h" | 46 | #include "mlx5_core.h" |
| 47 | 47 | ||
| 48 | enum { | 48 | enum { |
| 49 | CMD_IF_REV = 4, | 49 | CMD_IF_REV = 5, |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | enum { | 52 | enum { |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index c02cbcfd0fb8..443cc4d7b024 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c | |||
| @@ -268,7 +268,7 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq) | |||
| 268 | case MLX5_EVENT_TYPE_PAGE_REQUEST: | 268 | case MLX5_EVENT_TYPE_PAGE_REQUEST: |
| 269 | { | 269 | { |
| 270 | u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id); | 270 | u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id); |
| 271 | s16 npages = be16_to_cpu(eqe->data.req_pages.num_pages); | 271 | s32 npages = be32_to_cpu(eqe->data.req_pages.num_pages); |
| 272 | 272 | ||
| 273 | mlx5_core_dbg(dev, "page request for func 0x%x, napges %d\n", func_id, npages); | 273 | mlx5_core_dbg(dev, "page request for func 0x%x, napges %d\n", func_id, npages); |
| 274 | mlx5_core_req_pages_handler(dev, func_id, npages); | 274 | mlx5_core_req_pages_handler(dev, func_id, npages); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index 72a5222447f5..f012658b6a92 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c | |||
| @@ -113,7 +113,7 @@ int mlx5_cmd_query_hca_cap(struct mlx5_core_dev *dev, | |||
| 113 | caps->log_max_srq = out->hca_cap.log_max_srqs & 0x1f; | 113 | caps->log_max_srq = out->hca_cap.log_max_srqs & 0x1f; |
| 114 | caps->local_ca_ack_delay = out->hca_cap.local_ca_ack_delay & 0x1f; | 114 | caps->local_ca_ack_delay = out->hca_cap.local_ca_ack_delay & 0x1f; |
| 115 | caps->log_max_mcg = out->hca_cap.log_max_mcg; | 115 | caps->log_max_mcg = out->hca_cap.log_max_mcg; |
| 116 | caps->max_qp_mcg = be16_to_cpu(out->hca_cap.max_qp_mcg); | 116 | caps->max_qp_mcg = be32_to_cpu(out->hca_cap.max_qp_mcg) & 0xffffff; |
| 117 | caps->max_ra_res_qp = 1 << (out->hca_cap.log_max_ra_res_qp & 0x3f); | 117 | caps->max_ra_res_qp = 1 << (out->hca_cap.log_max_ra_res_qp & 0x3f); |
| 118 | caps->max_ra_req_qp = 1 << (out->hca_cap.log_max_ra_req_qp & 0x3f); | 118 | caps->max_ra_req_qp = 1 << (out->hca_cap.log_max_ra_req_qp & 0x3f); |
| 119 | caps->max_srq_wqes = 1 << out->hca_cap.log_max_srq_sz; | 119 | caps->max_srq_wqes = 1 << out->hca_cap.log_max_srq_sz; |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 748f10a155c4..3e6670c4a7cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c | |||
| @@ -55,33 +55,9 @@ enum { | |||
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | static DEFINE_SPINLOCK(health_lock); | 57 | static DEFINE_SPINLOCK(health_lock); |
| 58 | |||
| 59 | static LIST_HEAD(health_list); | 58 | static LIST_HEAD(health_list); |
| 60 | static struct work_struct health_work; | 59 | static struct work_struct health_work; |
| 61 | 60 | ||
| 62 | static health_handler_t reg_handler; | ||
| 63 | int mlx5_register_health_report_handler(health_handler_t handler) | ||
| 64 | { | ||
| 65 | spin_lock_irq(&health_lock); | ||
| 66 | if (reg_handler) { | ||
| 67 | spin_unlock_irq(&health_lock); | ||
| 68 | return -EEXIST; | ||
| 69 | } | ||
| 70 | reg_handler = handler; | ||
| 71 | spin_unlock_irq(&health_lock); | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | EXPORT_SYMBOL(mlx5_register_health_report_handler); | ||
| 76 | |||
| 77 | void mlx5_unregister_health_report_handler(void) | ||
| 78 | { | ||
| 79 | spin_lock_irq(&health_lock); | ||
| 80 | reg_handler = NULL; | ||
| 81 | spin_unlock_irq(&health_lock); | ||
| 82 | } | ||
| 83 | EXPORT_SYMBOL(mlx5_unregister_health_report_handler); | ||
| 84 | |||
| 85 | static void health_care(struct work_struct *work) | 61 | static void health_care(struct work_struct *work) |
| 86 | { | 62 | { |
| 87 | struct mlx5_core_health *health, *n; | 63 | struct mlx5_core_health *health, *n; |
| @@ -98,11 +74,8 @@ static void health_care(struct work_struct *work) | |||
| 98 | priv = container_of(health, struct mlx5_priv, health); | 74 | priv = container_of(health, struct mlx5_priv, health); |
| 99 | dev = container_of(priv, struct mlx5_core_dev, priv); | 75 | dev = container_of(priv, struct mlx5_core_dev, priv); |
| 100 | mlx5_core_warn(dev, "handling bad device here\n"); | 76 | mlx5_core_warn(dev, "handling bad device here\n"); |
| 77 | /* nothing yet */ | ||
| 101 | spin_lock_irq(&health_lock); | 78 | spin_lock_irq(&health_lock); |
| 102 | if (reg_handler) | ||
| 103 | reg_handler(dev->pdev, health->health, | ||
| 104 | sizeof(health->health)); | ||
| 105 | |||
| 106 | list_del_init(&health->list); | 79 | list_del_init(&health->list); |
| 107 | spin_unlock_irq(&health_lock); | 80 | spin_unlock_irq(&health_lock); |
| 108 | } | 81 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 4a3e137931a3..3a2408d44820 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | |||
| @@ -43,10 +43,16 @@ enum { | |||
| 43 | MLX5_PAGES_TAKE = 2 | 43 | MLX5_PAGES_TAKE = 2 |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | enum { | ||
| 47 | MLX5_BOOT_PAGES = 1, | ||
| 48 | MLX5_INIT_PAGES = 2, | ||
| 49 | MLX5_POST_INIT_PAGES = 3 | ||
| 50 | }; | ||
| 51 | |||
| 46 | struct mlx5_pages_req { | 52 | struct mlx5_pages_req { |
| 47 | struct mlx5_core_dev *dev; | 53 | struct mlx5_core_dev *dev; |
| 48 | u32 func_id; | 54 | u32 func_id; |
| 49 | s16 npages; | 55 | s32 npages; |
| 50 | struct work_struct work; | 56 | struct work_struct work; |
| 51 | }; | 57 | }; |
| 52 | 58 | ||
| @@ -64,27 +70,23 @@ struct mlx5_query_pages_inbox { | |||
| 64 | 70 | ||
| 65 | struct mlx5_query_pages_outbox { | 71 | struct mlx5_query_pages_outbox { |
| 66 | struct mlx5_outbox_hdr hdr; | 72 | struct mlx5_outbox_hdr hdr; |
| 67 | __be16 num_boot_pages; | 73 | __be16 rsvd; |
| 68 | __be16 func_id; | 74 | __be16 func_id; |
| 69 | __be16 init_pages; | 75 | __be32 num_pages; |
| 70 | __be16 num_pages; | ||
| 71 | }; | 76 | }; |
| 72 | 77 | ||
| 73 | struct mlx5_manage_pages_inbox { | 78 | struct mlx5_manage_pages_inbox { |
| 74 | struct mlx5_inbox_hdr hdr; | 79 | struct mlx5_inbox_hdr hdr; |
| 75 | __be16 rsvd0; | 80 | __be16 rsvd; |
| 76 | __be16 func_id; | 81 | __be16 func_id; |
| 77 | __be16 rsvd1; | 82 | __be32 num_entries; |
| 78 | __be16 num_entries; | ||
| 79 | u8 rsvd2[16]; | ||
| 80 | __be64 pas[0]; | 83 | __be64 pas[0]; |
| 81 | }; | 84 | }; |
| 82 | 85 | ||
| 83 | struct mlx5_manage_pages_outbox { | 86 | struct mlx5_manage_pages_outbox { |
| 84 | struct mlx5_outbox_hdr hdr; | 87 | struct mlx5_outbox_hdr hdr; |
| 85 | u8 rsvd0[2]; | 88 | __be32 num_entries; |
| 86 | __be16 num_entries; | 89 | u8 rsvd[4]; |
| 87 | u8 rsvd1[20]; | ||
| 88 | __be64 pas[0]; | 90 | __be64 pas[0]; |
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| @@ -146,7 +148,7 @@ static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr) | |||
| 146 | } | 148 | } |
| 147 | 149 | ||
| 148 | static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, | 150 | static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, |
| 149 | s16 *pages, s16 *init_pages, u16 *boot_pages) | 151 | s32 *npages, int boot) |
| 150 | { | 152 | { |
| 151 | struct mlx5_query_pages_inbox in; | 153 | struct mlx5_query_pages_inbox in; |
| 152 | struct mlx5_query_pages_outbox out; | 154 | struct mlx5_query_pages_outbox out; |
| @@ -155,6 +157,8 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, | |||
| 155 | memset(&in, 0, sizeof(in)); | 157 | memset(&in, 0, sizeof(in)); |
| 156 | memset(&out, 0, sizeof(out)); | 158 | memset(&out, 0, sizeof(out)); |
| 157 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_PAGES); | 159 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_PAGES); |
| 160 | in.hdr.opmod = boot ? cpu_to_be16(MLX5_BOOT_PAGES) : cpu_to_be16(MLX5_INIT_PAGES); | ||
| 161 | |||
| 158 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); | 162 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); |
| 159 | if (err) | 163 | if (err) |
| 160 | return err; | 164 | return err; |
| @@ -162,15 +166,7 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, | |||
| 162 | if (out.hdr.status) | 166 | if (out.hdr.status) |
| 163 | return mlx5_cmd_status_to_err(&out.hdr); | 167 | return mlx5_cmd_status_to_err(&out.hdr); |
| 164 | 168 | ||
| 165 | if (pages) | 169 | *npages = be32_to_cpu(out.num_pages); |
| 166 | *pages = be16_to_cpu(out.num_pages); | ||
| 167 | |||
| 168 | if (init_pages) | ||
| 169 | *init_pages = be16_to_cpu(out.init_pages); | ||
| 170 | |||
| 171 | if (boot_pages) | ||
| 172 | *boot_pages = be16_to_cpu(out.num_boot_pages); | ||
| 173 | |||
| 174 | *func_id = be16_to_cpu(out.func_id); | 170 | *func_id = be16_to_cpu(out.func_id); |
| 175 | 171 | ||
| 176 | return err; | 172 | return err; |
| @@ -224,7 +220,7 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, | |||
| 224 | in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); | 220 | in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); |
| 225 | in->hdr.opmod = cpu_to_be16(MLX5_PAGES_GIVE); | 221 | in->hdr.opmod = cpu_to_be16(MLX5_PAGES_GIVE); |
| 226 | in->func_id = cpu_to_be16(func_id); | 222 | in->func_id = cpu_to_be16(func_id); |
| 227 | in->num_entries = cpu_to_be16(npages); | 223 | in->num_entries = cpu_to_be32(npages); |
| 228 | err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); | 224 | err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); |
| 229 | mlx5_core_dbg(dev, "err %d\n", err); | 225 | mlx5_core_dbg(dev, "err %d\n", err); |
| 230 | if (err) { | 226 | if (err) { |
| @@ -292,7 +288,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, | |||
| 292 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); | 288 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); |
| 293 | in.hdr.opmod = cpu_to_be16(MLX5_PAGES_TAKE); | 289 | in.hdr.opmod = cpu_to_be16(MLX5_PAGES_TAKE); |
| 294 | in.func_id = cpu_to_be16(func_id); | 290 | in.func_id = cpu_to_be16(func_id); |
| 295 | in.num_entries = cpu_to_be16(npages); | 291 | in.num_entries = cpu_to_be32(npages); |
| 296 | mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen); | 292 | mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen); |
| 297 | err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); | 293 | err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); |
| 298 | if (err) { | 294 | if (err) { |
| @@ -306,7 +302,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, | |||
| 306 | goto out_free; | 302 | goto out_free; |
| 307 | } | 303 | } |
| 308 | 304 | ||
| 309 | num_claimed = be16_to_cpu(out->num_entries); | 305 | num_claimed = be32_to_cpu(out->num_entries); |
| 310 | if (nclaimed) | 306 | if (nclaimed) |
| 311 | *nclaimed = num_claimed; | 307 | *nclaimed = num_claimed; |
| 312 | 308 | ||
| @@ -345,7 +341,7 @@ static void pages_work_handler(struct work_struct *work) | |||
| 345 | } | 341 | } |
| 346 | 342 | ||
| 347 | void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, | 343 | void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, |
| 348 | s16 npages) | 344 | s32 npages) |
| 349 | { | 345 | { |
| 350 | struct mlx5_pages_req *req; | 346 | struct mlx5_pages_req *req; |
| 351 | 347 | ||
| @@ -364,20 +360,18 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, | |||
| 364 | 360 | ||
| 365 | int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot) | 361 | int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot) |
| 366 | { | 362 | { |
| 367 | u16 uninitialized_var(boot_pages); | ||
| 368 | s16 uninitialized_var(init_pages); | ||
| 369 | u16 uninitialized_var(func_id); | 363 | u16 uninitialized_var(func_id); |
| 364 | s32 uninitialized_var(npages); | ||
| 370 | int err; | 365 | int err; |
| 371 | 366 | ||
| 372 | err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages, | 367 | err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot); |
| 373 | &boot_pages); | ||
| 374 | if (err) | 368 | if (err) |
| 375 | return err; | 369 | return err; |
| 376 | 370 | ||
| 371 | mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n", | ||
| 372 | npages, boot ? "boot" : "init", func_id); | ||
| 377 | 373 | ||
| 378 | mlx5_core_dbg(dev, "requested %d init pages and %d boot pages for func_id 0x%x\n", | 374 | return give_pages(dev, func_id, npages, 0); |
| 379 | init_pages, boot_pages, func_id); | ||
| 380 | return give_pages(dev, func_id, boot ? boot_pages : init_pages, 0); | ||
| 381 | } | 375 | } |
| 382 | 376 | ||
| 383 | static int optimal_reclaimed_pages(void) | 377 | static int optimal_reclaimed_pages(void) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 92da9980a0a0..9d4bb7f83904 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
| @@ -3266,6 +3266,11 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) | |||
| 3266 | u8 val; | 3266 | u8 val; |
| 3267 | int ret, max_sds_rings = adapter->max_sds_rings; | 3267 | int ret, max_sds_rings = adapter->max_sds_rings; |
| 3268 | 3268 | ||
| 3269 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | ||
| 3270 | netdev_info(netdev, "Device is resetting\n"); | ||
| 3271 | return -EBUSY; | ||
| 3272 | } | ||
| 3273 | |||
| 3269 | if (qlcnic_get_diag_lock(adapter)) { | 3274 | if (qlcnic_get_diag_lock(adapter)) { |
| 3270 | netdev_info(netdev, "Device in diagnostics mode\n"); | 3275 | netdev_info(netdev, "Device in diagnostics mode\n"); |
| 3271 | return -EBUSY; | 3276 | return -EBUSY; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 9f4b8d5f0865..345d987aede4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
| @@ -629,7 +629,8 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | |||
| 629 | return -EIO; | 629 | return -EIO; |
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | qlcnic_set_drv_version(adapter); | 632 | if (adapter->portnum == 0) |
| 633 | qlcnic_set_drv_version(adapter); | ||
| 633 | qlcnic_83xx_idc_attach_driver(adapter); | 634 | qlcnic_83xx_idc_attach_driver(adapter); |
| 634 | 635 | ||
| 635 | return 0; | 636 | return 0; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index ee013fcc3322..bc05d016c859 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
| @@ -2165,7 +2165,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2165 | if (err) | 2165 | if (err) |
| 2166 | goto err_out_disable_mbx_intr; | 2166 | goto err_out_disable_mbx_intr; |
| 2167 | 2167 | ||
| 2168 | qlcnic_set_drv_version(adapter); | 2168 | if (adapter->portnum == 0) |
| 2169 | qlcnic_set_drv_version(adapter); | ||
| 2169 | 2170 | ||
| 2170 | pci_set_drvdata(pdev, adapter); | 2171 | pci_set_drvdata(pdev, adapter); |
| 2171 | 2172 | ||
| @@ -3085,7 +3086,8 @@ done: | |||
| 3085 | adapter->fw_fail_cnt = 0; | 3086 | adapter->fw_fail_cnt = 0; |
| 3086 | adapter->flags &= ~QLCNIC_FW_HANG; | 3087 | adapter->flags &= ~QLCNIC_FW_HANG; |
| 3087 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 3088 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
| 3088 | qlcnic_set_drv_version(adapter); | 3089 | if (adapter->portnum == 0) |
| 3090 | qlcnic_set_drv_version(adapter); | ||
| 3089 | 3091 | ||
| 3090 | if (!qlcnic_clr_drv_state(adapter)) | 3092 | if (!qlcnic_clr_drv_state(adapter)) |
| 3091 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, | 3093 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 10ed82b3baca..660c3f5b2237 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
| @@ -170,9 +170,9 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, | |||
| 170 | 170 | ||
| 171 | if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) { | 171 | if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) { |
| 172 | err = qlcnic_get_beacon_state(adapter, &h_beacon_state); | 172 | err = qlcnic_get_beacon_state(adapter, &h_beacon_state); |
| 173 | if (!err) { | 173 | if (err) { |
| 174 | dev_info(&adapter->pdev->dev, | 174 | netdev_err(adapter->netdev, |
| 175 | "Failed to get current beacon state\n"); | 175 | "Failed to get current beacon state\n"); |
| 176 | } else { | 176 | } else { |
| 177 | if (h_beacon_state == QLCNIC_BEACON_DISABLE) | 177 | if (h_beacon_state == QLCNIC_BEACON_DISABLE) |
| 178 | ahw->beacon_state = 0; | 178 | ahw->beacon_state = 0; |
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 6f35f8404d68..d2e591955bdd 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c | |||
| @@ -524,6 +524,7 @@ rx_status_loop: | |||
| 524 | PCI_DMA_FROMDEVICE); | 524 | PCI_DMA_FROMDEVICE); |
| 525 | if (dma_mapping_error(&cp->pdev->dev, new_mapping)) { | 525 | if (dma_mapping_error(&cp->pdev->dev, new_mapping)) { |
| 526 | dev->stats.rx_dropped++; | 526 | dev->stats.rx_dropped++; |
| 527 | kfree_skb(new_skb); | ||
| 527 | goto rx_next; | 528 | goto rx_next; |
| 528 | } | 529 | } |
| 529 | 530 | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c index c9d942a5c335..1ef9d8a555aa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c | |||
| @@ -33,10 +33,15 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) | |||
| 33 | struct stmmac_priv *priv = (struct stmmac_priv *)p; | 33 | struct stmmac_priv *priv = (struct stmmac_priv *)p; |
| 34 | unsigned int txsize = priv->dma_tx_size; | 34 | unsigned int txsize = priv->dma_tx_size; |
| 35 | unsigned int entry = priv->cur_tx % txsize; | 35 | unsigned int entry = priv->cur_tx % txsize; |
| 36 | struct dma_desc *desc = priv->dma_tx + entry; | 36 | struct dma_desc *desc; |
| 37 | unsigned int nopaged_len = skb_headlen(skb); | 37 | unsigned int nopaged_len = skb_headlen(skb); |
| 38 | unsigned int bmax, len; | 38 | unsigned int bmax, len; |
| 39 | 39 | ||
| 40 | if (priv->extend_desc) | ||
| 41 | desc = (struct dma_desc *)(priv->dma_etx + entry); | ||
| 42 | else | ||
| 43 | desc = priv->dma_tx + entry; | ||
| 44 | |||
| 40 | if (priv->plat->enh_desc) | 45 | if (priv->plat->enh_desc) |
| 41 | bmax = BUF_SIZE_8KiB; | 46 | bmax = BUF_SIZE_8KiB; |
| 42 | else | 47 | else |
| @@ -54,7 +59,11 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) | |||
| 54 | STMMAC_RING_MODE); | 59 | STMMAC_RING_MODE); |
| 55 | wmb(); | 60 | wmb(); |
| 56 | entry = (++priv->cur_tx) % txsize; | 61 | entry = (++priv->cur_tx) % txsize; |
| 57 | desc = priv->dma_tx + entry; | 62 | |
| 63 | if (priv->extend_desc) | ||
| 64 | desc = (struct dma_desc *)(priv->dma_etx + entry); | ||
| 65 | else | ||
| 66 | desc = priv->dma_tx + entry; | ||
| 58 | 67 | ||
| 59 | desc->des2 = dma_map_single(priv->device, skb->data + bmax, | 68 | desc->des2 = dma_map_single(priv->device, skb->data + bmax, |
| 60 | len, DMA_TO_DEVICE); | 69 | len, DMA_TO_DEVICE); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f2ccb36e8685..0a9bb9d30c3f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
| @@ -939,15 +939,20 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, | |||
| 939 | 939 | ||
| 940 | skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN, | 940 | skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN, |
| 941 | GFP_KERNEL); | 941 | GFP_KERNEL); |
| 942 | if (unlikely(skb == NULL)) { | 942 | if (!skb) { |
| 943 | pr_err("%s: Rx init fails; skb is NULL\n", __func__); | 943 | pr_err("%s: Rx init fails; skb is NULL\n", __func__); |
| 944 | return 1; | 944 | return -ENOMEM; |
| 945 | } | 945 | } |
| 946 | skb_reserve(skb, NET_IP_ALIGN); | 946 | skb_reserve(skb, NET_IP_ALIGN); |
| 947 | priv->rx_skbuff[i] = skb; | 947 | priv->rx_skbuff[i] = skb; |
| 948 | priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, | 948 | priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, |
| 949 | priv->dma_buf_sz, | 949 | priv->dma_buf_sz, |
| 950 | DMA_FROM_DEVICE); | 950 | DMA_FROM_DEVICE); |
| 951 | if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { | ||
| 952 | pr_err("%s: DMA mapping error\n", __func__); | ||
| 953 | dev_kfree_skb_any(skb); | ||
| 954 | return -EINVAL; | ||
| 955 | } | ||
| 951 | 956 | ||
| 952 | p->des2 = priv->rx_skbuff_dma[i]; | 957 | p->des2 = priv->rx_skbuff_dma[i]; |
| 953 | 958 | ||
| @@ -958,6 +963,16 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, | |||
| 958 | return 0; | 963 | return 0; |
| 959 | } | 964 | } |
| 960 | 965 | ||
| 966 | static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) | ||
| 967 | { | ||
| 968 | if (priv->rx_skbuff[i]) { | ||
| 969 | dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], | ||
| 970 | priv->dma_buf_sz, DMA_FROM_DEVICE); | ||
| 971 | dev_kfree_skb_any(priv->rx_skbuff[i]); | ||
| 972 | } | ||
| 973 | priv->rx_skbuff[i] = NULL; | ||
| 974 | } | ||
| 975 | |||
| 961 | /** | 976 | /** |
| 962 | * init_dma_desc_rings - init the RX/TX descriptor rings | 977 | * init_dma_desc_rings - init the RX/TX descriptor rings |
| 963 | * @dev: net device structure | 978 | * @dev: net device structure |
| @@ -965,13 +980,14 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, | |||
| 965 | * and allocates the socket buffers. It suppors the chained and ring | 980 | * and allocates the socket buffers. It suppors the chained and ring |
| 966 | * modes. | 981 | * modes. |
| 967 | */ | 982 | */ |
| 968 | static void init_dma_desc_rings(struct net_device *dev) | 983 | static int init_dma_desc_rings(struct net_device *dev) |
| 969 | { | 984 | { |
| 970 | int i; | 985 | int i; |
| 971 | struct stmmac_priv *priv = netdev_priv(dev); | 986 | struct stmmac_priv *priv = netdev_priv(dev); |
| 972 | unsigned int txsize = priv->dma_tx_size; | 987 | unsigned int txsize = priv->dma_tx_size; |
| 973 | unsigned int rxsize = priv->dma_rx_size; | 988 | unsigned int rxsize = priv->dma_rx_size; |
| 974 | unsigned int bfsize = 0; | 989 | unsigned int bfsize = 0; |
| 990 | int ret = -ENOMEM; | ||
| 975 | 991 | ||
| 976 | /* Set the max buffer size according to the DESC mode | 992 | /* Set the max buffer size according to the DESC mode |
| 977 | * and the MTU. Note that RING mode allows 16KiB bsize. | 993 | * and the MTU. Note that RING mode allows 16KiB bsize. |
| @@ -992,34 +1008,60 @@ static void init_dma_desc_rings(struct net_device *dev) | |||
| 992 | dma_extended_desc), | 1008 | dma_extended_desc), |
| 993 | &priv->dma_rx_phy, | 1009 | &priv->dma_rx_phy, |
| 994 | GFP_KERNEL); | 1010 | GFP_KERNEL); |
| 1011 | if (!priv->dma_erx) | ||
| 1012 | goto err_dma; | ||
| 1013 | |||
| 995 | priv->dma_etx = dma_alloc_coherent(priv->device, txsize * | 1014 | priv->dma_etx = dma_alloc_coherent(priv->device, txsize * |
| 996 | sizeof(struct | 1015 | sizeof(struct |
| 997 | dma_extended_desc), | 1016 | dma_extended_desc), |
| 998 | &priv->dma_tx_phy, | 1017 | &priv->dma_tx_phy, |
| 999 | GFP_KERNEL); | 1018 | GFP_KERNEL); |
| 1000 | if ((!priv->dma_erx) || (!priv->dma_etx)) | 1019 | if (!priv->dma_etx) { |
| 1001 | return; | 1020 | dma_free_coherent(priv->device, priv->dma_rx_size * |
| 1021 | sizeof(struct dma_extended_desc), | ||
| 1022 | priv->dma_erx, priv->dma_rx_phy); | ||
| 1023 | goto err_dma; | ||
| 1024 | } | ||
| 1002 | } else { | 1025 | } else { |
| 1003 | priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * | 1026 | priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * |
| 1004 | sizeof(struct dma_desc), | 1027 | sizeof(struct dma_desc), |
| 1005 | &priv->dma_rx_phy, | 1028 | &priv->dma_rx_phy, |
| 1006 | GFP_KERNEL); | 1029 | GFP_KERNEL); |
| 1030 | if (!priv->dma_rx) | ||
| 1031 | goto err_dma; | ||
| 1032 | |||
| 1007 | priv->dma_tx = dma_alloc_coherent(priv->device, txsize * | 1033 | priv->dma_tx = dma_alloc_coherent(priv->device, txsize * |
| 1008 | sizeof(struct dma_desc), | 1034 | sizeof(struct dma_desc), |
| 1009 | &priv->dma_tx_phy, | 1035 | &priv->dma_tx_phy, |
| 1010 | GFP_KERNEL); | 1036 | GFP_KERNEL); |
| 1011 | if ((!priv->dma_rx) || (!priv->dma_tx)) | 1037 | if (!priv->dma_tx) { |
| 1012 | return; | 1038 | dma_free_coherent(priv->device, priv->dma_rx_size * |
| 1039 | sizeof(struct dma_desc), | ||
| 1040 | priv->dma_rx, priv->dma_rx_phy); | ||
| 1041 | goto err_dma; | ||
| 1042 | } | ||
| 1013 | } | 1043 | } |
| 1014 | 1044 | ||
| 1015 | priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), | 1045 | priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), |
| 1016 | GFP_KERNEL); | 1046 | GFP_KERNEL); |
| 1047 | if (!priv->rx_skbuff_dma) | ||
| 1048 | goto err_rx_skbuff_dma; | ||
| 1049 | |||
| 1017 | priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), | 1050 | priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), |
| 1018 | GFP_KERNEL); | 1051 | GFP_KERNEL); |
| 1052 | if (!priv->rx_skbuff) | ||
| 1053 | goto err_rx_skbuff; | ||
| 1054 | |||
| 1019 | priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t), | 1055 | priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t), |
| 1020 | GFP_KERNEL); | 1056 | GFP_KERNEL); |
| 1057 | if (!priv->tx_skbuff_dma) | ||
| 1058 | goto err_tx_skbuff_dma; | ||
| 1059 | |||
| 1021 | priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), | 1060 | priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), |
| 1022 | GFP_KERNEL); | 1061 | GFP_KERNEL); |
| 1062 | if (!priv->tx_skbuff) | ||
| 1063 | goto err_tx_skbuff; | ||
| 1064 | |||
| 1023 | if (netif_msg_probe(priv)) { | 1065 | if (netif_msg_probe(priv)) { |
| 1024 | pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, | 1066 | pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, |
| 1025 | (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); | 1067 | (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); |
| @@ -1034,8 +1076,9 @@ static void init_dma_desc_rings(struct net_device *dev) | |||
| 1034 | else | 1076 | else |
| 1035 | p = priv->dma_rx + i; | 1077 | p = priv->dma_rx + i; |
| 1036 | 1078 | ||
| 1037 | if (stmmac_init_rx_buffers(priv, p, i)) | 1079 | ret = stmmac_init_rx_buffers(priv, p, i); |
| 1038 | break; | 1080 | if (ret) |
| 1081 | goto err_init_rx_buffers; | ||
| 1039 | 1082 | ||
| 1040 | if (netif_msg_probe(priv)) | 1083 | if (netif_msg_probe(priv)) |
| 1041 | pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], | 1084 | pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], |
| @@ -1081,20 +1124,44 @@ static void init_dma_desc_rings(struct net_device *dev) | |||
| 1081 | 1124 | ||
| 1082 | if (netif_msg_hw(priv)) | 1125 | if (netif_msg_hw(priv)) |
| 1083 | stmmac_display_rings(priv); | 1126 | stmmac_display_rings(priv); |
| 1127 | |||
| 1128 | return 0; | ||
| 1129 | err_init_rx_buffers: | ||
| 1130 | while (--i >= 0) | ||
| 1131 | stmmac_free_rx_buffers(priv, i); | ||
| 1132 | kfree(priv->tx_skbuff); | ||
| 1133 | err_tx_skbuff: | ||
| 1134 | kfree(priv->tx_skbuff_dma); | ||
| 1135 | err_tx_skbuff_dma: | ||
| 1136 | kfree(priv->rx_skbuff); | ||
| 1137 | err_rx_skbuff: | ||
| 1138 | kfree(priv->rx_skbuff_dma); | ||
| 1139 | err_rx_skbuff_dma: | ||
| 1140 | if (priv->extend_desc) { | ||
| 1141 | dma_free_coherent(priv->device, priv->dma_tx_size * | ||
| 1142 | sizeof(struct dma_extended_desc), | ||
| 1143 | priv->dma_etx, priv->dma_tx_phy); | ||
| 1144 | dma_free_coherent(priv->device, priv->dma_rx_size * | ||
| 1145 | sizeof(struct dma_extended_desc), | ||
| 1146 | priv->dma_erx, priv->dma_rx_phy); | ||
| 1147 | } else { | ||
| 1148 | dma_free_coherent(priv->device, | ||
| 1149 | priv->dma_tx_size * sizeof(struct dma_desc), | ||
| 1150 | priv->dma_tx, priv->dma_tx_phy); | ||
| 1151 | dma_free_coherent(priv->device, | ||
| 1152 | priv->dma_rx_size * sizeof(struct dma_desc), | ||
| 1153 | priv->dma_rx, priv->dma_rx_phy); | ||
| 1154 | } | ||
| 1155 | err_dma: | ||
| 1156 | return ret; | ||
| 1084 | } | 1157 | } |
| 1085 | 1158 | ||
| 1086 | static void dma_free_rx_skbufs(struct stmmac_priv *priv) | 1159 | static void dma_free_rx_skbufs(struct stmmac_priv *priv) |
| 1087 | { | 1160 | { |
| 1088 | int i; | 1161 | int i; |
| 1089 | 1162 | ||
| 1090 | for (i = 0; i < priv->dma_rx_size; i++) { | 1163 | for (i = 0; i < priv->dma_rx_size; i++) |
| 1091 | if (priv->rx_skbuff[i]) { | 1164 | stmmac_free_rx_buffers(priv, i); |
| 1092 | dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], | ||
| 1093 | priv->dma_buf_sz, DMA_FROM_DEVICE); | ||
| 1094 | dev_kfree_skb_any(priv->rx_skbuff[i]); | ||
| 1095 | } | ||
| 1096 | priv->rx_skbuff[i] = NULL; | ||
| 1097 | } | ||
| 1098 | } | 1165 | } |
| 1099 | 1166 | ||
| 1100 | static void dma_free_tx_skbufs(struct stmmac_priv *priv) | 1167 | static void dma_free_tx_skbufs(struct stmmac_priv *priv) |
| @@ -1560,12 +1627,17 @@ static int stmmac_open(struct net_device *dev) | |||
| 1560 | priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); | 1627 | priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); |
| 1561 | priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); | 1628 | priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); |
| 1562 | priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); | 1629 | priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); |
| 1563 | init_dma_desc_rings(dev); | 1630 | |
| 1631 | ret = init_dma_desc_rings(dev); | ||
| 1632 | if (ret < 0) { | ||
| 1633 | pr_err("%s: DMA descriptors initialization failed\n", __func__); | ||
| 1634 | goto dma_desc_error; | ||
| 1635 | } | ||
| 1564 | 1636 | ||
| 1565 | /* DMA initialization and SW reset */ | 1637 | /* DMA initialization and SW reset */ |
| 1566 | ret = stmmac_init_dma_engine(priv); | 1638 | ret = stmmac_init_dma_engine(priv); |
| 1567 | if (ret < 0) { | 1639 | if (ret < 0) { |
| 1568 | pr_err("%s: DMA initialization failed\n", __func__); | 1640 | pr_err("%s: DMA engine initialization failed\n", __func__); |
| 1569 | goto init_error; | 1641 | goto init_error; |
| 1570 | } | 1642 | } |
| 1571 | 1643 | ||
| @@ -1672,6 +1744,7 @@ wolirq_error: | |||
| 1672 | 1744 | ||
| 1673 | init_error: | 1745 | init_error: |
| 1674 | free_dma_desc_resources(priv); | 1746 | free_dma_desc_resources(priv); |
| 1747 | dma_desc_error: | ||
| 1675 | if (priv->phydev) | 1748 | if (priv->phydev) |
| 1676 | phy_disconnect(priv->phydev); | 1749 | phy_disconnect(priv->phydev); |
| 1677 | phy_error: | 1750 | phy_error: |
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 1d6dc41f755d..d01cacf8a7c2 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c | |||
| @@ -2100,7 +2100,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) | |||
| 2100 | 2100 | ||
| 2101 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); | 2101 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); |
| 2102 | } | 2102 | } |
| 2103 | netif_rx(skb); | 2103 | netif_receive_skb(skb); |
| 2104 | 2104 | ||
| 2105 | stats->rx_bytes += pkt_len; | 2105 | stats->rx_bytes += pkt_len; |
| 2106 | stats->rx_packets++; | 2106 | stats->rx_packets++; |
| @@ -2884,6 +2884,7 @@ out: | |||
| 2884 | return ret; | 2884 | return ret; |
| 2885 | 2885 | ||
| 2886 | err_iounmap: | 2886 | err_iounmap: |
| 2887 | netif_napi_del(&vptr->napi); | ||
| 2887 | iounmap(regs); | 2888 | iounmap(regs); |
| 2888 | err_free_dev: | 2889 | err_free_dev: |
| 2889 | free_netdev(netdev); | 2890 | free_netdev(netdev); |
| @@ -2904,6 +2905,7 @@ static int velocity_remove(struct device *dev) | |||
| 2904 | struct velocity_info *vptr = netdev_priv(netdev); | 2905 | struct velocity_info *vptr = netdev_priv(netdev); |
| 2905 | 2906 | ||
| 2906 | unregister_netdev(netdev); | 2907 | unregister_netdev(netdev); |
| 2908 | netif_napi_del(&vptr->napi); | ||
| 2907 | iounmap(vptr->mac_regs); | 2909 | iounmap(vptr->mac_regs); |
| 2908 | free_netdev(netdev); | 2910 | free_netdev(netdev); |
| 2909 | velocity_nics--; | 2911 | velocity_nics--; |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d0f9c2fd1d4f..16b43bf544b7 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
| @@ -739,6 +739,10 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
| 739 | return -EADDRNOTAVAIL; | 739 | return -EADDRNOTAVAIL; |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | if (data && data[IFLA_MACVLAN_FLAGS] && | ||
| 743 | nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC) | ||
| 744 | return -EINVAL; | ||
| 745 | |||
| 742 | if (data && data[IFLA_MACVLAN_MODE]) { | 746 | if (data && data[IFLA_MACVLAN_MODE]) { |
| 743 | switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) { | 747 | switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) { |
| 744 | case MACVLAN_MODE_PRIVATE: | 748 | case MACVLAN_MODE_PRIVATE: |
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index a98fb0ed6aef..b51db2abfe44 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
| @@ -818,10 +818,13 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
| 818 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 818 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; |
| 819 | skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; | 819 | skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; |
| 820 | } | 820 | } |
| 821 | if (vlan) | 821 | if (vlan) { |
| 822 | local_bh_disable(); | ||
| 822 | macvlan_start_xmit(skb, vlan->dev); | 823 | macvlan_start_xmit(skb, vlan->dev); |
| 823 | else | 824 | local_bh_enable(); |
| 825 | } else { | ||
| 824 | kfree_skb(skb); | 826 | kfree_skb(skb); |
| 827 | } | ||
| 825 | rcu_read_unlock(); | 828 | rcu_read_unlock(); |
| 826 | 829 | ||
| 827 | return total_len; | 830 | return total_len; |
| @@ -912,8 +915,11 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
| 912 | done: | 915 | done: |
| 913 | rcu_read_lock(); | 916 | rcu_read_lock(); |
| 914 | vlan = rcu_dereference(q->vlan); | 917 | vlan = rcu_dereference(q->vlan); |
| 915 | if (vlan) | 918 | if (vlan) { |
| 919 | preempt_disable(); | ||
| 916 | macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); | 920 | macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); |
| 921 | preempt_enable(); | ||
| 922 | } | ||
| 917 | rcu_read_unlock(); | 923 | rcu_read_unlock(); |
| 918 | 924 | ||
| 919 | return ret ? ret : copied; | 925 | return ret ? ret : copied; |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index db690a372260..71af122edf2d 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -1074,8 +1074,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1074 | u32 rxhash; | 1074 | u32 rxhash; |
| 1075 | 1075 | ||
| 1076 | if (!(tun->flags & TUN_NO_PI)) { | 1076 | if (!(tun->flags & TUN_NO_PI)) { |
| 1077 | if ((len -= sizeof(pi)) > total_len) | 1077 | if (len < sizeof(pi)) |
| 1078 | return -EINVAL; | 1078 | return -EINVAL; |
| 1079 | len -= sizeof(pi); | ||
| 1079 | 1080 | ||
| 1080 | if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) | 1081 | if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) |
| 1081 | return -EFAULT; | 1082 | return -EFAULT; |
| @@ -1083,8 +1084,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1083 | } | 1084 | } |
| 1084 | 1085 | ||
| 1085 | if (tun->flags & TUN_VNET_HDR) { | 1086 | if (tun->flags & TUN_VNET_HDR) { |
| 1086 | if ((len -= tun->vnet_hdr_sz) > total_len) | 1087 | if (len < tun->vnet_hdr_sz) |
| 1087 | return -EINVAL; | 1088 | return -EINVAL; |
| 1089 | len -= tun->vnet_hdr_sz; | ||
| 1088 | 1090 | ||
| 1089 | if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) | 1091 | if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) |
| 1090 | return -EFAULT; | 1092 | return -EFAULT; |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f4c6db419ddb..767f7af3bd40 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -1386,7 +1386,7 @@ static int vxlan_open(struct net_device *dev) | |||
| 1386 | return -ENOTCONN; | 1386 | return -ENOTCONN; |
| 1387 | 1387 | ||
| 1388 | if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) && | 1388 | if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) && |
| 1389 | ! vxlan_group_used(vn, vxlan->default_dst.remote_ip)) { | 1389 | vxlan_group_used(vn, vxlan->default_dst.remote_ip)) { |
| 1390 | vxlan_sock_hold(vs); | 1390 | vxlan_sock_hold(vs); |
| 1391 | dev_hold(dev); | 1391 | dev_hold(dev); |
| 1392 | queue_work(vxlan_wq, &vxlan->igmp_join); | 1392 | queue_work(vxlan_wq, &vxlan->igmp_join); |
| @@ -1793,8 +1793,6 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head) | |||
| 1793 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); | 1793 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); |
| 1794 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1794 | struct vxlan_dev *vxlan = netdev_priv(dev); |
| 1795 | 1795 | ||
| 1796 | flush_workqueue(vxlan_wq); | ||
| 1797 | |||
| 1798 | spin_lock(&vn->sock_lock); | 1796 | spin_lock(&vn->sock_lock); |
| 1799 | hlist_del_rcu(&vxlan->hlist); | 1797 | hlist_del_rcu(&vxlan->hlist); |
| 1800 | spin_unlock(&vn->sock_lock); | 1798 | spin_unlock(&vn->sock_lock); |
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index 7365674366f4..010b252be584 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c | |||
| @@ -1406,11 +1406,8 @@ static void cw1200_do_unjoin(struct cw1200_common *priv) | |||
| 1406 | if (!priv->join_status) | 1406 | if (!priv->join_status) |
| 1407 | goto done; | 1407 | goto done; |
| 1408 | 1408 | ||
| 1409 | if (priv->join_status > CW1200_JOIN_STATUS_IBSS) { | 1409 | if (priv->join_status == CW1200_JOIN_STATUS_AP) |
| 1410 | wiphy_err(priv->hw->wiphy, "Unexpected: join status: %d\n", | 1410 | goto done; |
| 1411 | priv->join_status); | ||
| 1412 | BUG_ON(1); | ||
| 1413 | } | ||
| 1414 | 1411 | ||
| 1415 | cancel_work_sync(&priv->update_filtering_work); | 1412 | cancel_work_sync(&priv->update_filtering_work); |
| 1416 | cancel_work_sync(&priv->set_beacon_wakeup_period_work); | 1413 | cancel_work_sync(&priv->set_beacon_wakeup_period_work); |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index b9b2bb51e605..f2ed62e37340 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
| @@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il) | |||
| 4460 | * is killed. Hence update the killswitch state here. The | 4460 | * is killed. Hence update the killswitch state here. The |
| 4461 | * rfkill handler will care about restarting if needed. | 4461 | * rfkill handler will care about restarting if needed. |
| 4462 | */ | 4462 | */ |
| 4463 | if (!test_bit(S_ALIVE, &il->status)) { | 4463 | if (hw_rf_kill) { |
| 4464 | if (hw_rf_kill) | 4464 | set_bit(S_RFKILL, &il->status); |
| 4465 | set_bit(S_RFKILL, &il->status); | 4465 | } else { |
| 4466 | else | 4466 | clear_bit(S_RFKILL, &il->status); |
| 4467 | clear_bit(S_RFKILL, &il->status); | ||
| 4468 | wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); | 4467 | wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); |
| 4468 | il_force_reset(il, true); | ||
| 4469 | } | 4469 | } |
| 4470 | 4470 | ||
| 4471 | handled |= CSR_INT_BIT_RF_KILL; | 4471 | handled |= CSR_INT_BIT_RF_KILL; |
| @@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il) | |||
| 5334 | 5334 | ||
| 5335 | il->active_rate = RATES_MASK; | 5335 | il->active_rate = RATES_MASK; |
| 5336 | 5336 | ||
| 5337 | il_power_update_mode(il, true); | ||
| 5338 | D_INFO("Updated power mode\n"); | ||
| 5339 | |||
| 5337 | if (il_is_associated(il)) { | 5340 | if (il_is_associated(il)) { |
| 5338 | struct il_rxon_cmd *active_rxon = | 5341 | struct il_rxon_cmd *active_rxon = |
| 5339 | (struct il_rxon_cmd *)&il->active; | 5342 | (struct il_rxon_cmd *)&il->active; |
| @@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il) | |||
| 5364 | D_INFO("ALIVE processing complete.\n"); | 5367 | D_INFO("ALIVE processing complete.\n"); |
| 5365 | wake_up(&il->wait_command_queue); | 5368 | wake_up(&il->wait_command_queue); |
| 5366 | 5369 | ||
| 5367 | il_power_update_mode(il, true); | ||
| 5368 | D_INFO("Updated power mode\n"); | ||
| 5369 | |||
| 5370 | return; | 5370 | return; |
| 5371 | 5371 | ||
| 5372 | restart: | 5372 | restart: |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 3195aad440dd..b03e22ef5462 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
| @@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external) | |||
| 4660 | 4660 | ||
| 4661 | return 0; | 4661 | return 0; |
| 4662 | } | 4662 | } |
| 4663 | EXPORT_SYMBOL(il_force_reset); | ||
| 4663 | 4664 | ||
| 4664 | int | 4665 | int |
| 4665 | il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 4666 | il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index dbdc5f7e2b29..01e264fb50e0 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -317,13 +317,20 @@ void acpi_pci_remove_bus(struct pci_bus *bus) | |||
| 317 | /* ACPI bus type */ | 317 | /* ACPI bus type */ |
| 318 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) | 318 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) |
| 319 | { | 319 | { |
| 320 | struct pci_dev * pci_dev; | 320 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 321 | u64 addr; | 321 | bool is_bridge; |
| 322 | u64 addr; | ||
| 322 | 323 | ||
| 323 | pci_dev = to_pci_dev(dev); | 324 | /* |
| 325 | * pci_is_bridge() is not suitable here, because pci_dev->subordinate | ||
| 326 | * is set only after acpi_pci_find_device() has been called for the | ||
| 327 | * given device. | ||
| 328 | */ | ||
| 329 | is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE | ||
| 330 | || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; | ||
| 324 | /* Please ref to ACPI spec for the syntax of _ADR */ | 331 | /* Please ref to ACPI spec for the syntax of _ADR */ |
| 325 | addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); | 332 | addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); |
| 326 | *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); | 333 | *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge); |
| 327 | if (!*handle) | 334 | if (!*handle) |
| 328 | return -ENODEV; | 335 | return -ENODEV; |
| 329 | return 0; | 336 | return 0; |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 767fee2ab340..26019531db15 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/delay.h> | ||
| 26 | #include <linux/rtc.h> | 27 | #include <linux/rtc.h> |
| 27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 28 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
| @@ -119,24 +120,39 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) | |||
| 119 | } | 120 | } |
| 120 | #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */ | 121 | #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */ |
| 121 | 122 | ||
| 122 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | 123 | static int stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) |
| 123 | { | 124 | { |
| 125 | int timeout = 5000; /* 3ms according to i.MX28 Ref Manual */ | ||
| 124 | /* | 126 | /* |
| 125 | * The datasheet doesn't say which way round the | 127 | * The i.MX28 Applications Processor Reference Manual, Rev. 1, 2010 |
| 126 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, | 128 | * states: |
| 127 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS | 129 | * | The order in which registers are updated is |
| 130 | * | Persistent 0, 1, 2, 3, 4, 5, Alarm, Seconds. | ||
| 131 | * | (This list is in bitfield order, from LSB to MSB, as they would | ||
| 132 | * | appear in the STALE_REGS and NEW_REGS bitfields of the HW_RTC_STAT | ||
| 133 | * | register. For example, the Seconds register corresponds to | ||
| 134 | * | STALE_REGS or NEW_REGS containing 0x80.) | ||
| 128 | */ | 135 | */ |
| 129 | while (readl(rtc_data->io + STMP3XXX_RTC_STAT) & | 136 | do { |
| 130 | (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) | 137 | if (!(readl(rtc_data->io + STMP3XXX_RTC_STAT) & |
| 131 | cpu_relax(); | 138 | (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))) |
| 139 | return 0; | ||
| 140 | udelay(1); | ||
| 141 | } while (--timeout > 0); | ||
| 142 | return (readl(rtc_data->io + STMP3XXX_RTC_STAT) & | ||
| 143 | (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) ? -ETIME : 0; | ||
| 132 | } | 144 | } |
| 133 | 145 | ||
| 134 | /* Time read/write */ | 146 | /* Time read/write */ |
| 135 | static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | 147 | static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) |
| 136 | { | 148 | { |
| 149 | int ret; | ||
| 137 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 150 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
| 138 | 151 | ||
| 139 | stmp3xxx_wait_time(rtc_data); | 152 | ret = stmp3xxx_wait_time(rtc_data); |
| 153 | if (ret) | ||
| 154 | return ret; | ||
| 155 | |||
| 140 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm); | 156 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm); |
| 141 | return 0; | 157 | return 0; |
| 142 | } | 158 | } |
| @@ -146,8 +162,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | |||
| 146 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 162 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
| 147 | 163 | ||
| 148 | writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS); | 164 | writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS); |
| 149 | stmp3xxx_wait_time(rtc_data); | 165 | return stmp3xxx_wait_time(rtc_data); |
| 150 | return 0; | ||
| 151 | } | 166 | } |
| 152 | 167 | ||
| 153 | /* interrupt(s) handler */ | 168 | /* interrupt(s) handler */ |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 17150a778984..451bf99582ff 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -2392,6 +2392,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) | |||
| 2392 | rc = cqr->intrc; | 2392 | rc = cqr->intrc; |
| 2393 | else | 2393 | else |
| 2394 | rc = -EIO; | 2394 | rc = -EIO; |
| 2395 | |||
| 2396 | /* kick tasklets */ | ||
| 2397 | dasd_schedule_device_bh(device); | ||
| 2398 | if (device->block) | ||
| 2399 | dasd_schedule_block_bh(device->block); | ||
| 2400 | |||
| 2395 | return rc; | 2401 | return rc; |
| 2396 | } | 2402 | } |
| 2397 | 2403 | ||
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index b6d1f92ed33c..c18c68150e9f 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #define DRV_NAME "fnic" | 39 | #define DRV_NAME "fnic" |
| 40 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 40 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 41 | #define DRV_VERSION "1.5.0.22" | 41 | #define DRV_VERSION "1.5.0.23" |
| 42 | #define PFX DRV_NAME ": " | 42 | #define PFX DRV_NAME ": " |
| 43 | #define DFX DRV_NAME "%d: " | 43 | #define DFX DRV_NAME "%d: " |
| 44 | 44 | ||
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 5f09d1814d26..42e15ee6e1bb 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
| @@ -642,19 +642,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 642 | INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); | 642 | INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); |
| 643 | INIT_WORK(&fnic->event_work, fnic_handle_event); | 643 | INIT_WORK(&fnic->event_work, fnic_handle_event); |
| 644 | skb_queue_head_init(&fnic->fip_frame_queue); | 644 | skb_queue_head_init(&fnic->fip_frame_queue); |
| 645 | spin_lock_irqsave(&fnic_list_lock, flags); | ||
| 646 | if (!fnic_fip_queue) { | ||
| 647 | fnic_fip_queue = | ||
| 648 | create_singlethread_workqueue("fnic_fip_q"); | ||
| 649 | if (!fnic_fip_queue) { | ||
| 650 | spin_unlock_irqrestore(&fnic_list_lock, flags); | ||
| 651 | printk(KERN_ERR PFX "fnic FIP work queue " | ||
| 652 | "create failed\n"); | ||
| 653 | err = -ENOMEM; | ||
| 654 | goto err_out_free_max_pool; | ||
| 655 | } | ||
| 656 | } | ||
| 657 | spin_unlock_irqrestore(&fnic_list_lock, flags); | ||
| 658 | INIT_LIST_HEAD(&fnic->evlist); | 645 | INIT_LIST_HEAD(&fnic->evlist); |
| 659 | INIT_LIST_HEAD(&fnic->vlans); | 646 | INIT_LIST_HEAD(&fnic->vlans); |
| 660 | } else { | 647 | } else { |
| @@ -960,6 +947,13 @@ static int __init fnic_init_module(void) | |||
| 960 | spin_lock_init(&fnic_list_lock); | 947 | spin_lock_init(&fnic_list_lock); |
| 961 | INIT_LIST_HEAD(&fnic_list); | 948 | INIT_LIST_HEAD(&fnic_list); |
| 962 | 949 | ||
| 950 | fnic_fip_queue = create_singlethread_workqueue("fnic_fip_q"); | ||
| 951 | if (!fnic_fip_queue) { | ||
| 952 | printk(KERN_ERR PFX "fnic FIP work queue create failed\n"); | ||
| 953 | err = -ENOMEM; | ||
| 954 | goto err_create_fip_workq; | ||
| 955 | } | ||
| 956 | |||
| 963 | fnic_fc_transport = fc_attach_transport(&fnic_fc_functions); | 957 | fnic_fc_transport = fc_attach_transport(&fnic_fc_functions); |
| 964 | if (!fnic_fc_transport) { | 958 | if (!fnic_fc_transport) { |
| 965 | printk(KERN_ERR PFX "fc_attach_transport error\n"); | 959 | printk(KERN_ERR PFX "fc_attach_transport error\n"); |
| @@ -978,6 +972,8 @@ static int __init fnic_init_module(void) | |||
| 978 | err_pci_register: | 972 | err_pci_register: |
| 979 | fc_release_transport(fnic_fc_transport); | 973 | fc_release_transport(fnic_fc_transport); |
| 980 | err_fc_transport: | 974 | err_fc_transport: |
| 975 | destroy_workqueue(fnic_fip_queue); | ||
| 976 | err_create_fip_workq: | ||
| 981 | destroy_workqueue(fnic_event_queue); | 977 | destroy_workqueue(fnic_event_queue); |
| 982 | err_create_fnic_workq: | 978 | err_create_fnic_workq: |
| 983 | kmem_cache_destroy(fnic_io_req_cache); | 979 | kmem_cache_destroy(fnic_io_req_cache); |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 0177295599e0..1f0ca68409d4 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
| @@ -3547,11 +3547,21 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 3547 | break; | 3547 | break; |
| 3548 | } | 3548 | } |
| 3549 | 3549 | ||
| 3550 | /* | 3550 | if (megasas_transition_to_ready(instance, 0)) { |
| 3551 | * We expect the FW state to be READY | 3551 | atomic_set(&instance->fw_reset_no_pci_access, 1); |
| 3552 | */ | 3552 | instance->instancet->adp_reset |
| 3553 | if (megasas_transition_to_ready(instance, 0)) | 3553 | (instance, instance->reg_set); |
| 3554 | goto fail_ready_state; | 3554 | atomic_set(&instance->fw_reset_no_pci_access, 0); |
| 3555 | dev_info(&instance->pdev->dev, | ||
| 3556 | "megasas: FW restarted successfully from %s!\n", | ||
| 3557 | __func__); | ||
| 3558 | |||
| 3559 | /*waitting for about 30 second before retry*/ | ||
| 3560 | ssleep(30); | ||
| 3561 | |||
| 3562 | if (megasas_transition_to_ready(instance, 0)) | ||
| 3563 | goto fail_ready_state; | ||
| 3564 | } | ||
| 3555 | 3565 | ||
| 3556 | /* | 3566 | /* |
| 3557 | * MSI-X host index 0 is common for all adapter. | 3567 | * MSI-X host index 0 is common for all adapter. |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 3b1ea34e1f5a..eaa808e6ba91 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -1031,6 +1031,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, | |||
| 1031 | { | 1031 | { |
| 1032 | int i, result; | 1032 | int i, result; |
| 1033 | 1033 | ||
| 1034 | if (sdev->skip_vpd_pages) | ||
| 1035 | goto fail; | ||
| 1036 | |||
| 1034 | /* Ask for all the pages supported by this device */ | 1037 | /* Ask for all the pages supported by this device */ |
| 1035 | result = scsi_vpd_inquiry(sdev, buf, 0, buf_len); | 1038 | result = scsi_vpd_inquiry(sdev, buf, 0, buf_len); |
| 1036 | if (result) | 1039 | if (result) |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 2168258fb2c3..74b88efde6ad 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
| @@ -751,7 +751,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) | |||
| 751 | 751 | ||
| 752 | vscsi->affinity_hint_set = true; | 752 | vscsi->affinity_hint_set = true; |
| 753 | } else { | 753 | } else { |
| 754 | for (i = 0; i < vscsi->num_queues - VIRTIO_SCSI_VQ_BASE; i++) | 754 | for (i = 0; i < vscsi->num_queues; i++) |
| 755 | virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); | 755 | virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); |
| 756 | 756 | ||
| 757 | vscsi->affinity_hint_set = false; | 757 | vscsi->affinity_hint_set = false; |
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 222d3e37fc28..707966bd5610 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c | |||
| @@ -609,7 +609,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 609 | else | 609 | else |
| 610 | buf = (void *)t->tx_buf; | 610 | buf = (void *)t->tx_buf; |
| 611 | t->tx_dma = dma_map_single(&spi->dev, buf, | 611 | t->tx_dma = dma_map_single(&spi->dev, buf, |
| 612 | t->len, DMA_FROM_DEVICE); | 612 | t->len, DMA_TO_DEVICE); |
| 613 | if (!t->tx_dma) { | 613 | if (!t->tx_dma) { |
| 614 | ret = -EFAULT; | 614 | ret = -EFAULT; |
| 615 | goto err_tx_map; | 615 | goto err_tx_map; |
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index dcceed29d31a..81972fa47beb 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c | |||
| @@ -1811,10 +1811,12 @@ static int zcache_comp_init(void) | |||
| 1811 | #else | 1811 | #else |
| 1812 | if (*zcache_comp_name != '\0') { | 1812 | if (*zcache_comp_name != '\0') { |
| 1813 | ret = crypto_has_comp(zcache_comp_name, 0, 0); | 1813 | ret = crypto_has_comp(zcache_comp_name, 0, 0); |
| 1814 | if (!ret) | 1814 | if (!ret) { |
| 1815 | pr_info("zcache: %s not supported\n", | 1815 | pr_info("zcache: %s not supported\n", |
| 1816 | zcache_comp_name); | 1816 | zcache_comp_name); |
| 1817 | goto out; | 1817 | ret = 1; |
| 1818 | goto out; | ||
| 1819 | } | ||
| 1818 | } | 1820 | } |
| 1819 | if (!ret) | 1821 | if (!ret) |
| 1820 | strcpy(zcache_comp_name, "lzo"); | 1822 | strcpy(zcache_comp_name, "lzo"); |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 609dbc2f7151..83b4ef4dfcf8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
| @@ -1119,11 +1119,11 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
| 1119 | /* Determine if it is a Rigol or not */ | 1119 | /* Determine if it is a Rigol or not */ |
| 1120 | data->rigol_quirk = 0; | 1120 | data->rigol_quirk = 0; |
| 1121 | dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", | 1121 | dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", |
| 1122 | data->usb_dev->descriptor.idVendor, | 1122 | le16_to_cpu(data->usb_dev->descriptor.idVendor), |
| 1123 | data->usb_dev->descriptor.idProduct); | 1123 | le16_to_cpu(data->usb_dev->descriptor.idProduct)); |
| 1124 | for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { | 1124 | for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { |
| 1125 | if ((usbtmc_id_quirk[n].idVendor == data->usb_dev->descriptor.idVendor) && | 1125 | if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) && |
| 1126 | (usbtmc_id_quirk[n].idProduct == data->usb_dev->descriptor.idProduct)) { | 1126 | (usbtmc_id_quirk[n].idProduct == le16_to_cpu(data->usb_dev->descriptor.idProduct))) { |
| 1127 | dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); | 1127 | dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); |
| 1128 | data->rigol_quirk = 1; | 1128 | data->rigol_quirk = 1; |
| 1129 | break; | 1129 | break; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4a8a1d68002c..558313de4911 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -4798,7 +4798,8 @@ static void hub_events(void) | |||
| 4798 | hub->ports[i - 1]->child; | 4798 | hub->ports[i - 1]->child; |
| 4799 | 4799 | ||
| 4800 | dev_dbg(hub_dev, "warm reset port %d\n", i); | 4800 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
| 4801 | if (!udev) { | 4801 | if (!udev || !(portstatus & |
| 4802 | USB_PORT_STAT_CONNECTION)) { | ||
| 4802 | status = hub_port_reset(hub, i, | 4803 | status = hub_port_reset(hub, i, |
| 4803 | NULL, HUB_BH_RESET_TIME, | 4804 | NULL, HUB_BH_RESET_TIME, |
| 4804 | true); | 4805 | true); |
| @@ -4808,8 +4809,8 @@ static void hub_events(void) | |||
| 4808 | usb_lock_device(udev); | 4809 | usb_lock_device(udev); |
| 4809 | status = usb_reset_device(udev); | 4810 | status = usb_reset_device(udev); |
| 4810 | usb_unlock_device(udev); | 4811 | usb_unlock_device(udev); |
| 4812 | connect_change = 0; | ||
| 4811 | } | 4813 | } |
| 4812 | connect_change = 0; | ||
| 4813 | } | 4814 | } |
| 4814 | 4815 | ||
| 4815 | if (connect_change) | 4816 | if (connect_change) |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index a63598895077..5b44cd47da5b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
| @@ -78,6 +78,12 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
| 78 | { USB_DEVICE(0x04d8, 0x000c), .driver_info = | 78 | { USB_DEVICE(0x04d8, 0x000c), .driver_info = |
| 79 | USB_QUIRK_CONFIG_INTF_STRINGS }, | 79 | USB_QUIRK_CONFIG_INTF_STRINGS }, |
| 80 | 80 | ||
| 81 | /* CarrolTouch 4000U */ | ||
| 82 | { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 83 | |||
| 84 | /* CarrolTouch 4500U */ | ||
| 85 | { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 86 | |||
| 81 | /* Samsung Android phone modem - ID conflict with SPH-I500 */ | 87 | /* Samsung Android phone modem - ID conflict with SPH-I500 */ |
| 82 | { USB_DEVICE(0x04e8, 0x6601), .driver_info = | 88 | { USB_DEVICE(0x04e8, 0x6601), .driver_info = |
| 83 | USB_QUIRK_CONFIG_INTF_STRINGS }, | 89 | USB_QUIRK_CONFIG_INTF_STRINGS }, |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f80d0330d548..8e3c878f38cf 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -1391,21 +1391,20 @@ iso_stream_schedule ( | |||
| 1391 | 1391 | ||
| 1392 | /* Behind the scheduling threshold? */ | 1392 | /* Behind the scheduling threshold? */ |
| 1393 | if (unlikely(start < next)) { | 1393 | if (unlikely(start < next)) { |
| 1394 | unsigned now2 = (now - base) & (mod - 1); | ||
| 1394 | 1395 | ||
| 1395 | /* USB_ISO_ASAP: Round up to the first available slot */ | 1396 | /* USB_ISO_ASAP: Round up to the first available slot */ |
| 1396 | if (urb->transfer_flags & URB_ISO_ASAP) | 1397 | if (urb->transfer_flags & URB_ISO_ASAP) |
| 1397 | start += (next - start + period - 1) & -period; | 1398 | start += (next - start + period - 1) & -period; |
| 1398 | 1399 | ||
| 1399 | /* | 1400 | /* |
| 1400 | * Not ASAP: Use the next slot in the stream. If | 1401 | * Not ASAP: Use the next slot in the stream, |
| 1401 | * the entire URB falls before the threshold, fail. | 1402 | * no matter what. |
| 1402 | */ | 1403 | */ |
| 1403 | else if (start + span - period < next) { | 1404 | else if (start + span - period < now2) { |
| 1404 | ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", | 1405 | ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", |
| 1405 | urb, start + base, | 1406 | urb, start + base, |
| 1406 | span - period, next + base); | 1407 | span - period, now2 + base); |
| 1407 | status = -EXDEV; | ||
| 1408 | goto fail; | ||
| 1409 | } | 1408 | } |
| 1410 | } | 1409 | } |
| 1411 | 1410 | ||
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index df6978abd7e6..6f8c2fd47675 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/dmapool.h> | 26 | #include <linux/dmapool.h> |
| 27 | #include <linux/dma-mapping.h> | ||
| 27 | 28 | ||
| 28 | #include "xhci.h" | 29 | #include "xhci.h" |
| 29 | 30 | ||
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 41eb4fc33453..9478caa2f71f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/dmi.h> | 29 | #include <linux/dmi.h> |
| 30 | #include <linux/dma-mapping.h> | ||
| 30 | 31 | ||
| 31 | #include "xhci.h" | 32 | #include "xhci.h" |
| 32 | 33 | ||
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index eb3c8c142fa9..eeb27208c0d1 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
| @@ -830,7 +830,7 @@ static int adu_probe(struct usb_interface *interface, | |||
| 830 | 830 | ||
| 831 | /* let the user know what node this device is now attached to */ | 831 | /* let the user know what node this device is now attached to */ |
| 832 | dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", | 832 | dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", |
| 833 | udev->descriptor.idProduct, dev->serial_number, | 833 | le16_to_cpu(udev->descriptor.idProduct), dev->serial_number, |
| 834 | (dev->minor - ADU_MINOR_BASE)); | 834 | (dev->minor - ADU_MINOR_BASE)); |
| 835 | exit: | 835 | exit: |
| 836 | dbg(2, " %s : leave, return value %p (dev)", __func__, dev); | 836 | dbg(2, " %s : leave, return value %p (dev)", __func__, dev); |
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 5a979729f8ec..58c17fdc85eb 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
| @@ -2303,7 +2303,7 @@ static int keyspan_startup(struct usb_serial *serial) | |||
| 2303 | if (d_details == NULL) { | 2303 | if (d_details == NULL) { |
| 2304 | dev_err(&serial->dev->dev, "%s - unknown product id %x\n", | 2304 | dev_err(&serial->dev->dev, "%s - unknown product id %x\n", |
| 2305 | __func__, le16_to_cpu(serial->dev->descriptor.idProduct)); | 2305 | __func__, le16_to_cpu(serial->dev->descriptor.idProduct)); |
| 2306 | return 1; | 2306 | return -ENODEV; |
| 2307 | } | 2307 | } |
| 2308 | 2308 | ||
| 2309 | /* Setup private data for serial driver */ | 2309 | /* Setup private data for serial driver */ |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 51da424327b0..b01300164fc0 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
| @@ -90,6 +90,7 @@ struct urbtracker { | |||
| 90 | struct list_head urblist_entry; | 90 | struct list_head urblist_entry; |
| 91 | struct kref ref_count; | 91 | struct kref ref_count; |
| 92 | struct urb *urb; | 92 | struct urb *urb; |
| 93 | struct usb_ctrlrequest *setup; | ||
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 95 | enum mos7715_pp_modes { | 96 | enum mos7715_pp_modes { |
| @@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref) | |||
| 271 | struct mos7715_parport *mos_parport = urbtrack->mos_parport; | 272 | struct mos7715_parport *mos_parport = urbtrack->mos_parport; |
| 272 | 273 | ||
| 273 | usb_free_urb(urbtrack->urb); | 274 | usb_free_urb(urbtrack->urb); |
| 275 | kfree(urbtrack->setup); | ||
| 274 | kfree(urbtrack); | 276 | kfree(urbtrack); |
| 275 | kref_put(&mos_parport->ref_count, destroy_mos_parport); | 277 | kref_put(&mos_parport->ref_count, destroy_mos_parport); |
| 276 | } | 278 | } |
| @@ -355,7 +357,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, | |||
| 355 | struct urbtracker *urbtrack; | 357 | struct urbtracker *urbtrack; |
| 356 | int ret_val; | 358 | int ret_val; |
| 357 | unsigned long flags; | 359 | unsigned long flags; |
| 358 | struct usb_ctrlrequest setup; | ||
| 359 | struct usb_serial *serial = mos_parport->serial; | 360 | struct usb_serial *serial = mos_parport->serial; |
| 360 | struct usb_device *usbdev = serial->dev; | 361 | struct usb_device *usbdev = serial->dev; |
| 361 | 362 | ||
| @@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, | |||
| 373 | kfree(urbtrack); | 374 | kfree(urbtrack); |
| 374 | return -ENOMEM; | 375 | return -ENOMEM; |
| 375 | } | 376 | } |
| 376 | setup.bRequestType = (__u8)0x40; | 377 | urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL); |
| 377 | setup.bRequest = (__u8)0x0e; | 378 | if (!urbtrack->setup) { |
| 378 | setup.wValue = get_reg_value(reg, dummy); | 379 | usb_free_urb(urbtrack->urb); |
| 379 | setup.wIndex = get_reg_index(reg); | 380 | kfree(urbtrack); |
| 380 | setup.wLength = 0; | 381 | return -ENOMEM; |
| 382 | } | ||
| 383 | urbtrack->setup->bRequestType = (__u8)0x40; | ||
| 384 | urbtrack->setup->bRequest = (__u8)0x0e; | ||
| 385 | urbtrack->setup->wValue = get_reg_value(reg, dummy); | ||
| 386 | urbtrack->setup->wIndex = get_reg_index(reg); | ||
| 387 | urbtrack->setup->wLength = 0; | ||
| 381 | usb_fill_control_urb(urbtrack->urb, usbdev, | 388 | usb_fill_control_urb(urbtrack->urb, usbdev, |
| 382 | usb_sndctrlpipe(usbdev, 0), | 389 | usb_sndctrlpipe(usbdev, 0), |
| 383 | (unsigned char *)&setup, | 390 | (unsigned char *)urbtrack->setup, |
| 384 | NULL, 0, async_complete, urbtrack); | 391 | NULL, 0, async_complete, urbtrack); |
| 385 | kref_init(&urbtrack->ref_count); | 392 | kref_init(&urbtrack->ref_count); |
| 386 | INIT_LIST_HEAD(&urbtrack->urblist_entry); | 393 | INIT_LIST_HEAD(&urbtrack->urblist_entry); |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d953d674f222..3bac4693c038 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
| @@ -2193,7 +2193,7 @@ static int mos7810_check(struct usb_serial *serial) | |||
| 2193 | static int mos7840_probe(struct usb_serial *serial, | 2193 | static int mos7840_probe(struct usb_serial *serial, |
| 2194 | const struct usb_device_id *id) | 2194 | const struct usb_device_id *id) |
| 2195 | { | 2195 | { |
| 2196 | u16 product = serial->dev->descriptor.idProduct; | 2196 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); |
| 2197 | u8 *buf; | 2197 | u8 *buf; |
| 2198 | int device_type; | 2198 | int device_type; |
| 2199 | 2199 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 375b5a400b6f..5c9f9b1d7736 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
| @@ -1536,14 +1536,15 @@ static int ti_download_firmware(struct ti_device *tdev) | |||
| 1536 | char buf[32]; | 1536 | char buf[32]; |
| 1537 | 1537 | ||
| 1538 | /* try ID specific firmware first, then try generic firmware */ | 1538 | /* try ID specific firmware first, then try generic firmware */ |
| 1539 | sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor, | 1539 | sprintf(buf, "ti_usb-v%04x-p%04x.fw", |
| 1540 | dev->descriptor.idProduct); | 1540 | le16_to_cpu(dev->descriptor.idVendor), |
| 1541 | le16_to_cpu(dev->descriptor.idProduct)); | ||
| 1541 | status = request_firmware(&fw_p, buf, &dev->dev); | 1542 | status = request_firmware(&fw_p, buf, &dev->dev); |
| 1542 | 1543 | ||
| 1543 | if (status != 0) { | 1544 | if (status != 0) { |
| 1544 | buf[0] = '\0'; | 1545 | buf[0] = '\0'; |
| 1545 | if (dev->descriptor.idVendor == MTS_VENDOR_ID) { | 1546 | if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) { |
| 1546 | switch (dev->descriptor.idProduct) { | 1547 | switch (le16_to_cpu(dev->descriptor.idProduct)) { |
| 1547 | case MTS_CDMA_PRODUCT_ID: | 1548 | case MTS_CDMA_PRODUCT_ID: |
| 1548 | strcpy(buf, "mts_cdma.fw"); | 1549 | strcpy(buf, "mts_cdma.fw"); |
| 1549 | break; | 1550 | break; |
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 8257d30c4072..85365784040b 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c | |||
| @@ -291,18 +291,18 @@ static void usb_wwan_indat_callback(struct urb *urb) | |||
| 291 | tty_flip_buffer_push(&port->port); | 291 | tty_flip_buffer_push(&port->port); |
| 292 | } else | 292 | } else |
| 293 | dev_dbg(dev, "%s: empty read urb received\n", __func__); | 293 | dev_dbg(dev, "%s: empty read urb received\n", __func__); |
| 294 | 294 | } | |
| 295 | /* Resubmit urb so we continue receiving */ | 295 | /* Resubmit urb so we continue receiving */ |
| 296 | err = usb_submit_urb(urb, GFP_ATOMIC); | 296 | err = usb_submit_urb(urb, GFP_ATOMIC); |
| 297 | if (err) { | 297 | if (err) { |
| 298 | if (err != -EPERM) { | 298 | if (err != -EPERM) { |
| 299 | dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err); | 299 | dev_err(dev, "%s: resubmit read urb failed. (%d)\n", |
| 300 | /* busy also in error unless we are killed */ | 300 | __func__, err); |
| 301 | usb_mark_last_busy(port->serial->dev); | 301 | /* busy also in error unless we are killed */ |
| 302 | } | ||
| 303 | } else { | ||
| 304 | usb_mark_last_busy(port->serial->dev); | 302 | usb_mark_last_busy(port->serial->dev); |
| 305 | } | 303 | } |
| 304 | } else { | ||
| 305 | usb_mark_last_busy(port->serial->dev); | ||
| 306 | } | 306 | } |
| 307 | } | 307 | } |
| 308 | 308 | ||
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 16968c899493..d3493ca0525d 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c | |||
| @@ -1226,6 +1226,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb) | |||
| 1226 | } | 1226 | } |
| 1227 | spin_lock_irqsave(&xfer->lock, flags); | 1227 | spin_lock_irqsave(&xfer->lock, flags); |
| 1228 | rpipe = xfer->ep->hcpriv; | 1228 | rpipe = xfer->ep->hcpriv; |
| 1229 | if (rpipe == NULL) { | ||
| 1230 | pr_debug("%s: xfer id 0x%08X has no RPIPE. %s", | ||
| 1231 | __func__, wa_xfer_id(xfer), | ||
| 1232 | "Probably already aborted.\n" ); | ||
| 1233 | goto out_unlock; | ||
| 1234 | } | ||
| 1229 | /* Check the delayed list -> if there, release and complete */ | 1235 | /* Check the delayed list -> if there, release and complete */ |
| 1230 | spin_lock_irqsave(&wa->xfer_list_lock, flags2); | 1236 | spin_lock_irqsave(&wa->xfer_list_lock, flags2); |
| 1231 | if (!list_empty(&xfer->list_node) && xfer->seg == NULL) | 1237 | if (!list_empty(&xfer->list_node) && xfer->seg == NULL) |
| @@ -1644,8 +1650,7 @@ static void wa_xfer_result_cb(struct urb *urb) | |||
| 1644 | break; | 1650 | break; |
| 1645 | } | 1651 | } |
| 1646 | usb_status = xfer_result->bTransferStatus & 0x3f; | 1652 | usb_status = xfer_result->bTransferStatus & 0x3f; |
| 1647 | if (usb_status == WA_XFER_STATUS_ABORTED | 1653 | if (usb_status == WA_XFER_STATUS_NOT_FOUND) |
| 1648 | || usb_status == WA_XFER_STATUS_NOT_FOUND) | ||
| 1649 | /* taken care of already */ | 1654 | /* taken care of already */ |
| 1650 | break; | 1655 | break; |
| 1651 | xfer_id = xfer_result->dwTransferID; | 1656 | xfer_id = xfer_result->dwTransferID; |
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 3ba37713b1f9..dc09ebe4aba5 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
| @@ -239,24 +239,6 @@ static const struct fb_bitfield def_rgb565[] = { | |||
| 239 | } | 239 | } |
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| 242 | static const struct fb_bitfield def_rgb666[] = { | ||
| 243 | [RED] = { | ||
| 244 | .offset = 16, | ||
| 245 | .length = 6, | ||
| 246 | }, | ||
| 247 | [GREEN] = { | ||
| 248 | .offset = 8, | ||
| 249 | .length = 6, | ||
| 250 | }, | ||
| 251 | [BLUE] = { | ||
| 252 | .offset = 0, | ||
| 253 | .length = 6, | ||
| 254 | }, | ||
| 255 | [TRANSP] = { /* no support for transparency */ | ||
| 256 | .length = 0, | ||
| 257 | } | ||
| 258 | }; | ||
| 259 | |||
| 260 | static const struct fb_bitfield def_rgb888[] = { | 242 | static const struct fb_bitfield def_rgb888[] = { |
| 261 | [RED] = { | 243 | [RED] = { |
| 262 | .offset = 16, | 244 | .offset = 16, |
| @@ -309,9 +291,6 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var, | |||
| 309 | break; | 291 | break; |
| 310 | case STMLCDIF_16BIT: | 292 | case STMLCDIF_16BIT: |
| 311 | case STMLCDIF_18BIT: | 293 | case STMLCDIF_18BIT: |
| 312 | /* 24 bit to 18 bit mapping */ | ||
| 313 | rgb = def_rgb666; | ||
| 314 | break; | ||
| 315 | case STMLCDIF_24BIT: | 294 | case STMLCDIF_24BIT: |
| 316 | /* real 24 bit */ | 295 | /* real 24 bit */ |
| 317 | rgb = def_rgb888; | 296 | rgb = def_rgb888; |
| @@ -453,11 +432,6 @@ static int mxsfb_set_par(struct fb_info *fb_info) | |||
| 453 | return -EINVAL; | 432 | return -EINVAL; |
| 454 | case STMLCDIF_16BIT: | 433 | case STMLCDIF_16BIT: |
| 455 | case STMLCDIF_18BIT: | 434 | case STMLCDIF_18BIT: |
| 456 | /* 24 bit to 18 bit mapping */ | ||
| 457 | ctrl |= CTRL_DF24; /* ignore the upper 2 bits in | ||
| 458 | * each colour component | ||
| 459 | */ | ||
| 460 | break; | ||
| 461 | case STMLCDIF_24BIT: | 435 | case STMLCDIF_24BIT: |
| 462 | /* real 24 bit */ | 436 | /* real 24 bit */ |
| 463 | break; | 437 | break; |
diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/omap2/displays-new/connector-analog-tv.c index 5338f362293b..1b60698f141e 100644 --- a/drivers/video/omap2/displays-new/connector-analog-tv.c +++ b/drivers/video/omap2/displays-new/connector-analog-tv.c | |||
| @@ -28,6 +28,20 @@ struct panel_drv_data { | |||
| 28 | bool invert_polarity; | 28 | bool invert_polarity; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static const struct omap_video_timings tvc_pal_timings = { | ||
| 32 | .x_res = 720, | ||
| 33 | .y_res = 574, | ||
| 34 | .pixel_clock = 13500, | ||
| 35 | .hsw = 64, | ||
| 36 | .hfp = 12, | ||
| 37 | .hbp = 68, | ||
| 38 | .vsw = 5, | ||
| 39 | .vfp = 5, | ||
| 40 | .vbp = 41, | ||
| 41 | |||
| 42 | .interlace = true, | ||
| 43 | }; | ||
| 44 | |||
| 31 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) | 45 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) |
| 32 | 46 | ||
| 33 | static int tvc_connect(struct omap_dss_device *dssdev) | 47 | static int tvc_connect(struct omap_dss_device *dssdev) |
| @@ -212,14 +226,14 @@ static int tvc_probe(struct platform_device *pdev) | |||
| 212 | return -ENODEV; | 226 | return -ENODEV; |
| 213 | } | 227 | } |
| 214 | 228 | ||
| 215 | ddata->timings = omap_dss_pal_timings; | 229 | ddata->timings = tvc_pal_timings; |
| 216 | 230 | ||
| 217 | dssdev = &ddata->dssdev; | 231 | dssdev = &ddata->dssdev; |
| 218 | dssdev->driver = &tvc_driver; | 232 | dssdev->driver = &tvc_driver; |
| 219 | dssdev->dev = &pdev->dev; | 233 | dssdev->dev = &pdev->dev; |
| 220 | dssdev->type = OMAP_DISPLAY_TYPE_VENC; | 234 | dssdev->type = OMAP_DISPLAY_TYPE_VENC; |
| 221 | dssdev->owner = THIS_MODULE; | 235 | dssdev->owner = THIS_MODULE; |
| 222 | dssdev->panel.timings = omap_dss_pal_timings; | 236 | dssdev->panel.timings = tvc_pal_timings; |
| 223 | 237 | ||
| 224 | r = omapdss_register_display(dssdev); | 238 | r = omapdss_register_display(dssdev); |
| 225 | if (r) { | 239 | if (r) { |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index eaf133384a8f..8bc5e8ccb091 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -36,16 +36,23 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb, | |||
| 36 | u64 extent_item_pos, | 36 | u64 extent_item_pos, |
| 37 | struct extent_inode_elem **eie) | 37 | struct extent_inode_elem **eie) |
| 38 | { | 38 | { |
| 39 | u64 data_offset; | 39 | u64 offset = 0; |
| 40 | u64 data_len; | ||
| 41 | struct extent_inode_elem *e; | 40 | struct extent_inode_elem *e; |
| 42 | 41 | ||
| 43 | data_offset = btrfs_file_extent_offset(eb, fi); | 42 | if (!btrfs_file_extent_compression(eb, fi) && |
| 44 | data_len = btrfs_file_extent_num_bytes(eb, fi); | 43 | !btrfs_file_extent_encryption(eb, fi) && |
| 44 | !btrfs_file_extent_other_encoding(eb, fi)) { | ||
| 45 | u64 data_offset; | ||
| 46 | u64 data_len; | ||
| 45 | 47 | ||
| 46 | if (extent_item_pos < data_offset || | 48 | data_offset = btrfs_file_extent_offset(eb, fi); |
| 47 | extent_item_pos >= data_offset + data_len) | 49 | data_len = btrfs_file_extent_num_bytes(eb, fi); |
| 48 | return 1; | 50 | |
| 51 | if (extent_item_pos < data_offset || | ||
| 52 | extent_item_pos >= data_offset + data_len) | ||
| 53 | return 1; | ||
| 54 | offset = extent_item_pos - data_offset; | ||
| 55 | } | ||
| 49 | 56 | ||
| 50 | e = kmalloc(sizeof(*e), GFP_NOFS); | 57 | e = kmalloc(sizeof(*e), GFP_NOFS); |
| 51 | if (!e) | 58 | if (!e) |
| @@ -53,7 +60,7 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb, | |||
| 53 | 60 | ||
| 54 | e->next = *eie; | 61 | e->next = *eie; |
| 55 | e->inum = key->objectid; | 62 | e->inum = key->objectid; |
| 56 | e->offset = key->offset + (extent_item_pos - data_offset); | 63 | e->offset = key->offset + offset; |
| 57 | *eie = e; | 64 | *eie = e; |
| 58 | 65 | ||
| 59 | return 0; | 66 | return 0; |
| @@ -189,7 +196,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 189 | struct extent_buffer *eb; | 196 | struct extent_buffer *eb; |
| 190 | struct btrfs_key key; | 197 | struct btrfs_key key; |
| 191 | struct btrfs_file_extent_item *fi; | 198 | struct btrfs_file_extent_item *fi; |
| 192 | struct extent_inode_elem *eie = NULL; | 199 | struct extent_inode_elem *eie = NULL, *old = NULL; |
| 193 | u64 disk_byte; | 200 | u64 disk_byte; |
| 194 | 201 | ||
| 195 | if (level != 0) { | 202 | if (level != 0) { |
| @@ -223,6 +230,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 223 | 230 | ||
| 224 | if (disk_byte == wanted_disk_byte) { | 231 | if (disk_byte == wanted_disk_byte) { |
| 225 | eie = NULL; | 232 | eie = NULL; |
| 233 | old = NULL; | ||
| 226 | if (extent_item_pos) { | 234 | if (extent_item_pos) { |
| 227 | ret = check_extent_in_eb(&key, eb, fi, | 235 | ret = check_extent_in_eb(&key, eb, fi, |
| 228 | *extent_item_pos, | 236 | *extent_item_pos, |
| @@ -230,18 +238,20 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 230 | if (ret < 0) | 238 | if (ret < 0) |
| 231 | break; | 239 | break; |
| 232 | } | 240 | } |
| 233 | if (!ret) { | 241 | if (ret > 0) |
| 234 | ret = ulist_add(parents, eb->start, | 242 | goto next; |
| 235 | (uintptr_t)eie, GFP_NOFS); | 243 | ret = ulist_add_merge(parents, eb->start, |
| 236 | if (ret < 0) | 244 | (uintptr_t)eie, |
| 237 | break; | 245 | (u64 *)&old, GFP_NOFS); |
| 238 | if (!extent_item_pos) { | 246 | if (ret < 0) |
| 239 | ret = btrfs_next_old_leaf(root, path, | 247 | break; |
| 240 | time_seq); | 248 | if (!ret && extent_item_pos) { |
| 241 | continue; | 249 | while (old->next) |
| 242 | } | 250 | old = old->next; |
| 251 | old->next = eie; | ||
| 243 | } | 252 | } |
| 244 | } | 253 | } |
| 254 | next: | ||
| 245 | ret = btrfs_next_old_item(root, path, time_seq); | 255 | ret = btrfs_next_old_item(root, path, time_seq); |
| 246 | } | 256 | } |
| 247 | 257 | ||
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 5bf4c39e2ad6..ed504607d8ec 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -1271,7 +1271,6 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1271 | BUG_ON(!eb_rewin); | 1271 | BUG_ON(!eb_rewin); |
| 1272 | } | 1272 | } |
| 1273 | 1273 | ||
| 1274 | extent_buffer_get(eb_rewin); | ||
| 1275 | btrfs_tree_read_unlock(eb); | 1274 | btrfs_tree_read_unlock(eb); |
| 1276 | free_extent_buffer(eb); | 1275 | free_extent_buffer(eb); |
| 1277 | 1276 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 583d98bd065e..fe443fece851 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -4048,7 +4048,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4048 | } | 4048 | } |
| 4049 | 4049 | ||
| 4050 | while (!end) { | 4050 | while (!end) { |
| 4051 | u64 offset_in_extent; | 4051 | u64 offset_in_extent = 0; |
| 4052 | 4052 | ||
| 4053 | /* break if the extent we found is outside the range */ | 4053 | /* break if the extent we found is outside the range */ |
| 4054 | if (em->start >= max || extent_map_end(em) < off) | 4054 | if (em->start >= max || extent_map_end(em) < off) |
| @@ -4064,9 +4064,12 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4064 | 4064 | ||
| 4065 | /* | 4065 | /* |
| 4066 | * record the offset from the start of the extent | 4066 | * record the offset from the start of the extent |
| 4067 | * for adjusting the disk offset below | 4067 | * for adjusting the disk offset below. Only do this if the |
| 4068 | * extent isn't compressed since our in ram offset may be past | ||
| 4069 | * what we have actually allocated on disk. | ||
| 4068 | */ | 4070 | */ |
| 4069 | offset_in_extent = em_start - em->start; | 4071 | if (!test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) |
| 4072 | offset_in_extent = em_start - em->start; | ||
| 4070 | em_end = extent_map_end(em); | 4073 | em_end = extent_map_end(em); |
| 4071 | em_len = em_end - em_start; | 4074 | em_len = em_end - em_start; |
| 4072 | emflags = em->flags; | 4075 | emflags = em->flags; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a005fe2c072a..8e686a427ce2 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -596,20 +596,29 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 596 | if (no_splits) | 596 | if (no_splits) |
| 597 | goto next; | 597 | goto next; |
| 598 | 598 | ||
| 599 | if (em->block_start < EXTENT_MAP_LAST_BYTE && | 599 | if (em->start < start) { |
| 600 | em->start < start) { | ||
| 601 | split->start = em->start; | 600 | split->start = em->start; |
| 602 | split->len = start - em->start; | 601 | split->len = start - em->start; |
| 603 | split->orig_start = em->orig_start; | ||
| 604 | split->block_start = em->block_start; | ||
| 605 | 602 | ||
| 606 | if (compressed) | 603 | if (em->block_start < EXTENT_MAP_LAST_BYTE) { |
| 607 | split->block_len = em->block_len; | 604 | split->orig_start = em->orig_start; |
| 608 | else | 605 | split->block_start = em->block_start; |
| 609 | split->block_len = split->len; | 606 | |
| 610 | split->ram_bytes = em->ram_bytes; | 607 | if (compressed) |
| 611 | split->orig_block_len = max(split->block_len, | 608 | split->block_len = em->block_len; |
| 612 | em->orig_block_len); | 609 | else |
| 610 | split->block_len = split->len; | ||
| 611 | split->orig_block_len = max(split->block_len, | ||
| 612 | em->orig_block_len); | ||
| 613 | split->ram_bytes = em->ram_bytes; | ||
| 614 | } else { | ||
| 615 | split->orig_start = split->start; | ||
| 616 | split->block_len = 0; | ||
| 617 | split->block_start = em->block_start; | ||
| 618 | split->orig_block_len = 0; | ||
| 619 | split->ram_bytes = split->len; | ||
| 620 | } | ||
| 621 | |||
| 613 | split->generation = gen; | 622 | split->generation = gen; |
| 614 | split->bdev = em->bdev; | 623 | split->bdev = em->bdev; |
| 615 | split->flags = flags; | 624 | split->flags = flags; |
| @@ -620,8 +629,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 620 | split = split2; | 629 | split = split2; |
| 621 | split2 = NULL; | 630 | split2 = NULL; |
| 622 | } | 631 | } |
| 623 | if (em->block_start < EXTENT_MAP_LAST_BYTE && | 632 | if (testend && em->start + em->len > start + len) { |
| 624 | testend && em->start + em->len > start + len) { | ||
| 625 | u64 diff = start + len - em->start; | 633 | u64 diff = start + len - em->start; |
| 626 | 634 | ||
| 627 | split->start = start + len; | 635 | split->start = start + len; |
| @@ -630,18 +638,28 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 630 | split->flags = flags; | 638 | split->flags = flags; |
| 631 | split->compress_type = em->compress_type; | 639 | split->compress_type = em->compress_type; |
| 632 | split->generation = gen; | 640 | split->generation = gen; |
| 633 | split->orig_block_len = max(em->block_len, | 641 | |
| 642 | if (em->block_start < EXTENT_MAP_LAST_BYTE) { | ||
| 643 | split->orig_block_len = max(em->block_len, | ||
| 634 | em->orig_block_len); | 644 | em->orig_block_len); |
| 635 | split->ram_bytes = em->ram_bytes; | ||
| 636 | 645 | ||
| 637 | if (compressed) { | 646 | split->ram_bytes = em->ram_bytes; |
| 638 | split->block_len = em->block_len; | 647 | if (compressed) { |
| 639 | split->block_start = em->block_start; | 648 | split->block_len = em->block_len; |
| 640 | split->orig_start = em->orig_start; | 649 | split->block_start = em->block_start; |
| 650 | split->orig_start = em->orig_start; | ||
| 651 | } else { | ||
| 652 | split->block_len = split->len; | ||
| 653 | split->block_start = em->block_start | ||
| 654 | + diff; | ||
| 655 | split->orig_start = em->orig_start; | ||
| 656 | } | ||
| 641 | } else { | 657 | } else { |
| 642 | split->block_len = split->len; | 658 | split->ram_bytes = split->len; |
| 643 | split->block_start = em->block_start + diff; | 659 | split->orig_start = split->start; |
| 644 | split->orig_start = em->orig_start; | 660 | split->block_len = 0; |
| 661 | split->block_start = em->block_start; | ||
| 662 | split->orig_block_len = 0; | ||
| 645 | } | 663 | } |
| 646 | 664 | ||
| 647 | ret = add_extent_mapping(em_tree, split, modified); | 665 | ret = add_extent_mapping(em_tree, split, modified); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6d1b93c8aafb..021694c08181 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -2166,16 +2166,23 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id, | |||
| 2166 | if (btrfs_file_extent_disk_bytenr(leaf, extent) != old->bytenr) | 2166 | if (btrfs_file_extent_disk_bytenr(leaf, extent) != old->bytenr) |
| 2167 | continue; | 2167 | continue; |
| 2168 | 2168 | ||
| 2169 | extent_offset = btrfs_file_extent_offset(leaf, extent); | 2169 | /* |
| 2170 | if (key.offset - extent_offset != offset) | 2170 | * 'offset' refers to the exact key.offset, |
| 2171 | * NOT the 'offset' field in btrfs_extent_data_ref, ie. | ||
| 2172 | * (key.offset - extent_offset). | ||
| 2173 | */ | ||
| 2174 | if (key.offset != offset) | ||
| 2171 | continue; | 2175 | continue; |
| 2172 | 2176 | ||
| 2177 | extent_offset = btrfs_file_extent_offset(leaf, extent); | ||
| 2173 | num_bytes = btrfs_file_extent_num_bytes(leaf, extent); | 2178 | num_bytes = btrfs_file_extent_num_bytes(leaf, extent); |
| 2179 | |||
| 2174 | if (extent_offset >= old->extent_offset + old->offset + | 2180 | if (extent_offset >= old->extent_offset + old->offset + |
| 2175 | old->len || extent_offset + num_bytes <= | 2181 | old->len || extent_offset + num_bytes <= |
| 2176 | old->extent_offset + old->offset) | 2182 | old->extent_offset + old->offset) |
| 2177 | continue; | 2183 | continue; |
| 2178 | 2184 | ||
| 2185 | ret = 0; | ||
| 2179 | break; | 2186 | break; |
| 2180 | } | 2187 | } |
| 2181 | 2188 | ||
| @@ -2187,7 +2194,7 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id, | |||
| 2187 | 2194 | ||
| 2188 | backref->root_id = root_id; | 2195 | backref->root_id = root_id; |
| 2189 | backref->inum = inum; | 2196 | backref->inum = inum; |
| 2190 | backref->file_pos = offset + extent_offset; | 2197 | backref->file_pos = offset; |
| 2191 | backref->num_bytes = num_bytes; | 2198 | backref->num_bytes = num_bytes; |
| 2192 | backref->extent_offset = extent_offset; | 2199 | backref->extent_offset = extent_offset; |
| 2193 | backref->generation = btrfs_file_extent_generation(leaf, extent); | 2200 | backref->generation = btrfs_file_extent_generation(leaf, extent); |
| @@ -2210,7 +2217,8 @@ static noinline bool record_extent_backrefs(struct btrfs_path *path, | |||
| 2210 | new->path = path; | 2217 | new->path = path; |
| 2211 | 2218 | ||
| 2212 | list_for_each_entry_safe(old, tmp, &new->head, list) { | 2219 | list_for_each_entry_safe(old, tmp, &new->head, list) { |
| 2213 | ret = iterate_inodes_from_logical(old->bytenr, fs_info, | 2220 | ret = iterate_inodes_from_logical(old->bytenr + |
| 2221 | old->extent_offset, fs_info, | ||
| 2214 | path, record_one_backref, | 2222 | path, record_one_backref, |
| 2215 | old); | 2223 | old); |
| 2216 | BUG_ON(ret < 0 && ret != -ENOENT); | 2224 | BUG_ON(ret < 0 && ret != -ENOENT); |
| @@ -4391,9 +4399,6 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr) | |||
| 4391 | int mask = attr->ia_valid; | 4399 | int mask = attr->ia_valid; |
| 4392 | int ret; | 4400 | int ret; |
| 4393 | 4401 | ||
| 4394 | if (newsize == oldsize) | ||
| 4395 | return 0; | ||
| 4396 | |||
| 4397 | /* | 4402 | /* |
| 4398 | * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a | 4403 | * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a |
| 4399 | * special case where we need to update the times despite not having | 4404 | * special case where we need to update the times despite not having |
| @@ -5165,14 +5170,31 @@ next: | |||
| 5165 | } | 5170 | } |
| 5166 | 5171 | ||
| 5167 | /* Reached end of directory/root. Bump pos past the last item. */ | 5172 | /* Reached end of directory/root. Bump pos past the last item. */ |
| 5168 | if (key_type == BTRFS_DIR_INDEX_KEY) | 5173 | ctx->pos++; |
| 5169 | /* | 5174 | |
| 5170 | * 32-bit glibc will use getdents64, but then strtol - | 5175 | /* |
| 5171 | * so the last number we can serve is this. | 5176 | * Stop new entries from being returned after we return the last |
| 5172 | */ | 5177 | * entry. |
| 5173 | ctx->pos = 0x7fffffff; | 5178 | * |
| 5174 | else | 5179 | * New directory entries are assigned a strictly increasing |
| 5175 | ctx->pos++; | 5180 | * offset. This means that new entries created during readdir |
| 5181 | * are *guaranteed* to be seen in the future by that readdir. | ||
| 5182 | * This has broken buggy programs which operate on names as | ||
| 5183 | * they're returned by readdir. Until we re-use freed offsets | ||
| 5184 | * we have this hack to stop new entries from being returned | ||
| 5185 | * under the assumption that they'll never reach this huge | ||
| 5186 | * offset. | ||
| 5187 | * | ||
| 5188 | * This is being careful not to overflow 32bit loff_t unless the | ||
| 5189 | * last entry requires it because doing so has broken 32bit apps | ||
| 5190 | * in the past. | ||
| 5191 | */ | ||
| 5192 | if (key_type == BTRFS_DIR_INDEX_KEY) { | ||
| 5193 | if (ctx->pos >= INT_MAX) | ||
| 5194 | ctx->pos = LLONG_MAX; | ||
| 5195 | else | ||
| 5196 | ctx->pos = INT_MAX; | ||
| 5197 | } | ||
| 5176 | nopos: | 5198 | nopos: |
| 5177 | ret = 0; | 5199 | ret = 0; |
| 5178 | err: | 5200 | err: |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index d58cce77fc6c..af1931a5960d 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -983,12 +983,12 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 983 | * a dirty root struct and adds it into the list of dead roots that need to | 983 | * a dirty root struct and adds it into the list of dead roots that need to |
| 984 | * be deleted | 984 | * be deleted |
| 985 | */ | 985 | */ |
| 986 | int btrfs_add_dead_root(struct btrfs_root *root) | 986 | void btrfs_add_dead_root(struct btrfs_root *root) |
| 987 | { | 987 | { |
| 988 | spin_lock(&root->fs_info->trans_lock); | 988 | spin_lock(&root->fs_info->trans_lock); |
| 989 | list_add_tail(&root->root_list, &root->fs_info->dead_roots); | 989 | if (list_empty(&root->root_list)) |
| 990 | list_add_tail(&root->root_list, &root->fs_info->dead_roots); | ||
| 990 | spin_unlock(&root->fs_info->trans_lock); | 991 | spin_unlock(&root->fs_info->trans_lock); |
| 991 | return 0; | ||
| 992 | } | 992 | } |
| 993 | 993 | ||
| 994 | /* | 994 | /* |
| @@ -1925,7 +1925,7 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root) | |||
| 1925 | } | 1925 | } |
| 1926 | root = list_first_entry(&fs_info->dead_roots, | 1926 | root = list_first_entry(&fs_info->dead_roots, |
| 1927 | struct btrfs_root, root_list); | 1927 | struct btrfs_root, root_list); |
| 1928 | list_del(&root->root_list); | 1928 | list_del_init(&root->root_list); |
| 1929 | spin_unlock(&fs_info->trans_lock); | 1929 | spin_unlock(&fs_info->trans_lock); |
| 1930 | 1930 | ||
| 1931 | pr_debug("btrfs: cleaner removing %llu\n", | 1931 | pr_debug("btrfs: cleaner removing %llu\n", |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 005b0375d18c..defbc4269897 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -143,7 +143,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid); | |||
| 143 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 143 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
| 144 | struct btrfs_root *root); | 144 | struct btrfs_root *root); |
| 145 | 145 | ||
| 146 | int btrfs_add_dead_root(struct btrfs_root *root); | 146 | void btrfs_add_dead_root(struct btrfs_root *root); |
| 147 | int btrfs_defrag_root(struct btrfs_root *root); | 147 | int btrfs_defrag_root(struct btrfs_root *root); |
| 148 | int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root); | 148 | int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root); |
| 149 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 149 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 2c6791493637..ff60d8978ae2 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -3746,8 +3746,9 @@ next_slot: | |||
| 3746 | } | 3746 | } |
| 3747 | 3747 | ||
| 3748 | log_extents: | 3748 | log_extents: |
| 3749 | btrfs_release_path(path); | ||
| 3750 | btrfs_release_path(dst_path); | ||
| 3749 | if (fast_search) { | 3751 | if (fast_search) { |
| 3750 | btrfs_release_path(dst_path); | ||
| 3751 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path); | 3752 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path); |
| 3752 | if (ret) { | 3753 | if (ret) { |
| 3753 | err = ret; | 3754 | err = ret; |
| @@ -3764,8 +3765,6 @@ log_extents: | |||
| 3764 | } | 3765 | } |
| 3765 | 3766 | ||
| 3766 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { | 3767 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { |
| 3767 | btrfs_release_path(path); | ||
| 3768 | btrfs_release_path(dst_path); | ||
| 3769 | ret = log_directory_changes(trans, root, inode, path, dst_path); | 3768 | ret = log_directory_changes(trans, root, inode, path, dst_path); |
| 3770 | if (ret) { | 3769 | if (ret) { |
| 3771 | err = ret; | 3770 | err = ret; |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 45e57cc38200..fc6f4f3a1a9d 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
| @@ -43,17 +43,18 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) | |||
| 43 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); | 43 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); |
| 44 | if (IS_ERR(server->secmech.md5)) { | 44 | if (IS_ERR(server->secmech.md5)) { |
| 45 | cifs_dbg(VFS, "could not allocate crypto md5\n"); | 45 | cifs_dbg(VFS, "could not allocate crypto md5\n"); |
| 46 | return PTR_ERR(server->secmech.md5); | 46 | rc = PTR_ERR(server->secmech.md5); |
| 47 | server->secmech.md5 = NULL; | ||
| 48 | return rc; | ||
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | size = sizeof(struct shash_desc) + | 51 | size = sizeof(struct shash_desc) + |
| 50 | crypto_shash_descsize(server->secmech.md5); | 52 | crypto_shash_descsize(server->secmech.md5); |
| 51 | server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); | 53 | server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); |
| 52 | if (!server->secmech.sdescmd5) { | 54 | if (!server->secmech.sdescmd5) { |
| 53 | rc = -ENOMEM; | ||
| 54 | crypto_free_shash(server->secmech.md5); | 55 | crypto_free_shash(server->secmech.md5); |
| 55 | server->secmech.md5 = NULL; | 56 | server->secmech.md5 = NULL; |
| 56 | return rc; | 57 | return -ENOMEM; |
| 57 | } | 58 | } |
| 58 | server->secmech.sdescmd5->shash.tfm = server->secmech.md5; | 59 | server->secmech.sdescmd5->shash.tfm = server->secmech.md5; |
| 59 | server->secmech.sdescmd5->shash.flags = 0x0; | 60 | server->secmech.sdescmd5->shash.flags = 0x0; |
| @@ -421,7 +422,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
| 421 | if (blobptr + attrsize > blobend) | 422 | if (blobptr + attrsize > blobend) |
| 422 | break; | 423 | break; |
| 423 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { | 424 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { |
| 424 | if (!attrsize) | 425 | if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN) |
| 425 | break; | 426 | break; |
| 426 | if (!ses->domainName) { | 427 | if (!ses->domainName) { |
| 427 | ses->domainName = | 428 | ses->domainName = |
| @@ -591,6 +592,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) | |||
| 591 | 592 | ||
| 592 | static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) | 593 | static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) |
| 593 | { | 594 | { |
| 595 | int rc; | ||
| 594 | unsigned int size; | 596 | unsigned int size; |
| 595 | 597 | ||
| 596 | /* check if already allocated */ | 598 | /* check if already allocated */ |
| @@ -600,7 +602,9 @@ static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) | |||
| 600 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | 602 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); |
| 601 | if (IS_ERR(server->secmech.hmacmd5)) { | 603 | if (IS_ERR(server->secmech.hmacmd5)) { |
| 602 | cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); | 604 | cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); |
| 603 | return PTR_ERR(server->secmech.hmacmd5); | 605 | rc = PTR_ERR(server->secmech.hmacmd5); |
| 606 | server->secmech.hmacmd5 = NULL; | ||
| 607 | return rc; | ||
| 604 | } | 608 | } |
| 605 | 609 | ||
| 606 | size = sizeof(struct shash_desc) + | 610 | size = sizeof(struct shash_desc) + |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4bdd547dbf6f..85ea98d139fc 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -147,18 +147,17 @@ cifs_read_super(struct super_block *sb) | |||
| 147 | goto out_no_root; | 147 | goto out_no_root; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | if (cifs_sb_master_tcon(cifs_sb)->nocase) | ||
| 151 | sb->s_d_op = &cifs_ci_dentry_ops; | ||
| 152 | else | ||
| 153 | sb->s_d_op = &cifs_dentry_ops; | ||
| 154 | |||
| 150 | sb->s_root = d_make_root(inode); | 155 | sb->s_root = d_make_root(inode); |
| 151 | if (!sb->s_root) { | 156 | if (!sb->s_root) { |
| 152 | rc = -ENOMEM; | 157 | rc = -ENOMEM; |
| 153 | goto out_no_root; | 158 | goto out_no_root; |
| 154 | } | 159 | } |
| 155 | 160 | ||
| 156 | /* do that *after* d_make_root() - we want NULL ->d_op for root here */ | ||
| 157 | if (cifs_sb_master_tcon(cifs_sb)->nocase) | ||
| 158 | sb->s_d_op = &cifs_ci_dentry_ops; | ||
| 159 | else | ||
| 160 | sb->s_d_op = &cifs_dentry_ops; | ||
| 161 | |||
| 162 | #ifdef CONFIG_CIFS_NFSD_EXPORT | 161 | #ifdef CONFIG_CIFS_NFSD_EXPORT |
| 163 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 162 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
| 164 | cifs_dbg(FYI, "export ops supported\n"); | 163 | cifs_dbg(FYI, "export ops supported\n"); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1fdc37041057..52ca861ed35e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1) | 44 | #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1) |
| 45 | #define MAX_SERVER_SIZE 15 | 45 | #define MAX_SERVER_SIZE 15 |
| 46 | #define MAX_SHARE_SIZE 80 | 46 | #define MAX_SHARE_SIZE 80 |
| 47 | #define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */ | ||
| 47 | #define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */ | 48 | #define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */ |
| 48 | #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ | 49 | #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ |
| 49 | 50 | ||
| @@ -369,6 +370,9 @@ struct smb_version_operations { | |||
| 369 | void (*generate_signingkey)(struct TCP_Server_Info *server); | 370 | void (*generate_signingkey)(struct TCP_Server_Info *server); |
| 370 | int (*calc_signature)(struct smb_rqst *rqst, | 371 | int (*calc_signature)(struct smb_rqst *rqst, |
| 371 | struct TCP_Server_Info *server); | 372 | struct TCP_Server_Info *server); |
| 373 | int (*query_mf_symlink)(const unsigned char *path, char *pbuf, | ||
| 374 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | ||
| 375 | unsigned int xid); | ||
| 372 | }; | 376 | }; |
| 373 | 377 | ||
| 374 | struct smb_version_values { | 378 | struct smb_version_values { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f7e584d047e2..b29a012bed33 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -497,5 +497,7 @@ void cifs_writev_complete(struct work_struct *work); | |||
| 497 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 497 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
| 498 | work_func_t complete); | 498 | work_func_t complete); |
| 499 | void cifs_writedata_release(struct kref *refcount); | 499 | void cifs_writedata_release(struct kref *refcount); |
| 500 | 500 | int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | |
| 501 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, | ||
| 502 | unsigned int xid); | ||
| 501 | #endif /* _CIFSPROTO_H */ | 503 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa68813396b5..d67c550c4980 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -1675,7 +1675,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1675 | if (string == NULL) | 1675 | if (string == NULL) |
| 1676 | goto out_nomem; | 1676 | goto out_nomem; |
| 1677 | 1677 | ||
| 1678 | if (strnlen(string, 256) == 256) { | 1678 | if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) |
| 1679 | == CIFS_MAX_DOMAINNAME_LEN) { | ||
| 1679 | printk(KERN_WARNING "CIFS: domain name too" | 1680 | printk(KERN_WARNING "CIFS: domain name too" |
| 1680 | " long\n"); | 1681 | " long\n"); |
| 1681 | goto cifs_parse_mount_err; | 1682 | goto cifs_parse_mount_err; |
| @@ -2276,8 +2277,8 @@ cifs_put_smb_ses(struct cifs_ses *ses) | |||
| 2276 | 2277 | ||
| 2277 | #ifdef CONFIG_KEYS | 2278 | #ifdef CONFIG_KEYS |
| 2278 | 2279 | ||
| 2279 | /* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ | 2280 | /* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */ |
| 2280 | #define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) | 2281 | #define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1) |
| 2281 | 2282 | ||
| 2282 | /* Populate username and pw fields from keyring if possible */ | 2283 | /* Populate username and pw fields from keyring if possible */ |
| 2283 | static int | 2284 | static int |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1e57f36ea1b2..7e36ae34e947 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -647,6 +647,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
| 647 | oflags, &oplock, &cfile->fid.netfid, xid); | 647 | oflags, &oplock, &cfile->fid.netfid, xid); |
| 648 | if (rc == 0) { | 648 | if (rc == 0) { |
| 649 | cifs_dbg(FYI, "posix reopen succeeded\n"); | 649 | cifs_dbg(FYI, "posix reopen succeeded\n"); |
| 650 | oparms.reconnect = true; | ||
| 650 | goto reopen_success; | 651 | goto reopen_success; |
| 651 | } | 652 | } |
| 652 | /* | 653 | /* |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index b83c3f5646bd..562044f700e5 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
| @@ -305,67 +305,89 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) | |||
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | int | 307 | int |
| 308 | CIFSCheckMFSymlink(struct cifs_fattr *fattr, | 308 | open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, |
| 309 | const unsigned char *path, | 309 | unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, |
| 310 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 310 | unsigned int xid) |
| 311 | { | 311 | { |
| 312 | int rc; | 312 | int rc; |
| 313 | int oplock = 0; | 313 | int oplock = 0; |
| 314 | __u16 netfid = 0; | 314 | __u16 netfid = 0; |
| 315 | struct tcon_link *tlink; | 315 | struct tcon_link *tlink; |
| 316 | struct cifs_tcon *pTcon; | 316 | struct cifs_tcon *ptcon; |
| 317 | struct cifs_io_parms io_parms; | 317 | struct cifs_io_parms io_parms; |
| 318 | u8 *buf; | ||
| 319 | char *pbuf; | ||
| 320 | unsigned int bytes_read = 0; | ||
| 321 | int buf_type = CIFS_NO_BUFFER; | 318 | int buf_type = CIFS_NO_BUFFER; |
| 322 | unsigned int link_len = 0; | ||
| 323 | FILE_ALL_INFO file_info; | 319 | FILE_ALL_INFO file_info; |
| 324 | 320 | ||
| 325 | if (!CIFSCouldBeMFSymlink(fattr)) | ||
| 326 | /* it's not a symlink */ | ||
| 327 | return 0; | ||
| 328 | |||
| 329 | tlink = cifs_sb_tlink(cifs_sb); | 321 | tlink = cifs_sb_tlink(cifs_sb); |
| 330 | if (IS_ERR(tlink)) | 322 | if (IS_ERR(tlink)) |
| 331 | return PTR_ERR(tlink); | 323 | return PTR_ERR(tlink); |
| 332 | pTcon = tlink_tcon(tlink); | 324 | ptcon = tlink_tcon(tlink); |
| 333 | 325 | ||
| 334 | rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, | 326 | rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, |
| 335 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, | 327 | CREATE_NOT_DIR, &netfid, &oplock, &file_info, |
| 336 | cifs_sb->local_nls, | 328 | cifs_sb->local_nls, |
| 337 | cifs_sb->mnt_cifs_flags & | 329 | cifs_sb->mnt_cifs_flags & |
| 338 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 330 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 339 | if (rc != 0) | 331 | if (rc != 0) { |
| 340 | goto out; | 332 | cifs_put_tlink(tlink); |
| 333 | return rc; | ||
| 334 | } | ||
| 341 | 335 | ||
| 342 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | 336 | if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { |
| 343 | CIFSSMBClose(xid, pTcon, netfid); | 337 | CIFSSMBClose(xid, ptcon, netfid); |
| 338 | cifs_put_tlink(tlink); | ||
| 344 | /* it's not a symlink */ | 339 | /* it's not a symlink */ |
| 345 | goto out; | 340 | return rc; |
| 346 | } | 341 | } |
| 347 | 342 | ||
| 348 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | ||
| 349 | if (!buf) { | ||
| 350 | rc = -ENOMEM; | ||
| 351 | goto out; | ||
| 352 | } | ||
| 353 | pbuf = buf; | ||
| 354 | io_parms.netfid = netfid; | 343 | io_parms.netfid = netfid; |
| 355 | io_parms.pid = current->tgid; | 344 | io_parms.pid = current->tgid; |
| 356 | io_parms.tcon = pTcon; | 345 | io_parms.tcon = ptcon; |
| 357 | io_parms.offset = 0; | 346 | io_parms.offset = 0; |
| 358 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | 347 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; |
| 359 | 348 | ||
| 360 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); | 349 | rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); |
| 361 | CIFSSMBClose(xid, pTcon, netfid); | 350 | CIFSSMBClose(xid, ptcon, netfid); |
| 362 | if (rc != 0) { | 351 | cifs_put_tlink(tlink); |
| 363 | kfree(buf); | 352 | return rc; |
| 353 | } | ||
| 354 | |||
| 355 | |||
| 356 | int | ||
| 357 | CIFSCheckMFSymlink(struct cifs_fattr *fattr, | ||
| 358 | const unsigned char *path, | ||
| 359 | struct cifs_sb_info *cifs_sb, unsigned int xid) | ||
| 360 | { | ||
| 361 | int rc = 0; | ||
| 362 | u8 *buf = NULL; | ||
| 363 | unsigned int link_len = 0; | ||
| 364 | unsigned int bytes_read = 0; | ||
| 365 | struct cifs_tcon *ptcon; | ||
| 366 | |||
| 367 | if (!CIFSCouldBeMFSymlink(fattr)) | ||
| 368 | /* it's not a symlink */ | ||
| 369 | return 0; | ||
| 370 | |||
| 371 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | ||
| 372 | if (!buf) { | ||
| 373 | rc = -ENOMEM; | ||
| 364 | goto out; | 374 | goto out; |
| 365 | } | 375 | } |
| 366 | 376 | ||
| 377 | ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb)); | ||
| 378 | if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink)) | ||
| 379 | rc = ptcon->ses->server->ops->query_mf_symlink(path, buf, | ||
| 380 | &bytes_read, cifs_sb, xid); | ||
| 381 | else | ||
| 382 | goto out; | ||
| 383 | |||
| 384 | if (rc != 0) | ||
| 385 | goto out; | ||
| 386 | |||
| 387 | if (bytes_read == 0) /* not a symlink */ | ||
| 388 | goto out; | ||
| 389 | |||
| 367 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); | 390 | rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); |
| 368 | kfree(buf); | ||
| 369 | if (rc == -EINVAL) { | 391 | if (rc == -EINVAL) { |
| 370 | /* it's not a symlink */ | 392 | /* it's not a symlink */ |
| 371 | rc = 0; | 393 | rc = 0; |
| @@ -381,7 +403,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, | |||
| 381 | fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; | 403 | fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; |
| 382 | fattr->cf_dtype = DT_LNK; | 404 | fattr->cf_dtype = DT_LNK; |
| 383 | out: | 405 | out: |
| 384 | cifs_put_tlink(tlink); | 406 | kfree(buf); |
| 385 | return rc; | 407 | return rc; |
| 386 | } | 408 | } |
| 387 | 409 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ab8778469394..69d2c826a23b 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -111,6 +111,14 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, | |||
| 111 | return; | 111 | return; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | /* | ||
| 115 | * If we know that the inode will need to be revalidated immediately, | ||
| 116 | * then don't create a new dentry for it. We'll end up doing an on | ||
| 117 | * the wire call either way and this spares us an invalidation. | ||
| 118 | */ | ||
| 119 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | ||
| 120 | return; | ||
| 121 | |||
| 114 | dentry = d_alloc(parent, name); | 122 | dentry = d_alloc(parent, name); |
| 115 | if (!dentry) | 123 | if (!dentry) |
| 116 | return; | 124 | return; |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 79358e341fd2..08dd37bb23aa 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -197,7 +197,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, | |||
| 197 | bytes_ret = 0; | 197 | bytes_ret = 0; |
| 198 | } else | 198 | } else |
| 199 | bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, | 199 | bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, |
| 200 | 256, nls_cp); | 200 | CIFS_MAX_DOMAINNAME_LEN, nls_cp); |
| 201 | bcc_ptr += 2 * bytes_ret; | 201 | bcc_ptr += 2 * bytes_ret; |
| 202 | bcc_ptr += 2; /* account for null terminator */ | 202 | bcc_ptr += 2; /* account for null terminator */ |
| 203 | 203 | ||
| @@ -255,8 +255,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, | |||
| 255 | 255 | ||
| 256 | /* copy domain */ | 256 | /* copy domain */ |
| 257 | if (ses->domainName != NULL) { | 257 | if (ses->domainName != NULL) { |
| 258 | strncpy(bcc_ptr, ses->domainName, 256); | 258 | strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); |
| 259 | bcc_ptr += strnlen(ses->domainName, 256); | 259 | bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); |
| 260 | } /* else we will send a null domain name | 260 | } /* else we will send a null domain name |
| 261 | so the server will default to its own domain */ | 261 | so the server will default to its own domain */ |
| 262 | *bcc_ptr = 0; | 262 | *bcc_ptr = 0; |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 6457690731a2..60943978aec3 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
| @@ -944,6 +944,7 @@ struct smb_version_operations smb1_operations = { | |||
| 944 | .mand_lock = cifs_mand_lock, | 944 | .mand_lock = cifs_mand_lock, |
| 945 | .mand_unlock_range = cifs_unlock_range, | 945 | .mand_unlock_range = cifs_unlock_range, |
| 946 | .push_mand_locks = cifs_push_mandatory_locks, | 946 | .push_mand_locks = cifs_push_mandatory_locks, |
| 947 | .query_mf_symlink = open_query_close_cifs_symlink, | ||
| 947 | }; | 948 | }; |
| 948 | 949 | ||
| 949 | struct smb_version_values smb1_values = { | 950 | struct smb_version_values smb1_values = { |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 301b191270b9..4f2300d020c7 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | static int | 42 | static int |
| 43 | smb2_crypto_shash_allocate(struct TCP_Server_Info *server) | 43 | smb2_crypto_shash_allocate(struct TCP_Server_Info *server) |
| 44 | { | 44 | { |
| 45 | int rc; | ||
| 45 | unsigned int size; | 46 | unsigned int size; |
| 46 | 47 | ||
| 47 | if (server->secmech.sdeschmacsha256 != NULL) | 48 | if (server->secmech.sdeschmacsha256 != NULL) |
| @@ -50,7 +51,9 @@ smb2_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
| 50 | server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); | 51 | server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); |
| 51 | if (IS_ERR(server->secmech.hmacsha256)) { | 52 | if (IS_ERR(server->secmech.hmacsha256)) { |
| 52 | cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); | 53 | cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); |
| 53 | return PTR_ERR(server->secmech.hmacsha256); | 54 | rc = PTR_ERR(server->secmech.hmacsha256); |
| 55 | server->secmech.hmacsha256 = NULL; | ||
| 56 | return rc; | ||
| 54 | } | 57 | } |
| 55 | 58 | ||
| 56 | size = sizeof(struct shash_desc) + | 59 | size = sizeof(struct shash_desc) + |
| @@ -87,7 +90,9 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
| 87 | server->secmech.sdeschmacsha256 = NULL; | 90 | server->secmech.sdeschmacsha256 = NULL; |
| 88 | crypto_free_shash(server->secmech.hmacsha256); | 91 | crypto_free_shash(server->secmech.hmacsha256); |
| 89 | server->secmech.hmacsha256 = NULL; | 92 | server->secmech.hmacsha256 = NULL; |
| 90 | return PTR_ERR(server->secmech.cmacaes); | 93 | rc = PTR_ERR(server->secmech.cmacaes); |
| 94 | server->secmech.cmacaes = NULL; | ||
| 95 | return rc; | ||
| 91 | } | 96 | } |
| 92 | 97 | ||
| 93 | size = sizeof(struct shash_desc) + | 98 | size = sizeof(struct shash_desc) + |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 4888cb3fdef7..c7c83ff0f752 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -533,8 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove); | |||
| 533 | */ | 533 | */ |
| 534 | void debugfs_remove_recursive(struct dentry *dentry) | 534 | void debugfs_remove_recursive(struct dentry *dentry) |
| 535 | { | 535 | { |
| 536 | struct dentry *child; | 536 | struct dentry *child, *next, *parent; |
| 537 | struct dentry *parent; | ||
| 538 | 537 | ||
| 539 | if (IS_ERR_OR_NULL(dentry)) | 538 | if (IS_ERR_OR_NULL(dentry)) |
| 540 | return; | 539 | return; |
| @@ -544,61 +543,37 @@ void debugfs_remove_recursive(struct dentry *dentry) | |||
| 544 | return; | 543 | return; |
| 545 | 544 | ||
| 546 | parent = dentry; | 545 | parent = dentry; |
| 546 | down: | ||
| 547 | mutex_lock(&parent->d_inode->i_mutex); | 547 | mutex_lock(&parent->d_inode->i_mutex); |
| 548 | list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) { | ||
| 549 | if (!debugfs_positive(child)) | ||
| 550 | continue; | ||
| 548 | 551 | ||
| 549 | while (1) { | 552 | /* perhaps simple_empty(child) makes more sense */ |
| 550 | /* | ||
| 551 | * When all dentries under "parent" has been removed, | ||
| 552 | * walk up the tree until we reach our starting point. | ||
| 553 | */ | ||
| 554 | if (list_empty(&parent->d_subdirs)) { | ||
| 555 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 556 | if (parent == dentry) | ||
| 557 | break; | ||
| 558 | parent = parent->d_parent; | ||
| 559 | mutex_lock(&parent->d_inode->i_mutex); | ||
| 560 | } | ||
| 561 | child = list_entry(parent->d_subdirs.next, struct dentry, | ||
| 562 | d_u.d_child); | ||
| 563 | next_sibling: | ||
| 564 | |||
| 565 | /* | ||
| 566 | * If "child" isn't empty, walk down the tree and | ||
| 567 | * remove all its descendants first. | ||
| 568 | */ | ||
| 569 | if (!list_empty(&child->d_subdirs)) { | 553 | if (!list_empty(&child->d_subdirs)) { |
| 570 | mutex_unlock(&parent->d_inode->i_mutex); | 554 | mutex_unlock(&parent->d_inode->i_mutex); |
| 571 | parent = child; | 555 | parent = child; |
| 572 | mutex_lock(&parent->d_inode->i_mutex); | 556 | goto down; |
| 573 | continue; | ||
| 574 | } | 557 | } |
| 575 | __debugfs_remove(child, parent); | 558 | up: |
| 576 | if (parent->d_subdirs.next == &child->d_u.d_child) { | 559 | if (!__debugfs_remove(child, parent)) |
| 577 | /* | 560 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
| 578 | * Try the next sibling. | ||
| 579 | */ | ||
| 580 | if (child->d_u.d_child.next != &parent->d_subdirs) { | ||
| 581 | child = list_entry(child->d_u.d_child.next, | ||
| 582 | struct dentry, | ||
| 583 | d_u.d_child); | ||
| 584 | goto next_sibling; | ||
| 585 | } | ||
| 586 | |||
| 587 | /* | ||
| 588 | * Avoid infinite loop if we fail to remove | ||
| 589 | * one dentry. | ||
| 590 | */ | ||
| 591 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 592 | break; | ||
| 593 | } | ||
| 594 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 595 | } | 561 | } |
| 596 | 562 | ||
| 597 | parent = dentry->d_parent; | 563 | mutex_unlock(&parent->d_inode->i_mutex); |
| 564 | child = parent; | ||
| 565 | parent = parent->d_parent; | ||
| 598 | mutex_lock(&parent->d_inode->i_mutex); | 566 | mutex_lock(&parent->d_inode->i_mutex); |
| 599 | __debugfs_remove(dentry, parent); | 567 | |
| 568 | if (child != dentry) { | ||
| 569 | next = list_entry(child->d_u.d_child.next, struct dentry, | ||
| 570 | d_u.d_child); | ||
| 571 | goto up; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (!__debugfs_remove(child, parent)) | ||
| 575 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 600 | mutex_unlock(&parent->d_inode->i_mutex); | 576 | mutex_unlock(&parent->d_inode->i_mutex); |
| 601 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 602 | } | 577 | } |
| 603 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); | 578 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); |
| 604 | 579 | ||
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 911649a47dd5..812149119fa3 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -686,7 +686,6 @@ static int device_close(struct inode *inode, struct file *file) | |||
| 686 | device_remove_lockspace() */ | 686 | device_remove_lockspace() */ |
| 687 | 687 | ||
| 688 | sigprocmask(SIG_SETMASK, &tmpsig, NULL); | 688 | sigprocmask(SIG_SETMASK, &tmpsig, NULL); |
| 689 | recalc_sigpending(); | ||
| 690 | 689 | ||
| 691 | return 0; | 690 | return 0; |
| 692 | } | 691 | } |
| @@ -608,7 +608,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
| 608 | return -ENOMEM; | 608 | return -ENOMEM; |
| 609 | 609 | ||
| 610 | lru_add_drain(); | 610 | lru_add_drain(); |
| 611 | tlb_gather_mmu(&tlb, mm, 0); | 611 | tlb_gather_mmu(&tlb, mm, old_start, old_end); |
| 612 | if (new_end > old_start) { | 612 | if (new_end > old_start) { |
| 613 | /* | 613 | /* |
| 614 | * when the old and new regions overlap clear from new_end. | 614 | * when the old and new regions overlap clear from new_end. |
| @@ -625,7 +625,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
| 625 | free_pgd_range(&tlb, old_start, old_end, new_end, | 625 | free_pgd_range(&tlb, old_start, old_end, new_end, |
| 626 | vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); | 626 | vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); |
| 627 | } | 627 | } |
| 628 | tlb_finish_mmu(&tlb, new_end, old_end); | 628 | tlb_finish_mmu(&tlb, old_start, old_end); |
| 629 | 629 | ||
| 630 | /* | 630 | /* |
| 631 | * Shrink the vma to just the new range. Always succeeds. | 631 | * Shrink the vma to just the new range. Always succeeds. |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index b577e45425b0..0ab26fbf3380 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -2086,6 +2086,7 @@ extern int ext4_sync_inode(handle_t *, struct inode *); | |||
| 2086 | extern void ext4_dirty_inode(struct inode *, int); | 2086 | extern void ext4_dirty_inode(struct inode *, int); |
| 2087 | extern int ext4_change_inode_journal_flag(struct inode *, int); | 2087 | extern int ext4_change_inode_journal_flag(struct inode *, int); |
| 2088 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); | 2088 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); |
| 2089 | extern int ext4_inode_attach_jinode(struct inode *inode); | ||
| 2089 | extern int ext4_can_truncate(struct inode *inode); | 2090 | extern int ext4_can_truncate(struct inode *inode); |
| 2090 | extern void ext4_truncate(struct inode *); | 2091 | extern void ext4_truncate(struct inode *); |
| 2091 | extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); | 2092 | extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 72a3600aedbd..17ac112ab101 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
| @@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, | |||
| 255 | set_buffer_prio(bh); | 255 | set_buffer_prio(bh); |
| 256 | if (ext4_handle_valid(handle)) { | 256 | if (ext4_handle_valid(handle)) { |
| 257 | err = jbd2_journal_dirty_metadata(handle, bh); | 257 | err = jbd2_journal_dirty_metadata(handle, bh); |
| 258 | if (err) { | 258 | /* Errors can only happen if there is a bug */ |
| 259 | /* Errors can only happen if there is a bug */ | 259 | if (WARN_ON_ONCE(err)) { |
| 260 | handle->h_err = err; | 260 | ext4_journal_abort_handle(where, line, __func__, bh, |
| 261 | __ext4_journal_stop(where, line, handle); | 261 | handle, err); |
| 262 | } | 262 | } |
| 263 | } else { | 263 | } else { |
| 264 | if (inode) | 264 | if (inode) |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a61873808f76..72ba4705d4fa 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -4412,7 +4412,7 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode) | |||
| 4412 | retry: | 4412 | retry: |
| 4413 | err = ext4_es_remove_extent(inode, last_block, | 4413 | err = ext4_es_remove_extent(inode, last_block, |
| 4414 | EXT_MAX_BLOCKS - last_block); | 4414 | EXT_MAX_BLOCKS - last_block); |
| 4415 | if (err == ENOMEM) { | 4415 | if (err == -ENOMEM) { |
| 4416 | cond_resched(); | 4416 | cond_resched(); |
| 4417 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 4417 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
| 4418 | goto retry; | 4418 | goto retry; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 6f4cc567c382..319c9d26279a 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
| 219 | { | 219 | { |
| 220 | struct super_block *sb = inode->i_sb; | 220 | struct super_block *sb = inode->i_sb; |
| 221 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 221 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
| 222 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 223 | struct vfsmount *mnt = filp->f_path.mnt; | 222 | struct vfsmount *mnt = filp->f_path.mnt; |
| 224 | struct path path; | 223 | struct path path; |
| 225 | char buf[64], *cp; | 224 | char buf[64], *cp; |
| @@ -259,22 +258,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
| 259 | * Set up the jbd2_inode if we are opening the inode for | 258 | * Set up the jbd2_inode if we are opening the inode for |
| 260 | * writing and the journal is present | 259 | * writing and the journal is present |
| 261 | */ | 260 | */ |
| 262 | if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) { | 261 | if (filp->f_mode & FMODE_WRITE) { |
| 263 | struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL); | 262 | int ret = ext4_inode_attach_jinode(inode); |
| 264 | 263 | if (ret < 0) | |
| 265 | spin_lock(&inode->i_lock); | 264 | return ret; |
| 266 | if (!ei->jinode) { | ||
| 267 | if (!jinode) { | ||
| 268 | spin_unlock(&inode->i_lock); | ||
| 269 | return -ENOMEM; | ||
| 270 | } | ||
| 271 | ei->jinode = jinode; | ||
| 272 | jbd2_journal_init_jbd_inode(ei->jinode, inode); | ||
| 273 | jinode = NULL; | ||
| 274 | } | ||
| 275 | spin_unlock(&inode->i_lock); | ||
| 276 | if (unlikely(jinode != NULL)) | ||
| 277 | jbd2_free_inode(jinode); | ||
| 278 | } | 265 | } |
| 279 | return dquot_file_open(inode, filp); | 266 | return dquot_file_open(inode, filp); |
| 280 | } | 267 | } |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f03598c6ffd3..8bf5999875ee 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -734,11 +734,8 @@ repeat_in_this_group: | |||
| 734 | ino = ext4_find_next_zero_bit((unsigned long *) | 734 | ino = ext4_find_next_zero_bit((unsigned long *) |
| 735 | inode_bitmap_bh->b_data, | 735 | inode_bitmap_bh->b_data, |
| 736 | EXT4_INODES_PER_GROUP(sb), ino); | 736 | EXT4_INODES_PER_GROUP(sb), ino); |
| 737 | if (ino >= EXT4_INODES_PER_GROUP(sb)) { | 737 | if (ino >= EXT4_INODES_PER_GROUP(sb)) |
| 738 | if (++group == ngroups) | 738 | goto next_group; |
| 739 | group = 0; | ||
| 740 | continue; | ||
| 741 | } | ||
| 742 | if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { | 739 | if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { |
| 743 | ext4_error(sb, "reserved inode found cleared - " | 740 | ext4_error(sb, "reserved inode found cleared - " |
| 744 | "inode=%lu", ino + 1); | 741 | "inode=%lu", ino + 1); |
| @@ -769,6 +766,9 @@ repeat_in_this_group: | |||
| 769 | goto got; /* we grabbed the inode! */ | 766 | goto got; /* we grabbed the inode! */ |
| 770 | if (ino < EXT4_INODES_PER_GROUP(sb)) | 767 | if (ino < EXT4_INODES_PER_GROUP(sb)) |
| 771 | goto repeat_in_this_group; | 768 | goto repeat_in_this_group; |
| 769 | next_group: | ||
| 770 | if (++group == ngroups) | ||
| 771 | group = 0; | ||
| 772 | } | 772 | } |
| 773 | err = -ENOSPC; | 773 | err = -ENOSPC; |
| 774 | goto out; | 774 | goto out; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ba33c67d6e48..c2ca04e67a4f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -555,14 +555,13 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
| 555 | int ret; | 555 | int ret; |
| 556 | unsigned long long status; | 556 | unsigned long long status; |
| 557 | 557 | ||
| 558 | #ifdef ES_AGGRESSIVE_TEST | 558 | if (unlikely(retval != map->m_len)) { |
| 559 | if (retval != map->m_len) { | 559 | ext4_warning(inode->i_sb, |
| 560 | printk("ES len assertion failed for inode: %lu " | 560 | "ES len assertion failed for inode " |
| 561 | "retval %d != map->m_len %d " | 561 | "%lu: retval %d != map->m_len %d", |
| 562 | "in %s (lookup)\n", inode->i_ino, retval, | 562 | inode->i_ino, retval, map->m_len); |
| 563 | map->m_len, __func__); | 563 | WARN_ON(1); |
| 564 | } | 564 | } |
| 565 | #endif | ||
| 566 | 565 | ||
| 567 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? | 566 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? |
| 568 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; | 567 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; |
| @@ -656,14 +655,13 @@ found: | |||
| 656 | int ret; | 655 | int ret; |
| 657 | unsigned long long status; | 656 | unsigned long long status; |
| 658 | 657 | ||
| 659 | #ifdef ES_AGGRESSIVE_TEST | 658 | if (unlikely(retval != map->m_len)) { |
| 660 | if (retval != map->m_len) { | 659 | ext4_warning(inode->i_sb, |
| 661 | printk("ES len assertion failed for inode: %lu " | 660 | "ES len assertion failed for inode " |
| 662 | "retval %d != map->m_len %d " | 661 | "%lu: retval %d != map->m_len %d", |
| 663 | "in %s (allocation)\n", inode->i_ino, retval, | 662 | inode->i_ino, retval, map->m_len); |
| 664 | map->m_len, __func__); | 663 | WARN_ON(1); |
| 665 | } | 664 | } |
| 666 | #endif | ||
| 667 | 665 | ||
| 668 | /* | 666 | /* |
| 669 | * If the extent has been zeroed out, we don't need to update | 667 | * If the extent has been zeroed out, we don't need to update |
| @@ -1637,14 +1635,13 @@ add_delayed: | |||
| 1637 | int ret; | 1635 | int ret; |
| 1638 | unsigned long long status; | 1636 | unsigned long long status; |
| 1639 | 1637 | ||
| 1640 | #ifdef ES_AGGRESSIVE_TEST | 1638 | if (unlikely(retval != map->m_len)) { |
| 1641 | if (retval != map->m_len) { | 1639 | ext4_warning(inode->i_sb, |
| 1642 | printk("ES len assertion failed for inode: %lu " | 1640 | "ES len assertion failed for inode " |
| 1643 | "retval %d != map->m_len %d " | 1641 | "%lu: retval %d != map->m_len %d", |
| 1644 | "in %s (lookup)\n", inode->i_ino, retval, | 1642 | inode->i_ino, retval, map->m_len); |
| 1645 | map->m_len, __func__); | 1643 | WARN_ON(1); |
| 1646 | } | 1644 | } |
| 1647 | #endif | ||
| 1648 | 1645 | ||
| 1649 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? | 1646 | status = map->m_flags & EXT4_MAP_UNWRITTEN ? |
| 1650 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; | 1647 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; |
| @@ -3536,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) | |||
| 3536 | offset; | 3533 | offset; |
| 3537 | } | 3534 | } |
| 3538 | 3535 | ||
| 3536 | if (offset & (sb->s_blocksize - 1) || | ||
| 3537 | (offset + length) & (sb->s_blocksize - 1)) { | ||
| 3538 | /* | ||
| 3539 | * Attach jinode to inode for jbd2 if we do any zeroing of | ||
| 3540 | * partial block | ||
| 3541 | */ | ||
| 3542 | ret = ext4_inode_attach_jinode(inode); | ||
| 3543 | if (ret < 0) | ||
| 3544 | goto out_mutex; | ||
| 3545 | |||
| 3546 | } | ||
| 3547 | |||
| 3539 | first_block_offset = round_up(offset, sb->s_blocksize); | 3548 | first_block_offset = round_up(offset, sb->s_blocksize); |
| 3540 | last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; | 3549 | last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; |
| 3541 | 3550 | ||
| @@ -3604,6 +3613,31 @@ out_mutex: | |||
| 3604 | return ret; | 3613 | return ret; |
| 3605 | } | 3614 | } |
| 3606 | 3615 | ||
| 3616 | int ext4_inode_attach_jinode(struct inode *inode) | ||
| 3617 | { | ||
| 3618 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 3619 | struct jbd2_inode *jinode; | ||
| 3620 | |||
| 3621 | if (ei->jinode || !EXT4_SB(inode->i_sb)->s_journal) | ||
| 3622 | return 0; | ||
| 3623 | |||
| 3624 | jinode = jbd2_alloc_inode(GFP_KERNEL); | ||
| 3625 | spin_lock(&inode->i_lock); | ||
| 3626 | if (!ei->jinode) { | ||
| 3627 | if (!jinode) { | ||
| 3628 | spin_unlock(&inode->i_lock); | ||
| 3629 | return -ENOMEM; | ||
| 3630 | } | ||
| 3631 | ei->jinode = jinode; | ||
| 3632 | jbd2_journal_init_jbd_inode(ei->jinode, inode); | ||
| 3633 | jinode = NULL; | ||
| 3634 | } | ||
| 3635 | spin_unlock(&inode->i_lock); | ||
| 3636 | if (unlikely(jinode != NULL)) | ||
| 3637 | jbd2_free_inode(jinode); | ||
| 3638 | return 0; | ||
| 3639 | } | ||
| 3640 | |||
| 3607 | /* | 3641 | /* |
| 3608 | * ext4_truncate() | 3642 | * ext4_truncate() |
| 3609 | * | 3643 | * |
| @@ -3664,6 +3698,12 @@ void ext4_truncate(struct inode *inode) | |||
| 3664 | return; | 3698 | return; |
| 3665 | } | 3699 | } |
| 3666 | 3700 | ||
| 3701 | /* If we zero-out tail of the page, we have to create jinode for jbd2 */ | ||
| 3702 | if (inode->i_size & (inode->i_sb->s_blocksize - 1)) { | ||
| 3703 | if (ext4_inode_attach_jinode(inode) < 0) | ||
| 3704 | return; | ||
| 3705 | } | ||
| 3706 | |||
| 3667 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) | 3707 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
| 3668 | credits = ext4_writepage_trans_blocks(inode); | 3708 | credits = ext4_writepage_trans_blocks(inode); |
| 3669 | else | 3709 | else |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 9491ac0590f7..c0427e2f6648 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -77,8 +77,10 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2) | |||
| 77 | memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data)); | 77 | memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data)); |
| 78 | memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags)); | 78 | memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags)); |
| 79 | memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize)); | 79 | memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize)); |
| 80 | memswap(&ei1->i_es_tree, &ei2->i_es_tree, sizeof(ei1->i_es_tree)); | 80 | ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS); |
| 81 | memswap(&ei1->i_es_lru_nr, &ei2->i_es_lru_nr, sizeof(ei1->i_es_lru_nr)); | 81 | ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS); |
| 82 | ext4_es_lru_del(inode1); | ||
| 83 | ext4_es_lru_del(inode2); | ||
| 82 | 84 | ||
| 83 | isize = i_size_read(inode1); | 85 | isize = i_size_read(inode1); |
| 84 | i_size_write(inode1, i_size_read(inode2)); | 86 | i_size_write(inode1, i_size_read(inode2)); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bca26f34edf4..b59373b625e9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -1359,7 +1359,7 @@ static const struct mount_opts { | |||
| 1359 | {Opt_delalloc, EXT4_MOUNT_DELALLOC, | 1359 | {Opt_delalloc, EXT4_MOUNT_DELALLOC, |
| 1360 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, | 1360 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, |
| 1361 | {Opt_nodelalloc, EXT4_MOUNT_DELALLOC, | 1361 | {Opt_nodelalloc, EXT4_MOUNT_DELALLOC, |
| 1362 | MOPT_EXT4_ONLY | MOPT_CLEAR | MOPT_EXPLICIT}, | 1362 | MOPT_EXT4_ONLY | MOPT_CLEAR}, |
| 1363 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, | 1363 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, |
| 1364 | MOPT_EXT4_ONLY | MOPT_SET}, | 1364 | MOPT_EXT4_ONLY | MOPT_SET}, |
| 1365 | {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT | | 1365 | {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT | |
| @@ -3483,7 +3483,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3483 | } | 3483 | } |
| 3484 | if (test_opt(sb, DIOREAD_NOLOCK)) { | 3484 | if (test_opt(sb, DIOREAD_NOLOCK)) { |
| 3485 | ext4_msg(sb, KERN_ERR, "can't mount with " | 3485 | ext4_msg(sb, KERN_ERR, "can't mount with " |
| 3486 | "both data=journal and delalloc"); | 3486 | "both data=journal and dioread_nolock"); |
| 3487 | goto failed_mount; | 3487 | goto failed_mount; |
| 3488 | } | 3488 | } |
| 3489 | if (test_opt(sb, DELALLOC)) | 3489 | if (test_opt(sb, DELALLOC)) |
| @@ -4727,6 +4727,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 4727 | goto restore_opts; | 4727 | goto restore_opts; |
| 4728 | } | 4728 | } |
| 4729 | 4729 | ||
| 4730 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { | ||
| 4731 | if (test_opt2(sb, EXPLICIT_DELALLOC)) { | ||
| 4732 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 4733 | "both data=journal and delalloc"); | ||
| 4734 | err = -EINVAL; | ||
| 4735 | goto restore_opts; | ||
| 4736 | } | ||
| 4737 | if (test_opt(sb, DIOREAD_NOLOCK)) { | ||
| 4738 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 4739 | "both data=journal and dioread_nolock"); | ||
| 4740 | err = -EINVAL; | ||
| 4741 | goto restore_opts; | ||
| 4742 | } | ||
| 4743 | } | ||
| 4744 | |||
| 4730 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) | 4745 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) |
| 4731 | ext4_abort(sb, "Abort forced by user"); | 4746 | ext4_abort(sb, "Abort forced by user"); |
| 4732 | 4747 | ||
| @@ -5481,6 +5496,7 @@ static void __exit ext4_exit_fs(void) | |||
| 5481 | kset_unregister(ext4_kset); | 5496 | kset_unregister(ext4_kset); |
| 5482 | ext4_exit_system_zone(); | 5497 | ext4_exit_system_zone(); |
| 5483 | ext4_exit_pageio(); | 5498 | ext4_exit_pageio(); |
| 5499 | ext4_exit_es(); | ||
| 5484 | } | 5500 | } |
| 5485 | 5501 | ||
| 5486 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); | 5502 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 6599222536eb..65343c3741ff 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
| @@ -730,14 +730,14 @@ static int __init fcntl_init(void) | |||
| 730 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY | 730 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY |
| 731 | * is defined as O_NONBLOCK on some platforms and not on others. | 731 | * is defined as O_NONBLOCK on some platforms and not on others. |
| 732 | */ | 732 | */ |
| 733 | BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( | 733 | BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( |
| 734 | O_RDONLY | O_WRONLY | O_RDWR | | 734 | O_RDONLY | O_WRONLY | O_RDWR | |
| 735 | O_CREAT | O_EXCL | O_NOCTTY | | 735 | O_CREAT | O_EXCL | O_NOCTTY | |
| 736 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ | 736 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ |
| 737 | __O_SYNC | O_DSYNC | FASYNC | | 737 | __O_SYNC | O_DSYNC | FASYNC | |
| 738 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | | 738 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | |
| 739 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | | 739 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | |
| 740 | __FMODE_EXEC | O_PATH | 740 | __FMODE_EXEC | O_PATH | __O_TMPFILE |
| 741 | )); | 741 | )); |
| 742 | 742 | ||
| 743 | fasync_cache = kmem_cache_create("fasync_cache", | 743 | fasync_cache = kmem_cache_create("fasync_cache", |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index a3f868ae3fd4..34423978b170 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -463,6 +463,14 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb, | |||
| 463 | return inode; | 463 | return inode; |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | /* | ||
| 467 | * Hugetlbfs is not reclaimable; therefore its i_mmap_mutex will never | ||
| 468 | * be taken from reclaim -- unlike regular filesystems. This needs an | ||
| 469 | * annotation because huge_pmd_share() does an allocation under | ||
| 470 | * i_mmap_mutex. | ||
| 471 | */ | ||
| 472 | struct lock_class_key hugetlbfs_i_mmap_mutex_key; | ||
| 473 | |||
| 466 | static struct inode *hugetlbfs_get_inode(struct super_block *sb, | 474 | static struct inode *hugetlbfs_get_inode(struct super_block *sb, |
| 467 | struct inode *dir, | 475 | struct inode *dir, |
| 468 | umode_t mode, dev_t dev) | 476 | umode_t mode, dev_t dev) |
| @@ -474,6 +482,8 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, | |||
| 474 | struct hugetlbfs_inode_info *info; | 482 | struct hugetlbfs_inode_info *info; |
| 475 | inode->i_ino = get_next_ino(); | 483 | inode->i_ino = get_next_ino(); |
| 476 | inode_init_owner(inode, dir, mode); | 484 | inode_init_owner(inode, dir, mode); |
| 485 | lockdep_set_class(&inode->i_mapping->i_mmap_mutex, | ||
| 486 | &hugetlbfs_i_mmap_mutex_key); | ||
| 477 | inode->i_mapping->a_ops = &hugetlbfs_aops; | 487 | inode->i_mapping->a_ops = &hugetlbfs_aops; |
| 478 | inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; | 488 | inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; |
| 479 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 489 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 01bfe7662751..41e491b8e5d7 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
| @@ -64,12 +64,17 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) | |||
| 64 | nlm_init->protocol, nlm_version, | 64 | nlm_init->protocol, nlm_version, |
| 65 | nlm_init->hostname, nlm_init->noresvport, | 65 | nlm_init->hostname, nlm_init->noresvport, |
| 66 | nlm_init->net); | 66 | nlm_init->net); |
| 67 | if (host == NULL) { | 67 | if (host == NULL) |
| 68 | lockd_down(nlm_init->net); | 68 | goto out_nohost; |
| 69 | return ERR_PTR(-ENOLCK); | 69 | if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL) |
| 70 | } | 70 | goto out_nobind; |
| 71 | 71 | ||
| 72 | return host; | 72 | return host; |
| 73 | out_nobind: | ||
| 74 | nlmclnt_release_host(host); | ||
| 75 | out_nohost: | ||
| 76 | lockd_down(nlm_init->net); | ||
| 77 | return ERR_PTR(-ENOLCK); | ||
| 73 | } | 78 | } |
| 74 | EXPORT_SYMBOL_GPL(nlmclnt_init); | 79 | EXPORT_SYMBOL_GPL(nlmclnt_init); |
| 75 | 80 | ||
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 9760ecb9b60f..acd394716349 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -125,14 +125,15 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) | |||
| 125 | { | 125 | { |
| 126 | struct nlm_args *argp = &req->a_args; | 126 | struct nlm_args *argp = &req->a_args; |
| 127 | struct nlm_lock *lock = &argp->lock; | 127 | struct nlm_lock *lock = &argp->lock; |
| 128 | char *nodename = req->a_host->h_rpcclnt->cl_nodename; | ||
| 128 | 129 | ||
| 129 | nlmclnt_next_cookie(&argp->cookie); | 130 | nlmclnt_next_cookie(&argp->cookie); |
| 130 | memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh)); | 131 | memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh)); |
| 131 | lock->caller = utsname()->nodename; | 132 | lock->caller = nodename; |
| 132 | lock->oh.data = req->a_owner; | 133 | lock->oh.data = req->a_owner; |
| 133 | lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", | 134 | lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", |
| 134 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, | 135 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, |
| 135 | utsname()->nodename); | 136 | nodename); |
| 136 | lock->svid = fl->fl_u.nfs_fl.owner->pid; | 137 | lock->svid = fl->fl_u.nfs_fl.owner->pid; |
| 137 | lock->fl.fl_start = fl->fl_start; | 138 | lock->fl.fl_start = fl->fl_start; |
| 138 | lock->fl.fl_end = fl->fl_end; | 139 | lock->fl.fl_end = fl->fl_end; |
diff --git a/fs/namei.c b/fs/namei.c index 8b61d103a8a7..89a612e392eb 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -3671,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, | |||
| 3671 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) | 3671 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) |
| 3672 | return -EINVAL; | 3672 | return -EINVAL; |
| 3673 | /* | 3673 | /* |
| 3674 | * To use null names we require CAP_DAC_READ_SEARCH | 3674 | * Using empty names is equivalent to using AT_SYMLINK_FOLLOW |
| 3675 | * This ensures that not everyone will be able to create | 3675 | * on /proc/self/fd/<fd>. |
| 3676 | * handlink using the passed filedescriptor. | ||
| 3677 | */ | 3676 | */ |
| 3678 | if (flags & AT_EMPTY_PATH) { | 3677 | if (flags & AT_EMPTY_PATH) |
| 3679 | if (!capable(CAP_DAC_READ_SEARCH)) | ||
| 3680 | return -ENOENT; | ||
| 3681 | how = LOOKUP_EMPTY; | 3678 | how = LOOKUP_EMPTY; |
| 3682 | } | ||
| 3683 | 3679 | ||
| 3684 | if (flags & AT_SYMLINK_FOLLOW) | 3680 | if (flags & AT_SYMLINK_FOLLOW) |
| 3685 | how |= LOOKUP_FOLLOW; | 3681 | how |= LOOKUP_FOLLOW; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index af6e806044d7..941246f2b43d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -463,7 +463,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
| 463 | unlock_new_inode(inode); | 463 | unlock_new_inode(inode); |
| 464 | } else | 464 | } else |
| 465 | nfs_refresh_inode(inode, fattr); | 465 | nfs_refresh_inode(inode, fattr); |
| 466 | nfs_setsecurity(inode, fattr, label); | ||
| 467 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", | 466 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", |
| 468 | inode->i_sb->s_id, | 467 | inode->i_sb->s_id, |
| 469 | (long long)NFS_FILEID(inode), | 468 | (long long)NFS_FILEID(inode), |
| @@ -963,9 +962,15 @@ EXPORT_SYMBOL_GPL(nfs_revalidate_inode); | |||
| 963 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) | 962 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) |
| 964 | { | 963 | { |
| 965 | struct nfs_inode *nfsi = NFS_I(inode); | 964 | struct nfs_inode *nfsi = NFS_I(inode); |
| 966 | 965 | int ret; | |
| 966 | |||
| 967 | if (mapping->nrpages != 0) { | 967 | if (mapping->nrpages != 0) { |
| 968 | int ret = invalidate_inode_pages2(mapping); | 968 | if (S_ISREG(inode->i_mode)) { |
| 969 | ret = nfs_sync_mapping(mapping); | ||
| 970 | if (ret < 0) | ||
| 971 | return ret; | ||
| 972 | } | ||
| 973 | ret = invalidate_inode_pages2(mapping); | ||
| 969 | if (ret < 0) | 974 | if (ret < 0) |
| 970 | return ret; | 975 | return ret; |
| 971 | } | 976 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cf11799297c4..108a774095f7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -3071,15 +3071,13 @@ struct rpc_clnt * | |||
| 3071 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | 3071 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, |
| 3072 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 3072 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
| 3073 | { | 3073 | { |
| 3074 | struct rpc_clnt *client = NFS_CLIENT(dir); | ||
| 3074 | int status; | 3075 | int status; |
| 3075 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | ||
| 3076 | 3076 | ||
| 3077 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL); | 3077 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL); |
| 3078 | if (status < 0) { | 3078 | if (status < 0) |
| 3079 | rpc_shutdown_client(client); | ||
| 3080 | return ERR_PTR(status); | 3079 | return ERR_PTR(status); |
| 3081 | } | 3080 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; |
| 3082 | return client; | ||
| 3083 | } | 3081 | } |
| 3084 | 3082 | ||
| 3085 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 3083 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 71fdc0dfa0d2..f6db66d8f647 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -2478,6 +2478,10 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server, | |||
| 2478 | if (server->flags & NFS_MOUNT_NOAC) | 2478 | if (server->flags & NFS_MOUNT_NOAC) |
| 2479 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; | 2479 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; |
| 2480 | 2480 | ||
| 2481 | if (mount_info->cloned != NULL && mount_info->cloned->sb != NULL) | ||
| 2482 | if (mount_info->cloned->sb->s_flags & MS_SYNCHRONOUS) | ||
| 2483 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; | ||
| 2484 | |||
| 2481 | /* Get a superblock - note that we may end up sharing one that already exists */ | 2485 | /* Get a superblock - note that we may end up sharing one that already exists */ |
| 2482 | s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata); | 2486 | s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata); |
| 2483 | if (IS_ERR(s)) { | 2487 | if (IS_ERR(s)) { |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0d4c410e4589..419572f33b72 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -1524,7 +1524,7 @@ static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | |||
| 1524 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1524 | static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
| 1525 | { | 1525 | { |
| 1526 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ | 1526 | return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ |
| 1527 | 1 + 1 + 0 + /* eir_flags, spr_how, SP4_NONE (for now) */\ | 1527 | 1 + 1 + 2 + /* eir_flags, spr_how, spo_must_enforce & _allow */\ |
| 1528 | 2 + /*eir_server_owner.so_minor_id */\ | 1528 | 2 + /*eir_server_owner.so_minor_id */\ |
| 1529 | /* eir_server_owner.so_major_id<> */\ | 1529 | /* eir_server_owner.so_major_id<> */\ |
| 1530 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ | 1530 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 280acef6f0dc..43f42290e5df 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -1264,6 +1264,8 @@ static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp) | |||
| 1264 | struct svc_cred *cr = &rqstp->rq_cred; | 1264 | struct svc_cred *cr = &rqstp->rq_cred; |
| 1265 | u32 service; | 1265 | u32 service; |
| 1266 | 1266 | ||
| 1267 | if (!cr->cr_gss_mech) | ||
| 1268 | return false; | ||
| 1267 | service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor); | 1269 | service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor); |
| 1268 | return service == RPC_GSS_SVC_INTEGRITY || | 1270 | return service == RPC_GSS_SVC_INTEGRITY || |
| 1269 | service == RPC_GSS_SVC_PRIVACY; | 1271 | service == RPC_GSS_SVC_PRIVACY; |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0c0f3ea90de5..c2a4701d7286 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -3360,7 +3360,8 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
| 3360 | 8 /* eir_clientid */ + | 3360 | 8 /* eir_clientid */ + |
| 3361 | 4 /* eir_sequenceid */ + | 3361 | 4 /* eir_sequenceid */ + |
| 3362 | 4 /* eir_flags */ + | 3362 | 4 /* eir_flags */ + |
| 3363 | 4 /* spr_how (SP4_NONE) */ + | 3363 | 4 /* spr_how */ + |
| 3364 | 8 /* spo_must_enforce, spo_must_allow */ + | ||
| 3364 | 8 /* so_minor_id */ + | 3365 | 8 /* so_minor_id */ + |
| 3365 | 4 /* so_major_id.len */ + | 3366 | 4 /* so_major_id.len */ + |
| 3366 | (XDR_QUADLEN(major_id_sz) * 4) + | 3367 | (XDR_QUADLEN(major_id_sz) * 4) + |
| @@ -3372,8 +3373,6 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
| 3372 | WRITE32(exid->seqid); | 3373 | WRITE32(exid->seqid); |
| 3373 | WRITE32(exid->flags); | 3374 | WRITE32(exid->flags); |
| 3374 | 3375 | ||
| 3375 | /* state_protect4_r. Currently only support SP4_NONE */ | ||
| 3376 | BUG_ON(exid->spa_how != SP4_NONE); | ||
| 3377 | WRITE32(exid->spa_how); | 3376 | WRITE32(exid->spa_how); |
| 3378 | switch (exid->spa_how) { | 3377 | switch (exid->spa_how) { |
| 3379 | case SP4_NONE: | 3378 | case SP4_NONE: |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 79736a28d84f..2abf97b2a592 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -1757,7 +1757,7 @@ try_again: | |||
| 1757 | goto out; | 1757 | goto out; |
| 1758 | } else if (ret == 1) { | 1758 | } else if (ret == 1) { |
| 1759 | clusters_need = wc->w_clen; | 1759 | clusters_need = wc->w_clen; |
| 1760 | ret = ocfs2_refcount_cow(inode, filp, di_bh, | 1760 | ret = ocfs2_refcount_cow(inode, di_bh, |
| 1761 | wc->w_cpos, wc->w_clen, UINT_MAX); | 1761 | wc->w_cpos, wc->w_clen, UINT_MAX); |
| 1762 | if (ret) { | 1762 | if (ret) { |
| 1763 | mlog_errno(ret); | 1763 | mlog_errno(ret); |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index eb760d8acd50..30544ce8e9f7 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
| @@ -2153,11 +2153,9 @@ int ocfs2_empty_dir(struct inode *inode) | |||
| 2153 | { | 2153 | { |
| 2154 | int ret; | 2154 | int ret; |
| 2155 | struct ocfs2_empty_dir_priv priv = { | 2155 | struct ocfs2_empty_dir_priv priv = { |
| 2156 | .ctx.actor = ocfs2_empty_dir_filldir | 2156 | .ctx.actor = ocfs2_empty_dir_filldir, |
| 2157 | }; | 2157 | }; |
| 2158 | 2158 | ||
| 2159 | memset(&priv, 0, sizeof(priv)); | ||
| 2160 | |||
| 2161 | if (ocfs2_dir_indexed(inode)) { | 2159 | if (ocfs2_dir_indexed(inode)) { |
| 2162 | ret = ocfs2_empty_dir_dx(inode, &priv); | 2160 | ret = ocfs2_empty_dir_dx(inode, &priv); |
| 2163 | if (ret) | 2161 | if (ret) |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 41000f223ca4..3261d71319ee 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -370,7 +370,7 @@ static int ocfs2_cow_file_pos(struct inode *inode, | |||
| 370 | if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) | 370 | if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) |
| 371 | goto out; | 371 | goto out; |
| 372 | 372 | ||
| 373 | return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1); | 373 | return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1); |
| 374 | 374 | ||
| 375 | out: | 375 | out: |
| 376 | return status; | 376 | return status; |
| @@ -899,7 +899,7 @@ static int ocfs2_zero_extend_get_range(struct inode *inode, | |||
| 899 | zero_clusters = last_cpos - zero_cpos; | 899 | zero_clusters = last_cpos - zero_cpos; |
| 900 | 900 | ||
| 901 | if (needs_cow) { | 901 | if (needs_cow) { |
| 902 | rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos, | 902 | rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, |
| 903 | zero_clusters, UINT_MAX); | 903 | zero_clusters, UINT_MAX); |
| 904 | if (rc) { | 904 | if (rc) { |
| 905 | mlog_errno(rc); | 905 | mlog_errno(rc); |
| @@ -2078,7 +2078,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode, | |||
| 2078 | 2078 | ||
| 2079 | *meta_level = 1; | 2079 | *meta_level = 1; |
| 2080 | 2080 | ||
| 2081 | ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX); | 2081 | ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX); |
| 2082 | if (ret) | 2082 | if (ret) |
| 2083 | mlog_errno(ret); | 2083 | mlog_errno(ret); |
| 2084 | out: | 2084 | out: |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 96f9ac237e86..0a992737dcaf 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
| @@ -537,7 +537,7 @@ static inline int ocfs2_calc_extend_credits(struct super_block *sb, | |||
| 537 | extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth); | 537 | extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth); |
| 538 | 538 | ||
| 539 | return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks + | 539 | return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks + |
| 540 | ocfs2_quota_trans_credits(sb) + bits_wanted; | 540 | ocfs2_quota_trans_credits(sb); |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | static inline int ocfs2_calc_symlink_credits(struct super_block *sb) | 543 | static inline int ocfs2_calc_symlink_credits(struct super_block *sb) |
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index f1fc172175b6..452068b45749 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
| @@ -69,7 +69,7 @@ static int __ocfs2_move_extent(handle_t *handle, | |||
| 69 | u64 ino = ocfs2_metadata_cache_owner(context->et.et_ci); | 69 | u64 ino = ocfs2_metadata_cache_owner(context->et.et_ci); |
| 70 | u64 old_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cpos); | 70 | u64 old_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cpos); |
| 71 | 71 | ||
| 72 | ret = ocfs2_duplicate_clusters_by_page(handle, context->file, cpos, | 72 | ret = ocfs2_duplicate_clusters_by_page(handle, inode, cpos, |
| 73 | p_cpos, new_p_cpos, len); | 73 | p_cpos, new_p_cpos, len); |
| 74 | if (ret) { | 74 | if (ret) { |
| 75 | mlog_errno(ret); | 75 | mlog_errno(ret); |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 9f6b96a09615..a70d604593b6 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -49,7 +49,6 @@ | |||
| 49 | 49 | ||
| 50 | struct ocfs2_cow_context { | 50 | struct ocfs2_cow_context { |
| 51 | struct inode *inode; | 51 | struct inode *inode; |
| 52 | struct file *file; | ||
| 53 | u32 cow_start; | 52 | u32 cow_start; |
| 54 | u32 cow_len; | 53 | u32 cow_len; |
| 55 | struct ocfs2_extent_tree data_et; | 54 | struct ocfs2_extent_tree data_et; |
| @@ -66,7 +65,7 @@ struct ocfs2_cow_context { | |||
| 66 | u32 *num_clusters, | 65 | u32 *num_clusters, |
| 67 | unsigned int *extent_flags); | 66 | unsigned int *extent_flags); |
| 68 | int (*cow_duplicate_clusters)(handle_t *handle, | 67 | int (*cow_duplicate_clusters)(handle_t *handle, |
| 69 | struct file *file, | 68 | struct inode *inode, |
| 70 | u32 cpos, u32 old_cluster, | 69 | u32 cpos, u32 old_cluster, |
| 71 | u32 new_cluster, u32 new_len); | 70 | u32 new_cluster, u32 new_len); |
| 72 | }; | 71 | }; |
| @@ -2922,14 +2921,12 @@ static int ocfs2_clear_cow_buffer(handle_t *handle, struct buffer_head *bh) | |||
| 2922 | } | 2921 | } |
| 2923 | 2922 | ||
| 2924 | int ocfs2_duplicate_clusters_by_page(handle_t *handle, | 2923 | int ocfs2_duplicate_clusters_by_page(handle_t *handle, |
| 2925 | struct file *file, | 2924 | struct inode *inode, |
| 2926 | u32 cpos, u32 old_cluster, | 2925 | u32 cpos, u32 old_cluster, |
| 2927 | u32 new_cluster, u32 new_len) | 2926 | u32 new_cluster, u32 new_len) |
| 2928 | { | 2927 | { |
| 2929 | int ret = 0, partial; | 2928 | int ret = 0, partial; |
| 2930 | struct inode *inode = file_inode(file); | 2929 | struct super_block *sb = inode->i_sb; |
| 2931 | struct ocfs2_caching_info *ci = INODE_CACHE(inode); | ||
| 2932 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | ||
| 2933 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); | 2930 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); |
| 2934 | struct page *page; | 2931 | struct page *page; |
| 2935 | pgoff_t page_index; | 2932 | pgoff_t page_index; |
| @@ -2978,13 +2975,6 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, | |||
| 2978 | if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) | 2975 | if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) |
| 2979 | BUG_ON(PageDirty(page)); | 2976 | BUG_ON(PageDirty(page)); |
| 2980 | 2977 | ||
| 2981 | if (PageReadahead(page)) { | ||
| 2982 | page_cache_async_readahead(mapping, | ||
| 2983 | &file->f_ra, file, | ||
| 2984 | page, page_index, | ||
| 2985 | readahead_pages); | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | if (!PageUptodate(page)) { | 2978 | if (!PageUptodate(page)) { |
| 2989 | ret = block_read_full_page(page, ocfs2_get_block); | 2979 | ret = block_read_full_page(page, ocfs2_get_block); |
| 2990 | if (ret) { | 2980 | if (ret) { |
| @@ -3004,7 +2994,8 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, | |||
| 3004 | } | 2994 | } |
| 3005 | } | 2995 | } |
| 3006 | 2996 | ||
| 3007 | ocfs2_map_and_dirty_page(inode, handle, from, to, | 2997 | ocfs2_map_and_dirty_page(inode, |
| 2998 | handle, from, to, | ||
| 3008 | page, 0, &new_block); | 2999 | page, 0, &new_block); |
| 3009 | mark_page_accessed(page); | 3000 | mark_page_accessed(page); |
| 3010 | unlock: | 3001 | unlock: |
| @@ -3020,12 +3011,11 @@ unlock: | |||
| 3020 | } | 3011 | } |
| 3021 | 3012 | ||
| 3022 | int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, | 3013 | int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, |
| 3023 | struct file *file, | 3014 | struct inode *inode, |
| 3024 | u32 cpos, u32 old_cluster, | 3015 | u32 cpos, u32 old_cluster, |
| 3025 | u32 new_cluster, u32 new_len) | 3016 | u32 new_cluster, u32 new_len) |
| 3026 | { | 3017 | { |
| 3027 | int ret = 0; | 3018 | int ret = 0; |
| 3028 | struct inode *inode = file_inode(file); | ||
| 3029 | struct super_block *sb = inode->i_sb; | 3019 | struct super_block *sb = inode->i_sb; |
| 3030 | struct ocfs2_caching_info *ci = INODE_CACHE(inode); | 3020 | struct ocfs2_caching_info *ci = INODE_CACHE(inode); |
| 3031 | int i, blocks = ocfs2_clusters_to_blocks(sb, new_len); | 3021 | int i, blocks = ocfs2_clusters_to_blocks(sb, new_len); |
| @@ -3150,7 +3140,7 @@ static int ocfs2_replace_clusters(handle_t *handle, | |||
| 3150 | 3140 | ||
| 3151 | /*If the old clusters is unwritten, no need to duplicate. */ | 3141 | /*If the old clusters is unwritten, no need to duplicate. */ |
| 3152 | if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { | 3142 | if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { |
| 3153 | ret = context->cow_duplicate_clusters(handle, context->file, | 3143 | ret = context->cow_duplicate_clusters(handle, context->inode, |
| 3154 | cpos, old, new, len); | 3144 | cpos, old, new, len); |
| 3155 | if (ret) { | 3145 | if (ret) { |
| 3156 | mlog_errno(ret); | 3146 | mlog_errno(ret); |
| @@ -3428,35 +3418,12 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context) | |||
| 3428 | return ret; | 3418 | return ret; |
| 3429 | } | 3419 | } |
| 3430 | 3420 | ||
| 3431 | static void ocfs2_readahead_for_cow(struct inode *inode, | ||
| 3432 | struct file *file, | ||
| 3433 | u32 start, u32 len) | ||
| 3434 | { | ||
| 3435 | struct address_space *mapping; | ||
| 3436 | pgoff_t index; | ||
| 3437 | unsigned long num_pages; | ||
| 3438 | int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits; | ||
| 3439 | |||
| 3440 | if (!file) | ||
| 3441 | return; | ||
| 3442 | |||
| 3443 | mapping = file->f_mapping; | ||
| 3444 | num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT; | ||
| 3445 | if (!num_pages) | ||
| 3446 | num_pages = 1; | ||
| 3447 | |||
| 3448 | index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT; | ||
| 3449 | page_cache_sync_readahead(mapping, &file->f_ra, file, | ||
| 3450 | index, num_pages); | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | /* | 3421 | /* |
| 3454 | * Starting at cpos, try to CoW write_len clusters. Don't CoW | 3422 | * Starting at cpos, try to CoW write_len clusters. Don't CoW |
| 3455 | * past max_cpos. This will stop when it runs into a hole or an | 3423 | * past max_cpos. This will stop when it runs into a hole or an |
| 3456 | * unrefcounted extent. | 3424 | * unrefcounted extent. |
| 3457 | */ | 3425 | */ |
| 3458 | static int ocfs2_refcount_cow_hunk(struct inode *inode, | 3426 | static int ocfs2_refcount_cow_hunk(struct inode *inode, |
| 3459 | struct file *file, | ||
| 3460 | struct buffer_head *di_bh, | 3427 | struct buffer_head *di_bh, |
| 3461 | u32 cpos, u32 write_len, u32 max_cpos) | 3428 | u32 cpos, u32 write_len, u32 max_cpos) |
| 3462 | { | 3429 | { |
| @@ -3485,8 +3452,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
| 3485 | 3452 | ||
| 3486 | BUG_ON(cow_len == 0); | 3453 | BUG_ON(cow_len == 0); |
| 3487 | 3454 | ||
| 3488 | ocfs2_readahead_for_cow(inode, file, cow_start, cow_len); | ||
| 3489 | |||
| 3490 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); | 3455 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); |
| 3491 | if (!context) { | 3456 | if (!context) { |
| 3492 | ret = -ENOMEM; | 3457 | ret = -ENOMEM; |
| @@ -3508,7 +3473,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
| 3508 | context->ref_root_bh = ref_root_bh; | 3473 | context->ref_root_bh = ref_root_bh; |
| 3509 | context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; | 3474 | context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; |
| 3510 | context->get_clusters = ocfs2_di_get_clusters; | 3475 | context->get_clusters = ocfs2_di_get_clusters; |
| 3511 | context->file = file; | ||
| 3512 | 3476 | ||
| 3513 | ocfs2_init_dinode_extent_tree(&context->data_et, | 3477 | ocfs2_init_dinode_extent_tree(&context->data_et, |
| 3514 | INODE_CACHE(inode), di_bh); | 3478 | INODE_CACHE(inode), di_bh); |
| @@ -3537,7 +3501,6 @@ out: | |||
| 3537 | * clusters between cpos and cpos+write_len are safe to modify. | 3501 | * clusters between cpos and cpos+write_len are safe to modify. |
| 3538 | */ | 3502 | */ |
| 3539 | int ocfs2_refcount_cow(struct inode *inode, | 3503 | int ocfs2_refcount_cow(struct inode *inode, |
| 3540 | struct file *file, | ||
| 3541 | struct buffer_head *di_bh, | 3504 | struct buffer_head *di_bh, |
| 3542 | u32 cpos, u32 write_len, u32 max_cpos) | 3505 | u32 cpos, u32 write_len, u32 max_cpos) |
| 3543 | { | 3506 | { |
| @@ -3557,7 +3520,7 @@ int ocfs2_refcount_cow(struct inode *inode, | |||
| 3557 | num_clusters = write_len; | 3520 | num_clusters = write_len; |
| 3558 | 3521 | ||
| 3559 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { | 3522 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { |
| 3560 | ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos, | 3523 | ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, |
| 3561 | num_clusters, max_cpos); | 3524 | num_clusters, max_cpos); |
| 3562 | if (ret) { | 3525 | if (ret) { |
| 3563 | mlog_errno(ret); | 3526 | mlog_errno(ret); |
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h index 7754608c83a4..6422bbcdb525 100644 --- a/fs/ocfs2/refcounttree.h +++ b/fs/ocfs2/refcounttree.h | |||
| @@ -53,7 +53,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, | |||
| 53 | int *credits, | 53 | int *credits, |
| 54 | int *ref_blocks); | 54 | int *ref_blocks); |
| 55 | int ocfs2_refcount_cow(struct inode *inode, | 55 | int ocfs2_refcount_cow(struct inode *inode, |
| 56 | struct file *filep, struct buffer_head *di_bh, | 56 | struct buffer_head *di_bh, |
| 57 | u32 cpos, u32 write_len, u32 max_cpos); | 57 | u32 cpos, u32 write_len, u32 max_cpos); |
| 58 | 58 | ||
| 59 | typedef int (ocfs2_post_refcount_func)(struct inode *inode, | 59 | typedef int (ocfs2_post_refcount_func)(struct inode *inode, |
| @@ -85,11 +85,11 @@ int ocfs2_refcount_cow_xattr(struct inode *inode, | |||
| 85 | u32 cpos, u32 write_len, | 85 | u32 cpos, u32 write_len, |
| 86 | struct ocfs2_post_refcount *post); | 86 | struct ocfs2_post_refcount *post); |
| 87 | int ocfs2_duplicate_clusters_by_page(handle_t *handle, | 87 | int ocfs2_duplicate_clusters_by_page(handle_t *handle, |
| 88 | struct file *file, | 88 | struct inode *inode, |
| 89 | u32 cpos, u32 old_cluster, | 89 | u32 cpos, u32 old_cluster, |
| 90 | u32 new_cluster, u32 new_len); | 90 | u32 new_cluster, u32 new_len); |
| 91 | int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, | 91 | int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, |
| 92 | struct file *file, | 92 | struct inode *inode, |
| 93 | u32 cpos, u32 old_cluster, | 93 | u32 cpos, u32 old_cluster, |
| 94 | u32 new_cluster, u32 new_len); | 94 | u32 new_cluster, u32 new_len); |
| 95 | int ocfs2_cow_sync_writeback(struct super_block *sb, | 95 | int ocfs2_cow_sync_writeback(struct super_block *sb, |
| @@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 823 | int lookup_flags = 0; | 823 | int lookup_flags = 0; |
| 824 | int acc_mode; | 824 | int acc_mode; |
| 825 | 825 | ||
| 826 | if (flags & O_CREAT) | 826 | if (flags & (O_CREAT | __O_TMPFILE)) |
| 827 | op->mode = (mode & S_IALLUGO) | S_IFREG; | 827 | op->mode = (mode & S_IALLUGO) | S_IFREG; |
| 828 | else | 828 | else |
| 829 | op->mode = 0; | 829 | op->mode = 0; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index dbf61f6174f0..107d026f5d6e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -730,8 +730,16 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma, | |||
| 730 | * of how soft-dirty works. | 730 | * of how soft-dirty works. |
| 731 | */ | 731 | */ |
| 732 | pte_t ptent = *pte; | 732 | pte_t ptent = *pte; |
| 733 | ptent = pte_wrprotect(ptent); | 733 | |
| 734 | ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY); | 734 | if (pte_present(ptent)) { |
| 735 | ptent = pte_wrprotect(ptent); | ||
| 736 | ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY); | ||
| 737 | } else if (is_swap_pte(ptent)) { | ||
| 738 | ptent = pte_swp_clear_soft_dirty(ptent); | ||
| 739 | } else if (pte_file(ptent)) { | ||
| 740 | ptent = pte_file_clear_soft_dirty(ptent); | ||
| 741 | } | ||
| 742 | |||
| 735 | set_pte_at(vma->vm_mm, addr, pte, ptent); | 743 | set_pte_at(vma->vm_mm, addr, pte, ptent); |
| 736 | #endif | 744 | #endif |
| 737 | } | 745 | } |
| @@ -752,14 +760,15 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | |||
| 752 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | 760 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
| 753 | for (; addr != end; pte++, addr += PAGE_SIZE) { | 761 | for (; addr != end; pte++, addr += PAGE_SIZE) { |
| 754 | ptent = *pte; | 762 | ptent = *pte; |
| 755 | if (!pte_present(ptent)) | ||
| 756 | continue; | ||
| 757 | 763 | ||
| 758 | if (cp->type == CLEAR_REFS_SOFT_DIRTY) { | 764 | if (cp->type == CLEAR_REFS_SOFT_DIRTY) { |
| 759 | clear_soft_dirty(vma, addr, pte); | 765 | clear_soft_dirty(vma, addr, pte); |
| 760 | continue; | 766 | continue; |
| 761 | } | 767 | } |
| 762 | 768 | ||
| 769 | if (!pte_present(ptent)) | ||
| 770 | continue; | ||
| 771 | |||
| 763 | page = vm_normal_page(vma, addr, ptent); | 772 | page = vm_normal_page(vma, addr, ptent); |
| 764 | if (!page) | 773 | if (!page) |
| 765 | continue; | 774 | continue; |
| @@ -859,7 +868,7 @@ typedef struct { | |||
| 859 | } pagemap_entry_t; | 868 | } pagemap_entry_t; |
| 860 | 869 | ||
| 861 | struct pagemapread { | 870 | struct pagemapread { |
| 862 | int pos, len; | 871 | int pos, len; /* units: PM_ENTRY_BYTES, not bytes */ |
| 863 | pagemap_entry_t *buffer; | 872 | pagemap_entry_t *buffer; |
| 864 | bool v2; | 873 | bool v2; |
| 865 | }; | 874 | }; |
| @@ -867,7 +876,7 @@ struct pagemapread { | |||
| 867 | #define PAGEMAP_WALK_SIZE (PMD_SIZE) | 876 | #define PAGEMAP_WALK_SIZE (PMD_SIZE) |
| 868 | #define PAGEMAP_WALK_MASK (PMD_MASK) | 877 | #define PAGEMAP_WALK_MASK (PMD_MASK) |
| 869 | 878 | ||
| 870 | #define PM_ENTRY_BYTES sizeof(u64) | 879 | #define PM_ENTRY_BYTES sizeof(pagemap_entry_t) |
| 871 | #define PM_STATUS_BITS 3 | 880 | #define PM_STATUS_BITS 3 |
| 872 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) | 881 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) |
| 873 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) | 882 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) |
| @@ -930,8 +939,10 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm, | |||
| 930 | flags = PM_PRESENT; | 939 | flags = PM_PRESENT; |
| 931 | page = vm_normal_page(vma, addr, pte); | 940 | page = vm_normal_page(vma, addr, pte); |
| 932 | } else if (is_swap_pte(pte)) { | 941 | } else if (is_swap_pte(pte)) { |
| 933 | swp_entry_t entry = pte_to_swp_entry(pte); | 942 | swp_entry_t entry; |
| 934 | 943 | if (pte_swp_soft_dirty(pte)) | |
| 944 | flags2 |= __PM_SOFT_DIRTY; | ||
| 945 | entry = pte_to_swp_entry(pte); | ||
| 935 | frame = swp_type(entry) | | 946 | frame = swp_type(entry) | |
| 936 | (swp_offset(entry) << MAX_SWAPFILES_SHIFT); | 947 | (swp_offset(entry) << MAX_SWAPFILES_SHIFT); |
| 937 | flags = PM_SWAP; | 948 | flags = PM_SWAP; |
| @@ -1116,8 +1127,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
| 1116 | goto out_task; | 1127 | goto out_task; |
| 1117 | 1128 | ||
| 1118 | pm.v2 = soft_dirty_cleared; | 1129 | pm.v2 = soft_dirty_cleared; |
| 1119 | pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); | 1130 | pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); |
| 1120 | pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); | 1131 | pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); |
| 1121 | ret = -ENOMEM; | 1132 | ret = -ENOMEM; |
| 1122 | if (!pm.buffer) | 1133 | if (!pm.buffer) |
| 1123 | goto out_task; | 1134 | goto out_task; |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 33532f79b4f7..a958444a75fc 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
| @@ -19,12 +19,13 @@ | |||
| 19 | /* | 19 | /* |
| 20 | * LOCKING: | 20 | * LOCKING: |
| 21 | * | 21 | * |
| 22 | * We rely on new Alexander Viro's super-block locking. | 22 | * These guys are evicted from procfs as the very first step in ->kill_sb(). |
| 23 | * | 23 | * |
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | static int show_version(struct seq_file *m, struct super_block *sb) | 26 | static int show_version(struct seq_file *m, void *unused) |
| 27 | { | 27 | { |
| 28 | struct super_block *sb = m->private; | ||
| 28 | char *format; | 29 | char *format; |
| 29 | 30 | ||
| 30 | if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) { | 31 | if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) { |
| @@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb) | |||
| 66 | #define DJP( x ) le32_to_cpu( jp -> x ) | 67 | #define DJP( x ) le32_to_cpu( jp -> x ) |
| 67 | #define JF( x ) ( r -> s_journal -> x ) | 68 | #define JF( x ) ( r -> s_journal -> x ) |
| 68 | 69 | ||
| 69 | static int show_super(struct seq_file *m, struct super_block *sb) | 70 | static int show_super(struct seq_file *m, void *unused) |
| 70 | { | 71 | { |
| 72 | struct super_block *sb = m->private; | ||
| 71 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 73 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
| 72 | 74 | ||
| 73 | seq_printf(m, "state: \t%s\n" | 75 | seq_printf(m, "state: \t%s\n" |
| @@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb) | |||
| 128 | return 0; | 130 | return 0; |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 131 | static int show_per_level(struct seq_file *m, struct super_block *sb) | 133 | static int show_per_level(struct seq_file *m, void *unused) |
| 132 | { | 134 | { |
| 135 | struct super_block *sb = m->private; | ||
| 133 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 136 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
| 134 | int level; | 137 | int level; |
| 135 | 138 | ||
| @@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb) | |||
| 186 | return 0; | 189 | return 0; |
| 187 | } | 190 | } |
| 188 | 191 | ||
| 189 | static int show_bitmap(struct seq_file *m, struct super_block *sb) | 192 | static int show_bitmap(struct seq_file *m, void *unused) |
| 190 | { | 193 | { |
| 194 | struct super_block *sb = m->private; | ||
| 191 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 195 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
| 192 | 196 | ||
| 193 | seq_printf(m, "free_block: %lu\n" | 197 | seq_printf(m, "free_block: %lu\n" |
| @@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb) | |||
| 218 | return 0; | 222 | return 0; |
| 219 | } | 223 | } |
| 220 | 224 | ||
| 221 | static int show_on_disk_super(struct seq_file *m, struct super_block *sb) | 225 | static int show_on_disk_super(struct seq_file *m, void *unused) |
| 222 | { | 226 | { |
| 227 | struct super_block *sb = m->private; | ||
| 223 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); | 228 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); |
| 224 | struct reiserfs_super_block *rs = sb_info->s_rs; | 229 | struct reiserfs_super_block *rs = sb_info->s_rs; |
| 225 | int hash_code = DFL(s_hash_function_code); | 230 | int hash_code = DFL(s_hash_function_code); |
| @@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb) | |||
| 261 | return 0; | 266 | return 0; |
| 262 | } | 267 | } |
| 263 | 268 | ||
| 264 | static int show_oidmap(struct seq_file *m, struct super_block *sb) | 269 | static int show_oidmap(struct seq_file *m, void *unused) |
| 265 | { | 270 | { |
| 271 | struct super_block *sb = m->private; | ||
| 266 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); | 272 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); |
| 267 | struct reiserfs_super_block *rs = sb_info->s_rs; | 273 | struct reiserfs_super_block *rs = sb_info->s_rs; |
| 268 | unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize); | 274 | unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize); |
| @@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb) | |||
| 291 | return 0; | 297 | return 0; |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | static int show_journal(struct seq_file *m, struct super_block *sb) | 300 | static int show_journal(struct seq_file *m, void *unused) |
| 295 | { | 301 | { |
| 302 | struct super_block *sb = m->private; | ||
| 296 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 303 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
| 297 | struct reiserfs_super_block *rs = r->s_rs; | 304 | struct reiserfs_super_block *rs = r->s_rs; |
| 298 | struct journal_params *jp = &rs->s_v1.s_journal; | 305 | struct journal_params *jp = &rs->s_v1.s_journal; |
| @@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb) | |||
| 383 | return 0; | 390 | return 0; |
| 384 | } | 391 | } |
| 385 | 392 | ||
| 386 | /* iterator */ | ||
| 387 | static int test_sb(struct super_block *sb, void *data) | ||
| 388 | { | ||
| 389 | return data == sb; | ||
| 390 | } | ||
| 391 | |||
| 392 | static int set_sb(struct super_block *sb, void *data) | ||
| 393 | { | ||
| 394 | return -ENOENT; | ||
| 395 | } | ||
| 396 | |||
| 397 | struct reiserfs_seq_private { | ||
| 398 | struct super_block *sb; | ||
| 399 | int (*show) (struct seq_file *, struct super_block *); | ||
| 400 | }; | ||
| 401 | |||
| 402 | static void *r_start(struct seq_file *m, loff_t * pos) | ||
| 403 | { | ||
| 404 | struct reiserfs_seq_private *priv = m->private; | ||
| 405 | loff_t l = *pos; | ||
| 406 | |||
| 407 | if (l) | ||
| 408 | return NULL; | ||
| 409 | |||
| 410 | if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb))) | ||
| 411 | return NULL; | ||
| 412 | |||
| 413 | up_write(&priv->sb->s_umount); | ||
| 414 | return priv->sb; | ||
| 415 | } | ||
| 416 | |||
| 417 | static void *r_next(struct seq_file *m, void *v, loff_t * pos) | ||
| 418 | { | ||
| 419 | ++*pos; | ||
| 420 | if (v) | ||
| 421 | deactivate_super(v); | ||
| 422 | return NULL; | ||
| 423 | } | ||
| 424 | |||
| 425 | static void r_stop(struct seq_file *m, void *v) | ||
| 426 | { | ||
| 427 | if (v) | ||
| 428 | deactivate_super(v); | ||
| 429 | } | ||
| 430 | |||
| 431 | static int r_show(struct seq_file *m, void *v) | ||
| 432 | { | ||
| 433 | struct reiserfs_seq_private *priv = m->private; | ||
| 434 | return priv->show(m, v); | ||
| 435 | } | ||
| 436 | |||
| 437 | static const struct seq_operations r_ops = { | ||
| 438 | .start = r_start, | ||
| 439 | .next = r_next, | ||
| 440 | .stop = r_stop, | ||
| 441 | .show = r_show, | ||
| 442 | }; | ||
| 443 | |||
| 444 | static int r_open(struct inode *inode, struct file *file) | 393 | static int r_open(struct inode *inode, struct file *file) |
| 445 | { | 394 | { |
| 446 | struct reiserfs_seq_private *priv; | 395 | return single_open(file, PDE_DATA(inode), |
| 447 | int ret = seq_open_private(file, &r_ops, | 396 | proc_get_parent_data(inode)); |
| 448 | sizeof(struct reiserfs_seq_private)); | ||
| 449 | |||
| 450 | if (!ret) { | ||
| 451 | struct seq_file *m = file->private_data; | ||
| 452 | priv = m->private; | ||
| 453 | priv->sb = proc_get_parent_data(inode); | ||
| 454 | priv->show = PDE_DATA(inode); | ||
| 455 | } | ||
| 456 | return ret; | ||
| 457 | } | 397 | } |
| 458 | 398 | ||
| 459 | static const struct file_operations r_file_operations = { | 399 | static const struct file_operations r_file_operations = { |
| 460 | .open = r_open, | 400 | .open = r_open, |
| 461 | .read = seq_read, | 401 | .read = seq_read, |
| 462 | .llseek = seq_lseek, | 402 | .llseek = seq_lseek, |
| 463 | .release = seq_release_private, | 403 | .release = single_release, |
| 464 | .owner = THIS_MODULE, | ||
| 465 | }; | 404 | }; |
| 466 | 405 | ||
| 467 | static struct proc_dir_entry *proc_info_root = NULL; | 406 | static struct proc_dir_entry *proc_info_root = NULL; |
| 468 | static const char proc_info_root_name[] = "fs/reiserfs"; | 407 | static const char proc_info_root_name[] = "fs/reiserfs"; |
| 469 | 408 | ||
| 470 | static void add_file(struct super_block *sb, char *name, | 409 | static void add_file(struct super_block *sb, char *name, |
| 471 | int (*func) (struct seq_file *, struct super_block *)) | 410 | int (*func) (struct seq_file *, void *)) |
| 472 | { | 411 | { |
| 473 | proc_create_data(name, 0, REISERFS_SB(sb)->procdir, | 412 | proc_create_data(name, 0, REISERFS_SB(sb)->procdir, |
| 474 | &r_file_operations, func); | 413 | &r_file_operations, func); |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f8a23c3078f8..e2e202a07b31 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate) | |||
| 499 | static void reiserfs_kill_sb(struct super_block *s) | 499 | static void reiserfs_kill_sb(struct super_block *s) |
| 500 | { | 500 | { |
| 501 | if (REISERFS_SB(s)) { | 501 | if (REISERFS_SB(s)) { |
| 502 | reiserfs_proc_info_done(s); | ||
| 502 | /* | 503 | /* |
| 503 | * Force any pending inode evictions to occur now. Any | 504 | * Force any pending inode evictions to occur now. Any |
| 504 | * inodes to be removed that have extended attributes | 505 | * inodes to be removed that have extended attributes |
| @@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s) | |||
| 554 | REISERFS_SB(s)->reserved_blocks); | 555 | REISERFS_SB(s)->reserved_blocks); |
| 555 | } | 556 | } |
| 556 | 557 | ||
| 557 | reiserfs_proc_info_done(s); | ||
| 558 | |||
| 559 | reiserfs_write_unlock(s); | 558 | reiserfs_write_unlock(s); |
| 560 | mutex_destroy(&REISERFS_SB(s)->lock); | 559 | mutex_destroy(&REISERFS_SB(s)->lock); |
| 561 | kfree(s->s_fs_info); | 560 | kfree(s->s_fs_info); |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 56e6b68c8d2f..94383a70c1a3 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -274,15 +274,12 @@ struct acpi_device_wakeup { | |||
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | struct acpi_device_physical_node { | 276 | struct acpi_device_physical_node { |
| 277 | u8 node_id; | 277 | unsigned int node_id; |
| 278 | struct list_head node; | 278 | struct list_head node; |
| 279 | struct device *dev; | 279 | struct device *dev; |
| 280 | bool put_online:1; | 280 | bool put_online:1; |
| 281 | }; | 281 | }; |
| 282 | 282 | ||
| 283 | /* set maximum of physical nodes to 32 for expansibility */ | ||
| 284 | #define ACPI_MAX_PHYSICAL_NODE 32 | ||
| 285 | |||
| 286 | /* Device */ | 283 | /* Device */ |
| 287 | struct acpi_device { | 284 | struct acpi_device { |
| 288 | int device_type; | 285 | int device_type; |
| @@ -302,10 +299,9 @@ struct acpi_device { | |||
| 302 | struct acpi_driver *driver; | 299 | struct acpi_driver *driver; |
| 303 | void *driver_data; | 300 | void *driver_data; |
| 304 | struct device dev; | 301 | struct device dev; |
| 305 | u8 physical_node_count; | 302 | unsigned int physical_node_count; |
| 306 | struct list_head physical_node_list; | 303 | struct list_head physical_node_list; |
| 307 | struct mutex physical_node_lock; | 304 | struct mutex physical_node_lock; |
| 308 | DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE); | ||
| 309 | struct list_head power_dependent; | 305 | struct list_head power_dependent; |
| 310 | void (*remove)(struct acpi_device *); | 306 | void (*remove)(struct acpi_device *); |
| 311 | }; | 307 | }; |
| @@ -445,7 +441,11 @@ struct acpi_pci_root { | |||
| 445 | }; | 441 | }; |
| 446 | 442 | ||
| 447 | /* helper */ | 443 | /* helper */ |
| 448 | acpi_handle acpi_get_child(acpi_handle, u64); | 444 | acpi_handle acpi_find_child(acpi_handle, u64, bool); |
| 445 | static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr) | ||
| 446 | { | ||
| 447 | return acpi_find_child(handle, addr, false); | ||
| 448 | } | ||
| 449 | int acpi_is_root_bridge(acpi_handle); | 449 | int acpi_is_root_bridge(acpi_handle); |
| 450 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); | 450 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); |
| 451 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev)) | 451 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev)) |
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 2f47ade1b567..0807ddf97b05 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h | |||
| @@ -417,6 +417,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd) | |||
| 417 | { | 417 | { |
| 418 | return pmd; | 418 | return pmd; |
| 419 | } | 419 | } |
| 420 | |||
| 421 | static inline pte_t pte_swp_mksoft_dirty(pte_t pte) | ||
| 422 | { | ||
| 423 | return pte; | ||
| 424 | } | ||
| 425 | |||
| 426 | static inline int pte_swp_soft_dirty(pte_t pte) | ||
| 427 | { | ||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) | ||
| 432 | { | ||
| 433 | return pte; | ||
| 434 | } | ||
| 435 | |||
| 436 | static inline pte_t pte_file_clear_soft_dirty(pte_t pte) | ||
| 437 | { | ||
| 438 | return pte; | ||
| 439 | } | ||
| 440 | |||
| 441 | static inline pte_t pte_file_mksoft_dirty(pte_t pte) | ||
| 442 | { | ||
| 443 | return pte; | ||
| 444 | } | ||
| 445 | |||
| 446 | static inline int pte_file_soft_dirty(pte_t pte) | ||
| 447 | { | ||
| 448 | return 0; | ||
| 449 | } | ||
| 420 | #endif | 450 | #endif |
| 421 | 451 | ||
| 422 | #ifndef __HAVE_PFNMAP_TRACKING | 452 | #ifndef __HAVE_PFNMAP_TRACKING |
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index 13821c339a41..5672d7ea1fa0 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h | |||
| @@ -112,7 +112,7 @@ struct mmu_gather { | |||
| 112 | 112 | ||
| 113 | #define HAVE_GENERIC_MMU_GATHER | 113 | #define HAVE_GENERIC_MMU_GATHER |
| 114 | 114 | ||
| 115 | void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm); | 115 | void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end); |
| 116 | void tlb_flush_mmu(struct mmu_gather *tlb); | 116 | void tlb_flush_mmu(struct mmu_gather *tlb); |
| 117 | void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, | 117 | void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, |
| 118 | unsigned long end); | 118 | unsigned long end); |
diff --git a/include/dt-bindings/sound/fsl-imx-audmux.h b/include/dt-bindings/sound/fsl-imx-audmux.h new file mode 100644 index 000000000000..50b09e96f247 --- /dev/null +++ b/include/dt-bindings/sound/fsl-imx-audmux.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #ifndef __DT_FSL_IMX_AUDMUX_H | ||
| 2 | #define __DT_FSL_IMX_AUDMUX_H | ||
| 3 | |||
| 4 | #define MX27_AUDMUX_HPCR1_SSI0 0 | ||
| 5 | #define MX27_AUDMUX_HPCR2_SSI1 1 | ||
| 6 | #define MX27_AUDMUX_HPCR3_SSI_PINS_4 2 | ||
| 7 | #define MX27_AUDMUX_PPCR1_SSI_PINS_1 3 | ||
| 8 | #define MX27_AUDMUX_PPCR2_SSI_PINS_2 4 | ||
| 9 | #define MX27_AUDMUX_PPCR3_SSI_PINS_3 5 | ||
| 10 | |||
| 11 | #define MX31_AUDMUX_PORT1_SSI0 0 | ||
| 12 | #define MX31_AUDMUX_PORT2_SSI1 1 | ||
| 13 | #define MX31_AUDMUX_PORT3_SSI_PINS_3 2 | ||
| 14 | #define MX31_AUDMUX_PORT4_SSI_PINS_4 3 | ||
| 15 | #define MX31_AUDMUX_PORT5_SSI_PINS_5 4 | ||
| 16 | #define MX31_AUDMUX_PORT6_SSI_PINS_6 5 | ||
| 17 | #define MX31_AUDMUX_PORT7_SSI_PINS_7 6 | ||
| 18 | |||
| 19 | #define MX51_AUDMUX_PORT1_SSI0 0 | ||
| 20 | #define MX51_AUDMUX_PORT2_SSI1 1 | ||
| 21 | #define MX51_AUDMUX_PORT3 2 | ||
| 22 | #define MX51_AUDMUX_PORT4 3 | ||
| 23 | #define MX51_AUDMUX_PORT5 4 | ||
| 24 | #define MX51_AUDMUX_PORT6 5 | ||
| 25 | #define MX51_AUDMUX_PORT7 6 | ||
| 26 | |||
| 27 | /* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ | ||
| 28 | #define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) | ||
| 29 | #define IMX_AUDMUX_V1_PCR_INMEN (1 << 8) | ||
| 30 | #define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10) | ||
| 31 | #define IMX_AUDMUX_V1_PCR_SYN (1 << 12) | ||
| 32 | #define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) | ||
| 33 | #define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) | ||
| 34 | #define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24) | ||
| 35 | #define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25) | ||
| 36 | #define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) | ||
| 37 | #define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30) | ||
| 38 | #define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31) | ||
| 39 | |||
| 40 | /* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ | ||
| 41 | #define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31) | ||
| 42 | #define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) | ||
| 43 | #define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) | ||
| 44 | #define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) | ||
| 45 | #define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21) | ||
| 46 | #define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) | ||
| 47 | #define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) | ||
| 48 | #define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) | ||
| 49 | #define IMX_AUDMUX_V2_PTCR_SYN (1 << 11) | ||
| 50 | |||
| 51 | #define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) | ||
| 52 | #define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12) | ||
| 53 | #define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) | ||
| 54 | #define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) | ||
| 55 | |||
| 56 | #endif /* __DT_FSL_IMX_AUDMUX_H */ | ||
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index deb0ae58b99b..66a0e5384edd 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h | |||
| @@ -11,7 +11,7 @@ struct atmel_ssc_platform_data { | |||
| 11 | 11 | ||
| 12 | struct ssc_device { | 12 | struct ssc_device { |
| 13 | struct list_head list; | 13 | struct list_head list; |
| 14 | resource_size_t phybase; | 14 | dma_addr_t phybase; |
| 15 | void __iomem *regs; | 15 | void __iomem *regs; |
| 16 | struct platform_device *pdev; | 16 | struct platform_device *pdev; |
| 17 | struct atmel_ssc_platform_data *pdata; | 17 | struct atmel_ssc_platform_data *pdata; |
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 4372658c73ae..120d57a1c3a5 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
| @@ -78,6 +78,11 @@ struct trace_iterator { | |||
| 78 | /* trace_seq for __print_flags() and __print_symbolic() etc. */ | 78 | /* trace_seq for __print_flags() and __print_symbolic() etc. */ |
| 79 | struct trace_seq tmp_seq; | 79 | struct trace_seq tmp_seq; |
| 80 | 80 | ||
| 81 | cpumask_var_t started; | ||
| 82 | |||
| 83 | /* it's true when current open file is snapshot */ | ||
| 84 | bool snapshot; | ||
| 85 | |||
| 81 | /* The below is zeroed out in pipe_read */ | 86 | /* The below is zeroed out in pipe_read */ |
| 82 | struct trace_seq seq; | 87 | struct trace_seq seq; |
| 83 | struct trace_entry *ent; | 88 | struct trace_entry *ent; |
| @@ -90,10 +95,7 @@ struct trace_iterator { | |||
| 90 | loff_t pos; | 95 | loff_t pos; |
| 91 | long idx; | 96 | long idx; |
| 92 | 97 | ||
| 93 | cpumask_var_t started; | 98 | /* All new field here will be zeroed out in pipe_read */ |
| 94 | |||
| 95 | /* it's true when current open file is snapshot */ | ||
| 96 | bool snapshot; | ||
| 97 | }; | 99 | }; |
| 98 | 100 | ||
| 99 | enum trace_iter_flags { | 101 | enum trace_iter_flags { |
| @@ -332,7 +334,7 @@ extern int trace_define_field(struct ftrace_event_call *call, const char *type, | |||
| 332 | const char *name, int offset, int size, | 334 | const char *name, int offset, int size, |
| 333 | int is_signed, int filter_type); | 335 | int is_signed, int filter_type); |
| 334 | extern int trace_add_event_call(struct ftrace_event_call *call); | 336 | extern int trace_add_event_call(struct ftrace_event_call *call); |
| 335 | extern void trace_remove_event_call(struct ftrace_event_call *call); | 337 | extern int trace_remove_event_call(struct ftrace_event_call *call); |
| 336 | 338 | ||
| 337 | #define is_signed_type(type) (((type)(-1)) < (type)1) | 339 | #define is_signed_type(type) (((type)(-1)) < (type)1) |
| 338 | 340 | ||
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 3869c525b052..369cf2cd5144 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | */ | 8 | */ |
| 9 | #include <linux/irq.h> | 9 | #include <linux/irq.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/atomic.h> | ||
| 11 | 12 | ||
| 12 | #ifndef _IIO_TRIGGER_H_ | 13 | #ifndef _IIO_TRIGGER_H_ |
| 13 | #define _IIO_TRIGGER_H_ | 14 | #define _IIO_TRIGGER_H_ |
| @@ -61,7 +62,7 @@ struct iio_trigger { | |||
| 61 | 62 | ||
| 62 | struct list_head list; | 63 | struct list_head list; |
| 63 | struct list_head alloc_list; | 64 | struct list_head alloc_list; |
| 64 | int use_count; | 65 | atomic_t use_count; |
| 65 | 66 | ||
| 66 | struct irq_chip subirq_chip; | 67 | struct irq_chip subirq_chip; |
| 67 | int subirq_base; | 68 | int subirq_base; |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3bef14c6586b..482ad2d84a32 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -629,7 +629,7 @@ extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode); | |||
| 629 | static inline void tracing_start(void) { } | 629 | static inline void tracing_start(void) { } |
| 630 | static inline void tracing_stop(void) { } | 630 | static inline void tracing_stop(void) { } |
| 631 | static inline void ftrace_off_permanent(void) { } | 631 | static inline void ftrace_off_permanent(void) { } |
| 632 | static inline void trace_dump_stack(void) { } | 632 | static inline void trace_dump_stack(int skip) { } |
| 633 | 633 | ||
| 634 | static inline void tracing_on(void) { } | 634 | static inline void tracing_on(void) { } |
| 635 | static inline void tracing_off(void) { } | 635 | static inline void tracing_off(void) { } |
diff --git a/include/linux/mfd/arizona/gpio.h b/include/linux/mfd/arizona/gpio.h new file mode 100644 index 000000000000..d2146bb74f89 --- /dev/null +++ b/include/linux/mfd/arizona/gpio.h | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* | ||
| 2 | * GPIO configuration for Arizona devices | ||
| 3 | * | ||
| 4 | * Copyright 2013 Wolfson Microelectronics. PLC. | ||
| 5 | * | ||
| 6 | * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | ||
| 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 | #ifndef _ARIZONA_GPIO_H | ||
| 14 | #define _ARIZONA_GPIO_H | ||
| 15 | |||
| 16 | #define ARIZONA_GP_FN_TXLRCLK 0x00 | ||
| 17 | #define ARIZONA_GP_FN_GPIO 0x01 | ||
| 18 | #define ARIZONA_GP_FN_IRQ1 0x02 | ||
| 19 | #define ARIZONA_GP_FN_IRQ2 0x03 | ||
| 20 | #define ARIZONA_GP_FN_OPCLK 0x04 | ||
| 21 | #define ARIZONA_GP_FN_FLL1_OUT 0x05 | ||
| 22 | #define ARIZONA_GP_FN_FLL2_OUT 0x06 | ||
| 23 | #define ARIZONA_GP_FN_PWM1 0x08 | ||
| 24 | #define ARIZONA_GP_FN_PWM2 0x09 | ||
| 25 | #define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED 0x0A | ||
| 26 | #define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED 0x0B | ||
| 27 | #define ARIZONA_GP_FN_FLL1_LOCK 0x0C | ||
| 28 | #define ARIZONA_GP_FN_FLL2_LOCK 0x0D | ||
| 29 | #define ARIZONA_GP_FN_FLL1_CLOCK_OK 0x0F | ||
| 30 | #define ARIZONA_GP_FN_FLL2_CLOCK_OK 0x10 | ||
| 31 | #define ARIZONA_GP_FN_HEADPHONE_DET 0x12 | ||
| 32 | #define ARIZONA_GP_FN_MIC_DET 0x13 | ||
| 33 | #define ARIZONA_GP_FN_WSEQ_STATUS 0x15 | ||
| 34 | #define ARIZONA_GP_FN_CIF_ADDRESS_ERROR 0x16 | ||
| 35 | #define ARIZONA_GP_FN_ASRC1_LOCK 0x1A | ||
| 36 | #define ARIZONA_GP_FN_ASRC2_LOCK 0x1B | ||
| 37 | #define ARIZONA_GP_FN_ASRC_CONFIG_ERROR 0x1C | ||
| 38 | #define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT 0x1D | ||
| 39 | #define ARIZONA_GP_FN_DRC1_ANTICLIP 0x1E | ||
| 40 | #define ARIZONA_GP_FN_DRC1_DECAY 0x1F | ||
| 41 | #define ARIZONA_GP_FN_DRC1_NOISE 0x20 | ||
| 42 | #define ARIZONA_GP_FN_DRC1_QUICK_RELEASE 0x21 | ||
| 43 | #define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT 0x22 | ||
| 44 | #define ARIZONA_GP_FN_DRC2_ANTICLIP 0x23 | ||
| 45 | #define ARIZONA_GP_FN_DRC2_DECAY 0x24 | ||
| 46 | #define ARIZONA_GP_FN_DRC2_NOISE 0x25 | ||
| 47 | #define ARIZONA_GP_FN_DRC2_QUICK_RELEASE 0x26 | ||
| 48 | #define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE 0x27 | ||
| 49 | #define ARIZONA_GP_FN_AIF1_CONFIG_ERROR 0x28 | ||
| 50 | #define ARIZONA_GP_FN_AIF2_CONFIG_ERROR 0x29 | ||
| 51 | #define ARIZONA_GP_FN_AIF3_CONFIG_ERROR 0x2A | ||
| 52 | #define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN 0x2B | ||
| 53 | #define ARIZONA_GP_FN_SPK_TEMP_WARNING 0x2C | ||
| 54 | #define ARIZONA_GP_FN_UNDERCLOCKED 0x2D | ||
| 55 | #define ARIZONA_GP_FN_OVERCLOCKED 0x2E | ||
| 56 | #define ARIZONA_GP_FN_DSP_IRQ1 0x35 | ||
| 57 | #define ARIZONA_GP_FN_DSP_IRQ2 0x36 | ||
| 58 | #define ARIZONA_GP_FN_ASYNC_OPCLK 0x3D | ||
| 59 | #define ARIZONA_GP_FN_BOOT_DONE 0x44 | ||
| 60 | #define ARIZONA_GP_FN_DSP1_RAM_READY 0x45 | ||
| 61 | #define ARIZONA_GP_FN_SYSCLK_ENA_STATUS 0x4B | ||
| 62 | #define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS 0x4C | ||
| 63 | |||
| 64 | #define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */ | ||
| 65 | #define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */ | ||
| 66 | #define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */ | ||
| 67 | #define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */ | ||
| 68 | #define ARIZONA_GPN_PU 0x4000 /* GPN_PU */ | ||
| 69 | #define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */ | ||
| 70 | #define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */ | ||
| 71 | #define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */ | ||
| 72 | #define ARIZONA_GPN_PD 0x2000 /* GPN_PD */ | ||
| 73 | #define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */ | ||
| 74 | #define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */ | ||
| 75 | #define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */ | ||
| 76 | #define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */ | ||
| 77 | #define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */ | ||
| 78 | #define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */ | ||
| 79 | #define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */ | ||
| 80 | #define ARIZONA_GPN_POL 0x0400 /* GPN_POL */ | ||
| 81 | #define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */ | ||
| 82 | #define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */ | ||
| 83 | #define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */ | ||
| 84 | #define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */ | ||
| 85 | #define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */ | ||
| 86 | #define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */ | ||
| 87 | #define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */ | ||
| 88 | #define ARIZONA_GPN_DB 0x0100 /* GPN_DB */ | ||
| 89 | #define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */ | ||
| 90 | #define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */ | ||
| 91 | #define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */ | ||
| 92 | #define ARIZONA_GPN_FN_MASK 0x007F /* GPN_DB */ | ||
| 93 | #define ARIZONA_GPN_FN_SHIFT 0 /* GPN_DB */ | ||
| 94 | #define ARIZONA_GPN_FN_WIDTH 7 /* GPN_DB */ | ||
| 95 | |||
| 96 | #endif | ||
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8d73fe29796a..db1791bb997a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h | |||
| @@ -113,11 +113,27 @@ | |||
| 113 | #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3) | 113 | #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3) |
| 114 | #define CNTRLREG_TSCENB BIT(7) | 114 | #define CNTRLREG_TSCENB BIT(7) |
| 115 | 115 | ||
| 116 | /* FIFO READ Register */ | ||
| 117 | #define FIFOREAD_DATA_MASK (0xfff << 0) | ||
| 118 | #define FIFOREAD_CHNLID_MASK (0xf << 16) | ||
| 119 | |||
| 120 | /* Sequencer Status */ | ||
| 121 | #define SEQ_STATUS BIT(5) | ||
| 122 | |||
| 116 | #define ADC_CLK 3000000 | 123 | #define ADC_CLK 3000000 |
| 117 | #define MAX_CLK_DIV 7 | 124 | #define MAX_CLK_DIV 7 |
| 118 | #define TOTAL_STEPS 16 | 125 | #define TOTAL_STEPS 16 |
| 119 | #define TOTAL_CHANNELS 8 | 126 | #define TOTAL_CHANNELS 8 |
| 120 | 127 | ||
| 128 | /* | ||
| 129 | * ADC runs at 3MHz, and it takes | ||
| 130 | * 15 cycles to latch one data output. | ||
| 131 | * Hence the idle time for ADC to | ||
| 132 | * process one sample data would be | ||
| 133 | * around 5 micro seconds. | ||
| 134 | */ | ||
| 135 | #define IDLE_TIMEOUT 5 /* microsec */ | ||
| 136 | |||
| 121 | #define TSCADC_CELLS 2 | 137 | #define TSCADC_CELLS 2 |
| 122 | 138 | ||
| 123 | struct ti_tscadc_dev { | 139 | struct ti_tscadc_dev { |
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 737685e9e852..68029b30c3dc 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h | |||
| @@ -309,21 +309,20 @@ struct mlx5_hca_cap { | |||
| 309 | __be16 max_desc_sz_rq; | 309 | __be16 max_desc_sz_rq; |
| 310 | u8 rsvd21[2]; | 310 | u8 rsvd21[2]; |
| 311 | __be16 max_desc_sz_sq_dc; | 311 | __be16 max_desc_sz_sq_dc; |
| 312 | u8 rsvd22[4]; | 312 | __be32 max_qp_mcg; |
| 313 | __be16 max_qp_mcg; | 313 | u8 rsvd22[3]; |
| 314 | u8 rsvd23; | ||
| 315 | u8 log_max_mcg; | 314 | u8 log_max_mcg; |
| 316 | u8 rsvd24; | 315 | u8 rsvd23; |
| 317 | u8 log_max_pd; | 316 | u8 log_max_pd; |
| 318 | u8 rsvd25; | 317 | u8 rsvd24; |
| 319 | u8 log_max_xrcd; | 318 | u8 log_max_xrcd; |
| 320 | u8 rsvd26[42]; | 319 | u8 rsvd25[42]; |
| 321 | __be16 log_uar_page_sz; | 320 | __be16 log_uar_page_sz; |
| 322 | u8 rsvd27[28]; | 321 | u8 rsvd26[28]; |
| 323 | u8 log_msx_atomic_size_qp; | 322 | u8 log_msx_atomic_size_qp; |
| 324 | u8 rsvd28[2]; | 323 | u8 rsvd27[2]; |
| 325 | u8 log_msx_atomic_size_dc; | 324 | u8 log_msx_atomic_size_dc; |
| 326 | u8 rsvd29[76]; | 325 | u8 rsvd28[76]; |
| 327 | }; | 326 | }; |
| 328 | 327 | ||
| 329 | 328 | ||
| @@ -472,9 +471,8 @@ struct mlx5_eqe_cmd { | |||
| 472 | struct mlx5_eqe_page_req { | 471 | struct mlx5_eqe_page_req { |
| 473 | u8 rsvd0[2]; | 472 | u8 rsvd0[2]; |
| 474 | __be16 func_id; | 473 | __be16 func_id; |
| 475 | u8 rsvd1[2]; | 474 | __be32 num_pages; |
| 476 | __be16 num_pages; | 475 | __be32 rsvd1[5]; |
| 477 | __be32 rsvd2[5]; | ||
| 478 | }; | 476 | }; |
| 479 | 477 | ||
| 480 | union ev_data { | 478 | union ev_data { |
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 2aa258b0ced1..8888381fc150 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h | |||
| @@ -358,7 +358,7 @@ struct mlx5_caps { | |||
| 358 | u32 reserved_lkey; | 358 | u32 reserved_lkey; |
| 359 | u8 local_ca_ack_delay; | 359 | u8 local_ca_ack_delay; |
| 360 | u8 log_max_mcg; | 360 | u8 log_max_mcg; |
| 361 | u16 max_qp_mcg; | 361 | u32 max_qp_mcg; |
| 362 | int min_page_sz; | 362 | int min_page_sz; |
| 363 | }; | 363 | }; |
| 364 | 364 | ||
| @@ -691,7 +691,7 @@ void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev); | |||
| 691 | int mlx5_pagealloc_start(struct mlx5_core_dev *dev); | 691 | int mlx5_pagealloc_start(struct mlx5_core_dev *dev); |
| 692 | void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); | 692 | void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); |
| 693 | void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, | 693 | void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, |
| 694 | s16 npages); | 694 | s32 npages); |
| 695 | int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot); | 695 | int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot); |
| 696 | int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); | 696 | int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); |
| 697 | void mlx5_register_debugfs(void); | 697 | void mlx5_register_debugfs(void); |
| @@ -731,9 +731,6 @@ void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev); | |||
| 731 | int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db); | 731 | int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db); |
| 732 | void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); | 732 | void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); |
| 733 | 733 | ||
| 734 | typedef void (*health_handler_t)(struct pci_dev *pdev, struct health_buffer __iomem *buf, int size); | ||
| 735 | int mlx5_register_health_report_handler(health_handler_t handler); | ||
| 736 | void mlx5_unregister_health_report_handler(void); | ||
| 737 | const char *mlx5_command_str(int command); | 734 | const char *mlx5_command_str(int command); |
| 738 | int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); | 735 | int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); |
| 739 | void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); | 736 | void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); |
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h index 88272591a895..9efc04dd255a 100644 --- a/include/linux/platform_data/asoc-s3c.h +++ b/include/linux/platform_data/asoc-s3c.h | |||
| @@ -36,6 +36,7 @@ struct samsung_i2s { | |||
| 36 | */ | 36 | */ |
| 37 | #define QUIRK_NO_MUXPSR (1 << 2) | 37 | #define QUIRK_NO_MUXPSR (1 << 2) |
| 38 | #define QUIRK_NEED_RSTCLR (1 << 3) | 38 | #define QUIRK_NEED_RSTCLR (1 << 3) |
| 39 | #define QUIRK_SUPPORTS_TDM (1 << 4) | ||
| 39 | /* Quirks of the I2S controller */ | 40 | /* Quirks of the I2S controller */ |
| 40 | u32 quirks; | 41 | u32 quirks; |
| 41 | dma_addr_t idma_addr; | 42 | dma_addr_t idma_addr; |
diff --git a/include/linux/platform_data/omap-abe-twl6040.h b/include/linux/platform_data/omap-abe-twl6040.h deleted file mode 100644 index 5d298ac10fc2..000000000000 --- a/include/linux/platform_data/omap-abe-twl6040.h +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | /** | ||
| 2 | * omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * version 2 as published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 21 | * 02110-1301 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _OMAP_ABE_TWL6040_H_ | ||
| 25 | #define _OMAP_ABE_TWL6040_H_ | ||
| 26 | |||
| 27 | /* To select if only one channel is connected in a stereo port */ | ||
| 28 | #define ABE_TWL6040_LEFT (1 << 0) | ||
| 29 | #define ABE_TWL6040_RIGHT (1 << 1) | ||
| 30 | |||
| 31 | struct omap_abe_twl6040_data { | ||
| 32 | char *card_name; | ||
| 33 | /* Feature flags for connected audio pins */ | ||
| 34 | u8 has_hs; | ||
| 35 | u8 has_hf; | ||
| 36 | bool has_ep; | ||
| 37 | u8 has_aux; | ||
| 38 | u8 has_vibra; | ||
| 39 | bool has_dmic; | ||
| 40 | bool has_hsmic; | ||
| 41 | bool has_mainmic; | ||
| 42 | bool has_submic; | ||
| 43 | u8 has_afm; | ||
| 44 | /* Other features */ | ||
| 45 | bool jack_detection; /* board can detect jack events */ | ||
| 46 | int mclk_freq; /* MCLK frequency speed for twl6040 */ | ||
| 47 | }; | ||
| 48 | |||
| 49 | #endif /* _OMAP_ABE_TWL6040_H_ */ | ||
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index 467cc6307b62..49444203328a 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/of.h> | ||
| 25 | |||
| 24 | 26 | ||
| 25 | /* | 27 | /* |
| 26 | * SSP Serial Port Registers | 28 | * SSP Serial Port Registers |
| @@ -190,6 +192,8 @@ struct ssp_device { | |||
| 190 | int irq; | 192 | int irq; |
| 191 | int drcmr_rx; | 193 | int drcmr_rx; |
| 192 | int drcmr_tx; | 194 | int drcmr_tx; |
| 195 | |||
| 196 | struct device_node *of_node; | ||
| 193 | }; | 197 | }; |
| 194 | 198 | ||
| 195 | /** | 199 | /** |
| @@ -218,11 +222,18 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) | |||
| 218 | #ifdef CONFIG_ARCH_PXA | 222 | #ifdef CONFIG_ARCH_PXA |
| 219 | struct ssp_device *pxa_ssp_request(int port, const char *label); | 223 | struct ssp_device *pxa_ssp_request(int port, const char *label); |
| 220 | void pxa_ssp_free(struct ssp_device *); | 224 | void pxa_ssp_free(struct ssp_device *); |
| 225 | struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node, | ||
| 226 | const char *label); | ||
| 221 | #else | 227 | #else |
| 222 | static inline struct ssp_device *pxa_ssp_request(int port, const char *label) | 228 | static inline struct ssp_device *pxa_ssp_request(int port, const char *label) |
| 223 | { | 229 | { |
| 224 | return NULL; | 230 | return NULL; |
| 225 | } | 231 | } |
| 232 | static inline struct ssp_device *pxa_ssp_request_of(const struct device_node *n, | ||
| 233 | const char *name) | ||
| 234 | { | ||
| 235 | return NULL; | ||
| 236 | } | ||
| 226 | static inline void pxa_ssp_free(struct ssp_device *ssp) {} | 237 | static inline void pxa_ssp_free(struct ssp_device *ssp) {} |
| 227 | #endif | 238 | #endif |
| 228 | 239 | ||
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 75981d0b57dc..580a5320cc96 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
| 17 | #include <linux/rbtree.h> | 17 | #include <linux/rbtree.h> |
| 18 | #include <linux/err.h> | ||
| 18 | 19 | ||
| 19 | struct module; | 20 | struct module; |
| 20 | struct device; | 21 | struct device; |
diff --git a/include/linux/sched.h b/include/linux/sched.h index d722490da030..e9995eb5985c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -314,6 +314,7 @@ struct nsproxy; | |||
| 314 | struct user_namespace; | 314 | struct user_namespace; |
| 315 | 315 | ||
| 316 | #ifdef CONFIG_MMU | 316 | #ifdef CONFIG_MMU |
| 317 | extern unsigned long mmap_legacy_base(void); | ||
| 317 | extern void arch_pick_mmap_layout(struct mm_struct *mm); | 318 | extern void arch_pick_mmap_layout(struct mm_struct *mm); |
| 318 | extern unsigned long | 319 | extern unsigned long |
| 319 | arch_get_unmapped_area(struct file *, unsigned long, unsigned long, | 320 | arch_get_unmapped_area(struct file *, unsigned long, unsigned long, |
| @@ -1532,6 +1533,8 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk) | |||
| 1532 | * Test if a process is not yet dead (at most zombie state) | 1533 | * Test if a process is not yet dead (at most zombie state) |
| 1533 | * If pid_alive fails, then pointers within the task structure | 1534 | * If pid_alive fails, then pointers within the task structure |
| 1534 | * can be stale and must not be dereferenced. | 1535 | * can be stale and must not be dereferenced. |
| 1536 | * | ||
| 1537 | * Return: 1 if the process is alive. 0 otherwise. | ||
| 1535 | */ | 1538 | */ |
| 1536 | static inline int pid_alive(struct task_struct *p) | 1539 | static inline int pid_alive(struct task_struct *p) |
| 1537 | { | 1540 | { |
| @@ -1543,6 +1546,8 @@ static inline int pid_alive(struct task_struct *p) | |||
| 1543 | * @tsk: Task structure to be checked. | 1546 | * @tsk: Task structure to be checked. |
| 1544 | * | 1547 | * |
| 1545 | * Check if a task structure is the first user space task the kernel created. | 1548 | * Check if a task structure is the first user space task the kernel created. |
| 1549 | * | ||
| 1550 | * Return: 1 if the task structure is init. 0 otherwise. | ||
| 1546 | */ | 1551 | */ |
| 1547 | static inline int is_global_init(struct task_struct *tsk) | 1552 | static inline int is_global_init(struct task_struct *tsk) |
| 1548 | { | 1553 | { |
| @@ -1894,6 +1899,8 @@ extern struct task_struct *idle_task(int cpu); | |||
| 1894 | /** | 1899 | /** |
| 1895 | * is_idle_task - is the specified task an idle task? | 1900 | * is_idle_task - is the specified task an idle task? |
| 1896 | * @p: the task in question. | 1901 | * @p: the task in question. |
| 1902 | * | ||
| 1903 | * Return: 1 if @p is an idle task. 0 otherwise. | ||
| 1897 | */ | 1904 | */ |
| 1898 | static inline bool is_idle_task(const struct task_struct *p) | 1905 | static inline bool is_idle_task(const struct task_struct *p) |
| 1899 | { | 1906 | { |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 7d537ced949a..75f34949d9ab 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -117,9 +117,17 @@ do { \ | |||
| 117 | #endif /*arch_spin_is_contended*/ | 117 | #endif /*arch_spin_is_contended*/ |
| 118 | #endif | 118 | #endif |
| 119 | 119 | ||
| 120 | /* The lock does not imply full memory barrier. */ | 120 | /* |
| 121 | #ifndef ARCH_HAS_SMP_MB_AFTER_LOCK | 121 | * Despite its name it doesn't necessarily has to be a full barrier. |
| 122 | static inline void smp_mb__after_lock(void) { smp_mb(); } | 122 | * It should only guarantee that a STORE before the critical section |
| 123 | * can not be reordered with a LOAD inside this section. | ||
| 124 | * spin_lock() is the one-way barrier, this LOAD can not escape out | ||
| 125 | * of the region. So the default implementation simply ensures that | ||
| 126 | * a STORE can not move into the critical section, smp_wmb() should | ||
| 127 | * serialize it with another STORE done by spin_lock(). | ||
| 128 | */ | ||
| 129 | #ifndef smp_mb__before_spinlock | ||
| 130 | #define smp_mb__before_spinlock() smp_wmb() | ||
| 123 | #endif | 131 | #endif |
| 124 | 132 | ||
| 125 | /** | 133 | /** |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 6d870353674a..1821445708d6 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
| @@ -121,6 +121,7 @@ struct rpc_task_setup { | |||
| 121 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ | 121 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ |
| 122 | #define RPC_TASK_SENT 0x0800 /* message was sent */ | 122 | #define RPC_TASK_SENT 0x0800 /* message was sent */ |
| 123 | #define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */ | 123 | #define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */ |
| 124 | #define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */ | ||
| 124 | 125 | ||
| 125 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) | 126 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) |
| 126 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) | 127 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
diff --git a/include/linux/swapops.h b/include/linux/swapops.h index c5fd30d2a415..8d4fa82bfb91 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h | |||
| @@ -67,6 +67,8 @@ static inline swp_entry_t pte_to_swp_entry(pte_t pte) | |||
| 67 | swp_entry_t arch_entry; | 67 | swp_entry_t arch_entry; |
| 68 | 68 | ||
| 69 | BUG_ON(pte_file(pte)); | 69 | BUG_ON(pte_file(pte)); |
| 70 | if (pte_swp_soft_dirty(pte)) | ||
| 71 | pte = pte_swp_clear_soft_dirty(pte); | ||
| 70 | arch_entry = __pte_to_swp_entry(pte); | 72 | arch_entry = __pte_to_swp_entry(pte); |
| 71 | return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); | 73 | return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); |
| 72 | } | 74 | } |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 4147d700a293..84662ecc7b51 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -802,9 +802,14 @@ asmlinkage long sys_vfork(void); | |||
| 802 | asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int, | 802 | asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int, |
| 803 | int __user *); | 803 | int __user *); |
| 804 | #else | 804 | #else |
| 805 | #ifdef CONFIG_CLONE_BACKWARDS3 | ||
| 806 | asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, | ||
| 807 | int __user *, int); | ||
| 808 | #else | ||
| 805 | asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, | 809 | asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, |
| 806 | int __user *, int); | 810 | int __user *, int); |
| 807 | #endif | 811 | #endif |
| 812 | #endif | ||
| 808 | 813 | ||
| 809 | asmlinkage long sys_execve(const char __user *filename, | 814 | asmlinkage long sys_execve(const char __user *filename, |
| 810 | const char __user *const __user *argv, | 815 | const char __user *const __user *argv, |
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index b6b215f13b45..14105c26a836 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h | |||
| @@ -23,6 +23,7 @@ struct user_namespace { | |||
| 23 | struct uid_gid_map projid_map; | 23 | struct uid_gid_map projid_map; |
| 24 | atomic_t count; | 24 | atomic_t count; |
| 25 | struct user_namespace *parent; | 25 | struct user_namespace *parent; |
| 26 | int level; | ||
| 26 | kuid_t owner; | 27 | kuid_t owner; |
| 27 | kgid_t group; | 28 | kgid_t group; |
| 28 | unsigned int proc_inum; | 29 | unsigned int proc_inum; |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 7343a27fe819..47ada23345a1 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #define _V4L2_CTRLS_H | 22 | #define _V4L2_CTRLS_H |
| 23 | 23 | ||
| 24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
| 25 | #include <linux/mutex.h> | ||
| 25 | #include <linux/videodev2.h> | 26 | #include <linux/videodev2.h> |
| 26 | 27 | ||
| 27 | /* forward references */ | 28 | /* forward references */ |
diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index f18b91966d3d..8a358a2c97e6 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h | |||
| @@ -122,7 +122,7 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock) | |||
| 122 | if (rc > 0) | 122 | if (rc > 0) |
| 123 | /* local bh are disabled so it is ok to use _BH */ | 123 | /* local bh are disabled so it is ok to use _BH */ |
| 124 | NET_ADD_STATS_BH(sock_net(sk), | 124 | NET_ADD_STATS_BH(sock_net(sk), |
| 125 | LINUX_MIB_LOWLATENCYRXPACKETS, rc); | 125 | LINUX_MIB_BUSYPOLLRXPACKETS, rc); |
| 126 | 126 | ||
| 127 | } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && | 127 | } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && |
| 128 | !need_resched() && !busy_loop_timeout(end_time)); | 128 | !need_resched() && !busy_loop_timeout(end_time)); |
| @@ -162,11 +162,6 @@ static inline bool sk_can_busy_loop(struct sock *sk) | |||
| 162 | return false; | 162 | return false; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static inline bool sk_busy_poll(struct sock *sk, int nonblock) | ||
| 166 | { | ||
| 167 | return false; | ||
| 168 | } | ||
| 169 | |||
| 170 | static inline void skb_mark_napi_id(struct sk_buff *skb, | 165 | static inline void skb_mark_napi_id(struct sk_buff *skb, |
| 171 | struct napi_struct *napi) | 166 | struct napi_struct *napi) |
| 172 | { | 167 | { |
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 781b3cf86a2f..a354db5b7662 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
| @@ -145,20 +145,6 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, | |||
| 145 | return INET_ECN_encapsulate(tos, inner); | 145 | return INET_ECN_encapsulate(tos, inner); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static inline void tunnel_ip_select_ident(struct sk_buff *skb, | ||
| 149 | const struct iphdr *old_iph, | ||
| 150 | struct dst_entry *dst) | ||
| 151 | { | ||
| 152 | struct iphdr *iph = ip_hdr(skb); | ||
| 153 | |||
| 154 | /* Use inner packet iph-id if possible. */ | ||
| 155 | if (skb->protocol == htons(ETH_P_IP) && old_iph->id) | ||
| 156 | iph->id = old_iph->id; | ||
| 157 | else | ||
| 158 | __ip_select_ident(iph, dst, | ||
| 159 | (skb_shinfo(skb)->gso_segs ?: 1) - 1); | ||
| 160 | } | ||
| 161 | |||
| 162 | int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); | 148 | int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); |
| 163 | int iptunnel_xmit(struct net *net, struct rtable *rt, | 149 | int iptunnel_xmit(struct net *net, struct rtable *rt, |
| 164 | struct sk_buff *skb, | 150 | struct sk_buff *skb, |
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 6eab63363e59..e5ae0c50fa9c 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
| @@ -683,13 +683,19 @@ struct psched_ratecfg { | |||
| 683 | u64 rate_bytes_ps; /* bytes per second */ | 683 | u64 rate_bytes_ps; /* bytes per second */ |
| 684 | u32 mult; | 684 | u32 mult; |
| 685 | u16 overhead; | 685 | u16 overhead; |
| 686 | u8 linklayer; | ||
| 686 | u8 shift; | 687 | u8 shift; |
| 687 | }; | 688 | }; |
| 688 | 689 | ||
| 689 | static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, | 690 | static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, |
| 690 | unsigned int len) | 691 | unsigned int len) |
| 691 | { | 692 | { |
| 692 | return ((u64)(len + r->overhead) * r->mult) >> r->shift; | 693 | len += r->overhead; |
| 694 | |||
| 695 | if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) | ||
| 696 | return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift; | ||
| 697 | |||
| 698 | return ((u64)len * r->mult) >> r->shift; | ||
| 693 | } | 699 | } |
| 694 | 700 | ||
| 695 | extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf); | 701 | extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf); |
| @@ -700,6 +706,7 @@ static inline void psched_ratecfg_getrate(struct tc_ratespec *res, | |||
| 700 | memset(res, 0, sizeof(*res)); | 706 | memset(res, 0, sizeof(*res)); |
| 701 | res->rate = r->rate_bytes_ps; | 707 | res->rate = r->rate_bytes_ps; |
| 702 | res->overhead = r->overhead; | 708 | res->overhead = r->overhead; |
| 709 | res->linklayer = (r->linklayer & TC_LINKLAYER_MASK); | ||
| 703 | } | 710 | } |
| 704 | 711 | ||
| 705 | #endif | 712 | #endif |
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index 2fd3d251d9a5..56e818e4a1cb 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h | |||
| @@ -6,13 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | /* PCM */ | 7 | /* PCM */ |
| 8 | 8 | ||
| 9 | struct pxa2xx_pcm_dma_params { | ||
| 10 | char *name; /* stream identifier */ | ||
| 11 | u32 dcmd; /* DMA descriptor dcmd field */ | ||
| 12 | volatile u32 *drcmr; /* the DMA request channel to use */ | ||
| 13 | u32 dev_addr; /* device physical address for DMA */ | ||
| 14 | }; | ||
| 15 | |||
| 16 | extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | 9 | extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, |
| 17 | struct snd_pcm_hw_params *params); | 10 | struct snd_pcm_hw_params *params); |
| 18 | extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream); | 11 | extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream); |
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h new file mode 100644 index 000000000000..d35412ae03b3 --- /dev/null +++ b/include/sound/rcar_snd.h | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car SRU/SCU/SSIU/SSI support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 RCAR_SND_H | ||
| 13 | #define RCAR_SND_H | ||
| 14 | |||
| 15 | #include <linux/sh_clk.h> | ||
| 16 | |||
| 17 | #define RSND_GEN1_SRU 0 | ||
| 18 | #define RSND_GEN1_ADG 1 | ||
| 19 | #define RSND_GEN1_SSI 2 | ||
| 20 | |||
| 21 | #define RSND_GEN2_SRU 0 | ||
| 22 | #define RSND_GEN2_ADG 1 | ||
| 23 | #define RSND_GEN2_SSIU 2 | ||
| 24 | #define RSND_GEN2_SSI 3 | ||
| 25 | |||
| 26 | #define RSND_BASE_MAX 4 | ||
| 27 | |||
| 28 | /* | ||
| 29 | * flags | ||
| 30 | * | ||
| 31 | * 0xAB000000 | ||
| 32 | * | ||
| 33 | * A : clock sharing settings | ||
| 34 | * B : SSI direction | ||
| 35 | */ | ||
| 36 | #define RSND_SSI_CLK_PIN_SHARE (1 << 31) | ||
| 37 | #define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */ | ||
| 38 | #define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ | ||
| 39 | #define RSND_SSI_DEPENDENT (1 << 28) /* SSI needs SRU/SCU */ | ||
| 40 | |||
| 41 | #define RSND_SSI_PLAY (1 << 24) | ||
| 42 | |||
| 43 | #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ | ||
| 44 | { .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } | ||
| 45 | #define RSND_SSI_UNUSED \ | ||
| 46 | { .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 } | ||
| 47 | |||
| 48 | struct rsnd_ssi_platform_info { | ||
| 49 | int dai_id; | ||
| 50 | int dma_id; | ||
| 51 | int pio_irq; | ||
| 52 | u32 flags; | ||
| 53 | }; | ||
| 54 | |||
| 55 | /* | ||
| 56 | * flags | ||
| 57 | */ | ||
| 58 | #define RSND_SCU_USB_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ | ||
| 59 | |||
| 60 | struct rsnd_scu_platform_info { | ||
| 61 | u32 flags; | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* | ||
| 65 | * flags | ||
| 66 | * | ||
| 67 | * 0x0000000A | ||
| 68 | * | ||
| 69 | * A : generation | ||
| 70 | */ | ||
| 71 | #define RSND_GEN1 (1 << 0) /* fixme */ | ||
| 72 | #define RSND_GEN2 (2 << 0) /* fixme */ | ||
| 73 | |||
| 74 | struct rcar_snd_info { | ||
| 75 | u32 flags; | ||
| 76 | struct rsnd_ssi_platform_info *ssi_info; | ||
| 77 | int ssi_info_nr; | ||
| 78 | struct rsnd_scu_platform_info *scu_info; | ||
| 79 | int scu_info_nr; | ||
| 80 | int (*start)(int id); | ||
| 81 | int (*stop)(int id); | ||
| 82 | }; | ||
| 83 | |||
| 84 | #endif | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3e479f4e15f5..c728d28ae9a5 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
| @@ -70,121 +70,144 @@ struct device; | |||
| 70 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ | 70 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 71 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} | 71 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} |
| 72 | 72 | ||
| 73 | #define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \ | ||
| 74 | .reg = wreg, .mask = 1, .shift = wshift, \ | ||
| 75 | .on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0 | ||
| 76 | |||
| 73 | /* path domain */ | 77 | /* path domain */ |
| 74 | #define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ | 78 | #define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ |
| 75 | wcontrols, wncontrols) \ | 79 | wcontrols, wncontrols) \ |
| 76 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | 80 | { .id = snd_soc_dapm_pga, .name = wname, \ |
| 77 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | 81 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 82 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | ||
| 78 | #define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ | 83 | #define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ |
| 79 | wcontrols, wncontrols) \ | 84 | wcontrols, wncontrols) \ |
| 80 | { .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ | 85 | { .id = snd_soc_dapm_out_drv, .name = wname, \ |
| 81 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | 86 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 87 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | ||
| 82 | #define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ | 88 | #define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ |
| 83 | wcontrols, wncontrols)\ | 89 | wcontrols, wncontrols)\ |
| 84 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 90 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 85 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | 91 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 92 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} | ||
| 86 | #define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ | 93 | #define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ |
| 87 | wcontrols, wncontrols)\ | 94 | wcontrols, wncontrols)\ |
| 88 | { .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ | 95 | { .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ |
| 89 | .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ | 96 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 90 | .num_kcontrols = wncontrols} | 97 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} |
| 91 | #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ | 98 | #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ |
| 92 | { .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ | 99 | { .id = snd_soc_dapm_micbias, .name = wname, \ |
| 93 | .invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0} | 100 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 101 | .kcontrol_news = NULL, .num_kcontrols = 0} | ||
| 94 | #define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ | 102 | #define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ |
| 95 | { .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ | 103 | { .id = snd_soc_dapm_switch, .name = wname, \ |
| 96 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} | 104 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 105 | .kcontrol_news = wcontrols, .num_kcontrols = 1} | ||
| 97 | #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ | 106 | #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ |
| 98 | { .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ | 107 | { .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \ |
| 99 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} | 108 | .kcontrol_news = wcontrols, .num_kcontrols = 1} |
| 100 | #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ | 109 | #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ |
| 101 | { .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ | 110 | { .id = snd_soc_dapm_virt_mux, .name = wname, \ |
| 102 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} | 111 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 112 | .kcontrol_news = wcontrols, .num_kcontrols = 1} | ||
| 103 | #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ | 113 | #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ |
| 104 | { .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \ | 114 | { .id = snd_soc_dapm_value_mux, .name = wname, \ |
| 105 | .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ | 115 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 106 | .num_kcontrols = 1} | 116 | .kcontrol_news = wcontrols, .num_kcontrols = 1} |
| 107 | 117 | ||
| 108 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ | 118 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ |
| 109 | #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ | 119 | #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ |
| 110 | wcontrols) \ | 120 | wcontrols) \ |
| 111 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | 121 | { .id = snd_soc_dapm_pga, .name = wname, \ |
| 112 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} | 122 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 123 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} | ||
| 113 | #define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ | 124 | #define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ |
| 114 | wcontrols)\ | 125 | wcontrols)\ |
| 115 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 126 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 116 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} | 127 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 128 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} | ||
| 117 | #define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ | 129 | #define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ |
| 118 | wcontrols)\ | 130 | wcontrols)\ |
| 119 | { .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ | 131 | { .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ |
| 120 | .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ | 132 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 121 | .num_kcontrols = ARRAY_SIZE(wcontrols)} | 133 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} |
| 122 | 134 | ||
| 123 | /* path domain with event - event handler must return 0 for success */ | 135 | /* path domain with event - event handler must return 0 for success */ |
| 124 | #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ | 136 | #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 125 | wncontrols, wevent, wflags) \ | 137 | wncontrols, wevent, wflags) \ |
| 126 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | 138 | { .id = snd_soc_dapm_pga, .name = wname, \ |
| 127 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | 139 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 140 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | ||
| 128 | .event = wevent, .event_flags = wflags} | 141 | .event = wevent, .event_flags = wflags} |
| 129 | #define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ | 142 | #define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 130 | wncontrols, wevent, wflags) \ | 143 | wncontrols, wevent, wflags) \ |
| 131 | { .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ | 144 | { .id = snd_soc_dapm_out_drv, .name = wname, \ |
| 132 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | 145 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 146 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | ||
| 133 | .event = wevent, .event_flags = wflags} | 147 | .event = wevent, .event_flags = wflags} |
| 134 | #define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ | 148 | #define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 135 | wncontrols, wevent, wflags) \ | 149 | wncontrols, wevent, wflags) \ |
| 136 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 150 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 137 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | 151 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 152 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ | ||
| 138 | .event = wevent, .event_flags = wflags} | 153 | .event = wevent, .event_flags = wflags} |
| 139 | #define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ | 154 | #define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ |
| 140 | wcontrols, wncontrols, wevent, wflags) \ | 155 | wcontrols, wncontrols, wevent, wflags) \ |
| 141 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 156 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 142 | .invert = winvert, .kcontrol_news = wcontrols, \ | 157 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 158 | .kcontrol_news = wcontrols, \ | ||
| 143 | .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} | 159 | .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} |
| 144 | #define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ | 160 | #define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 145 | wevent, wflags) \ | 161 | wevent, wflags) \ |
| 146 | { .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ | 162 | { .id = snd_soc_dapm_switch, .name = wname, \ |
| 147 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | 163 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 164 | .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | ||
| 148 | .event = wevent, .event_flags = wflags} | 165 | .event = wevent, .event_flags = wflags} |
| 149 | #define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ | 166 | #define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 150 | wevent, wflags) \ | 167 | wevent, wflags) \ |
| 151 | { .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ | 168 | { .id = snd_soc_dapm_mux, .name = wname, \ |
| 152 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | 169 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 170 | .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | ||
| 153 | .event = wevent, .event_flags = wflags} | 171 | .event = wevent, .event_flags = wflags} |
| 154 | #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ | 172 | #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 155 | wevent, wflags) \ | 173 | wevent, wflags) \ |
| 156 | { .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ | 174 | { .id = snd_soc_dapm_virt_mux, .name = wname, \ |
| 157 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | 175 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 176 | .kcontrol_news = wcontrols, .num_kcontrols = 1, \ | ||
| 158 | .event = wevent, .event_flags = wflags} | 177 | .event = wevent, .event_flags = wflags} |
| 159 | 178 | ||
| 160 | /* additional sequencing control within an event type */ | 179 | /* additional sequencing control within an event type */ |
| 161 | #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ | 180 | #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ |
| 162 | wevent, wflags) \ | 181 | wevent, wflags) \ |
| 163 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | 182 | { .id = snd_soc_dapm_pga, .name = wname, \ |
| 164 | .invert = winvert, .event = wevent, .event_flags = wflags, \ | 183 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 184 | .event = wevent, .event_flags = wflags, \ | ||
| 165 | .subseq = wsubseq} | 185 | .subseq = wsubseq} |
| 166 | #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ | 186 | #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ |
| 167 | wflags) \ | 187 | wflags) \ |
| 168 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ | 188 | { .id = snd_soc_dapm_supply, .name = wname, \ |
| 169 | .shift = wshift, .invert = winvert, .event = wevent, \ | 189 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 170 | .event_flags = wflags, .subseq = wsubseq} | 190 | .event = wevent, .event_flags = wflags, .subseq = wsubseq} |
| 171 | 191 | ||
| 172 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ | 192 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ |
| 173 | #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ | 193 | #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ |
| 174 | wevent, wflags) \ | 194 | wevent, wflags) \ |
| 175 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | 195 | { .id = snd_soc_dapm_pga, .name = wname, \ |
| 176 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ | 196 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 197 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ | ||
| 177 | .event = wevent, .event_flags = wflags} | 198 | .event = wevent, .event_flags = wflags} |
| 178 | #define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ | 199 | #define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ |
| 179 | wevent, wflags) \ | 200 | wevent, wflags) \ |
| 180 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 201 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 181 | .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ | 202 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 203 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ | ||
| 182 | .event = wevent, .event_flags = wflags} | 204 | .event = wevent, .event_flags = wflags} |
| 183 | #define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ | 205 | #define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ |
| 184 | wcontrols, wevent, wflags) \ | 206 | wcontrols, wevent, wflags) \ |
| 185 | { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ | 207 | { .id = snd_soc_dapm_mixer, .name = wname, \ |
| 186 | .invert = winvert, .kcontrol_news = wcontrols, \ | 208 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 187 | .num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags} | 209 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ |
| 210 | .event = wevent, .event_flags = wflags} | ||
| 188 | 211 | ||
| 189 | /* events that are pre and post DAPM */ | 212 | /* events that are pre and post DAPM */ |
| 190 | #define SND_SOC_DAPM_PRE(wname, wevent) \ | 213 | #define SND_SOC_DAPM_PRE(wname, wevent) \ |
| @@ -199,35 +222,36 @@ struct device; | |||
| 199 | /* stream domain */ | 222 | /* stream domain */ |
| 200 | #define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ | 223 | #define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ |
| 201 | { .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | 224 | { .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ |
| 202 | .reg = wreg, .shift = wshift, .invert = winvert } | 225 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 203 | #define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \ | 226 | #define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \ |
| 204 | wevent, wflags) \ | 227 | wevent, wflags) \ |
| 205 | { .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | 228 | { .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ |
| 206 | .reg = wreg, .shift = wshift, .invert = winvert, \ | 229 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 207 | .event = wevent, .event_flags = wflags } | 230 | .event = wevent, .event_flags = wflags } |
| 208 | #define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ | 231 | #define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ |
| 209 | { .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | 232 | { .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ |
| 210 | .reg = wreg, .shift = wshift, .invert = winvert } | 233 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 211 | #define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \ | 234 | #define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \ |
| 212 | wevent, wflags) \ | 235 | wevent, wflags) \ |
| 213 | { .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | 236 | { .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ |
| 214 | .reg = wreg, .shift = wshift, .invert = winvert, \ | 237 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 215 | .event = wevent, .event_flags = wflags } | 238 | .event = wevent, .event_flags = wflags } |
| 216 | #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ | 239 | #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ |
| 217 | { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ | 240 | { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ |
| 218 | .shift = wshift, .invert = winvert} | 241 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) } |
| 219 | #define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ | 242 | #define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ |
| 220 | wevent, wflags) \ | 243 | wevent, wflags) \ |
| 221 | { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ | 244 | { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ |
| 222 | .shift = wshift, .invert = winvert, \ | 245 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 223 | .event = wevent, .event_flags = wflags} | 246 | .event = wevent, .event_flags = wflags} |
| 247 | |||
| 224 | #define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ | 248 | #define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ |
| 225 | { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ | 249 | { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ |
| 226 | .shift = wshift, .invert = winvert} | 250 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 227 | #define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ | 251 | #define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ |
| 228 | wevent, wflags) \ | 252 | wevent, wflags) \ |
| 229 | { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ | 253 | { .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ |
| 230 | .shift = wshift, .invert = winvert, \ | 254 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 231 | .event = wevent, .event_flags = wflags} | 255 | .event = wevent, .event_flags = wflags} |
| 232 | #define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ | 256 | #define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ |
| 233 | { .id = snd_soc_dapm_clock_supply, .name = wname, \ | 257 | { .id = snd_soc_dapm_clock_supply, .name = wname, \ |
| @@ -241,14 +265,14 @@ struct device; | |||
| 241 | .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ | 265 | .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ |
| 242 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} | 266 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} |
| 243 | #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ | 267 | #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ |
| 244 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ | 268 | { .id = snd_soc_dapm_supply, .name = wname, \ |
| 245 | .shift = wshift, .invert = winvert, .event = wevent, \ | 269 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 246 | .event_flags = wflags} | 270 | .event = wevent, .event_flags = wflags} |
| 247 | #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ | 271 | #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ |
| 248 | { .id = snd_soc_dapm_regulator_supply, .name = wname, \ | 272 | { .id = snd_soc_dapm_regulator_supply, .name = wname, \ |
| 249 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ | 273 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ |
| 250 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ | 274 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ |
| 251 | .invert = wflags} | 275 | .on_val = wflags} |
| 252 | 276 | ||
| 253 | 277 | ||
| 254 | /* dapm kcontrol types */ | 278 | /* dapm kcontrol types */ |
| @@ -256,14 +280,26 @@ struct device; | |||
| 256 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 280 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 257 | .info = snd_soc_info_volsw, \ | 281 | .info = snd_soc_info_volsw, \ |
| 258 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | 282 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ |
| 259 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | 283 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } |
| 284 | #define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \ | ||
| 285 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
| 286 | .info = snd_soc_info_volsw, \ | ||
| 287 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | ||
| 288 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } | ||
| 260 | #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ | 289 | #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ |
| 261 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 290 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 262 | .info = snd_soc_info_volsw, \ | 291 | .info = snd_soc_info_volsw, \ |
| 263 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | 292 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ |
| 264 | .tlv.p = (tlv_array), \ | 293 | .tlv.p = (tlv_array), \ |
| 265 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | 294 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ |
| 266 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | 295 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } |
| 296 | #define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \ | ||
| 297 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
| 298 | .info = snd_soc_info_volsw, \ | ||
| 299 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
| 300 | .tlv.p = (tlv_array), \ | ||
| 301 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | ||
| 302 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } | ||
| 267 | #define SOC_DAPM_ENUM(xname, xenum) \ | 303 | #define SOC_DAPM_ENUM(xname, xenum) \ |
| 268 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 304 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 269 | .info = snd_soc_info_enum_double, \ | 305 | .info = snd_soc_info_enum_double, \ |
| @@ -333,6 +369,7 @@ struct snd_soc_dapm_route; | |||
| 333 | struct snd_soc_dapm_context; | 369 | struct snd_soc_dapm_context; |
| 334 | struct regulator; | 370 | struct regulator; |
| 335 | struct snd_soc_dapm_widget_list; | 371 | struct snd_soc_dapm_widget_list; |
| 372 | struct snd_soc_dapm_update; | ||
| 336 | 373 | ||
| 337 | int dapm_reg_event(struct snd_soc_dapm_widget *w, | 374 | int dapm_reg_event(struct snd_soc_dapm_widget *w, |
| 338 | struct snd_kcontrol *kcontrol, int event); | 375 | struct snd_kcontrol *kcontrol, int event); |
| @@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | |||
| 391 | void snd_soc_dapm_shutdown(struct snd_soc_card *card); | 428 | void snd_soc_dapm_shutdown(struct snd_soc_card *card); |
| 392 | 429 | ||
| 393 | /* external DAPM widget events */ | 430 | /* external DAPM widget events */ |
| 394 | int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | 431 | int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, |
| 395 | struct snd_kcontrol *kcontrol, int connect); | 432 | struct snd_kcontrol *kcontrol, int connect, |
| 396 | int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | 433 | struct snd_soc_dapm_update *update); |
| 397 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e); | 434 | int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, |
| 435 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e, | ||
| 436 | struct snd_soc_dapm_update *update); | ||
| 398 | 437 | ||
| 399 | /* dapm sys fs - used by the core */ | 438 | /* dapm sys fs - used by the core */ |
| 400 | int snd_soc_dapm_sys_add(struct device *dev); | 439 | int snd_soc_dapm_sys_add(struct device *dev); |
| @@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); | |||
| 424 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | 463 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, |
| 425 | struct snd_soc_dapm_widget_list **list); | 464 | struct snd_soc_dapm_widget_list **list); |
| 426 | 465 | ||
| 466 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol); | ||
| 467 | |||
| 427 | /* dapm widget types */ | 468 | /* dapm widget types */ |
| 428 | enum snd_soc_dapm_type { | 469 | enum snd_soc_dapm_type { |
| 429 | snd_soc_dapm_input = 0, /* input pin */ | 470 | snd_soc_dapm_input = 0, /* input pin */ |
| @@ -455,6 +496,7 @@ enum snd_soc_dapm_type { | |||
| 455 | snd_soc_dapm_dai_in, /* link to DAI structure */ | 496 | snd_soc_dapm_dai_in, /* link to DAI structure */ |
| 456 | snd_soc_dapm_dai_out, | 497 | snd_soc_dapm_dai_out, |
| 457 | snd_soc_dapm_dai_link, /* link between two DAI structures */ | 498 | snd_soc_dapm_dai_link, /* link between two DAI structures */ |
| 499 | snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */ | ||
| 458 | }; | 500 | }; |
| 459 | 501 | ||
| 460 | enum snd_soc_dapm_subclass { | 502 | enum snd_soc_dapm_subclass { |
| @@ -485,7 +527,6 @@ struct snd_soc_dapm_path { | |||
| 485 | /* source (input) and sink (output) widgets */ | 527 | /* source (input) and sink (output) widgets */ |
| 486 | struct snd_soc_dapm_widget *source; | 528 | struct snd_soc_dapm_widget *source; |
| 487 | struct snd_soc_dapm_widget *sink; | 529 | struct snd_soc_dapm_widget *sink; |
| 488 | struct snd_kcontrol *kcontrol; | ||
| 489 | 530 | ||
| 490 | /* status */ | 531 | /* status */ |
| 491 | u32 connect:1; /* source and sink widgets are connected */ | 532 | u32 connect:1; /* source and sink widgets are connected */ |
| @@ -498,6 +539,7 @@ struct snd_soc_dapm_path { | |||
| 498 | 539 | ||
| 499 | struct list_head list_source; | 540 | struct list_head list_source; |
| 500 | struct list_head list_sink; | 541 | struct list_head list_sink; |
| 542 | struct list_head list_kcontrol; | ||
| 501 | struct list_head list; | 543 | struct list_head list; |
| 502 | }; | 544 | }; |
| 503 | 545 | ||
| @@ -518,12 +560,10 @@ struct snd_soc_dapm_widget { | |||
| 518 | /* dapm control */ | 560 | /* dapm control */ |
| 519 | int reg; /* negative reg = no direct dapm */ | 561 | int reg; /* negative reg = no direct dapm */ |
| 520 | unsigned char shift; /* bits to shift */ | 562 | unsigned char shift; /* bits to shift */ |
| 521 | unsigned int value; /* widget current value */ | ||
| 522 | unsigned int mask; /* non-shifted mask */ | 563 | unsigned int mask; /* non-shifted mask */ |
| 523 | unsigned int on_val; /* on state value */ | 564 | unsigned int on_val; /* on state value */ |
| 524 | unsigned int off_val; /* off state value */ | 565 | unsigned int off_val; /* off state value */ |
| 525 | unsigned char power:1; /* block power status */ | 566 | unsigned char power:1; /* block power status */ |
| 526 | unsigned char invert:1; /* invert the power bit */ | ||
| 527 | unsigned char active:1; /* active stream on DAC, ADC's */ | 567 | unsigned char active:1; /* active stream on DAC, ADC's */ |
| 528 | unsigned char connected:1; /* connected codec pin */ | 568 | unsigned char connected:1; /* connected codec pin */ |
| 529 | unsigned char new:1; /* cnew complete */ | 569 | unsigned char new:1; /* cnew complete */ |
| @@ -559,7 +599,6 @@ struct snd_soc_dapm_widget { | |||
| 559 | }; | 599 | }; |
| 560 | 600 | ||
| 561 | struct snd_soc_dapm_update { | 601 | struct snd_soc_dapm_update { |
| 562 | struct snd_soc_dapm_widget *widget; | ||
| 563 | struct snd_kcontrol *kcontrol; | 602 | struct snd_kcontrol *kcontrol; |
| 564 | int reg; | 603 | int reg; |
| 565 | int mask; | 604 | int mask; |
| @@ -573,8 +612,6 @@ struct snd_soc_dapm_context { | |||
| 573 | struct delayed_work delayed_work; | 612 | struct delayed_work delayed_work; |
| 574 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 613 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
| 575 | 614 | ||
| 576 | struct snd_soc_dapm_update *update; | ||
| 577 | |||
| 578 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 615 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
| 579 | enum snd_soc_dapm_type, int); | 616 | enum snd_soc_dapm_type, int); |
| 580 | 617 | ||
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 04598f1efd77..047d657c331c 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h | |||
| @@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, | |||
| 133 | /* internal use only */ | 133 | /* internal use only */ |
| 134 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); | 134 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); |
| 135 | int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); | 135 | int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); |
| 136 | int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *); | 136 | int soc_dpcm_runtime_update(struct snd_soc_card *); |
| 137 | 137 | ||
| 138 | #endif | 138 | #endif |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 6eabee7ec15a..8e2ad52078b6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
| @@ -30,13 +30,13 @@ | |||
| 30 | /* | 30 | /* |
| 31 | * Convenience kcontrol builders | 31 | * Convenience kcontrol builders |
| 32 | */ | 32 | */ |
| 33 | #define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \ | 33 | #define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \ |
| 34 | ((unsigned long)&(struct soc_mixer_control) \ | 34 | ((unsigned long)&(struct soc_mixer_control) \ |
| 35 | {.reg = xreg, .rreg = xreg, .shift = shift_left, \ | 35 | {.reg = xreg, .rreg = xreg, .shift = shift_left, \ |
| 36 | .rshift = shift_right, .max = xmax, .platform_max = xmax, \ | 36 | .rshift = shift_right, .max = xmax, .platform_max = xmax, \ |
| 37 | .invert = xinvert}) | 37 | .invert = xinvert, .autodisable = xautodisable}) |
| 38 | #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ | 38 | #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ |
| 39 | SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) | 39 | SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) |
| 40 | #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ | 40 | #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ |
| 41 | ((unsigned long)&(struct soc_mixer_control) \ | 41 | ((unsigned long)&(struct soc_mixer_control) \ |
| 42 | {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) | 42 | {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) |
| @@ -52,7 +52,7 @@ | |||
| 52 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 52 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 53 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | 53 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ |
| 54 | .put = snd_soc_put_volsw, \ | 54 | .put = snd_soc_put_volsw, \ |
| 55 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | 55 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } |
| 56 | #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ | 56 | #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ |
| 57 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | 57 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
| 58 | .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ | 58 | .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ |
| @@ -68,7 +68,7 @@ | |||
| 68 | .tlv.p = (tlv_array), \ | 68 | .tlv.p = (tlv_array), \ |
| 69 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | 69 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ |
| 70 | .put = snd_soc_put_volsw, \ | 70 | .put = snd_soc_put_volsw, \ |
| 71 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | 71 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } |
| 72 | #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ | 72 | #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ |
| 73 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 73 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 74 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 74 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
| @@ -97,7 +97,7 @@ | |||
| 97 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ | 97 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ |
| 98 | .put = snd_soc_put_volsw, \ | 98 | .put = snd_soc_put_volsw, \ |
| 99 | .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ | 99 | .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ |
| 100 | max, invert) } | 100 | max, invert, 0) } |
| 101 | #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ | 101 | #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ |
| 102 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 102 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
| 103 | .info = snd_soc_info_volsw, \ | 103 | .info = snd_soc_info_volsw, \ |
| @@ -119,7 +119,7 @@ | |||
| 119 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ | 119 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ |
| 120 | .put = snd_soc_put_volsw, \ | 120 | .put = snd_soc_put_volsw, \ |
| 121 | .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ | 121 | .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ |
| 122 | max, invert) } | 122 | max, invert, 0) } |
| 123 | #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ | 123 | #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ |
| 124 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | 124 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
| 125 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 125 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ |
| @@ -190,14 +190,14 @@ | |||
| 190 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 190 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 191 | .info = snd_soc_info_volsw, \ | 191 | .info = snd_soc_info_volsw, \ |
| 192 | .get = xhandler_get, .put = xhandler_put, \ | 192 | .get = xhandler_get, .put = xhandler_put, \ |
| 193 | .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } | 193 | .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } |
| 194 | #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ | 194 | #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ |
| 195 | xhandler_get, xhandler_put) \ | 195 | xhandler_get, xhandler_put) \ |
| 196 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | 196 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
| 197 | .info = snd_soc_info_volsw, \ | 197 | .info = snd_soc_info_volsw, \ |
| 198 | .get = xhandler_get, .put = xhandler_put, \ | 198 | .get = xhandler_get, .put = xhandler_put, \ |
| 199 | .private_value = \ | 199 | .private_value = \ |
| 200 | SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) } | 200 | SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } |
| 201 | #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ | 201 | #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ |
| 202 | xhandler_get, xhandler_put, tlv_array) \ | 202 | xhandler_get, xhandler_put, tlv_array) \ |
| 203 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 203 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| @@ -206,7 +206,7 @@ | |||
| 206 | .tlv.p = (tlv_array), \ | 206 | .tlv.p = (tlv_array), \ |
| 207 | .info = snd_soc_info_volsw, \ | 207 | .info = snd_soc_info_volsw, \ |
| 208 | .get = xhandler_get, .put = xhandler_put, \ | 208 | .get = xhandler_get, .put = xhandler_put, \ |
| 209 | .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } | 209 | .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } |
| 210 | #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ | 210 | #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ |
| 211 | xhandler_get, xhandler_put, tlv_array) \ | 211 | xhandler_get, xhandler_put, tlv_array) \ |
| 212 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 212 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
| @@ -216,7 +216,7 @@ | |||
| 216 | .info = snd_soc_info_volsw, \ | 216 | .info = snd_soc_info_volsw, \ |
| 217 | .get = xhandler_get, .put = xhandler_put, \ | 217 | .get = xhandler_get, .put = xhandler_put, \ |
| 218 | .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ | 218 | .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ |
| 219 | xmax, xinvert) } | 219 | xmax, xinvert, 0) } |
| 220 | #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ | 220 | #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ |
| 221 | xhandler_get, xhandler_put, tlv_array) \ | 221 | xhandler_get, xhandler_put, tlv_array) \ |
| 222 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 222 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
| @@ -234,7 +234,7 @@ | |||
| 234 | .private_value = xdata } | 234 | .private_value = xdata } |
| 235 | #define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \ | 235 | #define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \ |
| 236 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 236 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
| 237 | .info = snd_soc_info_enum_ext, \ | 237 | .info = snd_soc_info_enum_double, \ |
| 238 | .get = xhandler_get, .put = xhandler_put, \ | 238 | .get = xhandler_get, .put = xhandler_put, \ |
| 239 | .private_value = (unsigned long)&xenum } | 239 | .private_value = (unsigned long)&xenum } |
| 240 | 240 | ||
| @@ -468,6 +468,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
| 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); | 470 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); |
| 471 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
| 472 | struct platform_device *pdev); | ||
| 471 | 473 | ||
| 472 | /* | 474 | /* |
| 473 | *Controls | 475 | *Controls |
| @@ -475,6 +477,8 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); | |||
| 475 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | 477 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, |
| 476 | void *data, const char *long_name, | 478 | void *data, const char *long_name, |
| 477 | const char *prefix); | 479 | const char *prefix); |
| 480 | struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | ||
| 481 | const char *name); | ||
| 478 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, | 482 | int snd_soc_add_codec_controls(struct snd_soc_codec *codec, |
| 479 | const struct snd_kcontrol_new *controls, int num_controls); | 483 | const struct snd_kcontrol_new *controls, int num_controls); |
| 480 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, | 484 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, |
| @@ -485,8 +489,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | |||
| 485 | const struct snd_kcontrol_new *controls, int num_controls); | 489 | const struct snd_kcontrol_new *controls, int num_controls); |
| 486 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | 490 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, |
| 487 | struct snd_ctl_elem_info *uinfo); | 491 | struct snd_ctl_elem_info *uinfo); |
| 488 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, | ||
| 489 | struct snd_ctl_elem_info *uinfo); | ||
| 490 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | 492 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, |
| 491 | struct snd_ctl_elem_value *ucontrol); | 493 | struct snd_ctl_elem_value *ucontrol); |
| 492 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | 494 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, |
| @@ -497,8 +499,6 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
| 497 | struct snd_ctl_elem_value *ucontrol); | 499 | struct snd_ctl_elem_value *ucontrol); |
| 498 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | 500 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, |
| 499 | struct snd_ctl_elem_info *uinfo); | 501 | struct snd_ctl_elem_info *uinfo); |
| 500 | int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, | ||
| 501 | struct snd_ctl_elem_info *uinfo); | ||
| 502 | #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info | 502 | #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info |
| 503 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | 503 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, |
| 504 | struct snd_ctl_elem_value *ucontrol); | 504 | struct snd_ctl_elem_value *ucontrol); |
| @@ -1042,6 +1042,7 @@ struct snd_soc_card { | |||
| 1042 | /* Generic DAPM context for the card */ | 1042 | /* Generic DAPM context for the card */ |
| 1043 | struct snd_soc_dapm_context dapm; | 1043 | struct snd_soc_dapm_context dapm; |
| 1044 | struct snd_soc_dapm_stats dapm_stats; | 1044 | struct snd_soc_dapm_stats dapm_stats; |
| 1045 | struct snd_soc_dapm_update *update; | ||
| 1045 | 1046 | ||
| 1046 | #ifdef CONFIG_DEBUG_FS | 1047 | #ifdef CONFIG_DEBUG_FS |
| 1047 | struct dentry *debugfs_card_root; | 1048 | struct dentry *debugfs_card_root; |
| @@ -1087,7 +1088,9 @@ struct snd_soc_pcm_runtime { | |||
| 1087 | /* mixer control */ | 1088 | /* mixer control */ |
| 1088 | struct soc_mixer_control { | 1089 | struct soc_mixer_control { |
| 1089 | int min, max, platform_max; | 1090 | int min, max, platform_max; |
| 1090 | unsigned int reg, rreg, shift, rshift, invert; | 1091 | unsigned int reg, rreg, shift, rshift; |
| 1092 | unsigned int invert:1; | ||
| 1093 | unsigned int autodisable:1; | ||
| 1091 | }; | 1094 | }; |
| 1092 | 1095 | ||
| 1093 | struct soc_bytes { | 1096 | struct soc_bytes { |
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index dbd71b0c7d8c..09d62b9228ff 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h | |||
| @@ -73,9 +73,17 @@ struct tc_estimator { | |||
| 73 | #define TC_H_ROOT (0xFFFFFFFFU) | 73 | #define TC_H_ROOT (0xFFFFFFFFU) |
| 74 | #define TC_H_INGRESS (0xFFFFFFF1U) | 74 | #define TC_H_INGRESS (0xFFFFFFF1U) |
| 75 | 75 | ||
| 76 | /* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */ | ||
| 77 | enum tc_link_layer { | ||
| 78 | TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */ | ||
| 79 | TC_LINKLAYER_ETHERNET, | ||
| 80 | TC_LINKLAYER_ATM, | ||
| 81 | }; | ||
| 82 | #define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */ | ||
| 83 | |||
| 76 | struct tc_ratespec { | 84 | struct tc_ratespec { |
| 77 | unsigned char cell_log; | 85 | unsigned char cell_log; |
| 78 | unsigned char __reserved; | 86 | __u8 linklayer; /* lower 4 bits */ |
| 79 | unsigned short overhead; | 87 | unsigned short overhead; |
| 80 | short cell_align; | 88 | short cell_align; |
| 81 | unsigned short mpu; | 89 | unsigned short mpu; |
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index af0a674cc677..a1356d3b54df 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h | |||
| @@ -253,7 +253,7 @@ enum | |||
| 253 | LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ | 253 | LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ |
| 254 | LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ | 254 | LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ |
| 255 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */ | 255 | LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */ |
| 256 | LINUX_MIB_LOWLATENCYRXPACKETS, /* LowLatencyRxPackets */ | 256 | LINUX_MIB_BUSYPOLLRXPACKETS, /* BusyPollRxPackets */ |
| 257 | __LINUX_MIB_MAX | 257 | __LINUX_MIB_MAX |
| 258 | }; | 258 | }; |
| 259 | 259 | ||
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 789ec4683db3..781845a013ab 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -4335,8 +4335,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
| 4335 | } | 4335 | } |
| 4336 | 4336 | ||
| 4337 | err = percpu_ref_init(&css->refcnt, css_release); | 4337 | err = percpu_ref_init(&css->refcnt, css_release); |
| 4338 | if (err) | 4338 | if (err) { |
| 4339 | ss->css_free(cgrp); | ||
| 4339 | goto err_free_all; | 4340 | goto err_free_all; |
| 4341 | } | ||
| 4340 | 4342 | ||
| 4341 | init_cgroup_css(css, ss, cgrp); | 4343 | init_cgroup_css(css, ss, cgrp); |
| 4342 | 4344 | ||
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index e5657788fedd..010a0083c0ae 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -1608,11 +1608,13 @@ static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val) | |||
| 1608 | { | 1608 | { |
| 1609 | struct cpuset *cs = cgroup_cs(cgrp); | 1609 | struct cpuset *cs = cgroup_cs(cgrp); |
| 1610 | cpuset_filetype_t type = cft->private; | 1610 | cpuset_filetype_t type = cft->private; |
| 1611 | int retval = -ENODEV; | 1611 | int retval = 0; |
| 1612 | 1612 | ||
| 1613 | mutex_lock(&cpuset_mutex); | 1613 | mutex_lock(&cpuset_mutex); |
| 1614 | if (!is_cpuset_online(cs)) | 1614 | if (!is_cpuset_online(cs)) { |
| 1615 | retval = -ENODEV; | ||
| 1615 | goto out_unlock; | 1616 | goto out_unlock; |
| 1617 | } | ||
| 1616 | 1618 | ||
| 1617 | switch (type) { | 1619 | switch (type) { |
| 1618 | case FILE_CPU_EXCLUSIVE: | 1620 | case FILE_CPU_EXCLUSIVE: |
diff --git a/kernel/fork.c b/kernel/fork.c index 403d2bb8a968..e23bb19e2a3e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1679,6 +1679,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, | |||
| 1679 | int __user *, parent_tidptr, | 1679 | int __user *, parent_tidptr, |
| 1680 | int __user *, child_tidptr, | 1680 | int __user *, child_tidptr, |
| 1681 | int, tls_val) | 1681 | int, tls_val) |
| 1682 | #elif defined(CONFIG_CLONE_BACKWARDS3) | ||
| 1683 | SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, | ||
| 1684 | int, stack_size, | ||
| 1685 | int __user *, parent_tidptr, | ||
| 1686 | int __user *, child_tidptr, | ||
| 1687 | int, tls_val) | ||
| 1682 | #else | 1688 | #else |
| 1683 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | 1689 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, |
| 1684 | int __user *, parent_tidptr, | 1690 | int __user *, parent_tidptr, |
diff --git a/kernel/mutex.c b/kernel/mutex.c index ff05f4bd86eb..a52ee7bb830d 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
| @@ -686,7 +686,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) | |||
| 686 | might_sleep(); | 686 | might_sleep(); |
| 687 | ret = __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, | 687 | ret = __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, |
| 688 | 0, &ctx->dep_map, _RET_IP_, ctx); | 688 | 0, &ctx->dep_map, _RET_IP_, ctx); |
| 689 | if (!ret && ctx->acquired > 0) | 689 | if (!ret && ctx->acquired > 1) |
| 690 | return ww_mutex_deadlock_injection(lock, ctx); | 690 | return ww_mutex_deadlock_injection(lock, ctx); |
| 691 | 691 | ||
| 692 | return ret; | 692 | return ret; |
| @@ -702,7 +702,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) | |||
| 702 | ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, | 702 | ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, |
| 703 | 0, &ctx->dep_map, _RET_IP_, ctx); | 703 | 0, &ctx->dep_map, _RET_IP_, ctx); |
| 704 | 704 | ||
| 705 | if (!ret && ctx->acquired > 0) | 705 | if (!ret && ctx->acquired > 1) |
| 706 | return ww_mutex_deadlock_injection(lock, ctx); | 706 | return ww_mutex_deadlock_injection(lock, ctx); |
| 707 | 707 | ||
| 708 | return ret; | 708 | return ret; |
diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 06fe28589e9c..a394297f8b2f 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c | |||
| @@ -296,6 +296,17 @@ int pm_qos_request_active(struct pm_qos_request *req) | |||
| 296 | } | 296 | } |
| 297 | EXPORT_SYMBOL_GPL(pm_qos_request_active); | 297 | EXPORT_SYMBOL_GPL(pm_qos_request_active); |
| 298 | 298 | ||
| 299 | static void __pm_qos_update_request(struct pm_qos_request *req, | ||
| 300 | s32 new_value) | ||
| 301 | { | ||
| 302 | trace_pm_qos_update_request(req->pm_qos_class, new_value); | ||
| 303 | |||
| 304 | if (new_value != req->node.prio) | ||
| 305 | pm_qos_update_target( | ||
| 306 | pm_qos_array[req->pm_qos_class]->constraints, | ||
| 307 | &req->node, PM_QOS_UPDATE_REQ, new_value); | ||
| 308 | } | ||
| 309 | |||
| 299 | /** | 310 | /** |
| 300 | * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout | 311 | * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout |
| 301 | * @work: work struct for the delayed work (timeout) | 312 | * @work: work struct for the delayed work (timeout) |
| @@ -308,7 +319,7 @@ static void pm_qos_work_fn(struct work_struct *work) | |||
| 308 | struct pm_qos_request, | 319 | struct pm_qos_request, |
| 309 | work); | 320 | work); |
| 310 | 321 | ||
| 311 | pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE); | 322 | __pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE); |
| 312 | } | 323 | } |
| 313 | 324 | ||
| 314 | /** | 325 | /** |
| @@ -364,12 +375,7 @@ void pm_qos_update_request(struct pm_qos_request *req, | |||
| 364 | } | 375 | } |
| 365 | 376 | ||
| 366 | cancel_delayed_work_sync(&req->work); | 377 | cancel_delayed_work_sync(&req->work); |
| 367 | 378 | __pm_qos_update_request(req, new_value); | |
| 368 | trace_pm_qos_update_request(req->pm_qos_class, new_value); | ||
| 369 | if (new_value != req->node.prio) | ||
| 370 | pm_qos_update_target( | ||
| 371 | pm_qos_array[req->pm_qos_class]->constraints, | ||
| 372 | &req->node, PM_QOS_UPDATE_REQ, new_value); | ||
| 373 | } | 379 | } |
| 374 | EXPORT_SYMBOL_GPL(pm_qos_update_request); | 380 | EXPORT_SYMBOL_GPL(pm_qos_update_request); |
| 375 | 381 | ||
diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c index b51087fb9ace..276762f3a460 100644 --- a/kernel/printk/braille.c +++ b/kernel/printk/braille.c | |||
| @@ -19,7 +19,8 @@ char *_braille_console_setup(char **str, char **brl_options) | |||
| 19 | pr_err("need port name after brl=\n"); | 19 | pr_err("need port name after brl=\n"); |
| 20 | else | 20 | else |
| 21 | *((*str)++) = 0; | 21 | *((*str)++) = 0; |
| 22 | } | 22 | } else |
| 23 | return NULL; | ||
| 23 | 24 | ||
| 24 | return *str; | 25 | return *str; |
| 25 | } | 26 | } |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4041f5747e73..a146ee327f6a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -469,7 +469,6 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) | |||
| 469 | /* Architecture-specific hardware disable .. */ | 469 | /* Architecture-specific hardware disable .. */ |
| 470 | ptrace_disable(child); | 470 | ptrace_disable(child); |
| 471 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 471 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 472 | flush_ptrace_hw_breakpoint(child); | ||
| 473 | 472 | ||
| 474 | write_lock_irq(&tasklist_lock); | 473 | write_lock_irq(&tasklist_lock); |
| 475 | /* | 474 | /* |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b7c32cb7bfeb..05c39f030314 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -933,6 +933,8 @@ static int effective_prio(struct task_struct *p) | |||
| 933 | /** | 933 | /** |
| 934 | * task_curr - is this task currently executing on a CPU? | 934 | * task_curr - is this task currently executing on a CPU? |
| 935 | * @p: the task in question. | 935 | * @p: the task in question. |
| 936 | * | ||
| 937 | * Return: 1 if the task is currently executing. 0 otherwise. | ||
| 936 | */ | 938 | */ |
| 937 | inline int task_curr(const struct task_struct *p) | 939 | inline int task_curr(const struct task_struct *p) |
| 938 | { | 940 | { |
| @@ -1482,7 +1484,7 @@ static void ttwu_queue(struct task_struct *p, int cpu) | |||
| 1482 | * the simpler "current->state = TASK_RUNNING" to mark yourself | 1484 | * the simpler "current->state = TASK_RUNNING" to mark yourself |
| 1483 | * runnable without the overhead of this. | 1485 | * runnable without the overhead of this. |
| 1484 | * | 1486 | * |
| 1485 | * Returns %true if @p was woken up, %false if it was already running | 1487 | * Return: %true if @p was woken up, %false if it was already running. |
| 1486 | * or @state didn't match @p's state. | 1488 | * or @state didn't match @p's state. |
| 1487 | */ | 1489 | */ |
| 1488 | static int | 1490 | static int |
| @@ -1491,7 +1493,13 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) | |||
| 1491 | unsigned long flags; | 1493 | unsigned long flags; |
| 1492 | int cpu, success = 0; | 1494 | int cpu, success = 0; |
| 1493 | 1495 | ||
| 1494 | smp_wmb(); | 1496 | /* |
| 1497 | * If we are going to wake up a thread waiting for CONDITION we | ||
| 1498 | * need to ensure that CONDITION=1 done by the caller can not be | ||
| 1499 | * reordered with p->state check below. This pairs with mb() in | ||
| 1500 | * set_current_state() the waiting thread does. | ||
| 1501 | */ | ||
| 1502 | smp_mb__before_spinlock(); | ||
| 1495 | raw_spin_lock_irqsave(&p->pi_lock, flags); | 1503 | raw_spin_lock_irqsave(&p->pi_lock, flags); |
| 1496 | if (!(p->state & state)) | 1504 | if (!(p->state & state)) |
| 1497 | goto out; | 1505 | goto out; |
| @@ -1577,8 +1585,9 @@ out: | |||
| 1577 | * @p: The process to be woken up. | 1585 | * @p: The process to be woken up. |
| 1578 | * | 1586 | * |
| 1579 | * Attempt to wake up the nominated process and move it to the set of runnable | 1587 | * Attempt to wake up the nominated process and move it to the set of runnable |
| 1580 | * processes. Returns 1 if the process was woken up, 0 if it was already | 1588 | * processes. |
| 1581 | * running. | 1589 | * |
| 1590 | * Return: 1 if the process was woken up, 0 if it was already running. | ||
| 1582 | * | 1591 | * |
| 1583 | * It may be assumed that this function implies a write memory barrier before | 1592 | * It may be assumed that this function implies a write memory barrier before |
| 1584 | * changing the task state if and only if any tasks are woken up. | 1593 | * changing the task state if and only if any tasks are woken up. |
| @@ -2191,6 +2200,8 @@ void scheduler_tick(void) | |||
| 2191 | * This makes sure that uptime, CFS vruntime, load | 2200 | * This makes sure that uptime, CFS vruntime, load |
| 2192 | * balancing, etc... continue to move forward, even | 2201 | * balancing, etc... continue to move forward, even |
| 2193 | * with a very low granularity. | 2202 | * with a very low granularity. |
| 2203 | * | ||
| 2204 | * Return: Maximum deferment in nanoseconds. | ||
| 2194 | */ | 2205 | */ |
| 2195 | u64 scheduler_tick_max_deferment(void) | 2206 | u64 scheduler_tick_max_deferment(void) |
| 2196 | { | 2207 | { |
| @@ -2394,6 +2405,12 @@ need_resched: | |||
| 2394 | if (sched_feat(HRTICK)) | 2405 | if (sched_feat(HRTICK)) |
| 2395 | hrtick_clear(rq); | 2406 | hrtick_clear(rq); |
| 2396 | 2407 | ||
| 2408 | /* | ||
| 2409 | * Make sure that signal_pending_state()->signal_pending() below | ||
| 2410 | * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE) | ||
| 2411 | * done by the caller to avoid the race with signal_wake_up(). | ||
| 2412 | */ | ||
| 2413 | smp_mb__before_spinlock(); | ||
| 2397 | raw_spin_lock_irq(&rq->lock); | 2414 | raw_spin_lock_irq(&rq->lock); |
| 2398 | 2415 | ||
| 2399 | switch_count = &prev->nivcsw; | 2416 | switch_count = &prev->nivcsw; |
| @@ -2796,8 +2813,8 @@ EXPORT_SYMBOL(wait_for_completion); | |||
| 2796 | * specified timeout to expire. The timeout is in jiffies. It is not | 2813 | * specified timeout to expire. The timeout is in jiffies. It is not |
| 2797 | * interruptible. | 2814 | * interruptible. |
| 2798 | * | 2815 | * |
| 2799 | * The return value is 0 if timed out, and positive (at least 1, or number of | 2816 | * Return: 0 if timed out, and positive (at least 1, or number of jiffies left |
| 2800 | * jiffies left till timeout) if completed. | 2817 | * till timeout) if completed. |
| 2801 | */ | 2818 | */ |
| 2802 | unsigned long __sched | 2819 | unsigned long __sched |
| 2803 | wait_for_completion_timeout(struct completion *x, unsigned long timeout) | 2820 | wait_for_completion_timeout(struct completion *x, unsigned long timeout) |
| @@ -2829,8 +2846,8 @@ EXPORT_SYMBOL(wait_for_completion_io); | |||
| 2829 | * specified timeout to expire. The timeout is in jiffies. It is not | 2846 | * specified timeout to expire. The timeout is in jiffies. It is not |
| 2830 | * interruptible. The caller is accounted as waiting for IO. | 2847 | * interruptible. The caller is accounted as waiting for IO. |
| 2831 | * | 2848 | * |
| 2832 | * The return value is 0 if timed out, and positive (at least 1, or number of | 2849 | * Return: 0 if timed out, and positive (at least 1, or number of jiffies left |
| 2833 | * jiffies left till timeout) if completed. | 2850 | * till timeout) if completed. |
| 2834 | */ | 2851 | */ |
| 2835 | unsigned long __sched | 2852 | unsigned long __sched |
| 2836 | wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) | 2853 | wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) |
| @@ -2846,7 +2863,7 @@ EXPORT_SYMBOL(wait_for_completion_io_timeout); | |||
| 2846 | * This waits for completion of a specific task to be signaled. It is | 2863 | * This waits for completion of a specific task to be signaled. It is |
| 2847 | * interruptible. | 2864 | * interruptible. |
| 2848 | * | 2865 | * |
| 2849 | * The return value is -ERESTARTSYS if interrupted, 0 if completed. | 2866 | * Return: -ERESTARTSYS if interrupted, 0 if completed. |
| 2850 | */ | 2867 | */ |
| 2851 | int __sched wait_for_completion_interruptible(struct completion *x) | 2868 | int __sched wait_for_completion_interruptible(struct completion *x) |
| 2852 | { | 2869 | { |
| @@ -2865,8 +2882,8 @@ EXPORT_SYMBOL(wait_for_completion_interruptible); | |||
| 2865 | * This waits for either a completion of a specific task to be signaled or for a | 2882 | * This waits for either a completion of a specific task to be signaled or for a |
| 2866 | * specified timeout to expire. It is interruptible. The timeout is in jiffies. | 2883 | * specified timeout to expire. It is interruptible. The timeout is in jiffies. |
| 2867 | * | 2884 | * |
| 2868 | * The return value is -ERESTARTSYS if interrupted, 0 if timed out, | 2885 | * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1, |
| 2869 | * positive (at least 1, or number of jiffies left till timeout) if completed. | 2886 | * or number of jiffies left till timeout) if completed. |
| 2870 | */ | 2887 | */ |
| 2871 | long __sched | 2888 | long __sched |
| 2872 | wait_for_completion_interruptible_timeout(struct completion *x, | 2889 | wait_for_completion_interruptible_timeout(struct completion *x, |
| @@ -2883,7 +2900,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); | |||
| 2883 | * This waits to be signaled for completion of a specific task. It can be | 2900 | * This waits to be signaled for completion of a specific task. It can be |
| 2884 | * interrupted by a kill signal. | 2901 | * interrupted by a kill signal. |
| 2885 | * | 2902 | * |
| 2886 | * The return value is -ERESTARTSYS if interrupted, 0 if completed. | 2903 | * Return: -ERESTARTSYS if interrupted, 0 if completed. |
| 2887 | */ | 2904 | */ |
| 2888 | int __sched wait_for_completion_killable(struct completion *x) | 2905 | int __sched wait_for_completion_killable(struct completion *x) |
| 2889 | { | 2906 | { |
| @@ -2903,8 +2920,8 @@ EXPORT_SYMBOL(wait_for_completion_killable); | |||
| 2903 | * signaled or for a specified timeout to expire. It can be | 2920 | * signaled or for a specified timeout to expire. It can be |
| 2904 | * interrupted by a kill signal. The timeout is in jiffies. | 2921 | * interrupted by a kill signal. The timeout is in jiffies. |
| 2905 | * | 2922 | * |
| 2906 | * The return value is -ERESTARTSYS if interrupted, 0 if timed out, | 2923 | * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1, |
| 2907 | * positive (at least 1, or number of jiffies left till timeout) if completed. | 2924 | * or number of jiffies left till timeout) if completed. |
| 2908 | */ | 2925 | */ |
| 2909 | long __sched | 2926 | long __sched |
| 2910 | wait_for_completion_killable_timeout(struct completion *x, | 2927 | wait_for_completion_killable_timeout(struct completion *x, |
| @@ -2918,7 +2935,7 @@ EXPORT_SYMBOL(wait_for_completion_killable_timeout); | |||
| 2918 | * try_wait_for_completion - try to decrement a completion without blocking | 2935 | * try_wait_for_completion - try to decrement a completion without blocking |
| 2919 | * @x: completion structure | 2936 | * @x: completion structure |
| 2920 | * | 2937 | * |
| 2921 | * Returns: 0 if a decrement cannot be done without blocking | 2938 | * Return: 0 if a decrement cannot be done without blocking |
| 2922 | * 1 if a decrement succeeded. | 2939 | * 1 if a decrement succeeded. |
| 2923 | * | 2940 | * |
| 2924 | * If a completion is being used as a counting completion, | 2941 | * If a completion is being used as a counting completion, |
| @@ -2945,7 +2962,7 @@ EXPORT_SYMBOL(try_wait_for_completion); | |||
| 2945 | * completion_done - Test to see if a completion has any waiters | 2962 | * completion_done - Test to see if a completion has any waiters |
| 2946 | * @x: completion structure | 2963 | * @x: completion structure |
| 2947 | * | 2964 | * |
| 2948 | * Returns: 0 if there are waiters (wait_for_completion() in progress) | 2965 | * Return: 0 if there are waiters (wait_for_completion() in progress) |
| 2949 | * 1 if there are no waiters. | 2966 | * 1 if there are no waiters. |
| 2950 | * | 2967 | * |
| 2951 | */ | 2968 | */ |
| @@ -3182,7 +3199,7 @@ SYSCALL_DEFINE1(nice, int, increment) | |||
| 3182 | * task_prio - return the priority value of a given task. | 3199 | * task_prio - return the priority value of a given task. |
| 3183 | * @p: the task in question. | 3200 | * @p: the task in question. |
| 3184 | * | 3201 | * |
| 3185 | * This is the priority value as seen by users in /proc. | 3202 | * Return: The priority value as seen by users in /proc. |
| 3186 | * RT tasks are offset by -200. Normal tasks are centered | 3203 | * RT tasks are offset by -200. Normal tasks are centered |
| 3187 | * around 0, value goes from -16 to +15. | 3204 | * around 0, value goes from -16 to +15. |
| 3188 | */ | 3205 | */ |
| @@ -3194,6 +3211,8 @@ int task_prio(const struct task_struct *p) | |||
| 3194 | /** | 3211 | /** |
| 3195 | * task_nice - return the nice value of a given task. | 3212 | * task_nice - return the nice value of a given task. |
| 3196 | * @p: the task in question. | 3213 | * @p: the task in question. |
| 3214 | * | ||
| 3215 | * Return: The nice value [ -20 ... 0 ... 19 ]. | ||
| 3197 | */ | 3216 | */ |
| 3198 | int task_nice(const struct task_struct *p) | 3217 | int task_nice(const struct task_struct *p) |
| 3199 | { | 3218 | { |
| @@ -3204,6 +3223,8 @@ EXPORT_SYMBOL(task_nice); | |||
| 3204 | /** | 3223 | /** |
| 3205 | * idle_cpu - is a given cpu idle currently? | 3224 | * idle_cpu - is a given cpu idle currently? |
| 3206 | * @cpu: the processor in question. | 3225 | * @cpu: the processor in question. |
| 3226 | * | ||
| 3227 | * Return: 1 if the CPU is currently idle. 0 otherwise. | ||
| 3207 | */ | 3228 | */ |
| 3208 | int idle_cpu(int cpu) | 3229 | int idle_cpu(int cpu) |
| 3209 | { | 3230 | { |
| @@ -3226,6 +3247,8 @@ int idle_cpu(int cpu) | |||
| 3226 | /** | 3247 | /** |
| 3227 | * idle_task - return the idle task for a given cpu. | 3248 | * idle_task - return the idle task for a given cpu. |
| 3228 | * @cpu: the processor in question. | 3249 | * @cpu: the processor in question. |
| 3250 | * | ||
| 3251 | * Return: The idle task for the cpu @cpu. | ||
| 3229 | */ | 3252 | */ |
| 3230 | struct task_struct *idle_task(int cpu) | 3253 | struct task_struct *idle_task(int cpu) |
| 3231 | { | 3254 | { |
| @@ -3235,6 +3258,8 @@ struct task_struct *idle_task(int cpu) | |||
| 3235 | /** | 3258 | /** |
| 3236 | * find_process_by_pid - find a process with a matching PID value. | 3259 | * find_process_by_pid - find a process with a matching PID value. |
| 3237 | * @pid: the pid in question. | 3260 | * @pid: the pid in question. |
| 3261 | * | ||
| 3262 | * The task of @pid, if found. %NULL otherwise. | ||
| 3238 | */ | 3263 | */ |
| 3239 | static struct task_struct *find_process_by_pid(pid_t pid) | 3264 | static struct task_struct *find_process_by_pid(pid_t pid) |
| 3240 | { | 3265 | { |
| @@ -3432,6 +3457,8 @@ recheck: | |||
| 3432 | * @policy: new policy. | 3457 | * @policy: new policy. |
| 3433 | * @param: structure containing the new RT priority. | 3458 | * @param: structure containing the new RT priority. |
| 3434 | * | 3459 | * |
| 3460 | * Return: 0 on success. An error code otherwise. | ||
| 3461 | * | ||
| 3435 | * NOTE that the task may be already dead. | 3462 | * NOTE that the task may be already dead. |
| 3436 | */ | 3463 | */ |
| 3437 | int sched_setscheduler(struct task_struct *p, int policy, | 3464 | int sched_setscheduler(struct task_struct *p, int policy, |
| @@ -3451,6 +3478,8 @@ EXPORT_SYMBOL_GPL(sched_setscheduler); | |||
| 3451 | * current context has permission. For example, this is needed in | 3478 | * current context has permission. For example, this is needed in |
| 3452 | * stop_machine(): we create temporary high priority worker threads, | 3479 | * stop_machine(): we create temporary high priority worker threads, |
| 3453 | * but our caller might not have that capability. | 3480 | * but our caller might not have that capability. |
| 3481 | * | ||
| 3482 | * Return: 0 on success. An error code otherwise. | ||
| 3454 | */ | 3483 | */ |
| 3455 | int sched_setscheduler_nocheck(struct task_struct *p, int policy, | 3484 | int sched_setscheduler_nocheck(struct task_struct *p, int policy, |
| 3456 | const struct sched_param *param) | 3485 | const struct sched_param *param) |
| @@ -3485,6 +3514,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) | |||
| 3485 | * @pid: the pid in question. | 3514 | * @pid: the pid in question. |
| 3486 | * @policy: new policy. | 3515 | * @policy: new policy. |
| 3487 | * @param: structure containing the new RT priority. | 3516 | * @param: structure containing the new RT priority. |
| 3517 | * | ||
| 3518 | * Return: 0 on success. An error code otherwise. | ||
| 3488 | */ | 3519 | */ |
| 3489 | SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, | 3520 | SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, |
| 3490 | struct sched_param __user *, param) | 3521 | struct sched_param __user *, param) |
| @@ -3500,6 +3531,8 @@ SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, | |||
| 3500 | * sys_sched_setparam - set/change the RT priority of a thread | 3531 | * sys_sched_setparam - set/change the RT priority of a thread |
| 3501 | * @pid: the pid in question. | 3532 | * @pid: the pid in question. |
| 3502 | * @param: structure containing the new RT priority. | 3533 | * @param: structure containing the new RT priority. |
| 3534 | * | ||
| 3535 | * Return: 0 on success. An error code otherwise. | ||
| 3503 | */ | 3536 | */ |
| 3504 | SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) | 3537 | SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) |
| 3505 | { | 3538 | { |
| @@ -3509,6 +3542,9 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) | |||
| 3509 | /** | 3542 | /** |
| 3510 | * sys_sched_getscheduler - get the policy (scheduling class) of a thread | 3543 | * sys_sched_getscheduler - get the policy (scheduling class) of a thread |
| 3511 | * @pid: the pid in question. | 3544 | * @pid: the pid in question. |
| 3545 | * | ||
| 3546 | * Return: On success, the policy of the thread. Otherwise, a negative error | ||
| 3547 | * code. | ||
| 3512 | */ | 3548 | */ |
| 3513 | SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) | 3549 | SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) |
| 3514 | { | 3550 | { |
| @@ -3535,6 +3571,9 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) | |||
| 3535 | * sys_sched_getparam - get the RT priority of a thread | 3571 | * sys_sched_getparam - get the RT priority of a thread |
| 3536 | * @pid: the pid in question. | 3572 | * @pid: the pid in question. |
| 3537 | * @param: structure containing the RT priority. | 3573 | * @param: structure containing the RT priority. |
| 3574 | * | ||
| 3575 | * Return: On success, 0 and the RT priority is in @param. Otherwise, an error | ||
| 3576 | * code. | ||
| 3538 | */ | 3577 | */ |
| 3539 | SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) | 3578 | SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) |
| 3540 | { | 3579 | { |
| @@ -3659,6 +3698,8 @@ static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, | |||
| 3659 | * @pid: pid of the process | 3698 | * @pid: pid of the process |
| 3660 | * @len: length in bytes of the bitmask pointed to by user_mask_ptr | 3699 | * @len: length in bytes of the bitmask pointed to by user_mask_ptr |
| 3661 | * @user_mask_ptr: user-space pointer to the new cpu mask | 3700 | * @user_mask_ptr: user-space pointer to the new cpu mask |
| 3701 | * | ||
| 3702 | * Return: 0 on success. An error code otherwise. | ||
| 3662 | */ | 3703 | */ |
| 3663 | SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, | 3704 | SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, |
| 3664 | unsigned long __user *, user_mask_ptr) | 3705 | unsigned long __user *, user_mask_ptr) |
| @@ -3710,6 +3751,8 @@ out_unlock: | |||
| 3710 | * @pid: pid of the process | 3751 | * @pid: pid of the process |
| 3711 | * @len: length in bytes of the bitmask pointed to by user_mask_ptr | 3752 | * @len: length in bytes of the bitmask pointed to by user_mask_ptr |
| 3712 | * @user_mask_ptr: user-space pointer to hold the current cpu mask | 3753 | * @user_mask_ptr: user-space pointer to hold the current cpu mask |
| 3754 | * | ||
| 3755 | * Return: 0 on success. An error code otherwise. | ||
| 3713 | */ | 3756 | */ |
| 3714 | SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, | 3757 | SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, |
| 3715 | unsigned long __user *, user_mask_ptr) | 3758 | unsigned long __user *, user_mask_ptr) |
| @@ -3744,6 +3787,8 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, | |||
| 3744 | * | 3787 | * |
| 3745 | * This function yields the current CPU to other tasks. If there are no | 3788 | * This function yields the current CPU to other tasks. If there are no |
| 3746 | * other threads running on this CPU then this function will return. | 3789 | * other threads running on this CPU then this function will return. |
| 3790 | * | ||
| 3791 | * Return: 0. | ||
| 3747 | */ | 3792 | */ |
| 3748 | SYSCALL_DEFINE0(sched_yield) | 3793 | SYSCALL_DEFINE0(sched_yield) |
| 3749 | { | 3794 | { |
| @@ -3869,7 +3914,7 @@ EXPORT_SYMBOL(yield); | |||
| 3869 | * It's the caller's job to ensure that the target task struct | 3914 | * It's the caller's job to ensure that the target task struct |
| 3870 | * can't go away on us before we can do any checks. | 3915 | * can't go away on us before we can do any checks. |
| 3871 | * | 3916 | * |
| 3872 | * Returns: | 3917 | * Return: |
| 3873 | * true (>0) if we indeed boosted the target task. | 3918 | * true (>0) if we indeed boosted the target task. |
| 3874 | * false (0) if we failed to boost the target. | 3919 | * false (0) if we failed to boost the target. |
| 3875 | * -ESRCH if there's no task to yield to. | 3920 | * -ESRCH if there's no task to yield to. |
| @@ -3972,8 +4017,9 @@ long __sched io_schedule_timeout(long timeout) | |||
| 3972 | * sys_sched_get_priority_max - return maximum RT priority. | 4017 | * sys_sched_get_priority_max - return maximum RT priority. |
| 3973 | * @policy: scheduling class. | 4018 | * @policy: scheduling class. |
| 3974 | * | 4019 | * |
| 3975 | * this syscall returns the maximum rt_priority that can be used | 4020 | * Return: On success, this syscall returns the maximum |
| 3976 | * by a given scheduling class. | 4021 | * rt_priority that can be used by a given scheduling class. |
| 4022 | * On failure, a negative error code is returned. | ||
| 3977 | */ | 4023 | */ |
| 3978 | SYSCALL_DEFINE1(sched_get_priority_max, int, policy) | 4024 | SYSCALL_DEFINE1(sched_get_priority_max, int, policy) |
| 3979 | { | 4025 | { |
| @@ -3997,8 +4043,9 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy) | |||
| 3997 | * sys_sched_get_priority_min - return minimum RT priority. | 4043 | * sys_sched_get_priority_min - return minimum RT priority. |
| 3998 | * @policy: scheduling class. | 4044 | * @policy: scheduling class. |
| 3999 | * | 4045 | * |
| 4000 | * this syscall returns the minimum rt_priority that can be used | 4046 | * Return: On success, this syscall returns the minimum |
| 4001 | * by a given scheduling class. | 4047 | * rt_priority that can be used by a given scheduling class. |
| 4048 | * On failure, a negative error code is returned. | ||
| 4002 | */ | 4049 | */ |
| 4003 | SYSCALL_DEFINE1(sched_get_priority_min, int, policy) | 4050 | SYSCALL_DEFINE1(sched_get_priority_min, int, policy) |
| 4004 | { | 4051 | { |
| @@ -4024,6 +4071,9 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) | |||
| 4024 | * | 4071 | * |
| 4025 | * this syscall writes the default timeslice value of a given process | 4072 | * this syscall writes the default timeslice value of a given process |
| 4026 | * into the user-space timespec buffer. A value of '0' means infinity. | 4073 | * into the user-space timespec buffer. A value of '0' means infinity. |
| 4074 | * | ||
| 4075 | * Return: On success, 0 and the timeslice is in @interval. Otherwise, | ||
| 4076 | * an error code. | ||
| 4027 | */ | 4077 | */ |
| 4028 | SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, | 4078 | SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, |
| 4029 | struct timespec __user *, interval) | 4079 | struct timespec __user *, interval) |
| @@ -6632,6 +6682,8 @@ void normalize_rt_tasks(void) | |||
| 6632 | * @cpu: the processor in question. | 6682 | * @cpu: the processor in question. |
| 6633 | * | 6683 | * |
| 6634 | * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! | 6684 | * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! |
| 6685 | * | ||
| 6686 | * Return: The current task for @cpu. | ||
| 6635 | */ | 6687 | */ |
| 6636 | struct task_struct *curr_task(int cpu) | 6688 | struct task_struct *curr_task(int cpu) |
| 6637 | { | 6689 | { |
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index 1095e878a46f..8b836b376d91 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c | |||
| @@ -62,7 +62,7 @@ static int convert_prio(int prio) | |||
| 62 | * any discrepancies created by racing against the uncertainty of the current | 62 | * any discrepancies created by racing against the uncertainty of the current |
| 63 | * priority configuration. | 63 | * priority configuration. |
| 64 | * | 64 | * |
| 65 | * Returns: (int)bool - CPUs were found | 65 | * Return: (int)bool - CPUs were found |
| 66 | */ | 66 | */ |
| 67 | int cpupri_find(struct cpupri *cp, struct task_struct *p, | 67 | int cpupri_find(struct cpupri *cp, struct task_struct *p, |
| 68 | struct cpumask *lowest_mask) | 68 | struct cpumask *lowest_mask) |
| @@ -203,7 +203,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri) | |||
| 203 | * cpupri_init - initialize the cpupri structure | 203 | * cpupri_init - initialize the cpupri structure |
| 204 | * @cp: The cpupri context | 204 | * @cp: The cpupri context |
| 205 | * | 205 | * |
| 206 | * Returns: -ENOMEM if memory fails. | 206 | * Return: -ENOMEM on memory allocation failure. |
| 207 | */ | 207 | */ |
| 208 | int cpupri_init(struct cpupri *cp) | 208 | int cpupri_init(struct cpupri *cp) |
| 209 | { | 209 | { |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 9565645e3202..68f1609ca149 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
| @@ -2032,6 +2032,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued) | |||
| 2032 | */ | 2032 | */ |
| 2033 | update_entity_load_avg(curr, 1); | 2033 | update_entity_load_avg(curr, 1); |
| 2034 | update_cfs_rq_blocked_load(cfs_rq, 1); | 2034 | update_cfs_rq_blocked_load(cfs_rq, 1); |
| 2035 | update_cfs_shares(cfs_rq); | ||
| 2035 | 2036 | ||
| 2036 | #ifdef CONFIG_SCHED_HRTICK | 2037 | #ifdef CONFIG_SCHED_HRTICK |
| 2037 | /* | 2038 | /* |
| @@ -4280,6 +4281,8 @@ struct sg_lb_stats { | |||
| 4280 | * get_sd_load_idx - Obtain the load index for a given sched domain. | 4281 | * get_sd_load_idx - Obtain the load index for a given sched domain. |
| 4281 | * @sd: The sched_domain whose load_idx is to be obtained. | 4282 | * @sd: The sched_domain whose load_idx is to be obtained. |
| 4282 | * @idle: The Idle status of the CPU for whose sd load_icx is obtained. | 4283 | * @idle: The Idle status of the CPU for whose sd load_icx is obtained. |
| 4284 | * | ||
| 4285 | * Return: The load index. | ||
| 4283 | */ | 4286 | */ |
| 4284 | static inline int get_sd_load_idx(struct sched_domain *sd, | 4287 | static inline int get_sd_load_idx(struct sched_domain *sd, |
| 4285 | enum cpu_idle_type idle) | 4288 | enum cpu_idle_type idle) |
| @@ -4574,6 +4577,9 @@ static inline void update_sg_lb_stats(struct lb_env *env, | |||
| 4574 | * | 4577 | * |
| 4575 | * Determine if @sg is a busier group than the previously selected | 4578 | * Determine if @sg is a busier group than the previously selected |
| 4576 | * busiest group. | 4579 | * busiest group. |
| 4580 | * | ||
| 4581 | * Return: %true if @sg is a busier group than the previously selected | ||
| 4582 | * busiest group. %false otherwise. | ||
| 4577 | */ | 4583 | */ |
| 4578 | static bool update_sd_pick_busiest(struct lb_env *env, | 4584 | static bool update_sd_pick_busiest(struct lb_env *env, |
| 4579 | struct sd_lb_stats *sds, | 4585 | struct sd_lb_stats *sds, |
| @@ -4691,7 +4697,7 @@ static inline void update_sd_lb_stats(struct lb_env *env, | |||
| 4691 | * assuming lower CPU number will be equivalent to lower a SMT thread | 4697 | * assuming lower CPU number will be equivalent to lower a SMT thread |
| 4692 | * number. | 4698 | * number. |
| 4693 | * | 4699 | * |
| 4694 | * Returns 1 when packing is required and a task should be moved to | 4700 | * Return: 1 when packing is required and a task should be moved to |
| 4695 | * this CPU. The amount of the imbalance is returned in *imbalance. | 4701 | * this CPU. The amount of the imbalance is returned in *imbalance. |
| 4696 | * | 4702 | * |
| 4697 | * @env: The load balancing environment. | 4703 | * @env: The load balancing environment. |
| @@ -4869,7 +4875,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s | |||
| 4869 | * @balance: Pointer to a variable indicating if this_cpu | 4875 | * @balance: Pointer to a variable indicating if this_cpu |
| 4870 | * is the appropriate cpu to perform load balancing at this_level. | 4876 | * is the appropriate cpu to perform load balancing at this_level. |
| 4871 | * | 4877 | * |
| 4872 | * Returns: - the busiest group if imbalance exists. | 4878 | * Return: - The busiest group if imbalance exists. |
| 4873 | * - If no imbalance and user has opted for power-savings balance, | 4879 | * - If no imbalance and user has opted for power-savings balance, |
| 4874 | * return the least loaded group whose CPUs can be | 4880 | * return the least loaded group whose CPUs can be |
| 4875 | * put to idle by rebalancing its tasks onto our group. | 4881 | * put to idle by rebalancing its tasks onto our group. |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8ce9eefc5bb4..a6d098c6df3f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -2169,12 +2169,57 @@ static cycle_t ftrace_update_time; | |||
| 2169 | static unsigned long ftrace_update_cnt; | 2169 | static unsigned long ftrace_update_cnt; |
| 2170 | unsigned long ftrace_update_tot_cnt; | 2170 | unsigned long ftrace_update_tot_cnt; |
| 2171 | 2171 | ||
| 2172 | static int ops_traces_mod(struct ftrace_ops *ops) | 2172 | static inline int ops_traces_mod(struct ftrace_ops *ops) |
| 2173 | { | 2173 | { |
| 2174 | struct ftrace_hash *hash; | 2174 | /* |
| 2175 | * Filter_hash being empty will default to trace module. | ||
| 2176 | * But notrace hash requires a test of individual module functions. | ||
| 2177 | */ | ||
| 2178 | return ftrace_hash_empty(ops->filter_hash) && | ||
| 2179 | ftrace_hash_empty(ops->notrace_hash); | ||
| 2180 | } | ||
| 2181 | |||
| 2182 | /* | ||
| 2183 | * Check if the current ops references the record. | ||
| 2184 | * | ||
| 2185 | * If the ops traces all functions, then it was already accounted for. | ||
| 2186 | * If the ops does not trace the current record function, skip it. | ||
| 2187 | * If the ops ignores the function via notrace filter, skip it. | ||
| 2188 | */ | ||
| 2189 | static inline bool | ||
| 2190 | ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec) | ||
| 2191 | { | ||
| 2192 | /* If ops isn't enabled, ignore it */ | ||
| 2193 | if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) | ||
| 2194 | return 0; | ||
| 2195 | |||
| 2196 | /* If ops traces all mods, we already accounted for it */ | ||
| 2197 | if (ops_traces_mod(ops)) | ||
| 2198 | return 0; | ||
| 2199 | |||
| 2200 | /* The function must be in the filter */ | ||
| 2201 | if (!ftrace_hash_empty(ops->filter_hash) && | ||
| 2202 | !ftrace_lookup_ip(ops->filter_hash, rec->ip)) | ||
| 2203 | return 0; | ||
| 2204 | |||
| 2205 | /* If in notrace hash, we ignore it too */ | ||
| 2206 | if (ftrace_lookup_ip(ops->notrace_hash, rec->ip)) | ||
| 2207 | return 0; | ||
| 2208 | |||
| 2209 | return 1; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | static int referenced_filters(struct dyn_ftrace *rec) | ||
| 2213 | { | ||
| 2214 | struct ftrace_ops *ops; | ||
| 2215 | int cnt = 0; | ||
| 2175 | 2216 | ||
| 2176 | hash = ops->filter_hash; | 2217 | for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) { |
| 2177 | return ftrace_hash_empty(hash); | 2218 | if (ops_references_rec(ops, rec)) |
| 2219 | cnt++; | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | return cnt; | ||
| 2178 | } | 2223 | } |
| 2179 | 2224 | ||
| 2180 | static int ftrace_update_code(struct module *mod) | 2225 | static int ftrace_update_code(struct module *mod) |
| @@ -2183,6 +2228,7 @@ static int ftrace_update_code(struct module *mod) | |||
| 2183 | struct dyn_ftrace *p; | 2228 | struct dyn_ftrace *p; |
| 2184 | cycle_t start, stop; | 2229 | cycle_t start, stop; |
| 2185 | unsigned long ref = 0; | 2230 | unsigned long ref = 0; |
| 2231 | bool test = false; | ||
| 2186 | int i; | 2232 | int i; |
| 2187 | 2233 | ||
| 2188 | /* | 2234 | /* |
| @@ -2196,9 +2242,12 @@ static int ftrace_update_code(struct module *mod) | |||
| 2196 | 2242 | ||
| 2197 | for (ops = ftrace_ops_list; | 2243 | for (ops = ftrace_ops_list; |
| 2198 | ops != &ftrace_list_end; ops = ops->next) { | 2244 | ops != &ftrace_list_end; ops = ops->next) { |
| 2199 | if (ops->flags & FTRACE_OPS_FL_ENABLED && | 2245 | if (ops->flags & FTRACE_OPS_FL_ENABLED) { |
| 2200 | ops_traces_mod(ops)) | 2246 | if (ops_traces_mod(ops)) |
| 2201 | ref++; | 2247 | ref++; |
| 2248 | else | ||
| 2249 | test = true; | ||
| 2250 | } | ||
| 2202 | } | 2251 | } |
| 2203 | } | 2252 | } |
| 2204 | 2253 | ||
| @@ -2208,12 +2257,16 @@ static int ftrace_update_code(struct module *mod) | |||
| 2208 | for (pg = ftrace_new_pgs; pg; pg = pg->next) { | 2257 | for (pg = ftrace_new_pgs; pg; pg = pg->next) { |
| 2209 | 2258 | ||
| 2210 | for (i = 0; i < pg->index; i++) { | 2259 | for (i = 0; i < pg->index; i++) { |
| 2260 | int cnt = ref; | ||
| 2261 | |||
| 2211 | /* If something went wrong, bail without enabling anything */ | 2262 | /* If something went wrong, bail without enabling anything */ |
| 2212 | if (unlikely(ftrace_disabled)) | 2263 | if (unlikely(ftrace_disabled)) |
| 2213 | return -1; | 2264 | return -1; |
| 2214 | 2265 | ||
| 2215 | p = &pg->records[i]; | 2266 | p = &pg->records[i]; |
| 2216 | p->flags = ref; | 2267 | if (test) |
| 2268 | cnt += referenced_filters(p); | ||
| 2269 | p->flags = cnt; | ||
| 2217 | 2270 | ||
| 2218 | /* | 2271 | /* |
| 2219 | * Do the initial record conversion from mcount jump | 2272 | * Do the initial record conversion from mcount jump |
| @@ -2233,7 +2286,7 @@ static int ftrace_update_code(struct module *mod) | |||
| 2233 | * conversion puts the module to the correct state, thus | 2286 | * conversion puts the module to the correct state, thus |
| 2234 | * passing the ftrace_make_call check. | 2287 | * passing the ftrace_make_call check. |
| 2235 | */ | 2288 | */ |
| 2236 | if (ftrace_start_up && ref) { | 2289 | if (ftrace_start_up && cnt) { |
| 2237 | int failed = __ftrace_replace_code(p, 1); | 2290 | int failed = __ftrace_replace_code(p, 1); |
| 2238 | if (failed) | 2291 | if (failed) |
| 2239 | ftrace_bug(failed, p->ip); | 2292 | ftrace_bug(failed, p->ip); |
| @@ -3384,6 +3437,12 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) | |||
| 3384 | return add_hash_entry(hash, ip); | 3437 | return add_hash_entry(hash, ip); |
| 3385 | } | 3438 | } |
| 3386 | 3439 | ||
| 3440 | static void ftrace_ops_update_code(struct ftrace_ops *ops) | ||
| 3441 | { | ||
| 3442 | if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled) | ||
| 3443 | ftrace_run_update_code(FTRACE_UPDATE_CALLS); | ||
| 3444 | } | ||
| 3445 | |||
| 3387 | static int | 3446 | static int |
| 3388 | ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | 3447 | ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, |
| 3389 | unsigned long ip, int remove, int reset, int enable) | 3448 | unsigned long ip, int remove, int reset, int enable) |
| @@ -3426,9 +3485,8 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3426 | 3485 | ||
| 3427 | mutex_lock(&ftrace_lock); | 3486 | mutex_lock(&ftrace_lock); |
| 3428 | ret = ftrace_hash_move(ops, enable, orig_hash, hash); | 3487 | ret = ftrace_hash_move(ops, enable, orig_hash, hash); |
| 3429 | if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED | 3488 | if (!ret) |
| 3430 | && ftrace_enabled) | 3489 | ftrace_ops_update_code(ops); |
| 3431 | ftrace_run_update_code(FTRACE_UPDATE_CALLS); | ||
| 3432 | 3490 | ||
| 3433 | mutex_unlock(&ftrace_lock); | 3491 | mutex_unlock(&ftrace_lock); |
| 3434 | 3492 | ||
| @@ -3655,9 +3713,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3655 | mutex_lock(&ftrace_lock); | 3713 | mutex_lock(&ftrace_lock); |
| 3656 | ret = ftrace_hash_move(iter->ops, filter_hash, | 3714 | ret = ftrace_hash_move(iter->ops, filter_hash, |
| 3657 | orig_hash, iter->hash); | 3715 | orig_hash, iter->hash); |
| 3658 | if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED) | 3716 | if (!ret) |
| 3659 | && ftrace_enabled) | 3717 | ftrace_ops_update_code(iter->ops); |
| 3660 | ftrace_run_update_code(FTRACE_UPDATE_CALLS); | ||
| 3661 | 3718 | ||
| 3662 | mutex_unlock(&ftrace_lock); | 3719 | mutex_unlock(&ftrace_lock); |
| 3663 | } | 3720 | } |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 882ec1dd1515..496f94d57698 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -243,20 +243,25 @@ int filter_current_check_discard(struct ring_buffer *buffer, | |||
| 243 | } | 243 | } |
| 244 | EXPORT_SYMBOL_GPL(filter_current_check_discard); | 244 | EXPORT_SYMBOL_GPL(filter_current_check_discard); |
| 245 | 245 | ||
| 246 | cycle_t ftrace_now(int cpu) | 246 | cycle_t buffer_ftrace_now(struct trace_buffer *buf, int cpu) |
| 247 | { | 247 | { |
| 248 | u64 ts; | 248 | u64 ts; |
| 249 | 249 | ||
| 250 | /* Early boot up does not have a buffer yet */ | 250 | /* Early boot up does not have a buffer yet */ |
| 251 | if (!global_trace.trace_buffer.buffer) | 251 | if (!buf->buffer) |
| 252 | return trace_clock_local(); | 252 | return trace_clock_local(); |
| 253 | 253 | ||
| 254 | ts = ring_buffer_time_stamp(global_trace.trace_buffer.buffer, cpu); | 254 | ts = ring_buffer_time_stamp(buf->buffer, cpu); |
| 255 | ring_buffer_normalize_time_stamp(global_trace.trace_buffer.buffer, cpu, &ts); | 255 | ring_buffer_normalize_time_stamp(buf->buffer, cpu, &ts); |
| 256 | 256 | ||
| 257 | return ts; | 257 | return ts; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | cycle_t ftrace_now(int cpu) | ||
| 261 | { | ||
| 262 | return buffer_ftrace_now(&global_trace.trace_buffer, cpu); | ||
| 263 | } | ||
| 264 | |||
| 260 | /** | 265 | /** |
| 261 | * tracing_is_enabled - Show if global_trace has been disabled | 266 | * tracing_is_enabled - Show if global_trace has been disabled |
| 262 | * | 267 | * |
| @@ -1211,7 +1216,7 @@ void tracing_reset_online_cpus(struct trace_buffer *buf) | |||
| 1211 | /* Make sure all commits have finished */ | 1216 | /* Make sure all commits have finished */ |
| 1212 | synchronize_sched(); | 1217 | synchronize_sched(); |
| 1213 | 1218 | ||
| 1214 | buf->time_start = ftrace_now(buf->cpu); | 1219 | buf->time_start = buffer_ftrace_now(buf, buf->cpu); |
| 1215 | 1220 | ||
| 1216 | for_each_online_cpu(cpu) | 1221 | for_each_online_cpu(cpu) |
| 1217 | ring_buffer_reset_cpu(buffer, cpu); | 1222 | ring_buffer_reset_cpu(buffer, cpu); |
| @@ -1219,11 +1224,6 @@ void tracing_reset_online_cpus(struct trace_buffer *buf) | |||
| 1219 | ring_buffer_record_enable(buffer); | 1224 | ring_buffer_record_enable(buffer); |
| 1220 | } | 1225 | } |
| 1221 | 1226 | ||
| 1222 | void tracing_reset_current(int cpu) | ||
| 1223 | { | ||
| 1224 | tracing_reset(&global_trace.trace_buffer, cpu); | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | /* Must have trace_types_lock held */ | 1227 | /* Must have trace_types_lock held */ |
| 1228 | void tracing_reset_all_online_cpus(void) | 1228 | void tracing_reset_all_online_cpus(void) |
| 1229 | { | 1229 | { |
| @@ -4151,6 +4151,7 @@ waitagain: | |||
| 4151 | memset(&iter->seq, 0, | 4151 | memset(&iter->seq, 0, |
| 4152 | sizeof(struct trace_iterator) - | 4152 | sizeof(struct trace_iterator) - |
| 4153 | offsetof(struct trace_iterator, seq)); | 4153 | offsetof(struct trace_iterator, seq)); |
| 4154 | cpumask_clear(iter->started); | ||
| 4154 | iter->pos = -1; | 4155 | iter->pos = -1; |
| 4155 | 4156 | ||
| 4156 | trace_event_read_lock(); | 4157 | trace_event_read_lock(); |
| @@ -4468,7 +4469,7 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp) | |||
| 4468 | 4469 | ||
| 4469 | /* disable tracing ? */ | 4470 | /* disable tracing ? */ |
| 4470 | if (trace_flags & TRACE_ITER_STOP_ON_FREE) | 4471 | if (trace_flags & TRACE_ITER_STOP_ON_FREE) |
| 4471 | tracing_off(); | 4472 | tracer_tracing_off(tr); |
| 4472 | /* resize the ring buffer to 0 */ | 4473 | /* resize the ring buffer to 0 */ |
| 4473 | tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS); | 4474 | tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS); |
| 4474 | 4475 | ||
| @@ -4633,12 +4634,12 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, | |||
| 4633 | * New clock may not be consistent with the previous clock. | 4634 | * New clock may not be consistent with the previous clock. |
| 4634 | * Reset the buffer so that it doesn't have incomparable timestamps. | 4635 | * Reset the buffer so that it doesn't have incomparable timestamps. |
| 4635 | */ | 4636 | */ |
| 4636 | tracing_reset_online_cpus(&global_trace.trace_buffer); | 4637 | tracing_reset_online_cpus(&tr->trace_buffer); |
| 4637 | 4638 | ||
| 4638 | #ifdef CONFIG_TRACER_MAX_TRACE | 4639 | #ifdef CONFIG_TRACER_MAX_TRACE |
| 4639 | if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer) | 4640 | if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer) |
| 4640 | ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func); | 4641 | ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func); |
| 4641 | tracing_reset_online_cpus(&global_trace.max_buffer); | 4642 | tracing_reset_online_cpus(&tr->max_buffer); |
| 4642 | #endif | 4643 | #endif |
| 4643 | 4644 | ||
| 4644 | mutex_unlock(&trace_types_lock); | 4645 | mutex_unlock(&trace_types_lock); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 898f868833f2..29a7ebcfb426 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -409,33 +409,42 @@ static void put_system(struct ftrace_subsystem_dir *dir) | |||
| 409 | mutex_unlock(&event_mutex); | 409 | mutex_unlock(&event_mutex); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | /* | 412 | static void remove_subsystem(struct ftrace_subsystem_dir *dir) |
| 413 | * Open and update trace_array ref count. | ||
| 414 | * Must have the current trace_array passed to it. | ||
| 415 | */ | ||
| 416 | static int tracing_open_generic_file(struct inode *inode, struct file *filp) | ||
| 417 | { | 413 | { |
| 418 | struct ftrace_event_file *file = inode->i_private; | 414 | if (!dir) |
| 419 | struct trace_array *tr = file->tr; | 415 | return; |
| 420 | int ret; | ||
| 421 | 416 | ||
| 422 | if (trace_array_get(tr) < 0) | 417 | if (!--dir->nr_events) { |
| 423 | return -ENODEV; | 418 | debugfs_remove_recursive(dir->entry); |
| 419 | list_del(&dir->list); | ||
| 420 | __put_system_dir(dir); | ||
| 421 | } | ||
| 422 | } | ||
| 424 | 423 | ||
| 425 | ret = tracing_open_generic(inode, filp); | 424 | static void *event_file_data(struct file *filp) |
| 426 | if (ret < 0) | 425 | { |
| 427 | trace_array_put(tr); | 426 | return ACCESS_ONCE(file_inode(filp)->i_private); |
| 428 | return ret; | ||
| 429 | } | 427 | } |
| 430 | 428 | ||
| 431 | static int tracing_release_generic_file(struct inode *inode, struct file *filp) | 429 | static void remove_event_file_dir(struct ftrace_event_file *file) |
| 432 | { | 430 | { |
| 433 | struct ftrace_event_file *file = inode->i_private; | 431 | struct dentry *dir = file->dir; |
| 434 | struct trace_array *tr = file->tr; | 432 | struct dentry *child; |
| 435 | 433 | ||
| 436 | trace_array_put(tr); | 434 | if (dir) { |
| 435 | spin_lock(&dir->d_lock); /* probably unneeded */ | ||
| 436 | list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) { | ||
| 437 | if (child->d_inode) /* probably unneeded */ | ||
| 438 | child->d_inode->i_private = NULL; | ||
| 439 | } | ||
| 440 | spin_unlock(&dir->d_lock); | ||
| 437 | 441 | ||
| 438 | return 0; | 442 | debugfs_remove_recursive(dir); |
| 443 | } | ||
| 444 | |||
| 445 | list_del(&file->list); | ||
| 446 | remove_subsystem(file->system); | ||
| 447 | kmem_cache_free(file_cachep, file); | ||
| 439 | } | 448 | } |
| 440 | 449 | ||
| 441 | /* | 450 | /* |
| @@ -679,15 +688,25 @@ static ssize_t | |||
| 679 | event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | 688 | event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, |
| 680 | loff_t *ppos) | 689 | loff_t *ppos) |
| 681 | { | 690 | { |
| 682 | struct ftrace_event_file *file = filp->private_data; | 691 | struct ftrace_event_file *file; |
| 692 | unsigned long flags; | ||
| 683 | char buf[4] = "0"; | 693 | char buf[4] = "0"; |
| 684 | 694 | ||
| 685 | if (file->flags & FTRACE_EVENT_FL_ENABLED && | 695 | mutex_lock(&event_mutex); |
| 686 | !(file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)) | 696 | file = event_file_data(filp); |
| 697 | if (likely(file)) | ||
| 698 | flags = file->flags; | ||
| 699 | mutex_unlock(&event_mutex); | ||
| 700 | |||
| 701 | if (!file) | ||
| 702 | return -ENODEV; | ||
| 703 | |||
| 704 | if (flags & FTRACE_EVENT_FL_ENABLED && | ||
| 705 | !(flags & FTRACE_EVENT_FL_SOFT_DISABLED)) | ||
| 687 | strcpy(buf, "1"); | 706 | strcpy(buf, "1"); |
| 688 | 707 | ||
| 689 | if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED || | 708 | if (flags & FTRACE_EVENT_FL_SOFT_DISABLED || |
| 690 | file->flags & FTRACE_EVENT_FL_SOFT_MODE) | 709 | flags & FTRACE_EVENT_FL_SOFT_MODE) |
| 691 | strcat(buf, "*"); | 710 | strcat(buf, "*"); |
| 692 | 711 | ||
| 693 | strcat(buf, "\n"); | 712 | strcat(buf, "\n"); |
| @@ -699,13 +718,10 @@ static ssize_t | |||
| 699 | event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | 718 | event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, |
| 700 | loff_t *ppos) | 719 | loff_t *ppos) |
| 701 | { | 720 | { |
| 702 | struct ftrace_event_file *file = filp->private_data; | 721 | struct ftrace_event_file *file; |
| 703 | unsigned long val; | 722 | unsigned long val; |
| 704 | int ret; | 723 | int ret; |
| 705 | 724 | ||
| 706 | if (!file) | ||
| 707 | return -EINVAL; | ||
| 708 | |||
| 709 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); | 725 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
| 710 | if (ret) | 726 | if (ret) |
| 711 | return ret; | 727 | return ret; |
| @@ -717,8 +733,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
| 717 | switch (val) { | 733 | switch (val) { |
| 718 | case 0: | 734 | case 0: |
| 719 | case 1: | 735 | case 1: |
| 736 | ret = -ENODEV; | ||
| 720 | mutex_lock(&event_mutex); | 737 | mutex_lock(&event_mutex); |
| 721 | ret = ftrace_event_enable_disable(file, val); | 738 | file = event_file_data(filp); |
| 739 | if (likely(file)) | ||
| 740 | ret = ftrace_event_enable_disable(file, val); | ||
| 722 | mutex_unlock(&event_mutex); | 741 | mutex_unlock(&event_mutex); |
| 723 | break; | 742 | break; |
| 724 | 743 | ||
| @@ -825,7 +844,7 @@ enum { | |||
| 825 | 844 | ||
| 826 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) | 845 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) |
| 827 | { | 846 | { |
| 828 | struct ftrace_event_call *call = m->private; | 847 | struct ftrace_event_call *call = event_file_data(m->private); |
| 829 | struct list_head *common_head = &ftrace_common_fields; | 848 | struct list_head *common_head = &ftrace_common_fields; |
| 830 | struct list_head *head = trace_get_fields(call); | 849 | struct list_head *head = trace_get_fields(call); |
| 831 | struct list_head *node = v; | 850 | struct list_head *node = v; |
| @@ -857,7 +876,7 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 857 | 876 | ||
| 858 | static int f_show(struct seq_file *m, void *v) | 877 | static int f_show(struct seq_file *m, void *v) |
| 859 | { | 878 | { |
| 860 | struct ftrace_event_call *call = m->private; | 879 | struct ftrace_event_call *call = event_file_data(m->private); |
| 861 | struct ftrace_event_field *field; | 880 | struct ftrace_event_field *field; |
| 862 | const char *array_descriptor; | 881 | const char *array_descriptor; |
| 863 | 882 | ||
| @@ -910,6 +929,11 @@ static void *f_start(struct seq_file *m, loff_t *pos) | |||
| 910 | void *p = (void *)FORMAT_HEADER; | 929 | void *p = (void *)FORMAT_HEADER; |
| 911 | loff_t l = 0; | 930 | loff_t l = 0; |
| 912 | 931 | ||
| 932 | /* ->stop() is called even if ->start() fails */ | ||
| 933 | mutex_lock(&event_mutex); | ||
| 934 | if (!event_file_data(m->private)) | ||
| 935 | return ERR_PTR(-ENODEV); | ||
| 936 | |||
| 913 | while (l < *pos && p) | 937 | while (l < *pos && p) |
| 914 | p = f_next(m, p, &l); | 938 | p = f_next(m, p, &l); |
| 915 | 939 | ||
| @@ -918,6 +942,7 @@ static void *f_start(struct seq_file *m, loff_t *pos) | |||
| 918 | 942 | ||
| 919 | static void f_stop(struct seq_file *m, void *p) | 943 | static void f_stop(struct seq_file *m, void *p) |
| 920 | { | 944 | { |
| 945 | mutex_unlock(&event_mutex); | ||
| 921 | } | 946 | } |
| 922 | 947 | ||
| 923 | static const struct seq_operations trace_format_seq_ops = { | 948 | static const struct seq_operations trace_format_seq_ops = { |
| @@ -929,7 +954,6 @@ static const struct seq_operations trace_format_seq_ops = { | |||
| 929 | 954 | ||
| 930 | static int trace_format_open(struct inode *inode, struct file *file) | 955 | static int trace_format_open(struct inode *inode, struct file *file) |
| 931 | { | 956 | { |
| 932 | struct ftrace_event_call *call = inode->i_private; | ||
| 933 | struct seq_file *m; | 957 | struct seq_file *m; |
| 934 | int ret; | 958 | int ret; |
| 935 | 959 | ||
| @@ -938,7 +962,7 @@ static int trace_format_open(struct inode *inode, struct file *file) | |||
| 938 | return ret; | 962 | return ret; |
| 939 | 963 | ||
| 940 | m = file->private_data; | 964 | m = file->private_data; |
| 941 | m->private = call; | 965 | m->private = file; |
| 942 | 966 | ||
| 943 | return 0; | 967 | return 0; |
| 944 | } | 968 | } |
| @@ -946,14 +970,18 @@ static int trace_format_open(struct inode *inode, struct file *file) | |||
| 946 | static ssize_t | 970 | static ssize_t |
| 947 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) | 971 | event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) |
| 948 | { | 972 | { |
| 949 | struct ftrace_event_call *call = filp->private_data; | 973 | int id = (long)event_file_data(filp); |
| 950 | char buf[32]; | 974 | char buf[32]; |
| 951 | int len; | 975 | int len; |
| 952 | 976 | ||
| 953 | if (*ppos) | 977 | if (*ppos) |
| 954 | return 0; | 978 | return 0; |
| 955 | 979 | ||
| 956 | len = sprintf(buf, "%d\n", call->event.type); | 980 | if (unlikely(!id)) |
| 981 | return -ENODEV; | ||
| 982 | |||
| 983 | len = sprintf(buf, "%d\n", id); | ||
| 984 | |||
| 957 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); | 985 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); |
| 958 | } | 986 | } |
| 959 | 987 | ||
| @@ -961,21 +989,28 @@ static ssize_t | |||
| 961 | event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, | 989 | event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, |
| 962 | loff_t *ppos) | 990 | loff_t *ppos) |
| 963 | { | 991 | { |
| 964 | struct ftrace_event_call *call = filp->private_data; | 992 | struct ftrace_event_call *call; |
| 965 | struct trace_seq *s; | 993 | struct trace_seq *s; |
| 966 | int r; | 994 | int r = -ENODEV; |
| 967 | 995 | ||
| 968 | if (*ppos) | 996 | if (*ppos) |
| 969 | return 0; | 997 | return 0; |
| 970 | 998 | ||
| 971 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 999 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
| 1000 | |||
| 972 | if (!s) | 1001 | if (!s) |
| 973 | return -ENOMEM; | 1002 | return -ENOMEM; |
| 974 | 1003 | ||
| 975 | trace_seq_init(s); | 1004 | trace_seq_init(s); |
| 976 | 1005 | ||
| 977 | print_event_filter(call, s); | 1006 | mutex_lock(&event_mutex); |
| 978 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); | 1007 | call = event_file_data(filp); |
| 1008 | if (call) | ||
| 1009 | print_event_filter(call, s); | ||
| 1010 | mutex_unlock(&event_mutex); | ||
| 1011 | |||
| 1012 | if (call) | ||
| 1013 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); | ||
| 979 | 1014 | ||
| 980 | kfree(s); | 1015 | kfree(s); |
| 981 | 1016 | ||
| @@ -986,9 +1021,9 @@ static ssize_t | |||
| 986 | event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | 1021 | event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, |
| 987 | loff_t *ppos) | 1022 | loff_t *ppos) |
| 988 | { | 1023 | { |
| 989 | struct ftrace_event_call *call = filp->private_data; | 1024 | struct ftrace_event_call *call; |
| 990 | char *buf; | 1025 | char *buf; |
| 991 | int err; | 1026 | int err = -ENODEV; |
| 992 | 1027 | ||
| 993 | if (cnt >= PAGE_SIZE) | 1028 | if (cnt >= PAGE_SIZE) |
| 994 | return -EINVAL; | 1029 | return -EINVAL; |
| @@ -1003,7 +1038,12 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
| 1003 | } | 1038 | } |
| 1004 | buf[cnt] = '\0'; | 1039 | buf[cnt] = '\0'; |
| 1005 | 1040 | ||
| 1006 | err = apply_event_filter(call, buf); | 1041 | mutex_lock(&event_mutex); |
| 1042 | call = event_file_data(filp); | ||
| 1043 | if (call) | ||
| 1044 | err = apply_event_filter(call, buf); | ||
| 1045 | mutex_unlock(&event_mutex); | ||
| 1046 | |||
| 1007 | free_page((unsigned long) buf); | 1047 | free_page((unsigned long) buf); |
| 1008 | if (err < 0) | 1048 | if (err < 0) |
| 1009 | return err; | 1049 | return err; |
| @@ -1225,10 +1265,9 @@ static const struct file_operations ftrace_set_event_fops = { | |||
| 1225 | }; | 1265 | }; |
| 1226 | 1266 | ||
| 1227 | static const struct file_operations ftrace_enable_fops = { | 1267 | static const struct file_operations ftrace_enable_fops = { |
| 1228 | .open = tracing_open_generic_file, | 1268 | .open = tracing_open_generic, |
| 1229 | .read = event_enable_read, | 1269 | .read = event_enable_read, |
| 1230 | .write = event_enable_write, | 1270 | .write = event_enable_write, |
| 1231 | .release = tracing_release_generic_file, | ||
| 1232 | .llseek = default_llseek, | 1271 | .llseek = default_llseek, |
| 1233 | }; | 1272 | }; |
| 1234 | 1273 | ||
| @@ -1240,7 +1279,6 @@ static const struct file_operations ftrace_event_format_fops = { | |||
| 1240 | }; | 1279 | }; |
| 1241 | 1280 | ||
| 1242 | static const struct file_operations ftrace_event_id_fops = { | 1281 | static const struct file_operations ftrace_event_id_fops = { |
| 1243 | .open = tracing_open_generic, | ||
| 1244 | .read = event_id_read, | 1282 | .read = event_id_read, |
| 1245 | .llseek = default_llseek, | 1283 | .llseek = default_llseek, |
| 1246 | }; | 1284 | }; |
| @@ -1488,8 +1526,8 @@ event_create_dir(struct dentry *parent, | |||
| 1488 | 1526 | ||
| 1489 | #ifdef CONFIG_PERF_EVENTS | 1527 | #ifdef CONFIG_PERF_EVENTS |
| 1490 | if (call->event.type && call->class->reg) | 1528 | if (call->event.type && call->class->reg) |
| 1491 | trace_create_file("id", 0444, file->dir, call, | 1529 | trace_create_file("id", 0444, file->dir, |
| 1492 | id); | 1530 | (void *)(long)call->event.type, id); |
| 1493 | #endif | 1531 | #endif |
| 1494 | 1532 | ||
| 1495 | /* | 1533 | /* |
| @@ -1514,33 +1552,16 @@ event_create_dir(struct dentry *parent, | |||
| 1514 | return 0; | 1552 | return 0; |
| 1515 | } | 1553 | } |
| 1516 | 1554 | ||
| 1517 | static void remove_subsystem(struct ftrace_subsystem_dir *dir) | ||
| 1518 | { | ||
| 1519 | if (!dir) | ||
| 1520 | return; | ||
| 1521 | |||
| 1522 | if (!--dir->nr_events) { | ||
| 1523 | debugfs_remove_recursive(dir->entry); | ||
| 1524 | list_del(&dir->list); | ||
| 1525 | __put_system_dir(dir); | ||
| 1526 | } | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | static void remove_event_from_tracers(struct ftrace_event_call *call) | 1555 | static void remove_event_from_tracers(struct ftrace_event_call *call) |
| 1530 | { | 1556 | { |
| 1531 | struct ftrace_event_file *file; | 1557 | struct ftrace_event_file *file; |
| 1532 | struct trace_array *tr; | 1558 | struct trace_array *tr; |
| 1533 | 1559 | ||
| 1534 | do_for_each_event_file_safe(tr, file) { | 1560 | do_for_each_event_file_safe(tr, file) { |
| 1535 | |||
| 1536 | if (file->event_call != call) | 1561 | if (file->event_call != call) |
| 1537 | continue; | 1562 | continue; |
| 1538 | 1563 | ||
| 1539 | list_del(&file->list); | 1564 | remove_event_file_dir(file); |
| 1540 | debugfs_remove_recursive(file->dir); | ||
| 1541 | remove_subsystem(file->system); | ||
| 1542 | kmem_cache_free(file_cachep, file); | ||
| 1543 | |||
| 1544 | /* | 1565 | /* |
| 1545 | * The do_for_each_event_file_safe() is | 1566 | * The do_for_each_event_file_safe() is |
| 1546 | * a double loop. After finding the call for this | 1567 | * a double loop. After finding the call for this |
| @@ -1692,16 +1713,53 @@ static void __trace_remove_event_call(struct ftrace_event_call *call) | |||
| 1692 | destroy_preds(call); | 1713 | destroy_preds(call); |
| 1693 | } | 1714 | } |
| 1694 | 1715 | ||
| 1716 | static int probe_remove_event_call(struct ftrace_event_call *call) | ||
| 1717 | { | ||
| 1718 | struct trace_array *tr; | ||
| 1719 | struct ftrace_event_file *file; | ||
| 1720 | |||
| 1721 | #ifdef CONFIG_PERF_EVENTS | ||
| 1722 | if (call->perf_refcount) | ||
| 1723 | return -EBUSY; | ||
| 1724 | #endif | ||
| 1725 | do_for_each_event_file(tr, file) { | ||
| 1726 | if (file->event_call != call) | ||
| 1727 | continue; | ||
| 1728 | /* | ||
| 1729 | * We can't rely on ftrace_event_enable_disable(enable => 0) | ||
| 1730 | * we are going to do, FTRACE_EVENT_FL_SOFT_MODE can suppress | ||
| 1731 | * TRACE_REG_UNREGISTER. | ||
| 1732 | */ | ||
| 1733 | if (file->flags & FTRACE_EVENT_FL_ENABLED) | ||
| 1734 | return -EBUSY; | ||
| 1735 | /* | ||
| 1736 | * The do_for_each_event_file_safe() is | ||
| 1737 | * a double loop. After finding the call for this | ||
| 1738 | * trace_array, we use break to jump to the next | ||
| 1739 | * trace_array. | ||
| 1740 | */ | ||
| 1741 | break; | ||
| 1742 | } while_for_each_event_file(); | ||
| 1743 | |||
| 1744 | __trace_remove_event_call(call); | ||
| 1745 | |||
| 1746 | return 0; | ||
| 1747 | } | ||
| 1748 | |||
| 1695 | /* Remove an event_call */ | 1749 | /* Remove an event_call */ |
| 1696 | void trace_remove_event_call(struct ftrace_event_call *call) | 1750 | int trace_remove_event_call(struct ftrace_event_call *call) |
| 1697 | { | 1751 | { |
| 1752 | int ret; | ||
| 1753 | |||
| 1698 | mutex_lock(&trace_types_lock); | 1754 | mutex_lock(&trace_types_lock); |
| 1699 | mutex_lock(&event_mutex); | 1755 | mutex_lock(&event_mutex); |
| 1700 | down_write(&trace_event_sem); | 1756 | down_write(&trace_event_sem); |
| 1701 | __trace_remove_event_call(call); | 1757 | ret = probe_remove_event_call(call); |
| 1702 | up_write(&trace_event_sem); | 1758 | up_write(&trace_event_sem); |
| 1703 | mutex_unlock(&event_mutex); | 1759 | mutex_unlock(&event_mutex); |
| 1704 | mutex_unlock(&trace_types_lock); | 1760 | mutex_unlock(&trace_types_lock); |
| 1761 | |||
| 1762 | return ret; | ||
| 1705 | } | 1763 | } |
| 1706 | 1764 | ||
| 1707 | #define for_each_event(event, start, end) \ | 1765 | #define for_each_event(event, start, end) \ |
| @@ -2270,12 +2328,8 @@ __trace_remove_event_dirs(struct trace_array *tr) | |||
| 2270 | { | 2328 | { |
| 2271 | struct ftrace_event_file *file, *next; | 2329 | struct ftrace_event_file *file, *next; |
| 2272 | 2330 | ||
| 2273 | list_for_each_entry_safe(file, next, &tr->events, list) { | 2331 | list_for_each_entry_safe(file, next, &tr->events, list) |
| 2274 | list_del(&file->list); | 2332 | remove_event_file_dir(file); |
| 2275 | debugfs_remove_recursive(file->dir); | ||
| 2276 | remove_subsystem(file->system); | ||
| 2277 | kmem_cache_free(file_cachep, file); | ||
| 2278 | } | ||
| 2279 | } | 2333 | } |
| 2280 | 2334 | ||
| 2281 | static void | 2335 | static void |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 0c7b75a8acc8..97daa8cf958d 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
| @@ -637,17 +637,15 @@ static void append_filter_err(struct filter_parse_state *ps, | |||
| 637 | free_page((unsigned long) buf); | 637 | free_page((unsigned long) buf); |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | /* caller must hold event_mutex */ | ||
| 640 | void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) | 641 | void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) |
| 641 | { | 642 | { |
| 642 | struct event_filter *filter; | 643 | struct event_filter *filter = call->filter; |
| 643 | 644 | ||
| 644 | mutex_lock(&event_mutex); | ||
| 645 | filter = call->filter; | ||
| 646 | if (filter && filter->filter_string) | 645 | if (filter && filter->filter_string) |
| 647 | trace_seq_printf(s, "%s\n", filter->filter_string); | 646 | trace_seq_printf(s, "%s\n", filter->filter_string); |
| 648 | else | 647 | else |
| 649 | trace_seq_puts(s, "none\n"); | 648 | trace_seq_puts(s, "none\n"); |
| 650 | mutex_unlock(&event_mutex); | ||
| 651 | } | 649 | } |
| 652 | 650 | ||
| 653 | void print_subsystem_event_filter(struct event_subsystem *system, | 651 | void print_subsystem_event_filter(struct event_subsystem *system, |
| @@ -1841,23 +1839,22 @@ static int create_system_filter(struct event_subsystem *system, | |||
| 1841 | return err; | 1839 | return err; |
| 1842 | } | 1840 | } |
| 1843 | 1841 | ||
| 1842 | /* caller must hold event_mutex */ | ||
| 1844 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | 1843 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) |
| 1845 | { | 1844 | { |
| 1846 | struct event_filter *filter; | 1845 | struct event_filter *filter; |
| 1847 | int err = 0; | 1846 | int err; |
| 1848 | |||
| 1849 | mutex_lock(&event_mutex); | ||
| 1850 | 1847 | ||
| 1851 | if (!strcmp(strstrip(filter_string), "0")) { | 1848 | if (!strcmp(strstrip(filter_string), "0")) { |
| 1852 | filter_disable(call); | 1849 | filter_disable(call); |
| 1853 | filter = call->filter; | 1850 | filter = call->filter; |
| 1854 | if (!filter) | 1851 | if (!filter) |
| 1855 | goto out_unlock; | 1852 | return 0; |
| 1856 | RCU_INIT_POINTER(call->filter, NULL); | 1853 | RCU_INIT_POINTER(call->filter, NULL); |
| 1857 | /* Make sure the filter is not being used */ | 1854 | /* Make sure the filter is not being used */ |
| 1858 | synchronize_sched(); | 1855 | synchronize_sched(); |
| 1859 | __free_filter(filter); | 1856 | __free_filter(filter); |
| 1860 | goto out_unlock; | 1857 | return 0; |
| 1861 | } | 1858 | } |
| 1862 | 1859 | ||
| 1863 | err = create_filter(call, filter_string, true, &filter); | 1860 | err = create_filter(call, filter_string, true, &filter); |
| @@ -1884,8 +1881,6 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | |||
| 1884 | __free_filter(tmp); | 1881 | __free_filter(tmp); |
| 1885 | } | 1882 | } |
| 1886 | } | 1883 | } |
| 1887 | out_unlock: | ||
| 1888 | mutex_unlock(&event_mutex); | ||
| 1889 | 1884 | ||
| 1890 | return err; | 1885 | return err; |
| 1891 | } | 1886 | } |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3811487e7a7a..243f6834d026 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -95,7 +95,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp) | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static int register_probe_event(struct trace_probe *tp); | 97 | static int register_probe_event(struct trace_probe *tp); |
| 98 | static void unregister_probe_event(struct trace_probe *tp); | 98 | static int unregister_probe_event(struct trace_probe *tp); |
| 99 | 99 | ||
| 100 | static DEFINE_MUTEX(probe_lock); | 100 | static DEFINE_MUTEX(probe_lock); |
| 101 | static LIST_HEAD(probe_list); | 101 | static LIST_HEAD(probe_list); |
| @@ -351,9 +351,12 @@ static int unregister_trace_probe(struct trace_probe *tp) | |||
| 351 | if (trace_probe_is_enabled(tp)) | 351 | if (trace_probe_is_enabled(tp)) |
| 352 | return -EBUSY; | 352 | return -EBUSY; |
| 353 | 353 | ||
| 354 | /* Will fail if probe is being used by ftrace or perf */ | ||
| 355 | if (unregister_probe_event(tp)) | ||
| 356 | return -EBUSY; | ||
| 357 | |||
| 354 | __unregister_trace_probe(tp); | 358 | __unregister_trace_probe(tp); |
| 355 | list_del(&tp->list); | 359 | list_del(&tp->list); |
| 356 | unregister_probe_event(tp); | ||
| 357 | 360 | ||
| 358 | return 0; | 361 | return 0; |
| 359 | } | 362 | } |
| @@ -632,7 +635,9 @@ static int release_all_trace_probes(void) | |||
| 632 | /* TODO: Use batch unregistration */ | 635 | /* TODO: Use batch unregistration */ |
| 633 | while (!list_empty(&probe_list)) { | 636 | while (!list_empty(&probe_list)) { |
| 634 | tp = list_entry(probe_list.next, struct trace_probe, list); | 637 | tp = list_entry(probe_list.next, struct trace_probe, list); |
| 635 | unregister_trace_probe(tp); | 638 | ret = unregister_trace_probe(tp); |
| 639 | if (ret) | ||
| 640 | goto end; | ||
| 636 | free_trace_probe(tp); | 641 | free_trace_probe(tp); |
| 637 | } | 642 | } |
| 638 | 643 | ||
| @@ -1247,11 +1252,15 @@ static int register_probe_event(struct trace_probe *tp) | |||
| 1247 | return ret; | 1252 | return ret; |
| 1248 | } | 1253 | } |
| 1249 | 1254 | ||
| 1250 | static void unregister_probe_event(struct trace_probe *tp) | 1255 | static int unregister_probe_event(struct trace_probe *tp) |
| 1251 | { | 1256 | { |
| 1257 | int ret; | ||
| 1258 | |||
| 1252 | /* tp->event is unregistered in trace_remove_event_call() */ | 1259 | /* tp->event is unregistered in trace_remove_event_call() */ |
| 1253 | trace_remove_event_call(&tp->call); | 1260 | ret = trace_remove_event_call(&tp->call); |
| 1254 | kfree(tp->call.print_fmt); | 1261 | if (!ret) |
| 1262 | kfree(tp->call.print_fmt); | ||
| 1263 | return ret; | ||
| 1255 | } | 1264 | } |
| 1256 | 1265 | ||
| 1257 | /* Make a debugfs interface for controlling probe points */ | 1266 | /* Make a debugfs interface for controlling probe points */ |
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index a23d2d71188e..272261b5f94f 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
| @@ -70,7 +70,7 @@ struct trace_uprobe { | |||
| 70 | (sizeof(struct probe_arg) * (n))) | 70 | (sizeof(struct probe_arg) * (n))) |
| 71 | 71 | ||
| 72 | static int register_uprobe_event(struct trace_uprobe *tu); | 72 | static int register_uprobe_event(struct trace_uprobe *tu); |
| 73 | static void unregister_uprobe_event(struct trace_uprobe *tu); | 73 | static int unregister_uprobe_event(struct trace_uprobe *tu); |
| 74 | 74 | ||
| 75 | static DEFINE_MUTEX(uprobe_lock); | 75 | static DEFINE_MUTEX(uprobe_lock); |
| 76 | static LIST_HEAD(uprobe_list); | 76 | static LIST_HEAD(uprobe_list); |
| @@ -164,11 +164,17 @@ static struct trace_uprobe *find_probe_event(const char *event, const char *grou | |||
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ | 166 | /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ |
| 167 | static void unregister_trace_uprobe(struct trace_uprobe *tu) | 167 | static int unregister_trace_uprobe(struct trace_uprobe *tu) |
| 168 | { | 168 | { |
| 169 | int ret; | ||
| 170 | |||
| 171 | ret = unregister_uprobe_event(tu); | ||
| 172 | if (ret) | ||
| 173 | return ret; | ||
| 174 | |||
| 169 | list_del(&tu->list); | 175 | list_del(&tu->list); |
| 170 | unregister_uprobe_event(tu); | ||
| 171 | free_trace_uprobe(tu); | 176 | free_trace_uprobe(tu); |
| 177 | return 0; | ||
| 172 | } | 178 | } |
| 173 | 179 | ||
| 174 | /* Register a trace_uprobe and probe_event */ | 180 | /* Register a trace_uprobe and probe_event */ |
| @@ -181,9 +187,12 @@ static int register_trace_uprobe(struct trace_uprobe *tu) | |||
| 181 | 187 | ||
| 182 | /* register as an event */ | 188 | /* register as an event */ |
| 183 | old_tp = find_probe_event(tu->call.name, tu->call.class->system); | 189 | old_tp = find_probe_event(tu->call.name, tu->call.class->system); |
| 184 | if (old_tp) | 190 | if (old_tp) { |
| 185 | /* delete old event */ | 191 | /* delete old event */ |
| 186 | unregister_trace_uprobe(old_tp); | 192 | ret = unregister_trace_uprobe(old_tp); |
| 193 | if (ret) | ||
| 194 | goto end; | ||
| 195 | } | ||
| 187 | 196 | ||
| 188 | ret = register_uprobe_event(tu); | 197 | ret = register_uprobe_event(tu); |
| 189 | if (ret) { | 198 | if (ret) { |
| @@ -256,6 +265,8 @@ static int create_trace_uprobe(int argc, char **argv) | |||
| 256 | group = UPROBE_EVENT_SYSTEM; | 265 | group = UPROBE_EVENT_SYSTEM; |
| 257 | 266 | ||
| 258 | if (is_delete) { | 267 | if (is_delete) { |
| 268 | int ret; | ||
| 269 | |||
| 259 | if (!event) { | 270 | if (!event) { |
| 260 | pr_info("Delete command needs an event name.\n"); | 271 | pr_info("Delete command needs an event name.\n"); |
| 261 | return -EINVAL; | 272 | return -EINVAL; |
| @@ -269,9 +280,9 @@ static int create_trace_uprobe(int argc, char **argv) | |||
| 269 | return -ENOENT; | 280 | return -ENOENT; |
| 270 | } | 281 | } |
| 271 | /* delete an event */ | 282 | /* delete an event */ |
| 272 | unregister_trace_uprobe(tu); | 283 | ret = unregister_trace_uprobe(tu); |
| 273 | mutex_unlock(&uprobe_lock); | 284 | mutex_unlock(&uprobe_lock); |
| 274 | return 0; | 285 | return ret; |
| 275 | } | 286 | } |
| 276 | 287 | ||
| 277 | if (argc < 2) { | 288 | if (argc < 2) { |
| @@ -408,16 +419,20 @@ fail_address_parse: | |||
| 408 | return ret; | 419 | return ret; |
| 409 | } | 420 | } |
| 410 | 421 | ||
| 411 | static void cleanup_all_probes(void) | 422 | static int cleanup_all_probes(void) |
| 412 | { | 423 | { |
| 413 | struct trace_uprobe *tu; | 424 | struct trace_uprobe *tu; |
| 425 | int ret = 0; | ||
| 414 | 426 | ||
| 415 | mutex_lock(&uprobe_lock); | 427 | mutex_lock(&uprobe_lock); |
| 416 | while (!list_empty(&uprobe_list)) { | 428 | while (!list_empty(&uprobe_list)) { |
| 417 | tu = list_entry(uprobe_list.next, struct trace_uprobe, list); | 429 | tu = list_entry(uprobe_list.next, struct trace_uprobe, list); |
| 418 | unregister_trace_uprobe(tu); | 430 | ret = unregister_trace_uprobe(tu); |
| 431 | if (ret) | ||
| 432 | break; | ||
| 419 | } | 433 | } |
| 420 | mutex_unlock(&uprobe_lock); | 434 | mutex_unlock(&uprobe_lock); |
| 435 | return ret; | ||
| 421 | } | 436 | } |
| 422 | 437 | ||
| 423 | /* Probes listing interfaces */ | 438 | /* Probes listing interfaces */ |
| @@ -462,8 +477,13 @@ static const struct seq_operations probes_seq_op = { | |||
| 462 | 477 | ||
| 463 | static int probes_open(struct inode *inode, struct file *file) | 478 | static int probes_open(struct inode *inode, struct file *file) |
| 464 | { | 479 | { |
| 465 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) | 480 | int ret; |
| 466 | cleanup_all_probes(); | 481 | |
| 482 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { | ||
| 483 | ret = cleanup_all_probes(); | ||
| 484 | if (ret) | ||
| 485 | return ret; | ||
| 486 | } | ||
| 467 | 487 | ||
| 468 | return seq_open(file, &probes_seq_op); | 488 | return seq_open(file, &probes_seq_op); |
| 469 | } | 489 | } |
| @@ -968,12 +988,17 @@ static int register_uprobe_event(struct trace_uprobe *tu) | |||
| 968 | return ret; | 988 | return ret; |
| 969 | } | 989 | } |
| 970 | 990 | ||
| 971 | static void unregister_uprobe_event(struct trace_uprobe *tu) | 991 | static int unregister_uprobe_event(struct trace_uprobe *tu) |
| 972 | { | 992 | { |
| 993 | int ret; | ||
| 994 | |||
| 973 | /* tu->event is unregistered in trace_remove_event_call() */ | 995 | /* tu->event is unregistered in trace_remove_event_call() */ |
| 974 | trace_remove_event_call(&tu->call); | 996 | ret = trace_remove_event_call(&tu->call); |
| 997 | if (ret) | ||
| 998 | return ret; | ||
| 975 | kfree(tu->call.print_fmt); | 999 | kfree(tu->call.print_fmt); |
| 976 | tu->call.print_fmt = NULL; | 1000 | tu->call.print_fmt = NULL; |
| 1001 | return 0; | ||
| 977 | } | 1002 | } |
| 978 | 1003 | ||
| 979 | /* Make a trace interface for controling probe points */ | 1004 | /* Make a trace interface for controling probe points */ |
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index d8c30db06c5b..9064b919a406 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
| @@ -62,6 +62,9 @@ int create_user_ns(struct cred *new) | |||
| 62 | kgid_t group = new->egid; | 62 | kgid_t group = new->egid; |
| 63 | int ret; | 63 | int ret; |
| 64 | 64 | ||
| 65 | if (parent_ns->level > 32) | ||
| 66 | return -EUSERS; | ||
| 67 | |||
| 65 | /* | 68 | /* |
| 66 | * Verify that we can not violate the policy of which files | 69 | * Verify that we can not violate the policy of which files |
| 67 | * may be accessed that is specified by the root directory, | 70 | * may be accessed that is specified by the root directory, |
| @@ -92,6 +95,7 @@ int create_user_ns(struct cred *new) | |||
| 92 | atomic_set(&ns->count, 1); | 95 | atomic_set(&ns->count, 1); |
| 93 | /* Leave the new->user_ns reference with the new user namespace. */ | 96 | /* Leave the new->user_ns reference with the new user namespace. */ |
| 94 | ns->parent = parent_ns; | 97 | ns->parent = parent_ns; |
| 98 | ns->level = parent_ns->level + 1; | ||
| 95 | ns->owner = owner; | 99 | ns->owner = owner; |
| 96 | ns->group = group; | 100 | ns->group = group; |
| 97 | 101 | ||
| @@ -105,16 +109,21 @@ int create_user_ns(struct cred *new) | |||
| 105 | int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) | 109 | int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) |
| 106 | { | 110 | { |
| 107 | struct cred *cred; | 111 | struct cred *cred; |
| 112 | int err = -ENOMEM; | ||
| 108 | 113 | ||
| 109 | if (!(unshare_flags & CLONE_NEWUSER)) | 114 | if (!(unshare_flags & CLONE_NEWUSER)) |
| 110 | return 0; | 115 | return 0; |
| 111 | 116 | ||
| 112 | cred = prepare_creds(); | 117 | cred = prepare_creds(); |
| 113 | if (!cred) | 118 | if (cred) { |
| 114 | return -ENOMEM; | 119 | err = create_user_ns(cred); |
| 120 | if (err) | ||
| 121 | put_cred(cred); | ||
| 122 | else | ||
| 123 | *new_cred = cred; | ||
| 124 | } | ||
| 115 | 125 | ||
| 116 | *new_cred = cred; | 126 | return err; |
| 117 | return create_user_ns(cred); | ||
| 118 | } | 127 | } |
| 119 | 128 | ||
| 120 | void free_user_ns(struct user_namespace *ns) | 129 | void free_user_ns(struct user_namespace *ns) |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 0b72e816b8d0..7f5d4be22034 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -2817,6 +2817,19 @@ already_gone: | |||
| 2817 | return false; | 2817 | return false; |
| 2818 | } | 2818 | } |
| 2819 | 2819 | ||
| 2820 | static bool __flush_work(struct work_struct *work) | ||
| 2821 | { | ||
| 2822 | struct wq_barrier barr; | ||
| 2823 | |||
| 2824 | if (start_flush_work(work, &barr)) { | ||
| 2825 | wait_for_completion(&barr.done); | ||
| 2826 | destroy_work_on_stack(&barr.work); | ||
| 2827 | return true; | ||
| 2828 | } else { | ||
| 2829 | return false; | ||
| 2830 | } | ||
| 2831 | } | ||
| 2832 | |||
| 2820 | /** | 2833 | /** |
| 2821 | * flush_work - wait for a work to finish executing the last queueing instance | 2834 | * flush_work - wait for a work to finish executing the last queueing instance |
| 2822 | * @work: the work to flush | 2835 | * @work: the work to flush |
| @@ -2830,18 +2843,10 @@ already_gone: | |||
| 2830 | */ | 2843 | */ |
| 2831 | bool flush_work(struct work_struct *work) | 2844 | bool flush_work(struct work_struct *work) |
| 2832 | { | 2845 | { |
| 2833 | struct wq_barrier barr; | ||
| 2834 | |||
| 2835 | lock_map_acquire(&work->lockdep_map); | 2846 | lock_map_acquire(&work->lockdep_map); |
| 2836 | lock_map_release(&work->lockdep_map); | 2847 | lock_map_release(&work->lockdep_map); |
| 2837 | 2848 | ||
| 2838 | if (start_flush_work(work, &barr)) { | 2849 | return __flush_work(work); |
| 2839 | wait_for_completion(&barr.done); | ||
| 2840 | destroy_work_on_stack(&barr.work); | ||
| 2841 | return true; | ||
| 2842 | } else { | ||
| 2843 | return false; | ||
| 2844 | } | ||
| 2845 | } | 2850 | } |
| 2846 | EXPORT_SYMBOL_GPL(flush_work); | 2851 | EXPORT_SYMBOL_GPL(flush_work); |
| 2847 | 2852 | ||
| @@ -3411,6 +3416,12 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to, | |||
| 3411 | { | 3416 | { |
| 3412 | to->nice = from->nice; | 3417 | to->nice = from->nice; |
| 3413 | cpumask_copy(to->cpumask, from->cpumask); | 3418 | cpumask_copy(to->cpumask, from->cpumask); |
| 3419 | /* | ||
| 3420 | * Unlike hash and equality test, this function doesn't ignore | ||
| 3421 | * ->no_numa as it is used for both pool and wq attrs. Instead, | ||
| 3422 | * get_unbound_pool() explicitly clears ->no_numa after copying. | ||
| 3423 | */ | ||
| 3424 | to->no_numa = from->no_numa; | ||
| 3414 | } | 3425 | } |
| 3415 | 3426 | ||
| 3416 | /* hash value of the content of @attr */ | 3427 | /* hash value of the content of @attr */ |
| @@ -3578,6 +3589,12 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs) | |||
| 3578 | lockdep_set_subclass(&pool->lock, 1); /* see put_pwq() */ | 3589 | lockdep_set_subclass(&pool->lock, 1); /* see put_pwq() */ |
| 3579 | copy_workqueue_attrs(pool->attrs, attrs); | 3590 | copy_workqueue_attrs(pool->attrs, attrs); |
| 3580 | 3591 | ||
| 3592 | /* | ||
| 3593 | * no_numa isn't a worker_pool attribute, always clear it. See | ||
| 3594 | * 'struct workqueue_attrs' comments for detail. | ||
| 3595 | */ | ||
| 3596 | pool->attrs->no_numa = false; | ||
| 3597 | |||
| 3581 | /* if cpumask is contained inside a NUMA node, we belong to that node */ | 3598 | /* if cpumask is contained inside a NUMA node, we belong to that node */ |
| 3582 | if (wq_numa_enabled) { | 3599 | if (wq_numa_enabled) { |
| 3583 | for_each_node(node) { | 3600 | for_each_node(node) { |
| @@ -4756,7 +4773,14 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg) | |||
| 4756 | 4773 | ||
| 4757 | INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); | 4774 | INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); |
| 4758 | schedule_work_on(cpu, &wfc.work); | 4775 | schedule_work_on(cpu, &wfc.work); |
| 4759 | flush_work(&wfc.work); | 4776 | |
| 4777 | /* | ||
| 4778 | * The work item is on-stack and can't lead to deadlock through | ||
| 4779 | * flushing. Use __flush_work() to avoid spurious lockdep warnings | ||
| 4780 | * when work_on_cpu()s are nested. | ||
| 4781 | */ | ||
| 4782 | __flush_work(&wfc.work); | ||
| 4783 | |||
| 4760 | return wfc.ret; | 4784 | return wfc.ret; |
| 4761 | } | 4785 | } |
| 4762 | EXPORT_SYMBOL_GPL(work_on_cpu); | 4786 | EXPORT_SYMBOL_GPL(work_on_cpu); |
diff --git a/mm/fremap.c b/mm/fremap.c index 87da3590c61e..5bff08147768 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
| @@ -57,17 +57,22 @@ static int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 57 | unsigned long addr, unsigned long pgoff, pgprot_t prot) | 57 | unsigned long addr, unsigned long pgoff, pgprot_t prot) |
| 58 | { | 58 | { |
| 59 | int err = -ENOMEM; | 59 | int err = -ENOMEM; |
| 60 | pte_t *pte; | 60 | pte_t *pte, ptfile; |
| 61 | spinlock_t *ptl; | 61 | spinlock_t *ptl; |
| 62 | 62 | ||
| 63 | pte = get_locked_pte(mm, addr, &ptl); | 63 | pte = get_locked_pte(mm, addr, &ptl); |
| 64 | if (!pte) | 64 | if (!pte) |
| 65 | goto out; | 65 | goto out; |
| 66 | 66 | ||
| 67 | if (!pte_none(*pte)) | 67 | ptfile = pgoff_to_pte(pgoff); |
| 68 | |||
| 69 | if (!pte_none(*pte)) { | ||
| 70 | if (pte_present(*pte) && pte_soft_dirty(*pte)) | ||
| 71 | pte_file_mksoft_dirty(ptfile); | ||
| 68 | zap_pte(mm, vma, addr, pte); | 72 | zap_pte(mm, vma, addr, pte); |
| 73 | } | ||
| 69 | 74 | ||
| 70 | set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff)); | 75 | set_pte_at(mm, addr, pte, ptfile); |
| 71 | /* | 76 | /* |
| 72 | * We don't need to run update_mmu_cache() here because the "file pte" | 77 | * We don't need to run update_mmu_cache() here because the "file pte" |
| 73 | * being installed by install_file_pte() is not a real pte - it's a | 78 | * being installed by install_file_pte() is not a real pte - it's a |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 83aff0a4d093..b60f33080a28 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -2490,7 +2490,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, | |||
| 2490 | 2490 | ||
| 2491 | mm = vma->vm_mm; | 2491 | mm = vma->vm_mm; |
| 2492 | 2492 | ||
| 2493 | tlb_gather_mmu(&tlb, mm, 0); | 2493 | tlb_gather_mmu(&tlb, mm, start, end); |
| 2494 | __unmap_hugepage_range(&tlb, vma, start, end, ref_page); | 2494 | __unmap_hugepage_range(&tlb, vma, start, end, ref_page); |
| 2495 | tlb_finish_mmu(&tlb, start, end); | 2495 | tlb_finish_mmu(&tlb, start, end); |
| 2496 | } | 2496 | } |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c290a1cf3862..c5792a5d87ce 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -3195,11 +3195,11 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s, | |||
| 3195 | if (!s->memcg_params) | 3195 | if (!s->memcg_params) |
| 3196 | return -ENOMEM; | 3196 | return -ENOMEM; |
| 3197 | 3197 | ||
| 3198 | INIT_WORK(&s->memcg_params->destroy, | ||
| 3199 | kmem_cache_destroy_work_func); | ||
| 3200 | if (memcg) { | 3198 | if (memcg) { |
| 3201 | s->memcg_params->memcg = memcg; | 3199 | s->memcg_params->memcg = memcg; |
| 3202 | s->memcg_params->root_cache = root_cache; | 3200 | s->memcg_params->root_cache = root_cache; |
| 3201 | INIT_WORK(&s->memcg_params->destroy, | ||
| 3202 | kmem_cache_destroy_work_func); | ||
| 3203 | } else | 3203 | } else |
| 3204 | s->memcg_params->is_root_cache = true; | 3204 | s->memcg_params->is_root_cache = true; |
| 3205 | 3205 | ||
diff --git a/mm/memory.c b/mm/memory.c index 1ce2e2a734fc..af84bc0ec17c 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -209,14 +209,15 @@ static int tlb_next_batch(struct mmu_gather *tlb) | |||
| 209 | * tear-down from @mm. The @fullmm argument is used when @mm is without | 209 | * tear-down from @mm. The @fullmm argument is used when @mm is without |
| 210 | * users and we're going to destroy the full address space (exit/execve). | 210 | * users and we're going to destroy the full address space (exit/execve). |
| 211 | */ | 211 | */ |
| 212 | void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) | 212 | void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) |
| 213 | { | 213 | { |
| 214 | tlb->mm = mm; | 214 | tlb->mm = mm; |
| 215 | 215 | ||
| 216 | tlb->fullmm = fullmm; | 216 | /* Is it from 0 to ~0? */ |
| 217 | tlb->fullmm = !(start | (end+1)); | ||
| 217 | tlb->need_flush_all = 0; | 218 | tlb->need_flush_all = 0; |
| 218 | tlb->start = -1UL; | 219 | tlb->start = start; |
| 219 | tlb->end = 0; | 220 | tlb->end = end; |
| 220 | tlb->need_flush = 0; | 221 | tlb->need_flush = 0; |
| 221 | tlb->local.next = NULL; | 222 | tlb->local.next = NULL; |
| 222 | tlb->local.nr = 0; | 223 | tlb->local.nr = 0; |
| @@ -256,8 +257,6 @@ void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long e | |||
| 256 | { | 257 | { |
| 257 | struct mmu_gather_batch *batch, *next; | 258 | struct mmu_gather_batch *batch, *next; |
| 258 | 259 | ||
| 259 | tlb->start = start; | ||
| 260 | tlb->end = end; | ||
| 261 | tlb_flush_mmu(tlb); | 260 | tlb_flush_mmu(tlb); |
| 262 | 261 | ||
| 263 | /* keep the page table cache within bounds */ | 262 | /* keep the page table cache within bounds */ |
| @@ -1099,7 +1098,6 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, | |||
| 1099 | spinlock_t *ptl; | 1098 | spinlock_t *ptl; |
| 1100 | pte_t *start_pte; | 1099 | pte_t *start_pte; |
| 1101 | pte_t *pte; | 1100 | pte_t *pte; |
| 1102 | unsigned long range_start = addr; | ||
| 1103 | 1101 | ||
| 1104 | again: | 1102 | again: |
| 1105 | init_rss_vec(rss); | 1103 | init_rss_vec(rss); |
| @@ -1141,9 +1139,12 @@ again: | |||
| 1141 | continue; | 1139 | continue; |
| 1142 | if (unlikely(details) && details->nonlinear_vma | 1140 | if (unlikely(details) && details->nonlinear_vma |
| 1143 | && linear_page_index(details->nonlinear_vma, | 1141 | && linear_page_index(details->nonlinear_vma, |
| 1144 | addr) != page->index) | 1142 | addr) != page->index) { |
| 1145 | set_pte_at(mm, addr, pte, | 1143 | pte_t ptfile = pgoff_to_pte(page->index); |
| 1146 | pgoff_to_pte(page->index)); | 1144 | if (pte_soft_dirty(ptent)) |
| 1145 | pte_file_mksoft_dirty(ptfile); | ||
| 1146 | set_pte_at(mm, addr, pte, ptfile); | ||
| 1147 | } | ||
| 1147 | if (PageAnon(page)) | 1148 | if (PageAnon(page)) |
| 1148 | rss[MM_ANONPAGES]--; | 1149 | rss[MM_ANONPAGES]--; |
| 1149 | else { | 1150 | else { |
| @@ -1202,17 +1203,25 @@ again: | |||
| 1202 | * and page-free while holding it. | 1203 | * and page-free while holding it. |
| 1203 | */ | 1204 | */ |
| 1204 | if (force_flush) { | 1205 | if (force_flush) { |
| 1206 | unsigned long old_end; | ||
| 1207 | |||
| 1205 | force_flush = 0; | 1208 | force_flush = 0; |
| 1206 | 1209 | ||
| 1207 | #ifdef HAVE_GENERIC_MMU_GATHER | 1210 | /* |
| 1208 | tlb->start = range_start; | 1211 | * Flush the TLB just for the previous segment, |
| 1212 | * then update the range to be the remaining | ||
| 1213 | * TLB range. | ||
| 1214 | */ | ||
| 1215 | old_end = tlb->end; | ||
| 1209 | tlb->end = addr; | 1216 | tlb->end = addr; |
| 1210 | #endif | 1217 | |
| 1211 | tlb_flush_mmu(tlb); | 1218 | tlb_flush_mmu(tlb); |
| 1212 | if (addr != end) { | 1219 | |
| 1213 | range_start = addr; | 1220 | tlb->start = addr; |
| 1221 | tlb->end = old_end; | ||
| 1222 | |||
| 1223 | if (addr != end) | ||
| 1214 | goto again; | 1224 | goto again; |
| 1215 | } | ||
| 1216 | } | 1225 | } |
| 1217 | 1226 | ||
| 1218 | return addr; | 1227 | return addr; |
| @@ -1397,7 +1406,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start, | |||
| 1397 | unsigned long end = start + size; | 1406 | unsigned long end = start + size; |
| 1398 | 1407 | ||
| 1399 | lru_add_drain(); | 1408 | lru_add_drain(); |
| 1400 | tlb_gather_mmu(&tlb, mm, 0); | 1409 | tlb_gather_mmu(&tlb, mm, start, end); |
| 1401 | update_hiwater_rss(mm); | 1410 | update_hiwater_rss(mm); |
| 1402 | mmu_notifier_invalidate_range_start(mm, start, end); | 1411 | mmu_notifier_invalidate_range_start(mm, start, end); |
| 1403 | for ( ; vma && vma->vm_start < end; vma = vma->vm_next) | 1412 | for ( ; vma && vma->vm_start < end; vma = vma->vm_next) |
| @@ -1423,7 +1432,7 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr | |||
| 1423 | unsigned long end = address + size; | 1432 | unsigned long end = address + size; |
| 1424 | 1433 | ||
| 1425 | lru_add_drain(); | 1434 | lru_add_drain(); |
| 1426 | tlb_gather_mmu(&tlb, mm, 0); | 1435 | tlb_gather_mmu(&tlb, mm, address, end); |
| 1427 | update_hiwater_rss(mm); | 1436 | update_hiwater_rss(mm); |
| 1428 | mmu_notifier_invalidate_range_start(mm, address, end); | 1437 | mmu_notifier_invalidate_range_start(mm, address, end); |
| 1429 | unmap_single_vma(&tlb, vma, address, end, details); | 1438 | unmap_single_vma(&tlb, vma, address, end, details); |
| @@ -3115,6 +3124,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3115 | exclusive = 1; | 3124 | exclusive = 1; |
| 3116 | } | 3125 | } |
| 3117 | flush_icache_page(vma, page); | 3126 | flush_icache_page(vma, page); |
| 3127 | if (pte_swp_soft_dirty(orig_pte)) | ||
| 3128 | pte = pte_mksoft_dirty(pte); | ||
| 3118 | set_pte_at(mm, address, page_table, pte); | 3129 | set_pte_at(mm, address, page_table, pte); |
| 3119 | if (page == swapcache) | 3130 | if (page == swapcache) |
| 3120 | do_page_add_anon_rmap(page, vma, address, exclusive); | 3131 | do_page_add_anon_rmap(page, vma, address, exclusive); |
| @@ -3408,6 +3419,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3408 | entry = mk_pte(page, vma->vm_page_prot); | 3419 | entry = mk_pte(page, vma->vm_page_prot); |
| 3409 | if (flags & FAULT_FLAG_WRITE) | 3420 | if (flags & FAULT_FLAG_WRITE) |
| 3410 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 3421 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
| 3422 | else if (pte_file(orig_pte) && pte_file_soft_dirty(orig_pte)) | ||
| 3423 | pte_mksoft_dirty(entry); | ||
| 3411 | if (anon) { | 3424 | if (anon) { |
| 3412 | inc_mm_counter_fast(mm, MM_ANONPAGES); | 3425 | inc_mm_counter_fast(mm, MM_ANONPAGES); |
| 3413 | page_add_new_anon_rmap(page, vma, address); | 3426 | page_add_new_anon_rmap(page, vma, address); |
| @@ -2336,7 +2336,7 @@ static void unmap_region(struct mm_struct *mm, | |||
| 2336 | struct mmu_gather tlb; | 2336 | struct mmu_gather tlb; |
| 2337 | 2337 | ||
| 2338 | lru_add_drain(); | 2338 | lru_add_drain(); |
| 2339 | tlb_gather_mmu(&tlb, mm, 0); | 2339 | tlb_gather_mmu(&tlb, mm, start, end); |
| 2340 | update_hiwater_rss(mm); | 2340 | update_hiwater_rss(mm); |
| 2341 | unmap_vmas(&tlb, vma, start, end); | 2341 | unmap_vmas(&tlb, vma, start, end); |
| 2342 | free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, | 2342 | free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, |
| @@ -2709,7 +2709,7 @@ void exit_mmap(struct mm_struct *mm) | |||
| 2709 | 2709 | ||
| 2710 | lru_add_drain(); | 2710 | lru_add_drain(); |
| 2711 | flush_cache_mm(mm); | 2711 | flush_cache_mm(mm); |
| 2712 | tlb_gather_mmu(&tlb, mm, 1); | 2712 | tlb_gather_mmu(&tlb, mm, 0, -1); |
| 2713 | /* update_hiwater_rss(mm) here? but nobody should be looking */ | 2713 | /* update_hiwater_rss(mm) here? but nobody should be looking */ |
| 2714 | /* Use -1 here to ensure all VMAs in the mm are unmapped */ | 2714 | /* Use -1 here to ensure all VMAs in the mm are unmapped */ |
| 2715 | unmap_vmas(&tlb, vma, 0, -1); | 2715 | unmap_vmas(&tlb, vma, 0, -1); |
| @@ -1236,6 +1236,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 1236 | swp_entry_to_pte(make_hwpoison_entry(page))); | 1236 | swp_entry_to_pte(make_hwpoison_entry(page))); |
| 1237 | } else if (PageAnon(page)) { | 1237 | } else if (PageAnon(page)) { |
| 1238 | swp_entry_t entry = { .val = page_private(page) }; | 1238 | swp_entry_t entry = { .val = page_private(page) }; |
| 1239 | pte_t swp_pte; | ||
| 1239 | 1240 | ||
| 1240 | if (PageSwapCache(page)) { | 1241 | if (PageSwapCache(page)) { |
| 1241 | /* | 1242 | /* |
| @@ -1264,7 +1265,10 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 1264 | BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION); | 1265 | BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION); |
| 1265 | entry = make_migration_entry(page, pte_write(pteval)); | 1266 | entry = make_migration_entry(page, pte_write(pteval)); |
| 1266 | } | 1267 | } |
| 1267 | set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); | 1268 | swp_pte = swp_entry_to_pte(entry); |
| 1269 | if (pte_soft_dirty(pteval)) | ||
| 1270 | swp_pte = pte_swp_mksoft_dirty(swp_pte); | ||
| 1271 | set_pte_at(mm, address, pte, swp_pte); | ||
| 1268 | BUG_ON(pte_file(*pte)); | 1272 | BUG_ON(pte_file(*pte)); |
| 1269 | } else if (IS_ENABLED(CONFIG_MIGRATION) && | 1273 | } else if (IS_ENABLED(CONFIG_MIGRATION) && |
| 1270 | (TTU_ACTION(flags) == TTU_MIGRATION)) { | 1274 | (TTU_ACTION(flags) == TTU_MIGRATION)) { |
| @@ -1401,8 +1405,12 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
| 1401 | pteval = ptep_clear_flush(vma, address, pte); | 1405 | pteval = ptep_clear_flush(vma, address, pte); |
| 1402 | 1406 | ||
| 1403 | /* If nonlinear, store the file page offset in the pte. */ | 1407 | /* If nonlinear, store the file page offset in the pte. */ |
| 1404 | if (page->index != linear_page_index(vma, address)) | 1408 | if (page->index != linear_page_index(vma, address)) { |
| 1405 | set_pte_at(mm, address, pte, pgoff_to_pte(page->index)); | 1409 | pte_t ptfile = pgoff_to_pte(page->index); |
| 1410 | if (pte_soft_dirty(pteval)) | ||
| 1411 | pte_file_mksoft_dirty(ptfile); | ||
| 1412 | set_pte_at(mm, address, pte, ptfile); | ||
| 1413 | } | ||
| 1406 | 1414 | ||
| 1407 | /* Move the dirty bit to the physical page now the pte is gone. */ | 1415 | /* Move the dirty bit to the physical page now the pte is gone. */ |
| 1408 | if (pte_dirty(pteval)) | 1416 | if (pte_dirty(pteval)) |
| @@ -1968,9 +1968,6 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) | |||
| 1968 | int pages; | 1968 | int pages; |
| 1969 | int pobjects; | 1969 | int pobjects; |
| 1970 | 1970 | ||
| 1971 | if (!s->cpu_partial) | ||
| 1972 | return; | ||
| 1973 | |||
| 1974 | do { | 1971 | do { |
| 1975 | pages = 0; | 1972 | pages = 0; |
| 1976 | pobjects = 0; | 1973 | pobjects = 0; |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 36af6eeaa67e..6cf2e60983b7 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
| @@ -866,6 +866,21 @@ unsigned int count_swap_pages(int type, int free) | |||
| 866 | } | 866 | } |
| 867 | #endif /* CONFIG_HIBERNATION */ | 867 | #endif /* CONFIG_HIBERNATION */ |
| 868 | 868 | ||
| 869 | static inline int maybe_same_pte(pte_t pte, pte_t swp_pte) | ||
| 870 | { | ||
| 871 | #ifdef CONFIG_MEM_SOFT_DIRTY | ||
| 872 | /* | ||
| 873 | * When pte keeps soft dirty bit the pte generated | ||
| 874 | * from swap entry does not has it, still it's same | ||
| 875 | * pte from logical point of view. | ||
| 876 | */ | ||
| 877 | pte_t swp_pte_dirty = pte_swp_mksoft_dirty(swp_pte); | ||
| 878 | return pte_same(pte, swp_pte) || pte_same(pte, swp_pte_dirty); | ||
| 879 | #else | ||
| 880 | return pte_same(pte, swp_pte); | ||
| 881 | #endif | ||
| 882 | } | ||
| 883 | |||
| 869 | /* | 884 | /* |
| 870 | * No need to decide whether this PTE shares the swap entry with others, | 885 | * No need to decide whether this PTE shares the swap entry with others, |
| 871 | * just let do_wp_page work it out if a write is requested later - to | 886 | * just let do_wp_page work it out if a write is requested later - to |
| @@ -892,7 +907,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, | |||
| 892 | } | 907 | } |
| 893 | 908 | ||
| 894 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | 909 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
| 895 | if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) { | 910 | if (unlikely(!maybe_same_pte(*pte, swp_entry_to_pte(entry)))) { |
| 896 | mem_cgroup_cancel_charge_swapin(memcg); | 911 | mem_cgroup_cancel_charge_swapin(memcg); |
| 897 | ret = 0; | 912 | ret = 0; |
| 898 | goto out; | 913 | goto out; |
| @@ -947,7 +962,7 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | |||
| 947 | * swapoff spends a _lot_ of time in this loop! | 962 | * swapoff spends a _lot_ of time in this loop! |
| 948 | * Test inline before going to call unuse_pte. | 963 | * Test inline before going to call unuse_pte. |
| 949 | */ | 964 | */ |
| 950 | if (unlikely(pte_same(*pte, swp_pte))) { | 965 | if (unlikely(maybe_same_pte(*pte, swp_pte))) { |
| 951 | pte_unmap(pte); | 966 | pte_unmap(pte); |
| 952 | ret = unuse_pte(vma, pmd, addr, entry, page); | 967 | ret = unuse_pte(vma, pmd, addr, entry, page); |
| 953 | if (ret) | 968 | if (ret) |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 4a78c4de9f20..6ee48aac776f 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
| @@ -91,7 +91,12 @@ EXPORT_SYMBOL(__vlan_find_dev_deep); | |||
| 91 | 91 | ||
| 92 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) | 92 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) |
| 93 | { | 93 | { |
| 94 | return vlan_dev_priv(dev)->real_dev; | 94 | struct net_device *ret = vlan_dev_priv(dev)->real_dev; |
| 95 | |||
| 96 | while (is_vlan_dev(ret)) | ||
| 97 | ret = vlan_dev_priv(ret)->real_dev; | ||
| 98 | |||
| 99 | return ret; | ||
| 95 | } | 100 | } |
| 96 | EXPORT_SYMBOL(vlan_dev_real_dev); | 101 | EXPORT_SYMBOL(vlan_dev_real_dev); |
| 97 | 102 | ||
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index e14531f1ce1c..264de88db320 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
| @@ -1529,6 +1529,8 @@ out: | |||
| 1529 | * in these cases, the skb is further handled by this function and | 1529 | * in these cases, the skb is further handled by this function and |
| 1530 | * returns 1, otherwise it returns 0 and the caller shall further | 1530 | * returns 1, otherwise it returns 0 and the caller shall further |
| 1531 | * process the skb. | 1531 | * process the skb. |
| 1532 | * | ||
| 1533 | * This call might reallocate skb data. | ||
| 1532 | */ | 1534 | */ |
| 1533 | int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, | 1535 | int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, |
| 1534 | unsigned short vid) | 1536 | unsigned short vid) |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index f105219f4a4b..7614af31daff 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -508,6 +508,7 @@ out: | |||
| 508 | return 0; | 508 | return 0; |
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | /* this call might reallocate skb data */ | ||
| 511 | static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) | 512 | static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) |
| 512 | { | 513 | { |
| 513 | int ret = false; | 514 | int ret = false; |
| @@ -568,6 +569,7 @@ out: | |||
| 568 | return ret; | 569 | return ret; |
| 569 | } | 570 | } |
| 570 | 571 | ||
| 572 | /* this call might reallocate skb data */ | ||
| 571 | bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) | 573 | bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) |
| 572 | { | 574 | { |
| 573 | struct ethhdr *ethhdr; | 575 | struct ethhdr *ethhdr; |
| @@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) | |||
| 619 | 621 | ||
| 620 | if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) | 622 | if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) |
| 621 | return false; | 623 | return false; |
| 624 | |||
| 625 | /* skb->data might have been reallocated by pskb_may_pull() */ | ||
| 626 | ethhdr = (struct ethhdr *)skb->data; | ||
| 627 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | ||
| 628 | ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); | ||
| 629 | |||
| 622 | udphdr = (struct udphdr *)(skb->data + *header_len); | 630 | udphdr = (struct udphdr *)(skb->data + *header_len); |
| 623 | *header_len += sizeof(*udphdr); | 631 | *header_len += sizeof(*udphdr); |
| 624 | 632 | ||
| @@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) | |||
| 634 | return true; | 642 | return true; |
| 635 | } | 643 | } |
| 636 | 644 | ||
| 645 | /* this call might reallocate skb data */ | ||
| 637 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | 646 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, |
| 638 | struct sk_buff *skb, struct ethhdr *ethhdr) | 647 | struct sk_buff *skb) |
| 639 | { | 648 | { |
| 640 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; | 649 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; |
| 641 | struct batadv_orig_node *orig_dst_node = NULL; | 650 | struct batadv_orig_node *orig_dst_node = NULL; |
| 642 | struct batadv_gw_node *curr_gw = NULL; | 651 | struct batadv_gw_node *curr_gw = NULL; |
| 652 | struct ethhdr *ethhdr; | ||
| 643 | bool ret, out_of_range = false; | 653 | bool ret, out_of_range = false; |
| 644 | unsigned int header_len = 0; | 654 | unsigned int header_len = 0; |
| 645 | uint8_t curr_tq_avg; | 655 | uint8_t curr_tq_avg; |
| @@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 648 | if (!ret) | 658 | if (!ret) |
| 649 | goto out; | 659 | goto out; |
| 650 | 660 | ||
| 661 | ethhdr = (struct ethhdr *)skb->data; | ||
| 651 | orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, | 662 | orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, |
| 652 | ethhdr->h_dest); | 663 | ethhdr->h_dest); |
| 653 | if (!orig_dst_node) | 664 | if (!orig_dst_node) |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 039902dca4a6..1037d75da51f 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
| @@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv, | |||
| 34 | void batadv_gw_node_purge(struct batadv_priv *bat_priv); | 34 | void batadv_gw_node_purge(struct batadv_priv *bat_priv); |
| 35 | int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset); | 35 | int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset); |
| 36 | bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); | 36 | bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); |
| 37 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | 37 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb); |
| 38 | struct sk_buff *skb, struct ethhdr *ethhdr); | ||
| 39 | 38 | ||
| 40 | #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ | 39 | #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 700d0b49742d..0f04e1c302b4 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
| @@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 180 | if (batadv_bla_tx(bat_priv, skb, vid)) | 180 | if (batadv_bla_tx(bat_priv, skb, vid)) |
| 181 | goto dropped; | 181 | goto dropped; |
| 182 | 182 | ||
| 183 | /* skb->data might have been reallocated by batadv_bla_tx() */ | ||
| 184 | ethhdr = (struct ethhdr *)skb->data; | ||
| 185 | |||
| 183 | /* Register the client MAC in the transtable */ | 186 | /* Register the client MAC in the transtable */ |
| 184 | if (!is_multicast_ether_addr(ethhdr->h_source)) | 187 | if (!is_multicast_ether_addr(ethhdr->h_source)) |
| 185 | batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); | 188 | batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); |
| @@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 220 | default: | 223 | default: |
| 221 | break; | 224 | break; |
| 222 | } | 225 | } |
| 226 | |||
| 227 | /* reminder: ethhdr might have become unusable from here on | ||
| 228 | * (batadv_gw_is_dhcp_target() might have reallocated skb data) | ||
| 229 | */ | ||
| 223 | } | 230 | } |
| 224 | 231 | ||
| 225 | /* ethernet packet should be broadcasted */ | 232 | /* ethernet packet should be broadcasted */ |
| @@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 266 | /* unicast packet */ | 273 | /* unicast packet */ |
| 267 | } else { | 274 | } else { |
| 268 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) { | 275 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) { |
| 269 | ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr); | 276 | ret = batadv_gw_out_of_range(bat_priv, skb); |
| 270 | if (ret) | 277 | if (ret) |
| 271 | goto dropped; | 278 | goto dropped; |
| 272 | } | 279 | } |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index dc8b5d4dd636..688a0419756b 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
| @@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size, | |||
| 326 | * @skb: the skb containing the payload to encapsulate | 326 | * @skb: the skb containing the payload to encapsulate |
| 327 | * @orig_node: the destination node | 327 | * @orig_node: the destination node |
| 328 | * | 328 | * |
| 329 | * Returns false if the payload could not be encapsulated or true otherwise | 329 | * Returns false if the payload could not be encapsulated or true otherwise. |
| 330 | * | ||
| 331 | * This call might reallocate skb data. | ||
| 330 | */ | 332 | */ |
| 331 | static bool batadv_unicast_prepare_skb(struct sk_buff *skb, | 333 | static bool batadv_unicast_prepare_skb(struct sk_buff *skb, |
| 332 | struct batadv_orig_node *orig_node) | 334 | struct batadv_orig_node *orig_node) |
| @@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb, | |||
| 343 | * @orig_node: the destination node | 345 | * @orig_node: the destination node |
| 344 | * @packet_subtype: the batman 4addr packet subtype to use | 346 | * @packet_subtype: the batman 4addr packet subtype to use |
| 345 | * | 347 | * |
| 346 | * Returns false if the payload could not be encapsulated or true otherwise | 348 | * Returns false if the payload could not be encapsulated or true otherwise. |
| 349 | * | ||
| 350 | * This call might reallocate skb data. | ||
| 347 | */ | 351 | */ |
| 348 | bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv, | 352 | bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv, |
| 349 | struct sk_buff *skb, | 353 | struct sk_buff *skb, |
| @@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, | |||
| 401 | struct batadv_neigh_node *neigh_node; | 405 | struct batadv_neigh_node *neigh_node; |
| 402 | int data_len = skb->len; | 406 | int data_len = skb->len; |
| 403 | int ret = NET_RX_DROP; | 407 | int ret = NET_RX_DROP; |
| 404 | unsigned int dev_mtu; | 408 | unsigned int dev_mtu, header_len; |
| 405 | 409 | ||
| 406 | /* get routing information */ | 410 | /* get routing information */ |
| 407 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 411 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
| @@ -429,10 +433,12 @@ find_router: | |||
| 429 | switch (packet_type) { | 433 | switch (packet_type) { |
| 430 | case BATADV_UNICAST: | 434 | case BATADV_UNICAST: |
| 431 | batadv_unicast_prepare_skb(skb, orig_node); | 435 | batadv_unicast_prepare_skb(skb, orig_node); |
| 436 | header_len = sizeof(struct batadv_unicast_packet); | ||
| 432 | break; | 437 | break; |
| 433 | case BATADV_UNICAST_4ADDR: | 438 | case BATADV_UNICAST_4ADDR: |
| 434 | batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node, | 439 | batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node, |
| 435 | packet_subtype); | 440 | packet_subtype); |
| 441 | header_len = sizeof(struct batadv_unicast_4addr_packet); | ||
| 436 | break; | 442 | break; |
| 437 | default: | 443 | default: |
| 438 | /* this function supports UNICAST and UNICAST_4ADDR only. It | 444 | /* this function supports UNICAST and UNICAST_4ADDR only. It |
| @@ -441,6 +447,7 @@ find_router: | |||
| 441 | goto out; | 447 | goto out; |
| 442 | } | 448 | } |
| 443 | 449 | ||
| 450 | ethhdr = (struct ethhdr *)(skb->data + header_len); | ||
| 444 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 451 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
| 445 | 452 | ||
| 446 | /* inform the destination node that we are still missing a correct route | 453 | /* inform the destination node that we are still missing a correct route |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 61c5e819380e..08e576ada0b2 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1195,7 +1195,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1195 | max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); | 1195 | max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); |
| 1196 | if (max_delay) | 1196 | if (max_delay) |
| 1197 | group = &mld->mld_mca; | 1197 | group = &mld->mld_mca; |
| 1198 | } else if (skb->len >= sizeof(*mld2q)) { | 1198 | } else { |
| 1199 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { | 1199 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { |
| 1200 | err = -EINVAL; | 1200 | err = -EINVAL; |
| 1201 | goto out; | 1201 | goto out; |
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 394bb96b6087..3b9637fb7939 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Sysfs attributes of bridge ports | 2 | * Sysfs attributes of bridge |
| 3 | * Linux ethernet bridge | 3 | * Linux ethernet bridge |
| 4 | * | 4 | * |
| 5 | * Authors: | 5 | * Authors: |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 00ee068efc1c..b84a1b155bc1 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
| @@ -65,6 +65,7 @@ ipv6: | |||
| 65 | nhoff += sizeof(struct ipv6hdr); | 65 | nhoff += sizeof(struct ipv6hdr); |
| 66 | break; | 66 | break; |
| 67 | } | 67 | } |
| 68 | case __constant_htons(ETH_P_8021AD): | ||
| 68 | case __constant_htons(ETH_P_8021Q): { | 69 | case __constant_htons(ETH_P_8021Q): { |
| 69 | const struct vlan_hdr *vlan; | 70 | const struct vlan_hdr *vlan; |
| 70 | struct vlan_hdr _vlan; | 71 | struct vlan_hdr _vlan; |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9232c68941ab..60533db8b72d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -1441,16 +1441,18 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
| 1441 | atomic_set(&p->refcnt, 1); | 1441 | atomic_set(&p->refcnt, 1); |
| 1442 | p->reachable_time = | 1442 | p->reachable_time = |
| 1443 | neigh_rand_reach_time(p->base_reachable_time); | 1443 | neigh_rand_reach_time(p->base_reachable_time); |
| 1444 | dev_hold(dev); | ||
| 1445 | p->dev = dev; | ||
| 1446 | write_pnet(&p->net, hold_net(net)); | ||
| 1447 | p->sysctl_table = NULL; | ||
| 1444 | 1448 | ||
| 1445 | if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) { | 1449 | if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) { |
| 1450 | release_net(net); | ||
| 1451 | dev_put(dev); | ||
| 1446 | kfree(p); | 1452 | kfree(p); |
| 1447 | return NULL; | 1453 | return NULL; |
| 1448 | } | 1454 | } |
| 1449 | 1455 | ||
| 1450 | dev_hold(dev); | ||
| 1451 | p->dev = dev; | ||
| 1452 | write_pnet(&p->net, hold_net(net)); | ||
| 1453 | p->sysctl_table = NULL; | ||
| 1454 | write_lock_bh(&tbl->lock); | 1456 | write_lock_bh(&tbl->lock); |
| 1455 | p->next = tbl->parms.next; | 1457 | p->next = tbl->parms.next; |
| 1456 | tbl->parms.next = p; | 1458 | tbl->parms.next = p; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 3de740834d1f..ca198c1d1d30 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2156,7 +2156,7 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm, | |||
| 2156 | /* If aging addresses are supported device will need to | 2156 | /* If aging addresses are supported device will need to |
| 2157 | * implement its own handler for this. | 2157 | * implement its own handler for this. |
| 2158 | */ | 2158 | */ |
| 2159 | if (ndm->ndm_state & NUD_PERMANENT) { | 2159 | if (!(ndm->ndm_state & NUD_PERMANENT)) { |
| 2160 | pr_info("%s: FDB only supports static addresses\n", dev->name); | 2160 | pr_info("%s: FDB only supports static addresses\n", dev->name); |
| 2161 | return -EINVAL; | 2161 | return -EINVAL; |
| 2162 | } | 2162 | } |
| @@ -2384,7 +2384,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2384 | struct nlattr *extfilt; | 2384 | struct nlattr *extfilt; |
| 2385 | u32 filter_mask = 0; | 2385 | u32 filter_mask = 0; |
| 2386 | 2386 | ||
| 2387 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct rtgenmsg), | 2387 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), |
| 2388 | IFLA_EXT_MASK); | 2388 | IFLA_EXT_MASK); |
| 2389 | if (extfilt) | 2389 | if (extfilt) |
| 2390 | filter_mask = nla_get_u32(extfilt); | 2390 | filter_mask = nla_get_u32(extfilt); |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index ab3d814bc80a..109ee89f123e 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -477,7 +477,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) | |||
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - | 479 | return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - |
| 480 | net_adj) & ~(align - 1)) + (net_adj - 2); | 480 | net_adj) & ~(align - 1)) + net_adj - 2; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | static void esp4_err(struct sk_buff *skb, u32 info) | 483 | static void esp4_err(struct sk_buff *skb, u32 info) |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 108a1e9c9eac..3df6d3edb2a1 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -71,7 +71,6 @@ | |||
| 71 | #include <linux/init.h> | 71 | #include <linux/init.h> |
| 72 | #include <linux/list.h> | 72 | #include <linux/list.h> |
| 73 | #include <linux/slab.h> | 73 | #include <linux/slab.h> |
| 74 | #include <linux/prefetch.h> | ||
| 75 | #include <linux/export.h> | 74 | #include <linux/export.h> |
| 76 | #include <net/net_namespace.h> | 75 | #include <net/net_namespace.h> |
| 77 | #include <net/ip.h> | 76 | #include <net/ip.h> |
| @@ -1761,10 +1760,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) | |||
| 1761 | if (!c) | 1760 | if (!c) |
| 1762 | continue; | 1761 | continue; |
| 1763 | 1762 | ||
| 1764 | if (IS_LEAF(c)) { | 1763 | if (IS_LEAF(c)) |
| 1765 | prefetch(rcu_dereference_rtnl(p->child[idx])); | ||
| 1766 | return (struct leaf *) c; | 1764 | return (struct leaf *) c; |
| 1767 | } | ||
| 1768 | 1765 | ||
| 1769 | /* Rescan start scanning in new node */ | 1766 | /* Rescan start scanning in new node */ |
| 1770 | p = (struct tnode *) c; | 1767 | p = (struct tnode *) c; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 1f6eab66f7ce..8d6939eeb492 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -383,7 +383,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, | |||
| 383 | if (daddr) | 383 | if (daddr) |
| 384 | memcpy(&iph->daddr, daddr, 4); | 384 | memcpy(&iph->daddr, daddr, 4); |
| 385 | if (iph->daddr) | 385 | if (iph->daddr) |
| 386 | return t->hlen; | 386 | return t->hlen + sizeof(*iph); |
| 387 | 387 | ||
| 388 | return -(t->hlen + sizeof(*iph)); | 388 | return -(t->hlen + sizeof(*iph)); |
| 389 | } | 389 | } |
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 7167b08977df..850525b34899 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
| @@ -76,9 +76,7 @@ int iptunnel_xmit(struct net *net, struct rtable *rt, | |||
| 76 | iph->daddr = dst; | 76 | iph->daddr = dst; |
| 77 | iph->saddr = src; | 77 | iph->saddr = src; |
| 78 | iph->ttl = ttl; | 78 | iph->ttl = ttl; |
| 79 | tunnel_ip_select_ident(skb, | 79 | __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); |
| 80 | (const struct iphdr *)skb_inner_network_header(skb), | ||
| 81 | &rt->dst); | ||
| 82 | 80 | ||
| 83 | err = ip_local_out(skb); | 81 | err = ip_local_out(skb); |
| 84 | if (unlikely(net_xmit_eval(err))) | 82 | if (unlikely(net_xmit_eval(err))) |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 6577a1149a47..463bd1273346 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
| @@ -273,7 +273,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
| 273 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), | 273 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), |
| 274 | SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD), | 274 | SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD), |
| 275 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), | 275 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), |
| 276 | SNMP_MIB_ITEM("LowLatencyRxPackets", LINUX_MIB_LOWLATENCYRXPACKETS), | 276 | SNMP_MIB_ITEM("BusyPollRxPackets", LINUX_MIB_BUSYPOLLRXPACKETS), |
| 277 | SNMP_MIB_SENTINEL | 277 | SNMP_MIB_SENTINEL |
| 278 | }; | 278 | }; |
| 279 | 279 | ||
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index a9077f441cb2..b6ae92a51f58 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
| @@ -206,8 +206,8 @@ static u32 cubic_root(u64 a) | |||
| 206 | */ | 206 | */ |
| 207 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | 207 | static inline void bictcp_update(struct bictcp *ca, u32 cwnd) |
| 208 | { | 208 | { |
| 209 | u64 offs; | 209 | u32 delta, bic_target, max_cnt; |
| 210 | u32 delta, t, bic_target, max_cnt; | 210 | u64 offs, t; |
| 211 | 211 | ||
| 212 | ca->ack_cnt++; /* count the number of ACKs */ | 212 | ca->ack_cnt++; /* count the number of ACKs */ |
| 213 | 213 | ||
| @@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) | |||
| 250 | * if the cwnd < 1 million packets !!! | 250 | * if the cwnd < 1 million packets !!! |
| 251 | */ | 251 | */ |
| 252 | 252 | ||
| 253 | t = (s32)(tcp_time_stamp - ca->epoch_start); | ||
| 254 | t += msecs_to_jiffies(ca->delay_min >> 3); | ||
| 253 | /* change the unit from HZ to bictcp_HZ */ | 255 | /* change the unit from HZ to bictcp_HZ */ |
| 254 | t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3) | 256 | t <<= BICTCP_HZ; |
| 255 | - ca->epoch_start) << BICTCP_HZ) / HZ; | 257 | do_div(t, HZ); |
| 256 | 258 | ||
| 257 | if (t < ca->bic_K) /* t - K */ | 259 | if (t < ca->bic_K) /* t - K */ |
| 258 | offs = ca->bic_K - t; | 260 | offs = ca->bic_K - t; |
| @@ -414,7 +416,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | |||
| 414 | return; | 416 | return; |
| 415 | 417 | ||
| 416 | /* Discard delay samples right after fast recovery */ | 418 | /* Discard delay samples right after fast recovery */ |
| 417 | if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ) | 419 | if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ) |
| 418 | return; | 420 | return; |
| 419 | 421 | ||
| 420 | delay = (rtt_us << 3) / USEC_PER_MSEC; | 422 | delay = (rtt_us << 3) / USEC_PER_MSEC; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 40ffd72243a4..aeac0dc3635d 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
| @@ -425,7 +425,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) | |||
| 425 | net_adj = 0; | 425 | net_adj = 0; |
| 426 | 426 | ||
| 427 | return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - | 427 | return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - |
| 428 | net_adj) & ~(align - 1)) + (net_adj - 2); | 428 | net_adj) & ~(align - 1)) + net_adj - 2; |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 431 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index bff3d821c7eb..c4ff5bbb45c4 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -993,14 +993,22 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | |||
| 993 | 993 | ||
| 994 | if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) { | 994 | if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) { |
| 995 | #ifdef CONFIG_IPV6_SUBTREES | 995 | #ifdef CONFIG_IPV6_SUBTREES |
| 996 | if (fn->subtree) | 996 | if (fn->subtree) { |
| 997 | fn = fib6_lookup_1(fn->subtree, args + 1); | 997 | struct fib6_node *sfn; |
| 998 | sfn = fib6_lookup_1(fn->subtree, | ||
| 999 | args + 1); | ||
| 1000 | if (!sfn) | ||
| 1001 | goto backtrack; | ||
| 1002 | fn = sfn; | ||
| 1003 | } | ||
| 998 | #endif | 1004 | #endif |
| 999 | if (!fn || fn->fn_flags & RTN_RTINFO) | 1005 | if (fn->fn_flags & RTN_RTINFO) |
| 1000 | return fn; | 1006 | return fn; |
| 1001 | } | 1007 | } |
| 1002 | } | 1008 | } |
| 1003 | 1009 | #ifdef CONFIG_IPV6_SUBTREES | |
| 1010 | backtrack: | ||
| 1011 | #endif | ||
| 1004 | if (fn->fn_flags & RTN_ROOT) | 1012 | if (fn->fn_flags & RTN_ROOT) |
| 1005 | break; | 1013 | break; |
| 1006 | 1014 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ae31968d42d3..cc9e02d79b55 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -31,10 +31,12 @@ | |||
| 31 | #include "led.h" | 31 | #include "led.h" |
| 32 | 32 | ||
| 33 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 33 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
| 34 | #define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) | ||
| 34 | #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) | 35 | #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) |
| 35 | #define IEEE80211_AUTH_MAX_TRIES 3 | 36 | #define IEEE80211_AUTH_MAX_TRIES 3 |
| 36 | #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) | 37 | #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) |
| 37 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 38 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
| 39 | #define IEEE80211_ASSOC_TIMEOUT_LONG (HZ / 2) | ||
| 38 | #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) | 40 | #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) |
| 39 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 41 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
| 40 | 42 | ||
| @@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 209 | struct ieee80211_channel *channel, | 211 | struct ieee80211_channel *channel, |
| 210 | const struct ieee80211_ht_operation *ht_oper, | 212 | const struct ieee80211_ht_operation *ht_oper, |
| 211 | const struct ieee80211_vht_operation *vht_oper, | 213 | const struct ieee80211_vht_operation *vht_oper, |
| 212 | struct cfg80211_chan_def *chandef, bool verbose) | 214 | struct cfg80211_chan_def *chandef, bool tracking) |
| 213 | { | 215 | { |
| 216 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
| 214 | struct cfg80211_chan_def vht_chandef; | 217 | struct cfg80211_chan_def vht_chandef; |
| 215 | u32 ht_cfreq, ret; | 218 | u32 ht_cfreq, ret; |
| 216 | 219 | ||
| @@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 229 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, | 232 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, |
| 230 | channel->band); | 233 | channel->band); |
| 231 | /* check that channel matches the right operating channel */ | 234 | /* check that channel matches the right operating channel */ |
| 232 | if (channel->center_freq != ht_cfreq) { | 235 | if (!tracking && channel->center_freq != ht_cfreq) { |
| 233 | /* | 236 | /* |
| 234 | * It's possible that some APs are confused here; | 237 | * It's possible that some APs are confused here; |
| 235 | * Netgear WNDR3700 sometimes reports 4 higher than | 238 | * Netgear WNDR3700 sometimes reports 4 higher than |
| @@ -237,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 237 | * since we look at probe response/beacon data here | 240 | * since we look at probe response/beacon data here |
| 238 | * it should be OK. | 241 | * it should be OK. |
| 239 | */ | 242 | */ |
| 240 | if (verbose) | 243 | sdata_info(sdata, |
| 241 | sdata_info(sdata, | 244 | "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", |
| 242 | "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", | 245 | channel->center_freq, ht_cfreq, |
| 243 | channel->center_freq, ht_cfreq, | 246 | ht_oper->primary_chan, channel->band); |
| 244 | ht_oper->primary_chan, channel->band); | ||
| 245 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | 247 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; |
| 246 | goto out; | 248 | goto out; |
| 247 | } | 249 | } |
| @@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 295 | channel->band); | 297 | channel->band); |
| 296 | break; | 298 | break; |
| 297 | default: | 299 | default: |
| 298 | if (verbose) | 300 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
| 299 | sdata_info(sdata, | 301 | sdata_info(sdata, |
| 300 | "AP VHT operation IE has invalid channel width (%d), disable VHT\n", | 302 | "AP VHT operation IE has invalid channel width (%d), disable VHT\n", |
| 301 | vht_oper->chan_width); | 303 | vht_oper->chan_width); |
| @@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 304 | } | 306 | } |
| 305 | 307 | ||
| 306 | if (!cfg80211_chandef_valid(&vht_chandef)) { | 308 | if (!cfg80211_chandef_valid(&vht_chandef)) { |
| 307 | if (verbose) | 309 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
| 308 | sdata_info(sdata, | 310 | sdata_info(sdata, |
| 309 | "AP VHT information is invalid, disable VHT\n"); | 311 | "AP VHT information is invalid, disable VHT\n"); |
| 310 | ret = IEEE80211_STA_DISABLE_VHT; | 312 | ret = IEEE80211_STA_DISABLE_VHT; |
| @@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 317 | } | 319 | } |
| 318 | 320 | ||
| 319 | if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { | 321 | if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { |
| 320 | if (verbose) | 322 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
| 321 | sdata_info(sdata, | 323 | sdata_info(sdata, |
| 322 | "AP VHT information doesn't match HT, disable VHT\n"); | 324 | "AP VHT information doesn't match HT, disable VHT\n"); |
| 323 | ret = IEEE80211_STA_DISABLE_VHT; | 325 | ret = IEEE80211_STA_DISABLE_VHT; |
| @@ -333,18 +335,27 @@ out: | |||
| 333 | if (ret & IEEE80211_STA_DISABLE_VHT) | 335 | if (ret & IEEE80211_STA_DISABLE_VHT) |
| 334 | vht_chandef = *chandef; | 336 | vht_chandef = *chandef; |
| 335 | 337 | ||
| 338 | /* | ||
| 339 | * Ignore the DISABLED flag when we're already connected and only | ||
| 340 | * tracking the APs beacon for bandwidth changes - otherwise we | ||
| 341 | * might get disconnected here if we connect to an AP, update our | ||
| 342 | * regulatory information based on the AP's country IE and the | ||
| 343 | * information we have is wrong/outdated and disables the channel | ||
| 344 | * that we're actually using for the connection to the AP. | ||
| 345 | */ | ||
| 336 | while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, | 346 | while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, |
| 337 | IEEE80211_CHAN_DISABLED)) { | 347 | tracking ? 0 : |
| 348 | IEEE80211_CHAN_DISABLED)) { | ||
| 338 | if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { | 349 | if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { |
| 339 | ret = IEEE80211_STA_DISABLE_HT | | 350 | ret = IEEE80211_STA_DISABLE_HT | |
| 340 | IEEE80211_STA_DISABLE_VHT; | 351 | IEEE80211_STA_DISABLE_VHT; |
| 341 | goto out; | 352 | break; |
| 342 | } | 353 | } |
| 343 | 354 | ||
| 344 | ret |= chandef_downgrade(chandef); | 355 | ret |= chandef_downgrade(chandef); |
| 345 | } | 356 | } |
| 346 | 357 | ||
| 347 | if (chandef->width != vht_chandef.width && verbose) | 358 | if (chandef->width != vht_chandef.width && !tracking) |
| 348 | sdata_info(sdata, | 359 | sdata_info(sdata, |
| 349 | "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); | 360 | "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); |
| 350 | 361 | ||
| @@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
| 384 | 395 | ||
| 385 | /* calculate new channel (type) based on HT/VHT operation IEs */ | 396 | /* calculate new channel (type) based on HT/VHT operation IEs */ |
| 386 | flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, | 397 | flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, |
| 387 | vht_oper, &chandef, false); | 398 | vht_oper, &chandef, true); |
| 388 | 399 | ||
| 389 | /* | 400 | /* |
| 390 | * Downgrade the new channel if we associated with restricted | 401 | * Downgrade the new channel if we associated with restricted |
| @@ -3394,10 +3405,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
| 3394 | 3405 | ||
| 3395 | if (tx_flags == 0) { | 3406 | if (tx_flags == 0) { |
| 3396 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 3407 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
| 3397 | ifmgd->auth_data->timeout_started = true; | 3408 | auth_data->timeout_started = true; |
| 3398 | run_again(sdata, auth_data->timeout); | 3409 | run_again(sdata, auth_data->timeout); |
| 3399 | } else { | 3410 | } else { |
| 3400 | auth_data->timeout_started = false; | 3411 | auth_data->timeout = |
| 3412 | round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG); | ||
| 3413 | auth_data->timeout_started = true; | ||
| 3414 | run_again(sdata, auth_data->timeout); | ||
| 3401 | } | 3415 | } |
| 3402 | 3416 | ||
| 3403 | return 0; | 3417 | return 0; |
| @@ -3434,7 +3448,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
| 3434 | assoc_data->timeout_started = true; | 3448 | assoc_data->timeout_started = true; |
| 3435 | run_again(sdata, assoc_data->timeout); | 3449 | run_again(sdata, assoc_data->timeout); |
| 3436 | } else { | 3450 | } else { |
| 3437 | assoc_data->timeout_started = false; | 3451 | assoc_data->timeout = |
| 3452 | round_jiffies_up(jiffies + | ||
| 3453 | IEEE80211_ASSOC_TIMEOUT_LONG); | ||
| 3454 | assoc_data->timeout_started = true; | ||
| 3455 | run_again(sdata, assoc_data->timeout); | ||
| 3438 | } | 3456 | } |
| 3439 | 3457 | ||
| 3440 | return 0; | 3458 | return 0; |
| @@ -3829,7 +3847,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
| 3829 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, | 3847 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, |
| 3830 | cbss->channel, | 3848 | cbss->channel, |
| 3831 | ht_oper, vht_oper, | 3849 | ht_oper, vht_oper, |
| 3832 | &chandef, true); | 3850 | &chandef, false); |
| 3833 | 3851 | ||
| 3834 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), | 3852 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), |
| 3835 | local->rx_chains); | 3853 | local->rx_chains); |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 7dcc376eea5f..2f8010707d01 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
| @@ -526,7 +526,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 526 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; | 526 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; |
| 527 | __u32 seq, ack, sack, end, win, swin; | 527 | __u32 seq, ack, sack, end, win, swin; |
| 528 | s16 receiver_offset; | 528 | s16 receiver_offset; |
| 529 | bool res; | 529 | bool res, in_recv_win; |
| 530 | 530 | ||
| 531 | /* | 531 | /* |
| 532 | * Get the required data from the packet. | 532 | * Get the required data from the packet. |
| @@ -649,14 +649,18 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 649 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | 649 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, |
| 650 | receiver->td_scale); | 650 | receiver->td_scale); |
| 651 | 651 | ||
| 652 | /* Is the ending sequence in the receive window (if available)? */ | ||
| 653 | in_recv_win = !receiver->td_maxwin || | ||
| 654 | after(end, sender->td_end - receiver->td_maxwin - 1); | ||
| 655 | |||
| 652 | pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n", | 656 | pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n", |
| 653 | before(seq, sender->td_maxend + 1), | 657 | before(seq, sender->td_maxend + 1), |
| 654 | after(end, sender->td_end - receiver->td_maxwin - 1), | 658 | (in_recv_win ? 1 : 0), |
| 655 | before(sack, receiver->td_end + 1), | 659 | before(sack, receiver->td_end + 1), |
| 656 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)); | 660 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)); |
| 657 | 661 | ||
| 658 | if (before(seq, sender->td_maxend + 1) && | 662 | if (before(seq, sender->td_maxend + 1) && |
| 659 | after(end, sender->td_end - receiver->td_maxwin - 1) && | 663 | in_recv_win && |
| 660 | before(sack, receiver->td_end + 1) && | 664 | before(sack, receiver->td_end + 1) && |
| 661 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) { | 665 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) { |
| 662 | /* | 666 | /* |
| @@ -725,7 +729,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 725 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, | 729 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, |
| 726 | "nf_ct_tcp: %s ", | 730 | "nf_ct_tcp: %s ", |
| 727 | before(seq, sender->td_maxend + 1) ? | 731 | before(seq, sender->td_maxend + 1) ? |
| 728 | after(end, sender->td_end - receiver->td_maxwin - 1) ? | 732 | in_recv_win ? |
| 729 | before(sack, receiver->td_end + 1) ? | 733 | before(sack, receiver->td_end + 1) ? |
| 730 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" | 734 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" |
| 731 | : "ACK is under the lower bound (possible overly delayed ACK)" | 735 | : "ACK is under the lower bound (possible overly delayed ACK)" |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 962e9792e317..d92cc317bf8b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -419,6 +419,7 @@ __build_packet_message(struct nfnl_log_net *log, | |||
| 419 | nfmsg->version = NFNETLINK_V0; | 419 | nfmsg->version = NFNETLINK_V0; |
| 420 | nfmsg->res_id = htons(inst->group_num); | 420 | nfmsg->res_id = htons(inst->group_num); |
| 421 | 421 | ||
| 422 | memset(&pmsg, 0, sizeof(pmsg)); | ||
| 422 | pmsg.hw_protocol = skb->protocol; | 423 | pmsg.hw_protocol = skb->protocol; |
| 423 | pmsg.hook = hooknum; | 424 | pmsg.hook = hooknum; |
| 424 | 425 | ||
| @@ -498,7 +499,10 @@ __build_packet_message(struct nfnl_log_net *log, | |||
| 498 | if (indev && skb->dev && | 499 | if (indev && skb->dev && |
| 499 | skb->mac_header != skb->network_header) { | 500 | skb->mac_header != skb->network_header) { |
| 500 | struct nfulnl_msg_packet_hw phw; | 501 | struct nfulnl_msg_packet_hw phw; |
| 501 | int len = dev_parse_header(skb, phw.hw_addr); | 502 | int len; |
| 503 | |||
| 504 | memset(&phw, 0, sizeof(phw)); | ||
| 505 | len = dev_parse_header(skb, phw.hw_addr); | ||
| 502 | if (len > 0) { | 506 | if (len > 0) { |
| 503 | phw.hw_addrlen = htons(len); | 507 | phw.hw_addrlen = htons(len); |
| 504 | if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) | 508 | if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 971ea145ab3e..8a703c3dd318 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
| @@ -463,7 +463,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
| 463 | if (indev && entskb->dev && | 463 | if (indev && entskb->dev && |
| 464 | entskb->mac_header != entskb->network_header) { | 464 | entskb->mac_header != entskb->network_header) { |
| 465 | struct nfqnl_msg_packet_hw phw; | 465 | struct nfqnl_msg_packet_hw phw; |
| 466 | int len = dev_parse_header(entskb, phw.hw_addr); | 466 | int len; |
| 467 | |||
| 468 | memset(&phw, 0, sizeof(phw)); | ||
| 469 | len = dev_parse_header(entskb, phw.hw_addr); | ||
| 467 | if (len) { | 470 | if (len) { |
| 468 | phw.hw_addrlen = htons(len); | 471 | phw.hw_addrlen = htons(len); |
| 469 | if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw)) | 472 | if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw)) |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 7011c71646f0..6113cc7efffc 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
| @@ -52,7 +52,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
| 52 | { | 52 | { |
| 53 | const struct xt_tcpmss_info *info = par->targinfo; | 53 | const struct xt_tcpmss_info *info = par->targinfo; |
| 54 | struct tcphdr *tcph; | 54 | struct tcphdr *tcph; |
| 55 | unsigned int tcplen, i; | 55 | int len, tcp_hdrlen; |
| 56 | unsigned int i; | ||
| 56 | __be16 oldval; | 57 | __be16 oldval; |
| 57 | u16 newmss; | 58 | u16 newmss; |
| 58 | u8 *opt; | 59 | u8 *opt; |
| @@ -64,11 +65,14 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
| 64 | if (!skb_make_writable(skb, skb->len)) | 65 | if (!skb_make_writable(skb, skb->len)) |
| 65 | return -1; | 66 | return -1; |
| 66 | 67 | ||
| 67 | tcplen = skb->len - tcphoff; | 68 | len = skb->len - tcphoff; |
| 69 | if (len < (int)sizeof(struct tcphdr)) | ||
| 70 | return -1; | ||
| 71 | |||
| 68 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 72 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
| 73 | tcp_hdrlen = tcph->doff * 4; | ||
| 69 | 74 | ||
| 70 | /* Header cannot be larger than the packet */ | 75 | if (len < tcp_hdrlen) |
| 71 | if (tcplen < tcph->doff*4) | ||
| 72 | return -1; | 76 | return -1; |
| 73 | 77 | ||
| 74 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 78 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
| @@ -87,9 +91,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
| 87 | newmss = info->mss; | 91 | newmss = info->mss; |
| 88 | 92 | ||
| 89 | opt = (u_int8_t *)tcph; | 93 | opt = (u_int8_t *)tcph; |
| 90 | for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { | 94 | for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { |
| 91 | if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && | 95 | if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { |
| 92 | opt[i+1] == TCPOLEN_MSS) { | ||
| 93 | u_int16_t oldmss; | 96 | u_int16_t oldmss; |
| 94 | 97 | ||
| 95 | oldmss = (opt[i+2] << 8) | opt[i+3]; | 98 | oldmss = (opt[i+2] << 8) | opt[i+3]; |
| @@ -112,9 +115,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
| 112 | } | 115 | } |
| 113 | 116 | ||
| 114 | /* There is data after the header so the option can't be added | 117 | /* There is data after the header so the option can't be added |
| 115 | without moving it, and doing so may make the SYN packet | 118 | * without moving it, and doing so may make the SYN packet |
| 116 | itself too large. Accept the packet unmodified instead. */ | 119 | * itself too large. Accept the packet unmodified instead. |
| 117 | if (tcplen > tcph->doff*4) | 120 | */ |
| 121 | if (len > tcp_hdrlen) | ||
| 118 | return 0; | 122 | return 0; |
| 119 | 123 | ||
| 120 | /* | 124 | /* |
| @@ -143,10 +147,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
| 143 | newmss = min(newmss, (u16)1220); | 147 | newmss = min(newmss, (u16)1220); |
| 144 | 148 | ||
| 145 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | 149 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); |
| 146 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | 150 | memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr)); |
| 147 | 151 | ||
| 148 | inet_proto_csum_replace2(&tcph->check, skb, | 152 | inet_proto_csum_replace2(&tcph->check, skb, |
| 149 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); | 153 | htons(len), htons(len + TCPOLEN_MSS), 1); |
| 150 | opt[0] = TCPOPT_MSS; | 154 | opt[0] = TCPOPT_MSS; |
| 151 | opt[1] = TCPOLEN_MSS; | 155 | opt[1] = TCPOLEN_MSS; |
| 152 | opt[2] = (newmss & 0xff00) >> 8; | 156 | opt[2] = (newmss & 0xff00) >> 8; |
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index b68fa191710f..625fa1d636a0 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c | |||
| @@ -38,7 +38,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
| 38 | struct tcphdr *tcph; | 38 | struct tcphdr *tcph; |
| 39 | u_int16_t n, o; | 39 | u_int16_t n, o; |
| 40 | u_int8_t *opt; | 40 | u_int8_t *opt; |
| 41 | int len; | 41 | int len, tcp_hdrlen; |
| 42 | 42 | ||
| 43 | /* This is a fragment, no TCP header is available */ | 43 | /* This is a fragment, no TCP header is available */ |
| 44 | if (par->fragoff != 0) | 44 | if (par->fragoff != 0) |
| @@ -52,7 +52,9 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
| 52 | return NF_DROP; | 52 | return NF_DROP; |
| 53 | 53 | ||
| 54 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 54 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
| 55 | if (tcph->doff * 4 > len) | 55 | tcp_hdrlen = tcph->doff * 4; |
| 56 | |||
| 57 | if (len < tcp_hdrlen) | ||
| 56 | return NF_DROP; | 58 | return NF_DROP; |
| 57 | 59 | ||
| 58 | opt = (u_int8_t *)tcph; | 60 | opt = (u_int8_t *)tcph; |
| @@ -61,10 +63,10 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
| 61 | * Walk through all TCP options - if we find some option to remove, | 63 | * Walk through all TCP options - if we find some option to remove, |
| 62 | * set all octets to %TCPOPT_NOP and adjust checksum. | 64 | * set all octets to %TCPOPT_NOP and adjust checksum. |
| 63 | */ | 65 | */ |
| 64 | for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) { | 66 | for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) { |
| 65 | optl = optlen(opt, i); | 67 | optl = optlen(opt, i); |
| 66 | 68 | ||
| 67 | if (i + optl > tcp_hdrlen(skb)) | 69 | if (i + optl > tcp_hdrlen) |
| 68 | break; | 70 | break; |
| 69 | 71 | ||
| 70 | if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i])) | 72 | if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i])) |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 512718adb0d5..f85f8a2ad6cf 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -789,6 +789,10 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 789 | struct net *net = sock_net(skb->sk); | 789 | struct net *net = sock_net(skb->sk); |
| 790 | int chains_to_skip = cb->args[0]; | 790 | int chains_to_skip = cb->args[0]; |
| 791 | int fams_to_skip = cb->args[1]; | 791 | int fams_to_skip = cb->args[1]; |
| 792 | bool need_locking = chains_to_skip || fams_to_skip; | ||
| 793 | |||
| 794 | if (need_locking) | ||
| 795 | genl_lock(); | ||
| 792 | 796 | ||
| 793 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { | 797 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { |
| 794 | n = 0; | 798 | n = 0; |
| @@ -810,6 +814,9 @@ errout: | |||
| 810 | cb->args[0] = i; | 814 | cb->args[0] = i; |
| 811 | cb->args[1] = n; | 815 | cb->args[1] = n; |
| 812 | 816 | ||
| 817 | if (need_locking) | ||
| 818 | genl_unlock(); | ||
| 819 | |||
| 813 | return skb->len; | 820 | return skb->len; |
| 814 | } | 821 | } |
| 815 | 822 | ||
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 22c5f399f1cf..ab101f715447 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
| @@ -535,6 +535,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb) | |||
| 535 | { | 535 | { |
| 536 | struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); | 536 | struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); |
| 537 | 537 | ||
| 538 | OVS_CB(skb)->tun_key = NULL; | ||
| 538 | return do_execute_actions(dp, skb, acts->actions, | 539 | return do_execute_actions(dp, skb, acts->actions, |
| 539 | acts->actions_len, false); | 540 | acts->actions_len, false); |
| 540 | } | 541 | } |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index f7e3a0d84c40..f2ed7600084e 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -2076,9 +2076,6 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
| 2076 | ovs_notify(reply, info, &ovs_dp_vport_multicast_group); | 2076 | ovs_notify(reply, info, &ovs_dp_vport_multicast_group); |
| 2077 | return 0; | 2077 | return 0; |
| 2078 | 2078 | ||
| 2079 | rtnl_unlock(); | ||
| 2080 | return 0; | ||
| 2081 | |||
| 2082 | exit_free: | 2079 | exit_free: |
| 2083 | kfree_skb(reply); | 2080 | kfree_skb(reply); |
| 2084 | exit_unlock: | 2081 | exit_unlock: |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 5c519b121e1b..1aa84dc58777 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -240,7 +240,7 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets) | |||
| 240 | struct flex_array *buckets; | 240 | struct flex_array *buckets; |
| 241 | int i, err; | 241 | int i, err; |
| 242 | 242 | ||
| 243 | buckets = flex_array_alloc(sizeof(struct hlist_head *), | 243 | buckets = flex_array_alloc(sizeof(struct hlist_head), |
| 244 | n_buckets, GFP_KERNEL); | 244 | n_buckets, GFP_KERNEL); |
| 245 | if (!buckets) | 245 | if (!buckets) |
| 246 | return NULL; | 246 | return NULL; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 281c1bded1f6..51b968d3febb 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -285,6 +285,45 @@ static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind) | |||
| 285 | return q; | 285 | return q; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | /* The linklayer setting were not transferred from iproute2, in older | ||
| 289 | * versions, and the rate tables lookup systems have been dropped in | ||
| 290 | * the kernel. To keep backward compatible with older iproute2 tc | ||
| 291 | * utils, we detect the linklayer setting by detecting if the rate | ||
| 292 | * table were modified. | ||
| 293 | * | ||
| 294 | * For linklayer ATM table entries, the rate table will be aligned to | ||
| 295 | * 48 bytes, thus some table entries will contain the same value. The | ||
| 296 | * mpu (min packet unit) is also encoded into the old rate table, thus | ||
| 297 | * starting from the mpu, we find low and high table entries for | ||
| 298 | * mapping this cell. If these entries contain the same value, when | ||
| 299 | * the rate tables have been modified for linklayer ATM. | ||
| 300 | * | ||
| 301 | * This is done by rounding mpu to the nearest 48 bytes cell/entry, | ||
| 302 | * and then roundup to the next cell, calc the table entry one below, | ||
| 303 | * and compare. | ||
| 304 | */ | ||
| 305 | static __u8 __detect_linklayer(struct tc_ratespec *r, __u32 *rtab) | ||
| 306 | { | ||
| 307 | int low = roundup(r->mpu, 48); | ||
| 308 | int high = roundup(low+1, 48); | ||
| 309 | int cell_low = low >> r->cell_log; | ||
| 310 | int cell_high = (high >> r->cell_log) - 1; | ||
| 311 | |||
| 312 | /* rtab is too inaccurate at rates > 100Mbit/s */ | ||
| 313 | if ((r->rate > (100000000/8)) || (rtab[0] == 0)) { | ||
| 314 | pr_debug("TC linklayer: Giving up ATM detection\n"); | ||
| 315 | return TC_LINKLAYER_ETHERNET; | ||
| 316 | } | ||
| 317 | |||
| 318 | if ((cell_high > cell_low) && (cell_high < 256) | ||
| 319 | && (rtab[cell_low] == rtab[cell_high])) { | ||
| 320 | pr_debug("TC linklayer: Detected ATM, low(%d)=high(%d)=%u\n", | ||
| 321 | cell_low, cell_high, rtab[cell_high]); | ||
| 322 | return TC_LINKLAYER_ATM; | ||
| 323 | } | ||
| 324 | return TC_LINKLAYER_ETHERNET; | ||
| 325 | } | ||
| 326 | |||
| 288 | static struct qdisc_rate_table *qdisc_rtab_list; | 327 | static struct qdisc_rate_table *qdisc_rtab_list; |
| 289 | 328 | ||
| 290 | struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab) | 329 | struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab) |
| @@ -308,6 +347,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta | |||
| 308 | rtab->rate = *r; | 347 | rtab->rate = *r; |
| 309 | rtab->refcnt = 1; | 348 | rtab->refcnt = 1; |
| 310 | memcpy(rtab->data, nla_data(tab), 1024); | 349 | memcpy(rtab->data, nla_data(tab), 1024); |
| 350 | if (r->linklayer == TC_LINKLAYER_UNAWARE) | ||
| 351 | r->linklayer = __detect_linklayer(r, rtab->data); | ||
| 311 | rtab->next = qdisc_rtab_list; | 352 | rtab->next = qdisc_rtab_list; |
| 312 | qdisc_rtab_list = rtab; | 353 | qdisc_rtab_list = rtab; |
| 313 | } | 354 | } |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 4626cef4b76e..48be3d5c0d92 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
| 26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/if_vlan.h> | ||
| 28 | #include <net/sch_generic.h> | 29 | #include <net/sch_generic.h> |
| 29 | #include <net/pkt_sched.h> | 30 | #include <net/pkt_sched.h> |
| 30 | #include <net/dst.h> | 31 | #include <net/dst.h> |
| @@ -207,15 +208,19 @@ void __qdisc_run(struct Qdisc *q) | |||
| 207 | 208 | ||
| 208 | unsigned long dev_trans_start(struct net_device *dev) | 209 | unsigned long dev_trans_start(struct net_device *dev) |
| 209 | { | 210 | { |
| 210 | unsigned long val, res = dev->trans_start; | 211 | unsigned long val, res; |
| 211 | unsigned int i; | 212 | unsigned int i; |
| 212 | 213 | ||
| 214 | if (is_vlan_dev(dev)) | ||
| 215 | dev = vlan_dev_real_dev(dev); | ||
| 216 | res = dev->trans_start; | ||
| 213 | for (i = 0; i < dev->num_tx_queues; i++) { | 217 | for (i = 0; i < dev->num_tx_queues; i++) { |
| 214 | val = netdev_get_tx_queue(dev, i)->trans_start; | 218 | val = netdev_get_tx_queue(dev, i)->trans_start; |
| 215 | if (val && time_after(val, res)) | 219 | if (val && time_after(val, res)) |
| 216 | res = val; | 220 | res = val; |
| 217 | } | 221 | } |
| 218 | dev->trans_start = res; | 222 | dev->trans_start = res; |
| 223 | |||
| 219 | return res; | 224 | return res; |
| 220 | } | 225 | } |
| 221 | EXPORT_SYMBOL(dev_trans_start); | 226 | EXPORT_SYMBOL(dev_trans_start); |
| @@ -904,6 +909,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, | |||
| 904 | memset(r, 0, sizeof(*r)); | 909 | memset(r, 0, sizeof(*r)); |
| 905 | r->overhead = conf->overhead; | 910 | r->overhead = conf->overhead; |
| 906 | r->rate_bytes_ps = conf->rate; | 911 | r->rate_bytes_ps = conf->rate; |
| 912 | r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK); | ||
| 907 | r->mult = 1; | 913 | r->mult = 1; |
| 908 | /* | 914 | /* |
| 909 | * The deal here is to replace a divide by a reciprocal one | 915 | * The deal here is to replace a divide by a reciprocal one |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 45e751527dfc..c2178b15ca6e 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
| @@ -1329,6 +1329,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
| 1329 | struct htb_sched *q = qdisc_priv(sch); | 1329 | struct htb_sched *q = qdisc_priv(sch); |
| 1330 | struct htb_class *cl = (struct htb_class *)*arg, *parent; | 1330 | struct htb_class *cl = (struct htb_class *)*arg, *parent; |
| 1331 | struct nlattr *opt = tca[TCA_OPTIONS]; | 1331 | struct nlattr *opt = tca[TCA_OPTIONS]; |
| 1332 | struct qdisc_rate_table *rtab = NULL, *ctab = NULL; | ||
| 1332 | struct nlattr *tb[TCA_HTB_MAX + 1]; | 1333 | struct nlattr *tb[TCA_HTB_MAX + 1]; |
| 1333 | struct tc_htb_opt *hopt; | 1334 | struct tc_htb_opt *hopt; |
| 1334 | 1335 | ||
| @@ -1350,6 +1351,18 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
| 1350 | if (!hopt->rate.rate || !hopt->ceil.rate) | 1351 | if (!hopt->rate.rate || !hopt->ceil.rate) |
| 1351 | goto failure; | 1352 | goto failure; |
| 1352 | 1353 | ||
| 1354 | /* Keeping backward compatible with rate_table based iproute2 tc */ | ||
| 1355 | if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) { | ||
| 1356 | rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]); | ||
| 1357 | if (rtab) | ||
| 1358 | qdisc_put_rtab(rtab); | ||
| 1359 | } | ||
| 1360 | if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) { | ||
| 1361 | ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]); | ||
| 1362 | if (ctab) | ||
| 1363 | qdisc_put_rtab(ctab); | ||
| 1364 | } | ||
| 1365 | |||
| 1353 | if (!cl) { /* new class */ | 1366 | if (!cl) { /* new class */ |
| 1354 | struct Qdisc *new_q; | 1367 | struct Qdisc *new_q; |
| 1355 | int prio; | 1368 | int prio; |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index bce5b79662a6..ab67efc64b24 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -846,12 +846,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 846 | else | 846 | else |
| 847 | spc_state = SCTP_ADDR_AVAILABLE; | 847 | spc_state = SCTP_ADDR_AVAILABLE; |
| 848 | /* Don't inform ULP about transition from PF to | 848 | /* Don't inform ULP about transition from PF to |
| 849 | * active state and set cwnd to 1, see SCTP | 849 | * active state and set cwnd to 1 MTU, see SCTP |
| 850 | * Quick failover draft section 5.1, point 5 | 850 | * Quick failover draft section 5.1, point 5 |
| 851 | */ | 851 | */ |
| 852 | if (transport->state == SCTP_PF) { | 852 | if (transport->state == SCTP_PF) { |
| 853 | ulp_notify = false; | 853 | ulp_notify = false; |
| 854 | transport->cwnd = 1; | 854 | transport->cwnd = asoc->pathmtu; |
| 855 | } | 855 | } |
| 856 | transport->state = SCTP_ACTIVE; | 856 | transport->state = SCTP_ACTIVE; |
| 857 | break; | 857 | break; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index bdbbc3fd7c14..8fdd16046d66 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -181,12 +181,12 @@ static void sctp_transport_destroy(struct sctp_transport *transport) | |||
| 181 | return; | 181 | return; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | call_rcu(&transport->rcu, sctp_transport_destroy_rcu); | ||
| 185 | |||
| 186 | sctp_packet_free(&transport->packet); | 184 | sctp_packet_free(&transport->packet); |
| 187 | 185 | ||
| 188 | if (transport->asoc) | 186 | if (transport->asoc) |
| 189 | sctp_association_put(transport->asoc); | 187 | sctp_association_put(transport->asoc); |
| 188 | |||
| 189 | call_rcu(&transport->rcu, sctp_transport_destroy_rcu); | ||
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | /* Start T3_rtx timer if it is not already running and update the heartbeat | 192 | /* Start T3_rtx timer if it is not already running and update the heartbeat |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 74f6a704e374..ecbc4e3d83ad 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -1660,6 +1660,10 @@ call_connect(struct rpc_task *task) | |||
| 1660 | task->tk_action = call_connect_status; | 1660 | task->tk_action = call_connect_status; |
| 1661 | if (task->tk_status < 0) | 1661 | if (task->tk_status < 0) |
| 1662 | return; | 1662 | return; |
| 1663 | if (task->tk_flags & RPC_TASK_NOCONNECT) { | ||
| 1664 | rpc_exit(task, -ENOTCONN); | ||
| 1665 | return; | ||
| 1666 | } | ||
| 1663 | xprt_connect(task); | 1667 | xprt_connect(task); |
| 1664 | } | 1668 | } |
| 1665 | } | 1669 | } |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 74d948f5d5a1..779742cfc1ff 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
| @@ -23,6 +23,7 @@ struct sunrpc_net { | |||
| 23 | struct rpc_clnt *rpcb_local_clnt4; | 23 | struct rpc_clnt *rpcb_local_clnt4; |
| 24 | spinlock_t rpcb_clnt_lock; | 24 | spinlock_t rpcb_clnt_lock; |
| 25 | unsigned int rpcb_users; | 25 | unsigned int rpcb_users; |
| 26 | unsigned int rpcb_is_af_local : 1; | ||
| 26 | 27 | ||
| 27 | struct mutex gssp_lock; | 28 | struct mutex gssp_lock; |
| 28 | wait_queue_head_t gssp_wq; | 29 | wait_queue_head_t gssp_wq; |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 3df764dc330c..1891a1022c17 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
| @@ -204,13 +204,15 @@ void rpcb_put_local(struct net *net) | |||
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, | 206 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, |
| 207 | struct rpc_clnt *clnt4) | 207 | struct rpc_clnt *clnt4, |
| 208 | bool is_af_local) | ||
| 208 | { | 209 | { |
| 209 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 210 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
| 210 | 211 | ||
| 211 | /* Protected by rpcb_create_local_mutex */ | 212 | /* Protected by rpcb_create_local_mutex */ |
| 212 | sn->rpcb_local_clnt = clnt; | 213 | sn->rpcb_local_clnt = clnt; |
| 213 | sn->rpcb_local_clnt4 = clnt4; | 214 | sn->rpcb_local_clnt4 = clnt4; |
| 215 | sn->rpcb_is_af_local = is_af_local ? 1 : 0; | ||
| 214 | smp_wmb(); | 216 | smp_wmb(); |
| 215 | sn->rpcb_users = 1; | 217 | sn->rpcb_users = 1; |
| 216 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | 218 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
| @@ -238,6 +240,14 @@ static int rpcb_create_local_unix(struct net *net) | |||
| 238 | .program = &rpcb_program, | 240 | .program = &rpcb_program, |
| 239 | .version = RPCBVERS_2, | 241 | .version = RPCBVERS_2, |
| 240 | .authflavor = RPC_AUTH_NULL, | 242 | .authflavor = RPC_AUTH_NULL, |
| 243 | /* | ||
| 244 | * We turn off the idle timeout to prevent the kernel | ||
| 245 | * from automatically disconnecting the socket. | ||
| 246 | * Otherwise, we'd have to cache the mount namespace | ||
| 247 | * of the caller and somehow pass that to the socket | ||
| 248 | * reconnect code. | ||
| 249 | */ | ||
| 250 | .flags = RPC_CLNT_CREATE_NO_IDLE_TIMEOUT, | ||
| 241 | }; | 251 | }; |
| 242 | struct rpc_clnt *clnt, *clnt4; | 252 | struct rpc_clnt *clnt, *clnt4; |
| 243 | int result = 0; | 253 | int result = 0; |
| @@ -263,7 +273,7 @@ static int rpcb_create_local_unix(struct net *net) | |||
| 263 | clnt4 = NULL; | 273 | clnt4 = NULL; |
| 264 | } | 274 | } |
| 265 | 275 | ||
| 266 | rpcb_set_local(net, clnt, clnt4); | 276 | rpcb_set_local(net, clnt, clnt4, true); |
| 267 | 277 | ||
| 268 | out: | 278 | out: |
| 269 | return result; | 279 | return result; |
| @@ -315,7 +325,7 @@ static int rpcb_create_local_net(struct net *net) | |||
| 315 | clnt4 = NULL; | 325 | clnt4 = NULL; |
| 316 | } | 326 | } |
| 317 | 327 | ||
| 318 | rpcb_set_local(net, clnt, clnt4); | 328 | rpcb_set_local(net, clnt, clnt4, false); |
| 319 | 329 | ||
| 320 | out: | 330 | out: |
| 321 | return result; | 331 | return result; |
| @@ -376,13 +386,16 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, | |||
| 376 | return rpc_create(&args); | 386 | return rpc_create(&args); |
| 377 | } | 387 | } |
| 378 | 388 | ||
| 379 | static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | 389 | static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set) |
| 380 | { | 390 | { |
| 381 | int result, error = 0; | 391 | int flags = RPC_TASK_NOCONNECT; |
| 392 | int error, result = 0; | ||
| 382 | 393 | ||
| 394 | if (is_set || !sn->rpcb_is_af_local) | ||
| 395 | flags = RPC_TASK_SOFTCONN; | ||
| 383 | msg->rpc_resp = &result; | 396 | msg->rpc_resp = &result; |
| 384 | 397 | ||
| 385 | error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); | 398 | error = rpc_call_sync(clnt, msg, flags); |
| 386 | if (error < 0) { | 399 | if (error < 0) { |
| 387 | dprintk("RPC: failed to contact local rpcbind " | 400 | dprintk("RPC: failed to contact local rpcbind " |
| 388 | "server (errno %d).\n", -error); | 401 | "server (errno %d).\n", -error); |
| @@ -439,16 +452,19 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short | |||
| 439 | .rpc_argp = &map, | 452 | .rpc_argp = &map, |
| 440 | }; | 453 | }; |
| 441 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 454 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
| 455 | bool is_set = false; | ||
| 442 | 456 | ||
| 443 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 457 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
| 444 | "rpcbind\n", (port ? "" : "un"), | 458 | "rpcbind\n", (port ? "" : "un"), |
| 445 | prog, vers, prot, port); | 459 | prog, vers, prot, port); |
| 446 | 460 | ||
| 447 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; | 461 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; |
| 448 | if (port) | 462 | if (port != 0) { |
| 449 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 463 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
| 464 | is_set = true; | ||
| 465 | } | ||
| 450 | 466 | ||
| 451 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); | 467 | return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set); |
| 452 | } | 468 | } |
| 453 | 469 | ||
| 454 | /* | 470 | /* |
| @@ -461,6 +477,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
| 461 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 477 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
| 462 | struct rpcbind_args *map = msg->rpc_argp; | 478 | struct rpcbind_args *map = msg->rpc_argp; |
| 463 | unsigned short port = ntohs(sin->sin_port); | 479 | unsigned short port = ntohs(sin->sin_port); |
| 480 | bool is_set = false; | ||
| 464 | int result; | 481 | int result; |
| 465 | 482 | ||
| 466 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 483 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
| @@ -471,10 +488,12 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
| 471 | map->r_addr, map->r_netid); | 488 | map->r_addr, map->r_netid); |
| 472 | 489 | ||
| 473 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 490 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
| 474 | if (port) | 491 | if (port != 0) { |
| 475 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 492 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
| 493 | is_set = true; | ||
| 494 | } | ||
| 476 | 495 | ||
| 477 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 496 | result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set); |
| 478 | kfree(map->r_addr); | 497 | kfree(map->r_addr); |
| 479 | return result; | 498 | return result; |
| 480 | } | 499 | } |
| @@ -489,6 +508,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
| 489 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 508 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
| 490 | struct rpcbind_args *map = msg->rpc_argp; | 509 | struct rpcbind_args *map = msg->rpc_argp; |
| 491 | unsigned short port = ntohs(sin6->sin6_port); | 510 | unsigned short port = ntohs(sin6->sin6_port); |
| 511 | bool is_set = false; | ||
| 492 | int result; | 512 | int result; |
| 493 | 513 | ||
| 494 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 514 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
| @@ -499,10 +519,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
| 499 | map->r_addr, map->r_netid); | 519 | map->r_addr, map->r_netid); |
| 500 | 520 | ||
| 501 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 521 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
| 502 | if (port) | 522 | if (port != 0) { |
| 503 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 523 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
| 524 | is_set = true; | ||
| 525 | } | ||
| 504 | 526 | ||
| 505 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 527 | result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set); |
| 506 | kfree(map->r_addr); | 528 | kfree(map->r_addr); |
| 507 | return result; | 529 | return result; |
| 508 | } | 530 | } |
| @@ -519,7 +541,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | |||
| 519 | map->r_addr = ""; | 541 | map->r_addr = ""; |
| 520 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 542 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
| 521 | 543 | ||
| 522 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); | 544 | return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false); |
| 523 | } | 545 | } |
| 524 | 546 | ||
| 525 | /** | 547 | /** |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index cb29ef7ba2f0..609c30c80816 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -460,6 +460,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
| 460 | { | 460 | { |
| 461 | struct tipc_link *l_ptr; | 461 | struct tipc_link *l_ptr; |
| 462 | struct tipc_link *temp_l_ptr; | 462 | struct tipc_link *temp_l_ptr; |
| 463 | struct tipc_link_req *temp_req; | ||
| 463 | 464 | ||
| 464 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 465 | pr_info("Disabling bearer <%s>\n", b_ptr->name); |
| 465 | spin_lock_bh(&b_ptr->lock); | 466 | spin_lock_bh(&b_ptr->lock); |
| @@ -468,9 +469,13 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
| 468 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 469 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
| 469 | tipc_link_delete(l_ptr); | 470 | tipc_link_delete(l_ptr); |
| 470 | } | 471 | } |
| 471 | if (b_ptr->link_req) | 472 | temp_req = b_ptr->link_req; |
| 472 | tipc_disc_delete(b_ptr->link_req); | 473 | b_ptr->link_req = NULL; |
| 473 | spin_unlock_bh(&b_ptr->lock); | 474 | spin_unlock_bh(&b_ptr->lock); |
| 475 | |||
| 476 | if (temp_req) | ||
| 477 | tipc_disc_delete(temp_req); | ||
| 478 | |||
| 474 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 479 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); |
| 475 | } | 480 | } |
| 476 | 481 | ||
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 593071dabd1c..4d9334683f84 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
| @@ -347,7 +347,7 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk)) | |||
| 347 | for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) { | 347 | for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) { |
| 348 | struct vsock_sock *vsk; | 348 | struct vsock_sock *vsk; |
| 349 | list_for_each_entry(vsk, &vsock_connected_table[i], | 349 | list_for_each_entry(vsk, &vsock_connected_table[i], |
| 350 | connected_table); | 350 | connected_table) |
| 351 | fn(sk_vsock(vsk)); | 351 | fn(sk_vsock(vsk)); |
| 352 | } | 352 | } |
| 353 | 353 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 4f9f216665e9..a8c29fa4f1b3 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -765,6 +765,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 765 | cfg80211_leave_mesh(rdev, dev); | 765 | cfg80211_leave_mesh(rdev, dev); |
| 766 | break; | 766 | break; |
| 767 | case NL80211_IFTYPE_AP: | 767 | case NL80211_IFTYPE_AP: |
| 768 | case NL80211_IFTYPE_P2P_GO: | ||
| 768 | cfg80211_stop_ap(rdev, dev); | 769 | cfg80211_stop_ap(rdev, dev); |
| 769 | break; | 770 | break; |
| 770 | default: | 771 | default: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 25d217d90807..3fcba69817e5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
| 441 | goto out_unlock; | 441 | goto out_unlock; |
| 442 | } | 442 | } |
| 443 | *rdev = wiphy_to_dev((*wdev)->wiphy); | 443 | *rdev = wiphy_to_dev((*wdev)->wiphy); |
| 444 | cb->args[0] = (*rdev)->wiphy_idx; | 444 | /* 0 is the first index - add 1 to parse only once */ |
| 445 | cb->args[0] = (*rdev)->wiphy_idx + 1; | ||
| 445 | cb->args[1] = (*wdev)->identifier; | 446 | cb->args[1] = (*wdev)->identifier; |
| 446 | } else { | 447 | } else { |
| 447 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]); | 448 | /* subtract the 1 again here */ |
| 449 | struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); | ||
| 448 | struct wireless_dev *tmp; | 450 | struct wireless_dev *tmp; |
| 449 | 451 | ||
| 450 | if (!wiphy) { | 452 | if (!wiphy) { |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 3f7682a387b7..eefbd10e408f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -1998,12 +1998,11 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) | |||
| 1998 | * | 1998 | * |
| 1999 | * Create or update the port list entry | 1999 | * Create or update the port list entry |
| 2000 | */ | 2000 | */ |
| 2001 | static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, | 2001 | static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, |
| 2002 | int act) | 2002 | int act) |
| 2003 | { | 2003 | { |
| 2004 | __be16 *bep; | 2004 | __be16 *bep; |
| 2005 | __be32 *be32p; | 2005 | __be32 *be32p; |
| 2006 | struct sockaddr_in6 *addr6; | ||
| 2007 | struct smk_port_label *spp; | 2006 | struct smk_port_label *spp; |
| 2008 | struct socket_smack *ssp = sk->sk_security; | 2007 | struct socket_smack *ssp = sk->sk_security; |
| 2009 | struct smack_known *skp; | 2008 | struct smack_known *skp; |
| @@ -2025,10 +2024,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, | |||
| 2025 | /* | 2024 | /* |
| 2026 | * Get the IP address and port from the address. | 2025 | * Get the IP address and port from the address. |
| 2027 | */ | 2026 | */ |
| 2028 | addr6 = (struct sockaddr_in6 *)address; | 2027 | port = ntohs(address->sin6_port); |
| 2029 | port = ntohs(addr6->sin6_port); | 2028 | bep = (__be16 *)(&address->sin6_addr); |
| 2030 | bep = (__be16 *)(&addr6->sin6_addr); | 2029 | be32p = (__be32 *)(&address->sin6_addr); |
| 2031 | be32p = (__be32 *)(&addr6->sin6_addr); | ||
| 2032 | 2030 | ||
| 2033 | /* | 2031 | /* |
| 2034 | * It's remote, so port lookup does no good. | 2032 | * It's remote, so port lookup does no good. |
| @@ -2060,9 +2058,9 @@ auditout: | |||
| 2060 | ad.a.u.net->family = sk->sk_family; | 2058 | ad.a.u.net->family = sk->sk_family; |
| 2061 | ad.a.u.net->dport = port; | 2059 | ad.a.u.net->dport = port; |
| 2062 | if (act == SMK_RECEIVING) | 2060 | if (act == SMK_RECEIVING) |
| 2063 | ad.a.u.net->v6info.saddr = addr6->sin6_addr; | 2061 | ad.a.u.net->v6info.saddr = address->sin6_addr; |
| 2064 | else | 2062 | else |
| 2065 | ad.a.u.net->v6info.daddr = addr6->sin6_addr; | 2063 | ad.a.u.net->v6info.daddr = address->sin6_addr; |
| 2066 | #endif | 2064 | #endif |
| 2067 | return smk_access(skp, object, MAY_WRITE, &ad); | 2065 | return smk_access(skp, object, MAY_WRITE, &ad); |
| 2068 | } | 2066 | } |
| @@ -2201,7 +2199,8 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | |||
| 2201 | case PF_INET6: | 2199 | case PF_INET6: |
| 2202 | if (addrlen < sizeof(struct sockaddr_in6)) | 2200 | if (addrlen < sizeof(struct sockaddr_in6)) |
| 2203 | return -EINVAL; | 2201 | return -EINVAL; |
| 2204 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING); | 2202 | rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, |
| 2203 | SMK_CONNECTING); | ||
| 2205 | break; | 2204 | break; |
| 2206 | } | 2205 | } |
| 2207 | return rc; | 2206 | return rc; |
| @@ -3034,7 +3033,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 3034 | int size) | 3033 | int size) |
| 3035 | { | 3034 | { |
| 3036 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; | 3035 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; |
| 3037 | struct sockaddr *sap = (struct sockaddr *) msg->msg_name; | 3036 | struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; |
| 3038 | int rc = 0; | 3037 | int rc = 0; |
| 3039 | 3038 | ||
| 3040 | /* | 3039 | /* |
| @@ -3121,9 +3120,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
| 3121 | return smack_net_ambient; | 3120 | return smack_net_ambient; |
| 3122 | } | 3121 | } |
| 3123 | 3122 | ||
| 3124 | static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap) | 3123 | static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) |
| 3125 | { | 3124 | { |
| 3126 | struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; | ||
| 3127 | u8 nexthdr; | 3125 | u8 nexthdr; |
| 3128 | int offset; | 3126 | int offset; |
| 3129 | int proto = -EINVAL; | 3127 | int proto = -EINVAL; |
| @@ -3181,7 +3179,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3181 | struct netlbl_lsm_secattr secattr; | 3179 | struct netlbl_lsm_secattr secattr; |
| 3182 | struct socket_smack *ssp = sk->sk_security; | 3180 | struct socket_smack *ssp = sk->sk_security; |
| 3183 | struct smack_known *skp; | 3181 | struct smack_known *skp; |
| 3184 | struct sockaddr sadd; | 3182 | struct sockaddr_in6 sadd; |
| 3185 | int rc = 0; | 3183 | int rc = 0; |
| 3186 | struct smk_audit_info ad; | 3184 | struct smk_audit_info ad; |
| 3187 | #ifdef CONFIG_AUDIT | 3185 | #ifdef CONFIG_AUDIT |
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index ce431e6e07cf..5066a3768b28 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
| @@ -14,12 +14,14 @@ | |||
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/dmaengine.h> | ||
| 17 | 18 | ||
| 18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
| 19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
| 20 | #include <sound/ac97_codec.h> | 21 | #include <sound/ac97_codec.h> |
| 21 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
| 22 | #include <sound/pxa2xx-lib.h> | 23 | #include <sound/pxa2xx-lib.h> |
| 24 | #include <sound/dmaengine_pcm.h> | ||
| 23 | 25 | ||
| 24 | #include <mach/regs-ac97.h> | 26 | #include <mach/regs-ac97.h> |
| 25 | #include <mach/audio.h> | 27 | #include <mach/audio.h> |
| @@ -41,20 +43,20 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { | |||
| 41 | .reset = pxa2xx_ac97_reset, | 43 | .reset = pxa2xx_ac97_reset, |
| 42 | }; | 44 | }; |
| 43 | 45 | ||
| 44 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { | 46 | static unsigned long pxa2xx_ac97_pcm_out_req = 12; |
| 45 | .name = "AC97 PCM out", | 47 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = { |
| 46 | .dev_addr = __PREG(PCDR), | 48 | .addr = __PREG(PCDR), |
| 47 | .drcmr = &DRCMR(12), | 49 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 48 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | 50 | .maxburst = 32, |
| 49 | DCMD_BURST32 | DCMD_WIDTH4, | 51 | .filter_data = &pxa2xx_ac97_pcm_out_req, |
| 50 | }; | 52 | }; |
| 51 | 53 | ||
| 52 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { | 54 | static unsigned long pxa2xx_ac97_pcm_in_req = 11; |
| 53 | .name = "AC97 PCM in", | 55 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = { |
| 54 | .dev_addr = __PREG(PCDR), | 56 | .addr = __PREG(PCDR), |
| 55 | .drcmr = &DRCMR(11), | 57 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 56 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | 58 | .maxburst = 32, |
| 57 | DCMD_BURST32 | DCMD_WIDTH4, | 59 | .filter_data = &pxa2xx_ac97_pcm_in_req, |
| 58 | }; | 60 | }; |
| 59 | 61 | ||
| 60 | static struct snd_pcm *pxa2xx_ac97_pcm; | 62 | static struct snd_pcm *pxa2xx_ac97_pcm; |
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c index 823359ed95e1..a61d7a9a995e 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/arm/pxa2xx-pcm-lib.c | |||
| @@ -7,11 +7,13 @@ | |||
| 7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/dmaengine.h> | ||
| 10 | 11 | ||
| 11 | #include <sound/core.h> | 12 | #include <sound/core.h> |
| 12 | #include <sound/pcm.h> | 13 | #include <sound/pcm.h> |
| 13 | #include <sound/pcm_params.h> | 14 | #include <sound/pcm_params.h> |
| 14 | #include <sound/pxa2xx-lib.h> | 15 | #include <sound/pxa2xx-lib.h> |
| 16 | #include <sound/dmaengine_pcm.h> | ||
| 15 | 17 | ||
| 16 | #include <mach/dma.h> | 18 | #include <mach/dma.h> |
| 17 | 19 | ||
| @@ -43,6 +45,35 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 43 | size_t period = params_period_bytes(params); | 45 | size_t period = params_period_bytes(params); |
| 44 | pxa_dma_desc *dma_desc; | 46 | pxa_dma_desc *dma_desc; |
| 45 | dma_addr_t dma_buff_phys, next_desc_phys; | 47 | dma_addr_t dma_buff_phys, next_desc_phys; |
| 48 | u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; | ||
| 49 | |||
| 50 | /* temporary transition hack */ | ||
| 51 | switch (rtd->params->addr_width) { | ||
| 52 | case DMA_SLAVE_BUSWIDTH_1_BYTE: | ||
| 53 | dcmd |= DCMD_WIDTH1; | ||
| 54 | break; | ||
| 55 | case DMA_SLAVE_BUSWIDTH_2_BYTES: | ||
| 56 | dcmd |= DCMD_WIDTH2; | ||
| 57 | break; | ||
| 58 | case DMA_SLAVE_BUSWIDTH_4_BYTES: | ||
| 59 | dcmd |= DCMD_WIDTH4; | ||
| 60 | break; | ||
| 61 | default: | ||
| 62 | /* can't happen */ | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | switch (rtd->params->maxburst) { | ||
| 67 | case 8: | ||
| 68 | dcmd |= DCMD_BURST8; | ||
| 69 | break; | ||
| 70 | case 16: | ||
| 71 | dcmd |= DCMD_BURST16; | ||
| 72 | break; | ||
| 73 | case 32: | ||
| 74 | dcmd |= DCMD_BURST32; | ||
| 75 | break; | ||
| 76 | } | ||
| 46 | 77 | ||
| 47 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 78 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
| 48 | runtime->dma_bytes = totsize; | 79 | runtime->dma_bytes = totsize; |
| @@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 55 | dma_desc->ddadr = next_desc_phys; | 86 | dma_desc->ddadr = next_desc_phys; |
| 56 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 87 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 57 | dma_desc->dsadr = dma_buff_phys; | 88 | dma_desc->dsadr = dma_buff_phys; |
| 58 | dma_desc->dtadr = rtd->params->dev_addr; | 89 | dma_desc->dtadr = rtd->params->addr; |
| 59 | } else { | 90 | } else { |
| 60 | dma_desc->dsadr = rtd->params->dev_addr; | 91 | dma_desc->dsadr = rtd->params->addr; |
| 61 | dma_desc->dtadr = dma_buff_phys; | 92 | dma_desc->dtadr = dma_buff_phys; |
| 62 | } | 93 | } |
| 63 | if (period > totsize) | 94 | if (period > totsize) |
| 64 | period = totsize; | 95 | period = totsize; |
| 65 | dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; | 96 | dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN; |
| 66 | dma_desc++; | 97 | dma_desc++; |
| 67 | dma_buff_phys += period; | 98 | dma_buff_phys += period; |
| 68 | } while (totsize -= period); | 99 | } while (totsize -= period); |
| @@ -76,8 +107,10 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
| 76 | { | 107 | { |
| 77 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | 108 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; |
| 78 | 109 | ||
| 79 | if (rtd && rtd->params && rtd->params->drcmr) | 110 | if (rtd && rtd->params && rtd->params->filter_data) { |
| 80 | *rtd->params->drcmr = 0; | 111 | unsigned long req = *(unsigned long *) rtd->params->filter_data; |
| 112 | DRCMR(req) = 0; | ||
| 113 | } | ||
| 81 | 114 | ||
| 82 | snd_pcm_set_runtime_buffer(substream, NULL); | 115 | snd_pcm_set_runtime_buffer(substream, NULL); |
| 83 | return 0; | 116 | return 0; |
| @@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer); | |||
| 136 | int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) | 169 | int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) |
| 137 | { | 170 | { |
| 138 | struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; | 171 | struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; |
| 172 | unsigned long req; | ||
| 139 | 173 | ||
| 140 | if (!prtd || !prtd->params) | 174 | if (!prtd || !prtd->params) |
| 141 | return 0; | 175 | return 0; |
| @@ -146,7 +180,8 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 146 | DCSR(prtd->dma_ch) &= ~DCSR_RUN; | 180 | DCSR(prtd->dma_ch) &= ~DCSR_RUN; |
| 147 | DCSR(prtd->dma_ch) = 0; | 181 | DCSR(prtd->dma_ch) = 0; |
| 148 | DCMD(prtd->dma_ch) = 0; | 182 | DCMD(prtd->dma_ch) = 0; |
| 149 | *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD; | 183 | req = *(unsigned long *) prtd->params->filter_data; |
| 184 | DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD; | ||
| 150 | 185 | ||
| 151 | return 0; | 186 | return 0; |
| 152 | } | 187 | } |
| @@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare); | |||
| 155 | void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) | 190 | void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) |
| 156 | { | 191 | { |
| 157 | struct snd_pcm_substream *substream = dev_id; | 192 | struct snd_pcm_substream *substream = dev_id; |
| 158 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
| 159 | int dcsr; | 193 | int dcsr; |
| 160 | 194 | ||
| 161 | dcsr = DCSR(dma_ch); | 195 | dcsr = DCSR(dma_ch); |
| @@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) | |||
| 164 | if (dcsr & DCSR_ENDINTR) { | 198 | if (dcsr & DCSR_ENDINTR) { |
| 165 | snd_pcm_period_elapsed(substream); | 199 | snd_pcm_period_elapsed(substream); |
| 166 | } else { | 200 | } else { |
| 167 | printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", | 201 | printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n", |
| 168 | rtd->params->name, dma_ch, dcsr); | 202 | dma_ch, dcsr); |
| 169 | snd_pcm_stream_lock(substream); | 203 | snd_pcm_stream_lock(substream); |
| 170 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | 204 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); |
| 171 | snd_pcm_stream_unlock(substream); | 205 | snd_pcm_stream_unlock(substream); |
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c index 26422a3584ea..69a2455b4472 100644 --- a/sound/arm/pxa2xx-pcm.c +++ b/sound/arm/pxa2xx-pcm.c | |||
| @@ -11,8 +11,11 @@ | |||
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/dmaengine.h> | ||
| 15 | |||
| 14 | #include <sound/core.h> | 16 | #include <sound/core.h> |
| 15 | #include <sound/pxa2xx-lib.h> | 17 | #include <sound/pxa2xx-lib.h> |
| 18 | #include <sound/dmaengine_pcm.h> | ||
| 16 | 19 | ||
| 17 | #include "pxa2xx-pcm.h" | 20 | #include "pxa2xx-pcm.h" |
| 18 | 21 | ||
| @@ -40,7 +43,7 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) | |||
| 40 | 43 | ||
| 41 | rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 44 | rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 42 | client->playback_params : client->capture_params; | 45 | client->playback_params : client->capture_params; |
| 43 | ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW, | 46 | ret = pxa_request_dma("dma", DMA_PRIO_LOW, |
| 44 | pxa2xx_pcm_dma_irq, substream); | 47 | pxa2xx_pcm_dma_irq, substream); |
| 45 | if (ret < 0) | 48 | if (ret < 0) |
| 46 | goto err2; | 49 | goto err2; |
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h index 65f86b56ba42..2a8fc08d52a1 100644 --- a/sound/arm/pxa2xx-pcm.h +++ b/sound/arm/pxa2xx-pcm.h | |||
| @@ -13,14 +13,14 @@ | |||
| 13 | 13 | ||
| 14 | struct pxa2xx_runtime_data { | 14 | struct pxa2xx_runtime_data { |
| 15 | int dma_ch; | 15 | int dma_ch; |
| 16 | struct pxa2xx_pcm_dma_params *params; | 16 | struct snd_dmaengine_dai_dma_data *params; |
| 17 | pxa_dma_desc *dma_desc_array; | 17 | pxa_dma_desc *dma_desc_array; |
| 18 | dma_addr_t dma_desc_array_phys; | 18 | dma_addr_t dma_desc_array_phys; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | struct pxa2xx_pcm_client { | 21 | struct pxa2xx_pcm_client { |
| 22 | struct pxa2xx_pcm_dma_params *playback_params; | 22 | struct snd_dmaengine_dai_dma_data *playback_params; |
| 23 | struct pxa2xx_pcm_dma_params *capture_params; | 23 | struct snd_dmaengine_dai_dma_data *capture_params; |
| 24 | int (*startup)(struct snd_pcm_substream *); | 24 | int (*startup)(struct snd_pcm_substream *); |
| 25 | void (*shutdown)(struct snd_pcm_substream *); | 25 | void (*shutdown)(struct snd_pcm_substream *); |
| 26 | int (*prepare)(struct snd_pcm_substream *); | 26 | int (*prepare)(struct snd_pcm_substream *); |
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index c0c2f57a0d6f..313f22e9d929 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
| @@ -6,6 +6,9 @@ config SND_PCM | |||
| 6 | tristate | 6 | tristate |
| 7 | select SND_TIMER | 7 | select SND_TIMER |
| 8 | 8 | ||
| 9 | config SND_DMAENGINE_PCM | ||
| 10 | tristate | ||
| 11 | |||
| 9 | config SND_HWDEP | 12 | config SND_HWDEP |
| 10 | tristate | 13 | tristate |
| 11 | 14 | ||
diff --git a/sound/core/Makefile b/sound/core/Makefile index 43d4117428ac..5e890cfed423 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile | |||
| @@ -13,6 +13,8 @@ snd-$(CONFIG_SND_JACK) += jack.o | |||
| 13 | snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ | 13 | snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ |
| 14 | pcm_memory.o | 14 | pcm_memory.o |
| 15 | 15 | ||
| 16 | snd-pcm-dmaengine-objs := pcm_dmaengine.o | ||
| 17 | |||
| 16 | snd-page-alloc-y := memalloc.o | 18 | snd-page-alloc-y := memalloc.o |
| 17 | snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o | 19 | snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o |
| 18 | 20 | ||
| @@ -30,6 +32,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o | |||
| 30 | obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o | 32 | obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o |
| 31 | obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o | 33 | obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o |
| 32 | obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o | 34 | obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o |
| 35 | obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o | ||
| 33 | obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o | 36 | obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o |
| 34 | 37 | ||
| 35 | obj-$(CONFIG_SND_OSSEMUL) += oss/ | 38 | obj-$(CONFIG_SND_OSSEMUL) += oss/ |
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/core/pcm_dmaengine.c index aa924d9b7986..aa924d9b7986 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/core/pcm_dmaengine.c | |||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 8e77cbbad871..e3c7ba8d7582 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -522,7 +522,7 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1, | |||
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | #define nid_has_mute(codec, nid, dir) \ | 524 | #define nid_has_mute(codec, nid, dir) \ |
| 525 | check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) | 525 | check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) |
| 526 | #define nid_has_volume(codec, nid, dir) \ | 526 | #define nid_has_volume(codec, nid, dir) \ |
| 527 | check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS) | 527 | check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS) |
| 528 | 528 | ||
| @@ -624,7 +624,7 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid, | |||
| 624 | if (enable) | 624 | if (enable) |
| 625 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 625 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
| 626 | } | 626 | } |
| 627 | if (caps & AC_AMPCAP_MUTE) { | 627 | if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) { |
| 628 | if (!enable) | 628 | if (!enable) |
| 629 | val |= HDA_AMP_MUTE; | 629 | val |= HDA_AMP_MUTE; |
| 630 | } | 630 | } |
| @@ -648,7 +648,7 @@ static unsigned int get_amp_mask_to_modify(struct hda_codec *codec, | |||
| 648 | { | 648 | { |
| 649 | unsigned int mask = 0xff; | 649 | unsigned int mask = 0xff; |
| 650 | 650 | ||
| 651 | if (caps & AC_AMPCAP_MUTE) { | 651 | if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) { |
| 652 | if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL)) | 652 | if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL)) |
| 653 | mask &= ~0x80; | 653 | mask &= ~0x80; |
| 654 | } | 654 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8bd226149868..f303cd898515 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -1031,6 +1031,7 @@ enum { | |||
| 1031 | ALC880_FIXUP_GPIO2, | 1031 | ALC880_FIXUP_GPIO2, |
| 1032 | ALC880_FIXUP_MEDION_RIM, | 1032 | ALC880_FIXUP_MEDION_RIM, |
| 1033 | ALC880_FIXUP_LG, | 1033 | ALC880_FIXUP_LG, |
| 1034 | ALC880_FIXUP_LG_LW25, | ||
| 1034 | ALC880_FIXUP_W810, | 1035 | ALC880_FIXUP_W810, |
| 1035 | ALC880_FIXUP_EAPD_COEF, | 1036 | ALC880_FIXUP_EAPD_COEF, |
| 1036 | ALC880_FIXUP_TCL_S700, | 1037 | ALC880_FIXUP_TCL_S700, |
| @@ -1089,6 +1090,14 @@ static const struct hda_fixup alc880_fixups[] = { | |||
| 1089 | { } | 1090 | { } |
| 1090 | } | 1091 | } |
| 1091 | }, | 1092 | }, |
| 1093 | [ALC880_FIXUP_LG_LW25] = { | ||
| 1094 | .type = HDA_FIXUP_PINS, | ||
| 1095 | .v.pins = (const struct hda_pintbl[]) { | ||
| 1096 | { 0x1a, 0x0181344f }, /* line-in */ | ||
| 1097 | { 0x1b, 0x0321403f }, /* headphone */ | ||
| 1098 | { } | ||
| 1099 | } | ||
| 1100 | }, | ||
| 1092 | [ALC880_FIXUP_W810] = { | 1101 | [ALC880_FIXUP_W810] = { |
| 1093 | .type = HDA_FIXUP_PINS, | 1102 | .type = HDA_FIXUP_PINS, |
| 1094 | .v.pins = (const struct hda_pintbl[]) { | 1103 | .v.pins = (const struct hda_pintbl[]) { |
| @@ -1341,6 +1350,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { | |||
| 1341 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), | 1350 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), |
| 1342 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), | 1351 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), |
| 1343 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), | 1352 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), |
| 1353 | SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25), | ||
| 1344 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), | 1354 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), |
| 1345 | 1355 | ||
| 1346 | /* Below is the copied entries from alc880_quirks.c. | 1356 | /* Below is the copied entries from alc880_quirks.c. |
| @@ -4329,6 +4339,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
| 4329 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), | 4339 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), |
| 4330 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 4340 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
| 4331 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), | 4341 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), |
| 4342 | SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), | ||
| 4332 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 4343 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
| 4333 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 4344 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
| 4334 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 4345 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 45eeaa9f7fec..5138b8493051 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
| @@ -26,12 +26,9 @@ if SND_SOC | |||
| 26 | config SND_SOC_AC97_BUS | 26 | config SND_SOC_AC97_BUS |
| 27 | bool | 27 | bool |
| 28 | 28 | ||
| 29 | config SND_SOC_DMAENGINE_PCM | ||
| 30 | bool | ||
| 31 | |||
| 32 | config SND_SOC_GENERIC_DMAENGINE_PCM | 29 | config SND_SOC_GENERIC_DMAENGINE_PCM |
| 33 | bool | 30 | bool |
| 34 | select SND_SOC_DMAENGINE_PCM | 31 | select SND_DMAENGINE_PCM |
| 35 | 32 | ||
| 36 | # All the supported SoCs | 33 | # All the supported SoCs |
| 37 | source "sound/soc/atmel/Kconfig" | 34 | source "sound/soc/atmel/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index bc0261476d7a..61a64d281905 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
| @@ -1,10 +1,6 @@ | |||
| 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
| 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o |
| 3 | 3 | ||
| 4 | ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) | ||
| 5 | snd-soc-core-objs += soc-dmaengine-pcm.o | ||
| 6 | endif | ||
| 7 | |||
| 8 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | 4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) |
| 9 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
| 10 | endif | 6 | endif |
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 3fdd87fa18a9..e48d38a1b95c 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
| @@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC | |||
| 13 | config SND_ATMEL_SOC_DMA | 13 | config SND_ATMEL_SOC_DMA |
| 14 | tristate | 14 | tristate |
| 15 | depends on SND_ATMEL_SOC | 15 | depends on SND_ATMEL_SOC |
| 16 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
| 16 | 17 | ||
| 17 | config SND_ATMEL_SOC_SSC | 18 | config SND_ATMEL_SOC_SSC |
| 18 | tristate | 19 | tristate |
| @@ -32,6 +33,26 @@ config SND_AT91_SOC_SAM9G20_WM8731 | |||
| 32 | Say Y if you want to add support for SoC audio on WM8731-based | 33 | Say Y if you want to add support for SoC audio on WM8731-based |
| 33 | AT91sam9g20 evaluation board. | 34 | AT91sam9g20 evaluation board. |
| 34 | 35 | ||
| 36 | config SND_ATMEL_SOC_WM8904 | ||
| 37 | tristate "Atmel ASoC driver for boards using WM8904 codec" | ||
| 38 | depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC | ||
| 39 | select SND_ATMEL_SOC_SSC | ||
| 40 | select SND_ATMEL_SOC_DMA | ||
| 41 | select SND_SOC_WM8904 | ||
| 42 | help | ||
| 43 | Say Y if you want to add support for Atmel ASoC driver for boards using | ||
| 44 | WM8904 codec. | ||
| 45 | |||
| 46 | config SND_AT91_SOC_SAM9X5_WM8731 | ||
| 47 | tristate "SoC Audio support for WM8731-based at91sam9x5 board" | ||
| 48 | depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5 | ||
| 49 | select SND_ATMEL_SOC_SSC | ||
| 50 | select SND_ATMEL_SOC_DMA | ||
| 51 | select SND_SOC_WM8731 | ||
| 52 | help | ||
| 53 | Say Y if you want to add support for audio SoC on an | ||
| 54 | at91sam9x5 based board that is using WM8731 codec. | ||
| 55 | |||
| 35 | config SND_AT91_SOC_AFEB9260 | 56 | config SND_AT91_SOC_AFEB9260 |
| 36 | tristate "SoC Audio support for AFEB9260 board" | 57 | tristate "SoC Audio support for AFEB9260 board" |
| 37 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC | 58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC |
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index 41967ccb6f41..5baabc8bde3a 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile | |||
| @@ -11,6 +11,10 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o | |||
| 11 | 11 | ||
| 12 | # AT91 Machine Support | 12 | # AT91 Machine Support |
| 13 | snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o | 13 | snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o |
| 14 | snd-atmel-soc-wm8904-objs := atmel_wm8904.o | ||
| 15 | snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o | ||
| 14 | 16 | ||
| 15 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o | 17 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o |
| 18 | obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o | ||
| 19 | obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o | ||
| 16 | obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o | 20 | obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o |
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index d12826526798..06082e5e5dcb 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c | |||
| @@ -91,138 +91,52 @@ static void atmel_pcm_dma_irq(u32 ssc_sr, | |||
| 91 | } | 91 | } |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | /*--------------------------------------------------------------------------*\ | ||
| 95 | * DMAENGINE operations | ||
| 96 | \*--------------------------------------------------------------------------*/ | ||
| 97 | static bool filter(struct dma_chan *chan, void *slave) | ||
| 98 | { | ||
| 99 | struct at_dma_slave *sl = slave; | ||
| 100 | |||
| 101 | if (sl->dma_dev == chan->device->dev) { | ||
| 102 | chan->private = sl; | ||
| 103 | return true; | ||
| 104 | } else { | ||
| 105 | return false; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, | 94 | static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, |
| 110 | struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd) | 95 | struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) |
| 111 | { | 96 | { |
| 97 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 98 | struct atmel_pcm_dma_params *prtd; | ||
| 112 | struct ssc_device *ssc; | 99 | struct ssc_device *ssc; |
| 113 | struct dma_chan *dma_chan; | ||
| 114 | struct dma_slave_config slave_config; | ||
| 115 | int ret; | 100 | int ret; |
| 116 | 101 | ||
| 102 | prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
| 117 | ssc = prtd->ssc; | 103 | ssc = prtd->ssc; |
| 118 | 104 | ||
| 119 | ret = snd_hwparams_to_dma_slave_config(substream, params, | 105 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); |
| 120 | &slave_config); | ||
| 121 | if (ret) { | 106 | if (ret) { |
| 122 | pr_err("atmel-pcm: hwparams to dma slave configure failed\n"); | 107 | pr_err("atmel-pcm: hwparams to dma slave configure failed\n"); |
| 123 | return ret; | 108 | return ret; |
| 124 | } | 109 | } |
| 125 | 110 | ||
| 126 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 111 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 127 | slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR; | 112 | slave_config->dst_addr = ssc->phybase + SSC_THR; |
| 128 | slave_config.dst_maxburst = 1; | 113 | slave_config->dst_maxburst = 1; |
| 129 | } else { | 114 | } else { |
| 130 | slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR; | 115 | slave_config->src_addr = ssc->phybase + SSC_RHR; |
| 131 | slave_config.src_maxburst = 1; | 116 | slave_config->src_maxburst = 1; |
| 132 | } | ||
| 133 | |||
| 134 | dma_chan = snd_dmaengine_pcm_get_chan(substream); | ||
| 135 | if (dmaengine_slave_config(dma_chan, &slave_config)) { | ||
| 136 | pr_err("atmel-pcm: failed to configure dma channel\n"); | ||
| 137 | ret = -EBUSY; | ||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, | ||
| 145 | struct snd_pcm_hw_params *params) | ||
| 146 | { | ||
| 147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 148 | struct atmel_pcm_dma_params *prtd; | ||
| 149 | struct ssc_device *ssc; | ||
| 150 | struct at_dma_slave *sdata = NULL; | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
| 154 | |||
| 155 | prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
| 156 | ssc = prtd->ssc; | ||
| 157 | if (ssc->pdev) | ||
| 158 | sdata = ssc->pdev->dev.platform_data; | ||
| 159 | |||
| 160 | ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata); | ||
| 161 | if (ret) { | ||
| 162 | pr_err("atmel-pcm: dmaengine pcm open failed\n"); | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | |||
| 166 | ret = atmel_pcm_configure_dma(substream, params, prtd); | ||
| 167 | if (ret) { | ||
| 168 | pr_err("atmel-pcm: failed to configure dmai\n"); | ||
| 169 | goto err; | ||
| 170 | } | 117 | } |
| 171 | 118 | ||
| 172 | prtd->dma_intr_handler = atmel_pcm_dma_irq; | 119 | prtd->dma_intr_handler = atmel_pcm_dma_irq; |
| 173 | 120 | ||
| 174 | return 0; | 121 | return 0; |
| 175 | err: | ||
| 176 | snd_dmaengine_pcm_close_release_chan(substream); | ||
| 177 | return ret; | ||
| 178 | } | 122 | } |
| 179 | 123 | ||
| 180 | static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) | 124 | static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = { |
| 181 | { | 125 | .prepare_slave_config = atmel_pcm_configure_dma, |
| 182 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 126 | .pcm_hardware = &atmel_pcm_dma_hardware, |
| 183 | struct atmel_pcm_dma_params *prtd; | 127 | .prealloc_buffer_size = ATMEL_SSC_DMABUF_SIZE, |
| 184 | |||
| 185 | prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
| 186 | |||
| 187 | ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error); | ||
| 188 | ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable); | ||
| 189 | |||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int atmel_pcm_open(struct snd_pcm_substream *substream) | ||
| 194 | { | ||
| 195 | snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static struct snd_pcm_ops atmel_pcm_ops = { | ||
| 201 | .open = atmel_pcm_open, | ||
| 202 | .close = snd_dmaengine_pcm_close_release_chan, | ||
| 203 | .ioctl = snd_pcm_lib_ioctl, | ||
| 204 | .hw_params = atmel_pcm_hw_params, | ||
| 205 | .prepare = atmel_pcm_dma_prepare, | ||
| 206 | .trigger = snd_dmaengine_pcm_trigger, | ||
| 207 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
| 208 | .mmap = atmel_pcm_mmap, | ||
| 209 | }; | ||
| 210 | |||
| 211 | static struct snd_soc_platform_driver atmel_soc_platform = { | ||
| 212 | .ops = &atmel_pcm_ops, | ||
| 213 | .pcm_new = atmel_pcm_new, | ||
| 214 | .pcm_free = atmel_pcm_free, | ||
| 215 | }; | 128 | }; |
| 216 | 129 | ||
| 217 | int atmel_pcm_dma_platform_register(struct device *dev) | 130 | int atmel_pcm_dma_platform_register(struct device *dev) |
| 218 | { | 131 | { |
| 219 | return snd_soc_register_platform(dev, &atmel_soc_platform); | 132 | return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config, |
| 133 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE); | ||
| 220 | } | 134 | } |
| 221 | EXPORT_SYMBOL(atmel_pcm_dma_platform_register); | 135 | EXPORT_SYMBOL(atmel_pcm_dma_platform_register); |
| 222 | 136 | ||
| 223 | void atmel_pcm_dma_platform_unregister(struct device *dev) | 137 | void atmel_pcm_dma_platform_unregister(struct device *dev) |
| 224 | { | 138 | { |
| 225 | snd_soc_unregister_platform(dev); | 139 | snd_dmaengine_pcm_unregister(dev); |
| 226 | } | 140 | } |
| 227 | EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister); | 141 | EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister); |
| 228 | 142 | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index f3fdfa07fcb9..0ecf356027f6 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
| @@ -73,6 +73,7 @@ static struct atmel_ssc_mask ssc_tx_mask = { | |||
| 73 | .ssc_disable = SSC_BIT(CR_TXDIS), | 73 | .ssc_disable = SSC_BIT(CR_TXDIS), |
| 74 | .ssc_endx = SSC_BIT(SR_ENDTX), | 74 | .ssc_endx = SSC_BIT(SR_ENDTX), |
| 75 | .ssc_endbuf = SSC_BIT(SR_TXBUFE), | 75 | .ssc_endbuf = SSC_BIT(SR_TXBUFE), |
| 76 | .ssc_error = SSC_BIT(SR_OVRUN), | ||
| 76 | .pdc_enable = ATMEL_PDC_TXTEN, | 77 | .pdc_enable = ATMEL_PDC_TXTEN, |
| 77 | .pdc_disable = ATMEL_PDC_TXTDIS, | 78 | .pdc_disable = ATMEL_PDC_TXTDIS, |
| 78 | }; | 79 | }; |
| @@ -82,6 +83,7 @@ static struct atmel_ssc_mask ssc_rx_mask = { | |||
| 82 | .ssc_disable = SSC_BIT(CR_RXDIS), | 83 | .ssc_disable = SSC_BIT(CR_RXDIS), |
| 83 | .ssc_endx = SSC_BIT(SR_ENDRX), | 84 | .ssc_endx = SSC_BIT(SR_ENDRX), |
| 84 | .ssc_endbuf = SSC_BIT(SR_RXBUFF), | 85 | .ssc_endbuf = SSC_BIT(SR_RXBUFF), |
| 86 | .ssc_error = SSC_BIT(SR_OVRUN), | ||
| 85 | .pdc_enable = ATMEL_PDC_RXTEN, | 87 | .pdc_enable = ATMEL_PDC_RXTEN, |
| 86 | .pdc_disable = ATMEL_PDC_RXTDIS, | 88 | .pdc_disable = ATMEL_PDC_RXTDIS, |
| 87 | }; | 89 | }; |
| @@ -196,15 +198,27 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, | |||
| 196 | struct snd_soc_dai *dai) | 198 | struct snd_soc_dai *dai) |
| 197 | { | 199 | { |
| 198 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; | 200 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; |
| 199 | int dir_mask; | 201 | struct atmel_pcm_dma_params *dma_params; |
| 202 | int dir, dir_mask; | ||
| 200 | 203 | ||
| 201 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", | 204 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", |
| 202 | ssc_readl(ssc_p->ssc->regs, SR)); | 205 | ssc_readl(ssc_p->ssc->regs, SR)); |
| 203 | 206 | ||
| 204 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 207 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 208 | dir = 0; | ||
| 205 | dir_mask = SSC_DIR_MASK_PLAYBACK; | 209 | dir_mask = SSC_DIR_MASK_PLAYBACK; |
| 206 | else | 210 | } else { |
| 211 | dir = 1; | ||
| 207 | dir_mask = SSC_DIR_MASK_CAPTURE; | 212 | dir_mask = SSC_DIR_MASK_CAPTURE; |
| 213 | } | ||
| 214 | |||
| 215 | dma_params = &ssc_dma_params[dai->id][dir]; | ||
| 216 | dma_params->ssc = ssc_p->ssc; | ||
| 217 | dma_params->substream = substream; | ||
| 218 | |||
| 219 | ssc_p->dma_params[dir] = dma_params; | ||
| 220 | |||
| 221 | snd_soc_dai_set_dma_data(dai, substream, dma_params); | ||
| 208 | 222 | ||
| 209 | spin_lock_irq(&ssc_p->lock); | 223 | spin_lock_irq(&ssc_p->lock); |
| 210 | if (ssc_p->dir_mask & dir_mask) { | 224 | if (ssc_p->dir_mask & dir_mask) { |
| @@ -325,7 +339,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 325 | struct snd_pcm_hw_params *params, | 339 | struct snd_pcm_hw_params *params, |
| 326 | struct snd_soc_dai *dai) | 340 | struct snd_soc_dai *dai) |
| 327 | { | 341 | { |
| 328 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
| 329 | int id = dai->id; | 342 | int id = dai->id; |
| 330 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; | 343 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; |
| 331 | struct atmel_pcm_dma_params *dma_params; | 344 | struct atmel_pcm_dma_params *dma_params; |
| @@ -344,19 +357,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 344 | else | 357 | else |
| 345 | dir = 1; | 358 | dir = 1; |
| 346 | 359 | ||
| 347 | dma_params = &ssc_dma_params[id][dir]; | 360 | dma_params = ssc_p->dma_params[dir]; |
| 348 | dma_params->ssc = ssc_p->ssc; | ||
| 349 | dma_params->substream = substream; | ||
| 350 | |||
| 351 | ssc_p->dma_params[dir] = dma_params; | ||
| 352 | |||
| 353 | /* | ||
| 354 | * The snd_soc_pcm_stream->dma_data field is only used to communicate | ||
| 355 | * the appropriate DMA parameters to the pcm driver hw_params() | ||
| 356 | * function. It should not be used for other purposes | ||
| 357 | * as it is common to all substreams. | ||
| 358 | */ | ||
| 359 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params); | ||
| 360 | 361 | ||
| 361 | channels = params_channels(params); | 362 | channels = params_channels(params); |
| 362 | 363 | ||
| @@ -648,6 +649,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | |||
| 648 | dma_params = ssc_p->dma_params[dir]; | 649 | dma_params = ssc_p->dma_params[dir]; |
| 649 | 650 | ||
| 650 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | 651 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); |
| 652 | ssc_writel(ssc_p->ssc->regs, IER, dma_params->mask->ssc_error); | ||
| 651 | 653 | ||
| 652 | pr_debug("%s enabled SSC_SR=0x%08x\n", | 654 | pr_debug("%s enabled SSC_SR=0x%08x\n", |
| 653 | dir ? "receive" : "transmit", | 655 | dir ? "receive" : "transmit", |
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c new file mode 100644 index 000000000000..7222380131ea --- /dev/null +++ b/sound/soc/atmel/atmel_wm8904.c | |||
| @@ -0,0 +1,254 @@ | |||
| 1 | /* | ||
| 2 | * atmel_wm8904 - Atmel ASoC driver for boards with WM8904 codec. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Atmel | ||
| 5 | * | ||
| 6 | * Author: Bo Shen <voice.shen@atmel.com> | ||
| 7 | * | ||
| 8 | * GPLv2 or later | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/of_device.h> | ||
| 15 | #include <linux/pinctrl/consumer.h> | ||
| 16 | |||
| 17 | #include <sound/soc.h> | ||
| 18 | |||
| 19 | #include "../codecs/wm8904.h" | ||
| 20 | #include "atmel_ssc_dai.h" | ||
| 21 | |||
| 22 | #define MCLK_RATE 32768 | ||
| 23 | |||
| 24 | static struct clk *mclk; | ||
| 25 | |||
| 26 | static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { | ||
| 27 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
| 28 | SND_SOC_DAPM_MIC("Mic", NULL), | ||
| 29 | SND_SOC_DAPM_LINE("Line In Jack", NULL), | ||
| 30 | }; | ||
| 31 | |||
| 32 | static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream, | ||
| 33 | struct snd_pcm_hw_params *params) | ||
| 34 | { | ||
| 35 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 36 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 37 | int ret; | ||
| 38 | |||
| 39 | ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK, | ||
| 40 | 32768, params_rate(params) * 256); | ||
| 41 | if (ret < 0) { | ||
| 42 | pr_err("%s - failed to set wm8904 codec PLL.", __func__); | ||
| 43 | return ret; | ||
| 44 | } | ||
| 45 | |||
| 46 | /* | ||
| 47 | * As here wm8904 use FLL output as its system clock | ||
| 48 | * so calling set_sysclk won't care freq parameter | ||
| 49 | * then we pass 0 | ||
| 50 | */ | ||
| 51 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_FLL, | ||
| 52 | 0, SND_SOC_CLOCK_IN); | ||
| 53 | if (ret < 0) { | ||
| 54 | pr_err("%s -failed to set wm8904 SYSCLK\n", __func__); | ||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static struct snd_soc_ops atmel_asoc_wm8904_ops = { | ||
| 62 | .hw_params = atmel_asoc_wm8904_hw_params, | ||
| 63 | }; | ||
| 64 | |||
| 65 | static int atmel_set_bias_level(struct snd_soc_card *card, | ||
| 66 | struct snd_soc_dapm_context *dapm, | ||
| 67 | enum snd_soc_bias_level level) | ||
| 68 | { | ||
| 69 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
| 70 | switch (level) { | ||
| 71 | case SND_SOC_BIAS_PREPARE: | ||
| 72 | clk_prepare_enable(mclk); | ||
| 73 | break; | ||
| 74 | case SND_SOC_BIAS_OFF: | ||
| 75 | clk_disable_unprepare(mclk); | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | }; | ||
| 84 | |||
| 85 | static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = { | ||
| 86 | .name = "WM8904", | ||
| 87 | .stream_name = "WM8904 PCM", | ||
| 88 | .codec_dai_name = "wm8904-hifi", | ||
| 89 | .dai_fmt = SND_SOC_DAIFMT_I2S | ||
| 90 | | SND_SOC_DAIFMT_NB_NF | ||
| 91 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 92 | .ops = &atmel_asoc_wm8904_ops, | ||
| 93 | }; | ||
| 94 | |||
| 95 | static struct snd_soc_card atmel_asoc_wm8904_card = { | ||
| 96 | .name = "atmel_asoc_wm8904", | ||
| 97 | .owner = THIS_MODULE, | ||
| 98 | .set_bias_level = atmel_set_bias_level, | ||
| 99 | .dai_link = &atmel_asoc_wm8904_dailink, | ||
| 100 | .num_links = 1, | ||
| 101 | .dapm_widgets = atmel_asoc_wm8904_dapm_widgets, | ||
| 102 | .num_dapm_widgets = ARRAY_SIZE(atmel_asoc_wm8904_dapm_widgets), | ||
| 103 | .fully_routed = true, | ||
| 104 | }; | ||
| 105 | |||
| 106 | static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev) | ||
| 107 | { | ||
| 108 | struct device_node *np = pdev->dev.of_node; | ||
| 109 | struct device_node *codec_np, *cpu_np; | ||
| 110 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; | ||
| 111 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | ||
| 112 | int ret; | ||
| 113 | |||
| 114 | if (!np) { | ||
| 115 | dev_err(&pdev->dev, "only device tree supported\n"); | ||
| 116 | return -EINVAL; | ||
| 117 | } | ||
| 118 | |||
| 119 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); | ||
| 120 | if (ret) { | ||
| 121 | dev_err(&pdev->dev, "failed to parse card name\n"); | ||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing"); | ||
| 126 | if (ret) { | ||
| 127 | dev_err(&pdev->dev, "failed to parse audio routing\n"); | ||
| 128 | return ret; | ||
| 129 | } | ||
| 130 | |||
| 131 | cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); | ||
| 132 | if (!cpu_np) { | ||
| 133 | dev_err(&pdev->dev, "failed to get dai and pcm info\n"); | ||
| 134 | ret = -EINVAL; | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | dailink->cpu_of_node = cpu_np; | ||
| 138 | dailink->platform_of_node = cpu_np; | ||
| 139 | of_node_put(cpu_np); | ||
| 140 | |||
| 141 | codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); | ||
| 142 | if (!codec_np) { | ||
| 143 | dev_err(&pdev->dev, "failed to get codec info\n"); | ||
| 144 | ret = -EINVAL; | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | dailink->codec_of_node = codec_np; | ||
| 148 | of_node_put(codec_np); | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int atmel_asoc_wm8904_probe(struct platform_device *pdev) | ||
| 154 | { | ||
| 155 | struct snd_soc_card *card = &atmel_asoc_wm8904_card; | ||
| 156 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | ||
| 157 | struct clk *clk_src; | ||
| 158 | struct pinctrl *pinctrl; | ||
| 159 | int id, ret; | ||
| 160 | |||
| 161 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
| 162 | if (IS_ERR(pinctrl)) { | ||
| 163 | dev_err(&pdev->dev, "failed to request pinctrl\n"); | ||
| 164 | return PTR_ERR(pinctrl); | ||
| 165 | } | ||
| 166 | |||
| 167 | card->dev = &pdev->dev; | ||
| 168 | ret = atmel_asoc_wm8904_dt_init(pdev); | ||
| 169 | if (ret) { | ||
| 170 | dev_err(&pdev->dev, "failed to init dt info\n"); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc"); | ||
| 175 | ret = atmel_ssc_set_audio(id); | ||
| 176 | if (ret != 0) { | ||
| 177 | dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id); | ||
| 178 | return ret; | ||
| 179 | } | ||
| 180 | |||
| 181 | mclk = clk_get(NULL, "pck0"); | ||
| 182 | if (IS_ERR(mclk)) { | ||
| 183 | dev_err(&pdev->dev, "failed to get pck0\n"); | ||
| 184 | ret = PTR_ERR(mclk); | ||
| 185 | goto err_set_audio; | ||
| 186 | } | ||
| 187 | |||
| 188 | clk_src = clk_get(NULL, "clk32k"); | ||
| 189 | if (IS_ERR(clk_src)) { | ||
| 190 | dev_err(&pdev->dev, "failed to get clk32k\n"); | ||
| 191 | ret = PTR_ERR(clk_src); | ||
| 192 | goto err_set_audio; | ||
| 193 | } | ||
| 194 | |||
| 195 | ret = clk_set_parent(mclk, clk_src); | ||
| 196 | clk_put(clk_src); | ||
| 197 | if (ret != 0) { | ||
| 198 | dev_err(&pdev->dev, "failed to set MCLK parent\n"); | ||
| 199 | goto err_set_audio; | ||
| 200 | } | ||
| 201 | |||
| 202 | dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE); | ||
| 203 | clk_set_rate(mclk, MCLK_RATE); | ||
| 204 | |||
| 205 | ret = snd_soc_register_card(card); | ||
| 206 | if (ret) { | ||
| 207 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); | ||
| 208 | goto err_set_audio; | ||
| 209 | } | ||
| 210 | |||
| 211 | return 0; | ||
| 212 | |||
| 213 | err_set_audio: | ||
| 214 | atmel_ssc_put_audio(id); | ||
| 215 | return ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | static int atmel_asoc_wm8904_remove(struct platform_device *pdev) | ||
| 219 | { | ||
| 220 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
| 221 | struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; | ||
| 222 | int id; | ||
| 223 | |||
| 224 | id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc"); | ||
| 225 | |||
| 226 | snd_soc_unregister_card(card); | ||
| 227 | atmel_ssc_put_audio(id); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | #ifdef CONFIG_OF | ||
| 233 | static const struct of_device_id atmel_asoc_wm8904_dt_ids[] = { | ||
| 234 | { .compatible = "atmel,asoc-wm8904", }, | ||
| 235 | { } | ||
| 236 | }; | ||
| 237 | #endif | ||
| 238 | |||
| 239 | static struct platform_driver atmel_asoc_wm8904_driver = { | ||
| 240 | .driver = { | ||
| 241 | .name = "atmel-wm8904-audio", | ||
| 242 | .owner = THIS_MODULE, | ||
| 243 | .of_match_table = of_match_ptr(atmel_asoc_wm8904_dt_ids), | ||
| 244 | }, | ||
| 245 | .probe = atmel_asoc_wm8904_probe, | ||
| 246 | .remove = atmel_asoc_wm8904_remove, | ||
| 247 | }; | ||
| 248 | |||
| 249 | module_platform_driver(atmel_asoc_wm8904_driver); | ||
| 250 | |||
| 251 | /* Module information */ | ||
| 252 | MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>"); | ||
| 253 | MODULE_DESCRIPTION("ALSA SoC machine driver for Atmel EK with WM8904 codec"); | ||
| 254 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c new file mode 100644 index 000000000000..992ae38d5a15 --- /dev/null +++ b/sound/soc/atmel/sam9x5_wm8731.c | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /* | ||
| 2 | * sam9x5_wm8731 -- SoC audio for AT91SAM9X5-based boards | ||
| 3 | * that are using WM8731 as codec. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2011 Atmel, | ||
| 6 | * Nicolas Ferre <nicolas.ferre@atmel.com> | ||
| 7 | * | ||
| 8 | * Copyright (C) 2013 Paratronic, | ||
| 9 | * Richard Genoud <richard.genoud@gmail.com> | ||
| 10 | * | ||
| 11 | * Based on sam9g20_wm8731.c by: | ||
| 12 | * Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify it | ||
| 15 | * under the terms of the GNU General Public License as published by the | ||
| 16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 17 | * option) any later version. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/export.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/mod_devicetable.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/device.h> | ||
| 26 | |||
| 27 | #include <sound/soc.h> | ||
| 28 | #include <sound/soc-dai.h> | ||
| 29 | #include <sound/soc-dapm.h> | ||
| 30 | |||
| 31 | #include "../codecs/wm8731.h" | ||
| 32 | #include "atmel_ssc_dai.h" | ||
| 33 | |||
| 34 | |||
| 35 | #define MCLK_RATE 12288000 | ||
| 36 | |||
| 37 | #define DRV_NAME "sam9x5-snd-wm8731" | ||
| 38 | |||
| 39 | struct sam9x5_drvdata { | ||
| 40 | int ssc_id; | ||
| 41 | }; | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Logic for a wm8731 as connected on a at91sam9x5ek based board. | ||
| 45 | */ | ||
| 46 | static int sam9x5_wm8731_init(struct snd_soc_pcm_runtime *rtd) | ||
| 47 | { | ||
| 48 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 49 | struct device *dev = rtd->dev; | ||
| 50 | int ret; | ||
| 51 | |||
| 52 | dev_dbg(dev, "ASoC: %s called\n", __func__); | ||
| 53 | |||
| 54 | /* set the codec system clock for DAC and ADC */ | ||
| 55 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, | ||
| 56 | MCLK_RATE, SND_SOC_CLOCK_IN); | ||
| 57 | if (ret < 0) { | ||
| 58 | dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Audio paths on at91sam9x5ek board: | ||
| 67 | * | ||
| 68 | * |A| ------------> | | ---R----> Headphone Jack | ||
| 69 | * |T| <----\ | WM | ---L--/ | ||
| 70 | * |9| ---> CLK <--> | 8731 | <--R----- Line In Jack | ||
| 71 | * |1| <------------ | | <--L--/ | ||
| 72 | */ | ||
| 73 | static const struct snd_soc_dapm_widget sam9x5_dapm_widgets[] = { | ||
| 74 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
| 75 | SND_SOC_DAPM_LINE("Line In Jack", NULL), | ||
| 76 | }; | ||
| 77 | |||
| 78 | static int sam9x5_wm8731_driver_probe(struct platform_device *pdev) | ||
| 79 | { | ||
| 80 | struct device_node *np = pdev->dev.of_node; | ||
| 81 | struct device_node *codec_np, *cpu_np; | ||
| 82 | struct snd_soc_card *card; | ||
| 83 | struct snd_soc_dai_link *dai; | ||
| 84 | struct sam9x5_drvdata *priv; | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | if (!np) { | ||
| 88 | dev_err(&pdev->dev, "No device node supplied\n"); | ||
| 89 | return -EINVAL; | ||
| 90 | } | ||
| 91 | |||
| 92 | card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); | ||
| 93 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
| 94 | dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); | ||
| 95 | if (!dai || !card || !priv) { | ||
| 96 | ret = -ENOMEM; | ||
| 97 | goto out; | ||
| 98 | } | ||
| 99 | |||
| 100 | card->dev = &pdev->dev; | ||
| 101 | card->owner = THIS_MODULE; | ||
| 102 | card->dai_link = dai; | ||
| 103 | card->num_links = 1; | ||
| 104 | card->dapm_widgets = sam9x5_dapm_widgets; | ||
| 105 | card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets); | ||
| 106 | dai->name = "WM8731"; | ||
| 107 | dai->stream_name = "WM8731 PCM"; | ||
| 108 | dai->codec_dai_name = "wm8731-hifi"; | ||
| 109 | dai->init = sam9x5_wm8731_init; | ||
| 110 | dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 111 | | SND_SOC_DAIFMT_CBM_CFM; | ||
| 112 | |||
| 113 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); | ||
| 114 | if (ret) { | ||
| 115 | dev_err(&pdev->dev, "atmel,model node missing\n"); | ||
| 116 | goto out; | ||
| 117 | } | ||
| 118 | |||
| 119 | ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing"); | ||
| 120 | if (ret) { | ||
| 121 | dev_err(&pdev->dev, "atmel,audio-routing node missing\n"); | ||
| 122 | goto out; | ||
| 123 | } | ||
| 124 | |||
| 125 | codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); | ||
| 126 | if (!codec_np) { | ||
| 127 | dev_err(&pdev->dev, "atmel,audio-codec node missing\n"); | ||
| 128 | ret = -EINVAL; | ||
| 129 | goto out; | ||
| 130 | } | ||
| 131 | |||
| 132 | dai->codec_of_node = codec_np; | ||
| 133 | |||
| 134 | cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); | ||
| 135 | if (!cpu_np) { | ||
| 136 | dev_err(&pdev->dev, "atmel,ssc-controller node missing\n"); | ||
| 137 | ret = -EINVAL; | ||
| 138 | goto out; | ||
| 139 | } | ||
| 140 | dai->cpu_of_node = cpu_np; | ||
| 141 | dai->platform_of_node = cpu_np; | ||
| 142 | |||
| 143 | priv->ssc_id = of_alias_get_id(cpu_np, "ssc"); | ||
| 144 | |||
| 145 | ret = atmel_ssc_set_audio(priv->ssc_id); | ||
| 146 | if (ret != 0) { | ||
| 147 | dev_err(&pdev->dev, | ||
| 148 | "ASoC: Failed to set SSC %d for audio: %d\n", | ||
| 149 | ret, priv->ssc_id); | ||
| 150 | goto out; | ||
| 151 | } | ||
| 152 | |||
| 153 | of_node_put(codec_np); | ||
| 154 | of_node_put(cpu_np); | ||
| 155 | |||
| 156 | platform_set_drvdata(pdev, card); | ||
| 157 | |||
| 158 | ret = snd_soc_register_card(card); | ||
| 159 | if (ret) { | ||
| 160 | dev_err(&pdev->dev, | ||
| 161 | "ASoC: Platform device allocation failed\n"); | ||
| 162 | goto out_put_audio; | ||
| 163 | } | ||
| 164 | |||
| 165 | dev_dbg(&pdev->dev, "ASoC: %s ok\n", __func__); | ||
| 166 | |||
| 167 | return ret; | ||
| 168 | |||
| 169 | out_put_audio: | ||
| 170 | atmel_ssc_put_audio(priv->ssc_id); | ||
| 171 | out: | ||
| 172 | return ret; | ||
| 173 | } | ||
| 174 | |||
| 175 | static int sam9x5_wm8731_driver_remove(struct platform_device *pdev) | ||
| 176 | { | ||
| 177 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
| 178 | struct sam9x5_drvdata *priv = card->drvdata; | ||
| 179 | |||
| 180 | snd_soc_unregister_card(card); | ||
| 181 | atmel_ssc_put_audio(priv->ssc_id); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static const struct of_device_id sam9x5_wm8731_of_match[] = { | ||
| 187 | { .compatible = "atmel,sam9x5-wm8731-audio", }, | ||
| 188 | {}, | ||
| 189 | }; | ||
| 190 | MODULE_DEVICE_TABLE(of, sam9x5_wm8731_of_match); | ||
| 191 | |||
| 192 | static struct platform_driver sam9x5_wm8731_driver = { | ||
| 193 | .driver = { | ||
| 194 | .name = DRV_NAME, | ||
| 195 | .owner = THIS_MODULE, | ||
| 196 | .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), | ||
| 197 | }, | ||
| 198 | .probe = sam9x5_wm8731_driver_probe, | ||
| 199 | .remove = sam9x5_wm8731_driver_remove, | ||
| 200 | }; | ||
| 201 | module_platform_driver(sam9x5_wm8731_driver); | ||
| 202 | |||
| 203 | /* Module information */ | ||
| 204 | MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); | ||
| 205 | MODULE_AUTHOR("Richard Genoud <richard.genoud@gmail.com>"); | ||
| 206 | MODULE_DESCRIPTION("ALSA SoC machine driver for AT91SAM9x5 - WM8731"); | ||
| 207 | MODULE_LICENSE("GPL"); | ||
| 208 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index a497a0cfeba1..decba87a074c 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
| @@ -73,12 +73,14 @@ static struct snd_soc_dai_link db1300_ac97_dai = { | |||
| 73 | 73 | ||
| 74 | static struct snd_soc_card db1300_ac97_machine = { | 74 | static struct snd_soc_card db1300_ac97_machine = { |
| 75 | .name = "DB1300_AC97", | 75 | .name = "DB1300_AC97", |
| 76 | .owner = THIS_MODULE, | ||
| 76 | .dai_link = &db1300_ac97_dai, | 77 | .dai_link = &db1300_ac97_dai, |
| 77 | .num_links = 1, | 78 | .num_links = 1, |
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 80 | static struct snd_soc_card db1550_ac97_machine = { | 81 | static struct snd_soc_card db1550_ac97_machine = { |
| 81 | .name = "DB1550_AC97", | 82 | .name = "DB1550_AC97", |
| 83 | .owner = THIS_MODULE, | ||
| 82 | .dai_link = &db1200_ac97_dai, | 84 | .dai_link = &db1200_ac97_dai, |
| 83 | .num_links = 1, | 85 | .num_links = 1, |
| 84 | }; | 86 | }; |
| @@ -145,6 +147,7 @@ static struct snd_soc_dai_link db1300_i2s_dai = { | |||
| 145 | 147 | ||
| 146 | static struct snd_soc_card db1300_i2s_machine = { | 148 | static struct snd_soc_card db1300_i2s_machine = { |
| 147 | .name = "DB1300_I2S", | 149 | .name = "DB1300_I2S", |
| 150 | .owner = THIS_MODULE, | ||
| 148 | .dai_link = &db1300_i2s_dai, | 151 | .dai_link = &db1300_i2s_dai, |
| 149 | .num_links = 1, | 152 | .num_links = 1, |
| 150 | }; | 153 | }; |
| @@ -161,6 +164,7 @@ static struct snd_soc_dai_link db1550_i2s_dai = { | |||
| 161 | 164 | ||
| 162 | static struct snd_soc_card db1550_i2s_machine = { | 165 | static struct snd_soc_card db1550_i2s_machine = { |
| 163 | .name = "DB1550_I2S", | 166 | .name = "DB1550_I2S", |
| 167 | .owner = THIS_MODULE, | ||
| 164 | .dai_link = &db1550_i2s_dai, | 168 | .dai_link = &db1550_i2s_dai, |
| 165 | .num_links = 1, | 169 | .num_links = 1, |
| 166 | }; | 170 | }; |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index a822ab822bb7..986dcec79fa0 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
| @@ -379,9 +379,6 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
| 379 | mutex_init(&wd->lock); | 379 | mutex_init(&wd->lock); |
| 380 | 380 | ||
| 381 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 381 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 382 | if (!iores) | ||
| 383 | return -ENODEV; | ||
| 384 | |||
| 385 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); | 382 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); |
| 386 | if (IS_ERR(wd->mmio)) | 383 | if (IS_ERR(wd->mmio)) |
| 387 | return PTR_ERR(wd->mmio); | 384 | return PTR_ERR(wd->mmio); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index 0c3e22d90a8d..a680fdc9bb42 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #ifndef _BF5XX_AC97_H | 9 | #ifndef _BF5XX_AC97_H |
| 10 | #define _BF5XX_AC97_H | 10 | #define _BF5XX_AC97_H |
| 11 | 11 | ||
| 12 | extern struct snd_ac97 *ac97; | ||
| 13 | /* Frame format in memory, only support stereo currently */ | 12 | /* Frame format in memory, only support stereo currently */ |
| 14 | struct ac97_frame { | 13 | struct ac97_frame { |
| 15 | u16 ac97_tag; /* slot 0 */ | 14 | u16 ac97_tag; /* slot 0 */ |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 04491f0e8d1b..efa75b5086a4 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
| @@ -363,9 +363,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
| 363 | return -ENOMEM; | 363 | return -ENOMEM; |
| 364 | 364 | ||
| 365 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 365 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 366 | if (!res) | ||
| 367 | return -ENODEV; | ||
| 368 | |||
| 369 | info->regs = devm_ioremap_resource(&pdev->dev, res); | 366 | info->regs = devm_ioremap_resource(&pdev->dev, res); |
| 370 | if (IS_ERR(info->regs)) | 367 | if (IS_ERR(info->regs)) |
| 371 | return PTR_ERR(info->regs); | 368 | return PTR_ERR(info->regs); |
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 17ad70bca9fe..f23f331e9a97 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
| @@ -376,9 +376,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
| 376 | return -ENOMEM; | 376 | return -ENOMEM; |
| 377 | 377 | ||
| 378 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 378 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 379 | if (!res) | ||
| 380 | return -ENODEV; | ||
| 381 | |||
| 382 | info->regs = devm_ioremap_resource(&pdev->dev, res); | 379 | info->regs = devm_ioremap_resource(&pdev->dev, res); |
| 383 | if (IS_ERR(info->regs)) | 380 | if (IS_ERR(info->regs)) |
| 384 | return PTR_ERR(info->regs); | 381 | return PTR_ERR(info->regs); |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index badb6fbacaa6..15106c045478 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI | |||
| 10 | 10 | ||
| 11 | config SND_SOC_ALL_CODECS | 11 | config SND_SOC_ALL_CODECS |
| 12 | tristate "Build all ASoC CODEC drivers" | 12 | tristate "Build all ASoC CODEC drivers" |
| 13 | depends on COMPILE_TEST | ||
| 13 | select SND_SOC_88PM860X if MFD_88PM860X | 14 | select SND_SOC_88PM860X if MFD_88PM860X |
| 14 | select SND_SOC_L3 | 15 | select SND_SOC_L3 |
| 15 | select SND_SOC_AB8500_CODEC if ABX500_CORE | 16 | select SND_SOC_AB8500_CODEC if ABX500_CORE |
| @@ -20,6 +21,7 @@ config SND_SOC_ALL_CODECS | |||
| 20 | select SND_SOC_AD73311 | 21 | select SND_SOC_AD73311 |
| 21 | select SND_SOC_ADAU1373 if I2C | 22 | select SND_SOC_ADAU1373 if I2C |
| 22 | select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI | 23 | select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI |
| 24 | select SND_SOC_ADAU1701 if I2C | ||
| 23 | select SND_SOC_ADS117X | 25 | select SND_SOC_ADS117X |
| 24 | select SND_SOC_AK4104 if SPI_MASTER | 26 | select SND_SOC_AK4104 if SPI_MASTER |
| 25 | select SND_SOC_AK4535 if I2C | 27 | select SND_SOC_AK4535 if I2C |
| @@ -54,6 +56,8 @@ config SND_SOC_ALL_CODECS | |||
| 54 | select SND_SOC_MC13783 if MFD_MC13XXX | 56 | select SND_SOC_MC13783 if MFD_MC13XXX |
| 55 | select SND_SOC_ML26124 if I2C | 57 | select SND_SOC_ML26124 if I2C |
| 56 | select SND_SOC_HDMI_CODEC | 58 | select SND_SOC_HDMI_CODEC |
| 59 | select SND_SOC_PCM1681 if I2C | ||
| 60 | select SND_SOC_PCM1792A if SPI_MASTER | ||
| 57 | select SND_SOC_PCM3008 | 61 | select SND_SOC_PCM3008 |
| 58 | select SND_SOC_RT5631 if I2C | 62 | select SND_SOC_RT5631 if I2C |
| 59 | select SND_SOC_RT5640 if I2C | 63 | select SND_SOC_RT5640 if I2C |
| @@ -122,6 +126,7 @@ config SND_SOC_ALL_CODECS | |||
| 122 | select SND_SOC_WM8994 if MFD_WM8994 | 126 | select SND_SOC_WM8994 if MFD_WM8994 |
| 123 | select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI | 127 | select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI |
| 124 | select SND_SOC_WM8996 if I2C | 128 | select SND_SOC_WM8996 if I2C |
| 129 | select SND_SOC_WM8997 if MFD_WM8997 | ||
| 125 | select SND_SOC_WM9081 if I2C | 130 | select SND_SOC_WM9081 if I2C |
| 126 | select SND_SOC_WM9090 if I2C | 131 | select SND_SOC_WM9090 if I2C |
| 127 | select SND_SOC_WM9705 if SND_SOC_AC97_BUS | 132 | select SND_SOC_WM9705 if SND_SOC_AC97_BUS |
| @@ -145,8 +150,10 @@ config SND_SOC_ARIZONA | |||
| 145 | tristate | 150 | tristate |
| 146 | default y if SND_SOC_WM5102=y | 151 | default y if SND_SOC_WM5102=y |
| 147 | default y if SND_SOC_WM5110=y | 152 | default y if SND_SOC_WM5110=y |
| 153 | default y if SND_SOC_WM8997=y | ||
| 148 | default m if SND_SOC_WM5102=m | 154 | default m if SND_SOC_WM5102=m |
| 149 | default m if SND_SOC_WM5110=m | 155 | default m if SND_SOC_WM5110=m |
| 156 | default m if SND_SOC_WM8997=m | ||
| 150 | 157 | ||
| 151 | config SND_SOC_WM_HUBS | 158 | config SND_SOC_WM_HUBS |
| 152 | tristate | 159 | tristate |
| @@ -198,6 +205,9 @@ config SND_SOC_AK4104 | |||
| 198 | config SND_SOC_AK4535 | 205 | config SND_SOC_AK4535 |
| 199 | tristate | 206 | tristate |
| 200 | 207 | ||
| 208 | config SND_SOC_AK4554 | ||
| 209 | tristate | ||
| 210 | |||
| 201 | config SND_SOC_AK4641 | 211 | config SND_SOC_AK4641 |
| 202 | tristate | 212 | tristate |
| 203 | 213 | ||
| @@ -292,6 +302,12 @@ config SND_SOC_MAX9850 | |||
| 292 | config SND_SOC_HDMI_CODEC | 302 | config SND_SOC_HDMI_CODEC |
| 293 | tristate | 303 | tristate |
| 294 | 304 | ||
| 305 | config SND_SOC_PCM1681 | ||
| 306 | tristate | ||
| 307 | |||
| 308 | config SND_SOC_PCM1792A | ||
| 309 | tristate | ||
| 310 | |||
| 295 | config SND_SOC_PCM3008 | 311 | config SND_SOC_PCM3008 |
| 296 | tristate | 312 | tristate |
| 297 | 313 | ||
| @@ -500,6 +516,9 @@ config SND_SOC_WM8995 | |||
| 500 | config SND_SOC_WM8996 | 516 | config SND_SOC_WM8996 |
| 501 | tristate | 517 | tristate |
| 502 | 518 | ||
| 519 | config SND_SOC_WM8997 | ||
| 520 | tristate | ||
| 521 | |||
| 503 | config SND_SOC_WM9081 | 522 | config SND_SOC_WM9081 |
| 504 | tristate | 523 | tristate |
| 505 | 524 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 70fd8066f546..bc126764a44d 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
| @@ -11,6 +11,7 @@ snd-soc-adav80x-objs := adav80x.o | |||
| 11 | snd-soc-ads117x-objs := ads117x.o | 11 | snd-soc-ads117x-objs := ads117x.o |
| 12 | snd-soc-ak4104-objs := ak4104.o | 12 | snd-soc-ak4104-objs := ak4104.o |
| 13 | snd-soc-ak4535-objs := ak4535.o | 13 | snd-soc-ak4535-objs := ak4535.o |
| 14 | snd-soc-ak4554-objs := ak4554.o | ||
| 14 | snd-soc-ak4641-objs := ak4641.o | 15 | snd-soc-ak4641-objs := ak4641.o |
| 15 | snd-soc-ak4642-objs := ak4642.o | 16 | snd-soc-ak4642-objs := ak4642.o |
| 16 | snd-soc-ak4671-objs := ak4671.o | 17 | snd-soc-ak4671-objs := ak4671.o |
| @@ -42,6 +43,8 @@ snd-soc-max9850-objs := max9850.o | |||
| 42 | snd-soc-mc13783-objs := mc13783.o | 43 | snd-soc-mc13783-objs := mc13783.o |
| 43 | snd-soc-ml26124-objs := ml26124.o | 44 | snd-soc-ml26124-objs := ml26124.o |
| 44 | snd-soc-hdmi-codec-objs := hdmi.o | 45 | snd-soc-hdmi-codec-objs := hdmi.o |
| 46 | snd-soc-pcm1681-objs := pcm1681.o | ||
| 47 | snd-soc-pcm1792a-codec-objs := pcm1792a.o | ||
| 45 | snd-soc-pcm3008-objs := pcm3008.o | 48 | snd-soc-pcm3008-objs := pcm3008.o |
| 46 | snd-soc-rt5631-objs := rt5631.o | 49 | snd-soc-rt5631-objs := rt5631.o |
| 47 | snd-soc-rt5640-objs := rt5640.o | 50 | snd-soc-rt5640-objs := rt5640.o |
| @@ -114,6 +117,7 @@ snd-soc-wm8991-objs := wm8991.o | |||
| 114 | snd-soc-wm8993-objs := wm8993.o | 117 | snd-soc-wm8993-objs := wm8993.o |
| 115 | snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o | 118 | snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o |
| 116 | snd-soc-wm8995-objs := wm8995.o | 119 | snd-soc-wm8995-objs := wm8995.o |
| 120 | snd-soc-wm8997-objs := wm8997.o | ||
| 117 | snd-soc-wm9081-objs := wm9081.o | 121 | snd-soc-wm9081-objs := wm9081.o |
| 118 | snd-soc-wm9090-objs := wm9090.o | 122 | snd-soc-wm9090-objs := wm9090.o |
| 119 | snd-soc-wm9705-objs := wm9705.o | 123 | snd-soc-wm9705-objs := wm9705.o |
| @@ -138,6 +142,7 @@ obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | |||
| 138 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 142 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
| 139 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 143 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
| 140 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 144 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
| 145 | obj-$(CONFIG_SND_SOC_AK4554) += snd-soc-ak4554.o | ||
| 141 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o | 146 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o |
| 142 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 147 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
| 143 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 148 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
| @@ -171,6 +176,8 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | |||
| 171 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 176 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
| 172 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 177 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
| 173 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o | 178 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o |
| 179 | obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o | ||
| 180 | obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o | ||
| 174 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 181 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
| 175 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 182 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
| 176 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 183 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
| @@ -239,6 +246,7 @@ obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o | |||
| 239 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o | 246 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o |
| 240 | obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o | 247 | obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o |
| 241 | obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o | 248 | obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o |
| 249 | obj-$(CONFIG_SND_SOC_WM8997) += snd-soc-wm8997.o | ||
| 242 | obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o | 250 | obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o |
| 243 | obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o | 251 | obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o |
| 244 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o | 252 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index ec7351803c24..8d9ba4ba4bfe 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
| @@ -23,6 +23,16 @@ | |||
| 23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
| 24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
| 25 | 25 | ||
| 26 | static const struct snd_soc_dapm_widget ac97_widgets[] = { | ||
| 27 | SND_SOC_DAPM_INPUT("RX"), | ||
| 28 | SND_SOC_DAPM_OUTPUT("TX"), | ||
| 29 | }; | ||
| 30 | |||
| 31 | static const struct snd_soc_dapm_route ac97_routes[] = { | ||
| 32 | { "AC97 Capture", NULL, "RX" }, | ||
| 33 | { "TX", NULL, "AC97 Playback" }, | ||
| 34 | }; | ||
| 35 | |||
| 26 | static int ac97_prepare(struct snd_pcm_substream *substream, | 36 | static int ac97_prepare(struct snd_pcm_substream *substream, |
| 27 | struct snd_soc_dai *dai) | 37 | struct snd_soc_dai *dai) |
| 28 | { | 38 | { |
| @@ -117,6 +127,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { | |||
| 117 | .probe = ac97_soc_probe, | 127 | .probe = ac97_soc_probe, |
| 118 | .suspend = ac97_soc_suspend, | 128 | .suspend = ac97_soc_suspend, |
| 119 | .resume = ac97_soc_resume, | 129 | .resume = ac97_soc_resume, |
| 130 | |||
| 131 | .dapm_widgets = ac97_widgets, | ||
| 132 | .num_dapm_widgets = ARRAY_SIZE(ac97_widgets), | ||
| 133 | .dapm_routes = ac97_routes, | ||
| 134 | .num_dapm_routes = ARRAY_SIZE(ac97_routes), | ||
| 120 | }; | 135 | }; |
| 121 | 136 | ||
| 122 | static int ac97_probe(struct platform_device *pdev) | 137 | static int ac97_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 89fcf7d6e7b8..7257a8885f42 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
| @@ -96,6 +96,44 @@ SOC_ENUM("Capture Source", ad1980_cap_src), | |||
| 96 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), | 96 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | static const struct snd_soc_dapm_widget ad1980_dapm_widgets[] = { | ||
| 100 | SND_SOC_DAPM_INPUT("MIC1"), | ||
| 101 | SND_SOC_DAPM_INPUT("MIC2"), | ||
| 102 | SND_SOC_DAPM_INPUT("CD_L"), | ||
| 103 | SND_SOC_DAPM_INPUT("CD_R"), | ||
| 104 | SND_SOC_DAPM_INPUT("AUX_L"), | ||
| 105 | SND_SOC_DAPM_INPUT("AUX_R"), | ||
| 106 | SND_SOC_DAPM_INPUT("LINE_IN_L"), | ||
| 107 | SND_SOC_DAPM_INPUT("LINE_IN_R"), | ||
| 108 | |||
| 109 | SND_SOC_DAPM_OUTPUT("LFE_OUT"), | ||
| 110 | SND_SOC_DAPM_OUTPUT("CENTER_OUT"), | ||
| 111 | SND_SOC_DAPM_OUTPUT("LINE_OUT_L"), | ||
| 112 | SND_SOC_DAPM_OUTPUT("LINE_OUT_R"), | ||
| 113 | SND_SOC_DAPM_OUTPUT("MONO_OUT"), | ||
| 114 | SND_SOC_DAPM_OUTPUT("HP_OUT_L"), | ||
| 115 | SND_SOC_DAPM_OUTPUT("HP_OUT_R"), | ||
| 116 | }; | ||
| 117 | |||
| 118 | static const struct snd_soc_dapm_route ad1980_dapm_routes[] = { | ||
| 119 | { "Capture", NULL, "MIC1" }, | ||
| 120 | { "Capture", NULL, "MIC2" }, | ||
| 121 | { "Capture", NULL, "CD_L" }, | ||
| 122 | { "Capture", NULL, "CD_R" }, | ||
| 123 | { "Capture", NULL, "AUX_L" }, | ||
| 124 | { "Capture", NULL, "AUX_R" }, | ||
| 125 | { "Capture", NULL, "LINE_IN_L" }, | ||
| 126 | { "Capture", NULL, "LINE_IN_R" }, | ||
| 127 | |||
| 128 | { "LFE_OUT", NULL, "Playback" }, | ||
| 129 | { "CENTER_OUT", NULL, "Playback" }, | ||
| 130 | { "LINE_OUT_L", NULL, "Playback" }, | ||
| 131 | { "LINE_OUT_R", NULL, "Playback" }, | ||
| 132 | { "MONO_OUT", NULL, "Playback" }, | ||
| 133 | { "HP_OUT_L", NULL, "Playback" }, | ||
| 134 | { "HP_OUT_R", NULL, "Playback" }, | ||
| 135 | }; | ||
| 136 | |||
| 99 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 137 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
| 100 | unsigned int reg) | 138 | unsigned int reg) |
| 101 | { | 139 | { |
| @@ -253,6 +291,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { | |||
| 253 | .reg_cache_step = 2, | 291 | .reg_cache_step = 2, |
| 254 | .write = ac97_write, | 292 | .write = ac97_write, |
| 255 | .read = ac97_read, | 293 | .read = ac97_read, |
| 294 | |||
| 295 | .dapm_widgets = ad1980_dapm_widgets, | ||
| 296 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), | ||
| 297 | .dapm_routes = ad1980_dapm_routes, | ||
| 298 | .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes), | ||
| 256 | }; | 299 | }; |
| 257 | 300 | ||
| 258 | static int ad1980_probe(struct platform_device *pdev) | 301 | static int ad1980_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index b1f2baf42b48..5fac8adbc136 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
| @@ -23,6 +23,21 @@ | |||
| 23 | 23 | ||
| 24 | #include "ad73311.h" | 24 | #include "ad73311.h" |
| 25 | 25 | ||
| 26 | static const struct snd_soc_dapm_widget ad73311_dapm_widgets[] = { | ||
| 27 | SND_SOC_DAPM_INPUT("VINP"), | ||
| 28 | SND_SOC_DAPM_INPUT("VINN"), | ||
| 29 | SND_SOC_DAPM_OUTPUT("VOUTN"), | ||
| 30 | SND_SOC_DAPM_OUTPUT("VOUTP"), | ||
| 31 | }; | ||
| 32 | |||
| 33 | static const struct snd_soc_dapm_route ad73311_dapm_routes[] = { | ||
| 34 | { "Capture", NULL, "VINP" }, | ||
| 35 | { "Capture", NULL, "VINN" }, | ||
| 36 | |||
| 37 | { "VOUTN", NULL, "Playback" }, | ||
| 38 | { "VOUTP", NULL, "Playback" }, | ||
| 39 | }; | ||
| 40 | |||
| 26 | static struct snd_soc_dai_driver ad73311_dai = { | 41 | static struct snd_soc_dai_driver ad73311_dai = { |
| 27 | .name = "ad73311-hifi", | 42 | .name = "ad73311-hifi", |
| 28 | .playback = { | 43 | .playback = { |
| @@ -39,7 +54,12 @@ static struct snd_soc_dai_driver ad73311_dai = { | |||
| 39 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 54 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
| 40 | }; | 55 | }; |
| 41 | 56 | ||
| 42 | static struct snd_soc_codec_driver soc_codec_dev_ad73311; | 57 | static struct snd_soc_codec_driver soc_codec_dev_ad73311 = { |
| 58 | .dapm_widgets = ad73311_dapm_widgets, | ||
| 59 | .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets), | ||
| 60 | .dapm_routes = ad73311_dapm_routes, | ||
| 61 | .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes), | ||
| 62 | }; | ||
| 43 | 63 | ||
| 44 | static int ad73311_probe(struct platform_device *pdev) | 64 | static int ad73311_probe(struct platform_device *pdev) |
| 45 | { | 65 | { |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d1124a5b3471..ebff1128be59 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
| @@ -91,7 +91,7 @@ | |||
| 91 | #define ADAU1701_OSCIPOW_OPD 0x04 | 91 | #define ADAU1701_OSCIPOW_OPD 0x04 |
| 92 | #define ADAU1701_DACSET_DACINIT 1 | 92 | #define ADAU1701_DACSET_DACINIT 1 |
| 93 | 93 | ||
| 94 | #define ADAU1707_CLKDIV_UNSET (-1UL) | 94 | #define ADAU1707_CLKDIV_UNSET (-1U) |
| 95 | 95 | ||
| 96 | #define ADAU1701_FIRMWARE "adau1701.bin" | 96 | #define ADAU1701_FIRMWARE "adau1701.bin" |
| 97 | 97 | ||
| @@ -247,21 +247,21 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) | |||
| 247 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { | 247 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { |
| 248 | switch (clkdiv) { | 248 | switch (clkdiv) { |
| 249 | case 64: | 249 | case 64: |
| 250 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | 250 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0); |
| 251 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | 251 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0); |
| 252 | break; | 252 | break; |
| 253 | case 256: | 253 | case 256: |
| 254 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | 254 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0); |
| 255 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | 255 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1); |
| 256 | break; | 256 | break; |
| 257 | case 384: | 257 | case 384: |
| 258 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | 258 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1); |
| 259 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | 259 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0); |
| 260 | break; | 260 | break; |
| 261 | case 0: /* fallback */ | 261 | case 0: /* fallback */ |
| 262 | case 512: | 262 | case 512: |
| 263 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | 263 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1); |
| 264 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | 264 | gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1); |
| 265 | break; | 265 | break; |
| 266 | } | 266 | } |
| 267 | } | 267 | } |
| @@ -269,10 +269,10 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) | |||
| 269 | adau1701->pll_clkdiv = clkdiv; | 269 | adau1701->pll_clkdiv = clkdiv; |
| 270 | 270 | ||
| 271 | if (gpio_is_valid(adau1701->gpio_nreset)) { | 271 | if (gpio_is_valid(adau1701->gpio_nreset)) { |
| 272 | gpio_set_value(adau1701->gpio_nreset, 0); | 272 | gpio_set_value_cansleep(adau1701->gpio_nreset, 0); |
| 273 | /* minimum reset time is 20ns */ | 273 | /* minimum reset time is 20ns */ |
| 274 | udelay(1); | 274 | udelay(1); |
| 275 | gpio_set_value(adau1701->gpio_nreset, 1); | 275 | gpio_set_value_cansleep(adau1701->gpio_nreset, 1); |
| 276 | /* power-up time may be as long as 85ms */ | 276 | /* power-up time may be as long as 85ms */ |
| 277 | mdelay(85); | 277 | mdelay(85); |
| 278 | } | 278 | } |
| @@ -734,7 +734,10 @@ static int adau1701_i2c_remove(struct i2c_client *client) | |||
| 734 | } | 734 | } |
| 735 | 735 | ||
| 736 | static const struct i2c_device_id adau1701_i2c_id[] = { | 736 | static const struct i2c_device_id adau1701_i2c_id[] = { |
| 737 | { "adau1401", 0 }, | ||
| 738 | { "adau1401a", 0 }, | ||
| 737 | { "adau1701", 0 }, | 739 | { "adau1701", 0 }, |
| 740 | { "adau1702", 0 }, | ||
| 738 | { } | 741 | { } |
| 739 | }; | 742 | }; |
| 740 | MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); | 743 | MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 3c839cc4e00e..15b012d0f226 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
| @@ -868,6 +868,12 @@ static int adav80x_bus_remove(struct device *dev) | |||
| 868 | } | 868 | } |
| 869 | 869 | ||
| 870 | #if defined(CONFIG_SPI_MASTER) | 870 | #if defined(CONFIG_SPI_MASTER) |
| 871 | static const struct spi_device_id adav80x_spi_id[] = { | ||
| 872 | { "adav801", 0 }, | ||
| 873 | { } | ||
| 874 | }; | ||
| 875 | MODULE_DEVICE_TABLE(spi, adav80x_spi_id); | ||
| 876 | |||
| 871 | static int adav80x_spi_probe(struct spi_device *spi) | 877 | static int adav80x_spi_probe(struct spi_device *spi) |
| 872 | { | 878 | { |
| 873 | return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); | 879 | return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); |
| @@ -885,15 +891,16 @@ static struct spi_driver adav80x_spi_driver = { | |||
| 885 | }, | 891 | }, |
| 886 | .probe = adav80x_spi_probe, | 892 | .probe = adav80x_spi_probe, |
| 887 | .remove = adav80x_spi_remove, | 893 | .remove = adav80x_spi_remove, |
| 894 | .id_table = adav80x_spi_id, | ||
| 888 | }; | 895 | }; |
| 889 | #endif | 896 | #endif |
| 890 | 897 | ||
| 891 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 898 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 892 | static const struct i2c_device_id adav80x_id[] = { | 899 | static const struct i2c_device_id adav80x_i2c_id[] = { |
| 893 | { "adav803", 0 }, | 900 | { "adav803", 0 }, |
| 894 | { } | 901 | { } |
| 895 | }; | 902 | }; |
| 896 | MODULE_DEVICE_TABLE(i2c, adav80x_id); | 903 | MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); |
| 897 | 904 | ||
| 898 | static int adav80x_i2c_probe(struct i2c_client *client, | 905 | static int adav80x_i2c_probe(struct i2c_client *client, |
| 899 | const struct i2c_device_id *id) | 906 | const struct i2c_device_id *id) |
| @@ -913,7 +920,7 @@ static struct i2c_driver adav80x_i2c_driver = { | |||
| 913 | }, | 920 | }, |
| 914 | .probe = adav80x_i2c_probe, | 921 | .probe = adav80x_i2c_probe, |
| 915 | .remove = adav80x_i2c_remove, | 922 | .remove = adav80x_i2c_remove, |
| 916 | .id_table = adav80x_id, | 923 | .id_table = adav80x_i2c_id, |
| 917 | }; | 924 | }; |
| 918 | #endif | 925 | #endif |
| 919 | 926 | ||
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index 506d474c4d22..8f388edff586 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c | |||
| @@ -23,6 +23,28 @@ | |||
| 23 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) | 23 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) |
| 24 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | 24 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) |
| 25 | 25 | ||
| 26 | static const struct snd_soc_dapm_widget ads117x_dapm_widgets[] = { | ||
| 27 | SND_SOC_DAPM_INPUT("Input1"), | ||
| 28 | SND_SOC_DAPM_INPUT("Input2"), | ||
| 29 | SND_SOC_DAPM_INPUT("Input3"), | ||
| 30 | SND_SOC_DAPM_INPUT("Input4"), | ||
| 31 | SND_SOC_DAPM_INPUT("Input5"), | ||
| 32 | SND_SOC_DAPM_INPUT("Input6"), | ||
| 33 | SND_SOC_DAPM_INPUT("Input7"), | ||
| 34 | SND_SOC_DAPM_INPUT("Input8"), | ||
| 35 | }; | ||
| 36 | |||
| 37 | static const struct snd_soc_dapm_route ads117x_dapm_routes[] = { | ||
| 38 | { "Capture", NULL, "Input1" }, | ||
| 39 | { "Capture", NULL, "Input2" }, | ||
| 40 | { "Capture", NULL, "Input3" }, | ||
| 41 | { "Capture", NULL, "Input4" }, | ||
| 42 | { "Capture", NULL, "Input5" }, | ||
| 43 | { "Capture", NULL, "Input6" }, | ||
| 44 | { "Capture", NULL, "Input7" }, | ||
| 45 | { "Capture", NULL, "Input8" }, | ||
| 46 | }; | ||
| 47 | |||
| 26 | static struct snd_soc_dai_driver ads117x_dai = { | 48 | static struct snd_soc_dai_driver ads117x_dai = { |
| 27 | /* ADC */ | 49 | /* ADC */ |
| 28 | .name = "ads117x-hifi", | 50 | .name = "ads117x-hifi", |
| @@ -34,7 +56,12 @@ static struct snd_soc_dai_driver ads117x_dai = { | |||
| 34 | .formats = ADS117X_FORMATS,}, | 56 | .formats = ADS117X_FORMATS,}, |
| 35 | }; | 57 | }; |
| 36 | 58 | ||
| 37 | static struct snd_soc_codec_driver soc_codec_dev_ads117x; | 59 | static struct snd_soc_codec_driver soc_codec_dev_ads117x = { |
| 60 | .dapm_widgets = ads117x_dapm_widgets, | ||
| 61 | .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets), | ||
| 62 | .dapm_routes = ads117x_dapm_routes, | ||
| 63 | .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes), | ||
| 64 | }; | ||
| 38 | 65 | ||
| 39 | static int ads117x_probe(struct platform_device *pdev) | 66 | static int ads117x_probe(struct platform_device *pdev) |
| 40 | { | 67 | { |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index c7cfdf957e4d..71059c07ae7b 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
| @@ -51,6 +51,17 @@ struct ak4104_private { | |||
| 51 | struct regmap *regmap; | 51 | struct regmap *regmap; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = { | ||
| 55 | SND_SOC_DAPM_PGA("TXE", AK4104_REG_TX, AK4104_TX_TXE, 0, NULL, 0), | ||
| 56 | |||
| 57 | SND_SOC_DAPM_OUTPUT("TX"), | ||
| 58 | }; | ||
| 59 | |||
| 60 | static const struct snd_soc_dapm_route ak4104_dapm_routes[] = { | ||
| 61 | { "TXE", NULL, "Playback" }, | ||
| 62 | { "TX", NULL, "TXE" }, | ||
| 63 | }; | ||
| 64 | |||
| 54 | static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, | 65 | static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, |
| 55 | unsigned int format) | 66 | unsigned int format) |
| 56 | { | 67 | { |
| @@ -138,29 +149,11 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
| 138 | if (ret < 0) | 149 | if (ret < 0) |
| 139 | return ret; | 150 | return ret; |
| 140 | 151 | ||
| 141 | /* enable transmitter */ | ||
| 142 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX, | ||
| 143 | AK4104_TX_TXE, AK4104_TX_TXE); | ||
| 144 | if (ret < 0) | ||
| 145 | return ret; | ||
| 146 | |||
| 147 | return 0; | 152 | return 0; |
| 148 | } | 153 | } |
| 149 | 154 | ||
| 150 | static int ak4104_hw_free(struct snd_pcm_substream *substream, | ||
| 151 | struct snd_soc_dai *dai) | ||
| 152 | { | ||
| 153 | struct snd_soc_codec *codec = dai->codec; | ||
| 154 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); | ||
| 155 | |||
| 156 | /* disable transmitter */ | ||
| 157 | return regmap_update_bits(ak4104->regmap, AK4104_REG_TX, | ||
| 158 | AK4104_TX_TXE, 0); | ||
| 159 | } | ||
| 160 | |||
| 161 | static const struct snd_soc_dai_ops ak4101_dai_ops = { | 155 | static const struct snd_soc_dai_ops ak4101_dai_ops = { |
| 162 | .hw_params = ak4104_hw_params, | 156 | .hw_params = ak4104_hw_params, |
| 163 | .hw_free = ak4104_hw_free, | ||
| 164 | .set_fmt = ak4104_set_dai_fmt, | 157 | .set_fmt = ak4104_set_dai_fmt, |
| 165 | }; | 158 | }; |
| 166 | 159 | ||
| @@ -214,6 +207,11 @@ static int ak4104_remove(struct snd_soc_codec *codec) | |||
| 214 | static struct snd_soc_codec_driver soc_codec_device_ak4104 = { | 207 | static struct snd_soc_codec_driver soc_codec_device_ak4104 = { |
| 215 | .probe = ak4104_probe, | 208 | .probe = ak4104_probe, |
| 216 | .remove = ak4104_remove, | 209 | .remove = ak4104_remove, |
| 210 | |||
| 211 | .dapm_widgets = ak4104_dapm_widgets, | ||
| 212 | .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), | ||
| 213 | .dapm_routes = ak4104_dapm_routes, | ||
| 214 | .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes), | ||
| 217 | }; | 215 | }; |
| 218 | 216 | ||
| 219 | static const struct regmap_config ak4104_regmap = { | 217 | static const struct regmap_config ak4104_regmap = { |
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c new file mode 100644 index 000000000000..79e9555766c0 --- /dev/null +++ b/sound/soc/codecs/ak4554.c | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | /* | ||
| 2 | * ak4554.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 <sound/soc.h> | ||
| 14 | |||
| 15 | /* | ||
| 16 | * ak4554 is very simple DA/AD converter which has no setting register. | ||
| 17 | * | ||
| 18 | * CAUTION | ||
| 19 | * | ||
| 20 | * ak4554 playback format is SND_SOC_DAIFMT_RIGHT_J, | ||
| 21 | * and, capture format is SND_SOC_DAIFMT_LEFT_J | ||
| 22 | * on same bit clock, LR clock. | ||
| 23 | * But, this driver doesn't have snd_soc_dai_ops :: set_fmt | ||
| 24 | * | ||
| 25 | * CPU/Codec DAI image | ||
| 26 | * | ||
| 27 | * CPU-DAI1 (plaback only fmt = RIGHT_J) --+-- ak4554 | ||
| 28 | * | | ||
| 29 | * CPU-DAI2 (capture only fmt = LEFT_J) ---+ | ||
| 30 | */ | ||
| 31 | |||
| 32 | static const struct snd_soc_dapm_widget ak4554_dapm_widgets[] = { | ||
| 33 | SND_SOC_DAPM_INPUT("AINL"), | ||
| 34 | SND_SOC_DAPM_INPUT("AINR"), | ||
| 35 | |||
| 36 | SND_SOC_DAPM_OUTPUT("AOUTL"), | ||
| 37 | SND_SOC_DAPM_OUTPUT("AOUTR"), | ||
| 38 | }; | ||
| 39 | |||
| 40 | static const struct snd_soc_dapm_route ak4554_dapm_routes[] = { | ||
| 41 | { "Capture", NULL, "AINL" }, | ||
| 42 | { "Capture", NULL, "AINR" }, | ||
| 43 | |||
| 44 | { "AOUTL", NULL, "Playback" }, | ||
| 45 | { "AOUTR", NULL, "Playback" }, | ||
| 46 | }; | ||
| 47 | |||
| 48 | static struct snd_soc_dai_driver ak4554_dai = { | ||
| 49 | .name = "ak4554-hifi", | ||
| 50 | .playback = { | ||
| 51 | .stream_name = "Playback", | ||
| 52 | .channels_min = 2, | ||
| 53 | .channels_max = 2, | ||
| 54 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
| 55 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 56 | }, | ||
| 57 | .capture = { | ||
| 58 | .stream_name = "Capture", | ||
| 59 | .channels_min = 2, | ||
| 60 | .channels_max = 2, | ||
| 61 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
| 62 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 63 | }, | ||
| 64 | .symmetric_rates = 1, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static struct snd_soc_codec_driver soc_codec_dev_ak4554 = { | ||
| 68 | .dapm_widgets = ak4554_dapm_widgets, | ||
| 69 | .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets), | ||
| 70 | .dapm_routes = ak4554_dapm_routes, | ||
| 71 | .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes), | ||
| 72 | }; | ||
| 73 | |||
| 74 | static int ak4554_soc_probe(struct platform_device *pdev) | ||
| 75 | { | ||
| 76 | return snd_soc_register_codec(&pdev->dev, | ||
| 77 | &soc_codec_dev_ak4554, | ||
| 78 | &ak4554_dai, 1); | ||
| 79 | } | ||
| 80 | |||
| 81 | static int ak4554_soc_remove(struct platform_device *pdev) | ||
| 82 | { | ||
| 83 | snd_soc_unregister_codec(&pdev->dev); | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct of_device_id ak4554_of_match[] = { | ||
| 88 | { .compatible = "asahi-kasei,ak4554" }, | ||
| 89 | {}, | ||
| 90 | }; | ||
| 91 | MODULE_DEVICE_TABLE(of, ak4554_of_match); | ||
| 92 | |||
| 93 | static struct platform_driver ak4554_driver = { | ||
| 94 | .driver = { | ||
| 95 | .name = "ak4554-adc-dac", | ||
| 96 | .owner = THIS_MODULE, | ||
| 97 | .of_match_table = ak4554_of_match, | ||
| 98 | }, | ||
| 99 | .probe = ak4554_soc_probe, | ||
| 100 | .remove = ak4554_soc_remove, | ||
| 101 | }; | ||
| 102 | module_platform_driver(ak4554_driver); | ||
| 103 | |||
| 104 | MODULE_LICENSE("GPL"); | ||
| 105 | MODULE_DESCRIPTION("SoC AK4554 driver"); | ||
| 106 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index 1f303983ae02..72e953b2cb41 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c | |||
| @@ -22,7 +22,22 @@ struct ak5386_priv { | |||
| 22 | int reset_gpio; | 22 | int reset_gpio; |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | static struct snd_soc_codec_driver soc_codec_ak5386; | 25 | static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = { |
| 26 | SND_SOC_DAPM_INPUT("AINL"), | ||
| 27 | SND_SOC_DAPM_INPUT("AINR"), | ||
| 28 | }; | ||
| 29 | |||
| 30 | static const struct snd_soc_dapm_route ak5386_dapm_routes[] = { | ||
| 31 | { "Capture", NULL, "AINL" }, | ||
| 32 | { "Capture", NULL, "AINR" }, | ||
| 33 | }; | ||
| 34 | |||
| 35 | static struct snd_soc_codec_driver soc_codec_ak5386 = { | ||
| 36 | .dapm_widgets = ak5386_dapm_widgets, | ||
| 37 | .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), | ||
| 38 | .dapm_routes = ak5386_dapm_routes, | ||
| 39 | .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), | ||
| 40 | }; | ||
| 26 | 41 | ||
| 27 | static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, | 42 | static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, |
| 28 | unsigned int format) | 43 | unsigned int format) |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index de625813c0e6..657808ba1418 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <sound/tlv.h> | 19 | #include <sound/tlv.h> |
| 20 | 20 | ||
| 21 | #include <linux/mfd/arizona/core.h> | 21 | #include <linux/mfd/arizona/core.h> |
| 22 | #include <linux/mfd/arizona/gpio.h> | ||
| 22 | #include <linux/mfd/arizona/registers.h> | 23 | #include <linux/mfd/arizona/registers.h> |
| 23 | 24 | ||
| 24 | #include "arizona.h" | 25 | #include "arizona.h" |
| @@ -199,9 +200,16 @@ int arizona_init_spk(struct snd_soc_codec *codec) | |||
| 199 | if (ret != 0) | 200 | if (ret != 0) |
| 200 | return ret; | 201 | return ret; |
| 201 | 202 | ||
| 202 | ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1); | 203 | switch (arizona->type) { |
| 203 | if (ret != 0) | 204 | case WM8997: |
| 204 | return ret; | 205 | break; |
| 206 | default: | ||
| 207 | ret = snd_soc_dapm_new_controls(&codec->dapm, | ||
| 208 | &arizona_spkr, 1); | ||
| 209 | if (ret != 0) | ||
| 210 | return ret; | ||
| 211 | break; | ||
| 212 | } | ||
| 205 | 213 | ||
| 206 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN, | 214 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN, |
| 207 | "Thermal warning", arizona_thermal_warn, | 215 | "Thermal warning", arizona_thermal_warn, |
| @@ -223,6 +231,41 @@ int arizona_init_spk(struct snd_soc_codec *codec) | |||
| 223 | } | 231 | } |
| 224 | EXPORT_SYMBOL_GPL(arizona_init_spk); | 232 | EXPORT_SYMBOL_GPL(arizona_init_spk); |
| 225 | 233 | ||
| 234 | int arizona_init_gpio(struct snd_soc_codec *codec) | ||
| 235 | { | ||
| 236 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
| 237 | struct arizona *arizona = priv->arizona; | ||
| 238 | int i; | ||
| 239 | |||
| 240 | switch (arizona->type) { | ||
| 241 | case WM5110: | ||
| 242 | snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity"); | ||
| 243 | break; | ||
| 244 | default: | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity"); | ||
| 249 | |||
| 250 | for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { | ||
| 251 | switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) { | ||
| 252 | case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT: | ||
| 253 | snd_soc_dapm_enable_pin(&codec->dapm, | ||
| 254 | "DRC1 Signal Activity"); | ||
| 255 | break; | ||
| 256 | case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT: | ||
| 257 | snd_soc_dapm_enable_pin(&codec->dapm, | ||
| 258 | "DRC2 Signal Activity"); | ||
| 259 | break; | ||
| 260 | default: | ||
| 261 | break; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | EXPORT_SYMBOL_GPL(arizona_init_gpio); | ||
| 268 | |||
| 226 | const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | 269 | const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { |
| 227 | "None", | 270 | "None", |
| 228 | "Tone Generator 1", | 271 | "Tone Generator 1", |
| @@ -517,6 +560,26 @@ const struct soc_enum arizona_ng_hold = | |||
| 517 | 4, arizona_ng_hold_text); | 560 | 4, arizona_ng_hold_text); |
| 518 | EXPORT_SYMBOL_GPL(arizona_ng_hold); | 561 | EXPORT_SYMBOL_GPL(arizona_ng_hold); |
| 519 | 562 | ||
| 563 | static const char * const arizona_in_dmic_osr_text[] = { | ||
| 564 | "1.536MHz", "3.072MHz", "6.144MHz", | ||
| 565 | }; | ||
| 566 | |||
| 567 | const struct soc_enum arizona_in_dmic_osr[] = { | ||
| 568 | SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT, | ||
| 569 | ARRAY_SIZE(arizona_in_dmic_osr_text), | ||
| 570 | arizona_in_dmic_osr_text), | ||
| 571 | SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT, | ||
| 572 | ARRAY_SIZE(arizona_in_dmic_osr_text), | ||
| 573 | arizona_in_dmic_osr_text), | ||
| 574 | SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT, | ||
| 575 | ARRAY_SIZE(arizona_in_dmic_osr_text), | ||
| 576 | arizona_in_dmic_osr_text), | ||
| 577 | SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT, | ||
| 578 | ARRAY_SIZE(arizona_in_dmic_osr_text), | ||
| 579 | arizona_in_dmic_osr_text), | ||
| 580 | }; | ||
| 581 | EXPORT_SYMBOL_GPL(arizona_in_dmic_osr); | ||
| 582 | |||
| 520 | static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) | 583 | static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) |
| 521 | { | 584 | { |
| 522 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 585 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index b60b08ccc1d0..9e81b6392692 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
| @@ -150,7 +150,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
| 150 | ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \ | 150 | ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \ |
| 151 | ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux) | 151 | ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux) |
| 152 | 152 | ||
| 153 | #define ARIZONA_MUX_ROUTES(name) \ | 153 | #define ARIZONA_MUX_ROUTES(widget, name) \ |
| 154 | { widget, NULL, name " Input" }, \ | ||
| 154 | ARIZONA_MIXER_INPUT_ROUTES(name " Input") | 155 | ARIZONA_MIXER_INPUT_ROUTES(name " Input") |
| 155 | 156 | ||
| 156 | #define ARIZONA_MIXER_ROUTES(widget, name) \ | 157 | #define ARIZONA_MIXER_ROUTES(widget, name) \ |
| @@ -198,6 +199,7 @@ extern const struct soc_enum arizona_lhpf3_mode; | |||
| 198 | extern const struct soc_enum arizona_lhpf4_mode; | 199 | extern const struct soc_enum arizona_lhpf4_mode; |
| 199 | 200 | ||
| 200 | extern const struct soc_enum arizona_ng_hold; | 201 | extern const struct soc_enum arizona_ng_hold; |
| 202 | extern const struct soc_enum arizona_in_dmic_osr[]; | ||
| 201 | 203 | ||
| 202 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | 204 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, |
| 203 | struct snd_kcontrol *kcontrol, | 205 | struct snd_kcontrol *kcontrol, |
| @@ -242,6 +244,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source, | |||
| 242 | unsigned int Fref, unsigned int Fout); | 244 | unsigned int Fref, unsigned int Fout); |
| 243 | 245 | ||
| 244 | extern int arizona_init_spk(struct snd_soc_codec *codec); | 246 | extern int arizona_init_spk(struct snd_soc_codec *codec); |
| 247 | extern int arizona_init_gpio(struct snd_soc_codec *codec); | ||
| 245 | 248 | ||
| 246 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); | 249 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); |
| 247 | 250 | ||
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c index a081d9fcb166..c4cf0699e77f 100644 --- a/sound/soc/codecs/bt-sco.c +++ b/sound/soc/codecs/bt-sco.c | |||
| @@ -15,15 +15,27 @@ | |||
| 15 | 15 | ||
| 16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
| 17 | 17 | ||
| 18 | static const struct snd_soc_dapm_widget bt_sco_widgets[] = { | ||
| 19 | SND_SOC_DAPM_INPUT("RX"), | ||
| 20 | SND_SOC_DAPM_OUTPUT("TX"), | ||
| 21 | }; | ||
| 22 | |||
| 23 | static const struct snd_soc_dapm_route bt_sco_routes[] = { | ||
| 24 | { "Capture", NULL, "RX" }, | ||
| 25 | { "TX", NULL, "Playback" }, | ||
| 26 | }; | ||
| 27 | |||
| 18 | static struct snd_soc_dai_driver bt_sco_dai = { | 28 | static struct snd_soc_dai_driver bt_sco_dai = { |
| 19 | .name = "bt-sco-pcm", | 29 | .name = "bt-sco-pcm", |
| 20 | .playback = { | 30 | .playback = { |
| 31 | .stream_name = "Playback", | ||
| 21 | .channels_min = 1, | 32 | .channels_min = 1, |
| 22 | .channels_max = 1, | 33 | .channels_max = 1, |
| 23 | .rates = SNDRV_PCM_RATE_8000, | 34 | .rates = SNDRV_PCM_RATE_8000, |
| 24 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 35 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 25 | }, | 36 | }, |
| 26 | .capture = { | 37 | .capture = { |
| 38 | .stream_name = "Capture", | ||
| 27 | .channels_min = 1, | 39 | .channels_min = 1, |
| 28 | .channels_max = 1, | 40 | .channels_max = 1, |
| 29 | .rates = SNDRV_PCM_RATE_8000, | 41 | .rates = SNDRV_PCM_RATE_8000, |
| @@ -31,7 +43,12 @@ static struct snd_soc_dai_driver bt_sco_dai = { | |||
| 31 | }, | 43 | }, |
| 32 | }; | 44 | }; |
| 33 | 45 | ||
| 34 | static struct snd_soc_codec_driver soc_codec_dev_bt_sco; | 46 | static struct snd_soc_codec_driver soc_codec_dev_bt_sco = { |
| 47 | .dapm_widgets = bt_sco_widgets, | ||
| 48 | .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), | ||
| 49 | .dapm_routes = bt_sco_routes, | ||
| 50 | .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), | ||
| 51 | }; | ||
| 35 | 52 | ||
| 36 | static int bt_sco_probe(struct platform_device *pdev) | 53 | static int bt_sco_probe(struct platform_device *pdev) |
| 37 | { | 54 | { |
| @@ -50,6 +67,9 @@ static struct platform_device_id bt_sco_driver_ids[] = { | |||
| 50 | { | 67 | { |
| 51 | .name = "dfbmcs320", | 68 | .name = "dfbmcs320", |
| 52 | }, | 69 | }, |
| 70 | { | ||
| 71 | .name = "bt-sco", | ||
| 72 | }, | ||
| 53 | {}, | 73 | {}, |
| 54 | }; | 74 | }; |
| 55 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); | 75 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 8e4779812b96..83c835d9fd88 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
| @@ -139,6 +139,22 @@ struct cs4270_private { | |||
| 139 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 139 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | static const struct snd_soc_dapm_widget cs4270_dapm_widgets[] = { | ||
| 143 | SND_SOC_DAPM_INPUT("AINL"), | ||
| 144 | SND_SOC_DAPM_INPUT("AINR"), | ||
| 145 | |||
| 146 | SND_SOC_DAPM_OUTPUT("AOUTL"), | ||
| 147 | SND_SOC_DAPM_OUTPUT("AOUTR"), | ||
| 148 | }; | ||
| 149 | |||
| 150 | static const struct snd_soc_dapm_route cs4270_dapm_routes[] = { | ||
| 151 | { "Capture", NULL, "AINA" }, | ||
| 152 | { "Capture", NULL, "AINB" }, | ||
| 153 | |||
| 154 | { "AOUTA", NULL, "Playback" }, | ||
| 155 | { "AOUTB", NULL, "Playback" }, | ||
| 156 | }; | ||
| 157 | |||
| 142 | /** | 158 | /** |
| 143 | * struct cs4270_mode_ratios - clock ratio tables | 159 | * struct cs4270_mode_ratios - clock ratio tables |
| 144 | * @ratio: the ratio of MCLK to the sample rate | 160 | * @ratio: the ratio of MCLK to the sample rate |
| @@ -612,6 +628,10 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
| 612 | 628 | ||
| 613 | .controls = cs4270_snd_controls, | 629 | .controls = cs4270_snd_controls, |
| 614 | .num_controls = ARRAY_SIZE(cs4270_snd_controls), | 630 | .num_controls = ARRAY_SIZE(cs4270_snd_controls), |
| 631 | .dapm_widgets = cs4270_dapm_widgets, | ||
| 632 | .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets), | ||
| 633 | .dapm_routes = cs4270_dapm_routes, | ||
| 634 | .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes), | ||
| 615 | }; | 635 | }; |
| 616 | 636 | ||
| 617 | /* | 637 | /* |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 03036b326732..a20f1bb8f071 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
| @@ -173,6 +173,26 @@ struct cs4271_private { | |||
| 173 | bool enable_soft_reset; | 173 | bool enable_soft_reset; |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = { | ||
| 177 | SND_SOC_DAPM_INPUT("AINA"), | ||
| 178 | SND_SOC_DAPM_INPUT("AINB"), | ||
| 179 | |||
| 180 | SND_SOC_DAPM_OUTPUT("AOUTA+"), | ||
| 181 | SND_SOC_DAPM_OUTPUT("AOUTA-"), | ||
| 182 | SND_SOC_DAPM_OUTPUT("AOUTB+"), | ||
| 183 | SND_SOC_DAPM_OUTPUT("AOUTB-"), | ||
| 184 | }; | ||
| 185 | |||
| 186 | static const struct snd_soc_dapm_route cs4271_dapm_routes[] = { | ||
| 187 | { "Capture", NULL, "AINA" }, | ||
| 188 | { "Capture", NULL, "AINB" }, | ||
| 189 | |||
| 190 | { "AOUTA+", NULL, "Playback" }, | ||
| 191 | { "AOUTA-", NULL, "Playback" }, | ||
| 192 | { "AOUTB+", NULL, "Playback" }, | ||
| 193 | { "AOUTB-", NULL, "Playback" }, | ||
| 194 | }; | ||
| 195 | |||
| 176 | /* | 196 | /* |
| 177 | * @freq is the desired MCLK rate | 197 | * @freq is the desired MCLK rate |
| 178 | * MCLK rate should (c) be the sample rate, multiplied by one of the | 198 | * MCLK rate should (c) be the sample rate, multiplied by one of the |
| @@ -576,8 +596,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
| 576 | CS4271_MODE2_MUTECAEQUB, | 596 | CS4271_MODE2_MUTECAEQUB, |
| 577 | CS4271_MODE2_MUTECAEQUB); | 597 | CS4271_MODE2_MUTECAEQUB); |
| 578 | 598 | ||
| 579 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, | 599 | return 0; |
| 580 | ARRAY_SIZE(cs4271_snd_controls)); | ||
| 581 | } | 600 | } |
| 582 | 601 | ||
| 583 | static int cs4271_remove(struct snd_soc_codec *codec) | 602 | static int cs4271_remove(struct snd_soc_codec *codec) |
| @@ -596,6 +615,13 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | |||
| 596 | .remove = cs4271_remove, | 615 | .remove = cs4271_remove, |
| 597 | .suspend = cs4271_soc_suspend, | 616 | .suspend = cs4271_soc_suspend, |
| 598 | .resume = cs4271_soc_resume, | 617 | .resume = cs4271_soc_resume, |
| 618 | |||
| 619 | .controls = cs4271_snd_controls, | ||
| 620 | .num_controls = ARRAY_SIZE(cs4271_snd_controls), | ||
| 621 | .dapm_widgets = cs4271_dapm_widgets, | ||
| 622 | .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets), | ||
| 623 | .dapm_routes = cs4271_dapm_routes, | ||
| 624 | .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), | ||
| 599 | }; | 625 | }; |
| 600 | 626 | ||
| 601 | #if defined(CONFIG_SPI_MASTER) | 627 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 987f728718c5..be2ba1b6fe4a 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
| @@ -195,6 +195,8 @@ static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); | |||
| 195 | 195 | ||
| 196 | static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0); | 196 | static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0); |
| 197 | 197 | ||
| 198 | static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); | ||
| 199 | |||
| 198 | static const unsigned int limiter_tlv[] = { | 200 | static const unsigned int limiter_tlv[] = { |
| 199 | TLV_DB_RANGE_HEAD(2), | 201 | TLV_DB_RANGE_HEAD(2), |
| 200 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), | 202 | 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), |
| @@ -451,7 +453,8 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { | |||
| 451 | SOC_ENUM("Beep Pitch", beep_pitch_enum), | 453 | SOC_ENUM("Beep Pitch", beep_pitch_enum), |
| 452 | SOC_ENUM("Beep on Time", beep_ontime_enum), | 454 | SOC_ENUM("Beep on Time", beep_ontime_enum), |
| 453 | SOC_ENUM("Beep off Time", beep_offtime_enum), | 455 | SOC_ENUM("Beep off Time", beep_offtime_enum), |
| 454 | SOC_SINGLE_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x1f, 0x07, hl_tlv), | 456 | SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL, |
| 457 | 0, 0x07, 0x1f, beep_tlv), | ||
| 455 | SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1), | 458 | SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1), |
| 456 | SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum), | 459 | SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum), |
| 457 | SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum), | 460 | SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum), |
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c index 2bcae2b40c92..68342b121c96 100644 --- a/sound/soc/codecs/hdmi.c +++ b/sound/soc/codecs/hdmi.c | |||
| @@ -23,11 +23,20 @@ | |||
| 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 hdmi_codec; | 26 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { |
| 27 | SND_SOC_DAPM_INPUT("RX"), | ||
| 28 | SND_SOC_DAPM_OUTPUT("TX"), | ||
| 29 | }; | ||
| 30 | |||
| 31 | static const struct snd_soc_dapm_route hdmi_routes[] = { | ||
| 32 | { "Capture", NULL, "RX" }, | ||
| 33 | { "TX", NULL, "Playback" }, | ||
| 34 | }; | ||
| 27 | 35 | ||
| 28 | static struct snd_soc_dai_driver hdmi_codec_dai = { | 36 | static struct snd_soc_dai_driver hdmi_codec_dai = { |
| 29 | .name = "hdmi-hifi", | 37 | .name = "hdmi-hifi", |
| 30 | .playback = { | 38 | .playback = { |
| 39 | .stream_name = "Playback", | ||
| 31 | .channels_min = 2, | 40 | .channels_min = 2, |
| 32 | .channels_max = 8, | 41 | .channels_max = 8, |
| 33 | .rates = SNDRV_PCM_RATE_32000 | | 42 | .rates = SNDRV_PCM_RATE_32000 | |
| @@ -37,6 +46,25 @@ static struct snd_soc_dai_driver hdmi_codec_dai = { | |||
| 37 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 46 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
| 38 | SNDRV_PCM_FMTBIT_S24_LE, | 47 | SNDRV_PCM_FMTBIT_S24_LE, |
| 39 | }, | 48 | }, |
| 49 | .capture = { | ||
| 50 | .stream_name = "Capture", | ||
| 51 | .channels_min = 2, | ||
| 52 | .channels_max = 2, | ||
| 53 | .rates = SNDRV_PCM_RATE_32000 | | ||
| 54 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | ||
| 55 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | | ||
| 56 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, | ||
| 57 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
| 58 | SNDRV_PCM_FMTBIT_S24_LE, | ||
| 59 | }, | ||
| 60 | |||
| 61 | }; | ||
| 62 | |||
| 63 | static struct snd_soc_codec_driver hdmi_codec = { | ||
| 64 | .dapm_widgets = hdmi_widgets, | ||
| 65 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), | ||
| 66 | .dapm_routes = hdmi_routes, | ||
| 67 | .num_dapm_routes = ARRAY_SIZE(hdmi_routes), | ||
| 40 | }; | 68 | }; |
| 41 | 69 | ||
| 42 | static int hdmi_codec_probe(struct platform_device *pdev) | 70 | static int hdmi_codec_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 9f9f59573f72..0e5743ea79df 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
| 19 | #include <linux/regmap.h> | ||
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | 21 | ||
| 21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
| @@ -23,12 +24,15 @@ | |||
| 23 | #include <sound/tlv.h> | 24 | #include <sound/tlv.h> |
| 24 | 25 | ||
| 25 | struct lm4857 { | 26 | struct lm4857 { |
| 26 | struct i2c_client *i2c; | 27 | struct regmap *regmap; |
| 27 | uint8_t mode; | 28 | uint8_t mode; |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 30 | static const uint8_t lm4857_default_regs[] = { | 31 | static const struct reg_default lm4857_default_regs[] = { |
| 31 | 0x00, 0x00, 0x00, 0x00, | 32 | { 0x0, 0x00 }, |
| 33 | { 0x1, 0x00 }, | ||
| 34 | { 0x2, 0x00 }, | ||
| 35 | { 0x3, 0x00 }, | ||
| 32 | }; | 36 | }; |
| 33 | 37 | ||
| 34 | /* The register offsets in the cache array */ | 38 | /* The register offsets in the cache array */ |
| @@ -42,39 +46,6 @@ static const uint8_t lm4857_default_regs[] = { | |||
| 42 | #define LM4857_WAKEUP 5 | 46 | #define LM4857_WAKEUP 5 |
| 43 | #define LM4857_EPGAIN 4 | 47 | #define LM4857_EPGAIN 4 |
| 44 | 48 | ||
| 45 | static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg, | ||
| 46 | unsigned int value) | ||
| 47 | { | ||
| 48 | uint8_t data; | ||
| 49 | int ret; | ||
| 50 | |||
| 51 | ret = snd_soc_cache_write(codec, reg, value); | ||
| 52 | if (ret < 0) | ||
| 53 | return ret; | ||
| 54 | |||
| 55 | data = (reg << 6) | value; | ||
| 56 | ret = i2c_master_send(codec->control_data, &data, 1); | ||
| 57 | if (ret != 1) { | ||
| 58 | dev_err(codec->dev, "Failed to write register: %d\n", ret); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static unsigned int lm4857_read(struct snd_soc_codec *codec, | ||
| 66 | unsigned int reg) | ||
| 67 | { | ||
| 68 | unsigned int val; | ||
| 69 | int ret; | ||
| 70 | |||
| 71 | ret = snd_soc_cache_read(codec, reg, &val); | ||
| 72 | if (ret) | ||
| 73 | return -1; | ||
| 74 | |||
| 75 | return val; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | 49 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, |
| 79 | struct snd_ctl_elem_value *ucontrol) | 50 | struct snd_ctl_elem_value *ucontrol) |
| 80 | { | 51 | { |
| @@ -96,7 +67,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | |||
| 96 | lm4857->mode = value; | 67 | lm4857->mode = value; |
| 97 | 68 | ||
| 98 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 69 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) |
| 99 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6); | 70 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6); |
| 100 | 71 | ||
| 101 | return 1; | 72 | return 1; |
| 102 | } | 73 | } |
| @@ -108,10 +79,11 @@ static int lm4857_set_bias_level(struct snd_soc_codec *codec, | |||
| 108 | 79 | ||
| 109 | switch (level) { | 80 | switch (level) { |
| 110 | case SND_SOC_BIAS_ON: | 81 | case SND_SOC_BIAS_ON: |
| 111 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6); | 82 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, |
| 83 | lm4857->mode + 6); | ||
| 112 | break; | 84 | break; |
| 113 | case SND_SOC_BIAS_STANDBY: | 85 | case SND_SOC_BIAS_STANDBY: |
| 114 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0); | 86 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0); |
| 115 | break; | 87 | break; |
| 116 | default: | 88 | default: |
| 117 | break; | 89 | break; |
| @@ -171,49 +143,32 @@ static const struct snd_soc_dapm_route lm4857_routes[] = { | |||
| 171 | {"EP", NULL, "IN"}, | 143 | {"EP", NULL, "IN"}, |
| 172 | }; | 144 | }; |
| 173 | 145 | ||
| 174 | static int lm4857_probe(struct snd_soc_codec *codec) | 146 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { |
| 175 | { | 147 | .set_bias_level = lm4857_set_bias_level, |
| 176 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
| 177 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | codec->control_data = lm4857->i2c; | ||
| 181 | |||
| 182 | ret = snd_soc_add_codec_controls(codec, lm4857_controls, | ||
| 183 | ARRAY_SIZE(lm4857_controls)); | ||
| 184 | if (ret) | ||
| 185 | return ret; | ||
| 186 | |||
| 187 | ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets, | ||
| 188 | ARRAY_SIZE(lm4857_dapm_widgets)); | ||
| 189 | if (ret) | ||
| 190 | return ret; | ||
| 191 | 148 | ||
| 192 | ret = snd_soc_dapm_add_routes(dapm, lm4857_routes, | 149 | .controls = lm4857_controls, |
| 193 | ARRAY_SIZE(lm4857_routes)); | 150 | .num_controls = ARRAY_SIZE(lm4857_controls), |
| 194 | if (ret) | 151 | .dapm_widgets = lm4857_dapm_widgets, |
| 195 | return ret; | 152 | .num_dapm_widgets = ARRAY_SIZE(lm4857_dapm_widgets), |
| 153 | .dapm_routes = lm4857_routes, | ||
| 154 | .num_dapm_routes = ARRAY_SIZE(lm4857_routes), | ||
| 155 | }; | ||
| 196 | 156 | ||
| 197 | snd_soc_dapm_new_widgets(dapm); | 157 | static const struct regmap_config lm4857_regmap_config = { |
| 158 | .val_bits = 6, | ||
| 159 | .reg_bits = 2, | ||
| 198 | 160 | ||
| 199 | return 0; | 161 | .max_register = LM4857_CTRL, |
| 200 | } | ||
| 201 | 162 | ||
| 202 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { | 163 | .cache_type = REGCACHE_FLAT, |
| 203 | .write = lm4857_write, | 164 | .reg_defaults = lm4857_default_regs, |
| 204 | .read = lm4857_read, | 165 | .num_reg_defaults = ARRAY_SIZE(lm4857_default_regs), |
| 205 | .probe = lm4857_probe, | ||
| 206 | .reg_cache_size = ARRAY_SIZE(lm4857_default_regs), | ||
| 207 | .reg_word_size = sizeof(uint8_t), | ||
| 208 | .reg_cache_default = lm4857_default_regs, | ||
| 209 | .set_bias_level = lm4857_set_bias_level, | ||
| 210 | }; | 166 | }; |
| 211 | 167 | ||
| 212 | static int lm4857_i2c_probe(struct i2c_client *i2c, | 168 | static int lm4857_i2c_probe(struct i2c_client *i2c, |
| 213 | const struct i2c_device_id *id) | 169 | const struct i2c_device_id *id) |
| 214 | { | 170 | { |
| 215 | struct lm4857 *lm4857; | 171 | struct lm4857 *lm4857; |
| 216 | int ret; | ||
| 217 | 172 | ||
| 218 | lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); | 173 | lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); |
| 219 | if (!lm4857) | 174 | if (!lm4857) |
| @@ -221,11 +176,11 @@ static int lm4857_i2c_probe(struct i2c_client *i2c, | |||
| 221 | 176 | ||
| 222 | i2c_set_clientdata(i2c, lm4857); | 177 | i2c_set_clientdata(i2c, lm4857); |
| 223 | 178 | ||
| 224 | lm4857->i2c = i2c; | 179 | lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config); |
| 225 | 180 | if (IS_ERR(lm4857->regmap)) | |
| 226 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); | 181 | return PTR_ERR(lm4857->regmap); |
| 227 | 182 | ||
| 228 | return ret; | 183 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); |
| 229 | } | 184 | } |
| 230 | 185 | ||
| 231 | static int lm4857_i2c_remove(struct i2c_client *i2c) | 186 | static int lm4857_i2c_remove(struct i2c_client *i2c) |
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index a6ac2313047d..31f91560e9f6 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c | |||
| @@ -118,6 +118,18 @@ static const struct snd_kcontrol_new max9768_mute[] = { | |||
| 118 | SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio), | 118 | SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio), |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | static const struct snd_soc_dapm_widget max9768_dapm_widgets[] = { | ||
| 122 | SND_SOC_DAPM_INPUT("IN"), | ||
| 123 | |||
| 124 | SND_SOC_DAPM_OUTPUT("OUT+"), | ||
| 125 | SND_SOC_DAPM_OUTPUT("OUT-"), | ||
| 126 | }; | ||
| 127 | |||
| 128 | static const struct snd_soc_dapm_route max9768_dapm_routes[] = { | ||
| 129 | { "OUT+", NULL, "IN" }, | ||
| 130 | { "OUT-", NULL, "IN" }, | ||
| 131 | }; | ||
| 132 | |||
| 121 | static int max9768_probe(struct snd_soc_codec *codec) | 133 | static int max9768_probe(struct snd_soc_codec *codec) |
| 122 | { | 134 | { |
| 123 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | 135 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); |
| @@ -148,6 +160,10 @@ static struct snd_soc_codec_driver max9768_codec_driver = { | |||
| 148 | .probe = max9768_probe, | 160 | .probe = max9768_probe, |
| 149 | .controls = max9768_volume, | 161 | .controls = max9768_volume, |
| 150 | .num_controls = ARRAY_SIZE(max9768_volume), | 162 | .num_controls = ARRAY_SIZE(max9768_volume), |
| 163 | .dapm_widgets = max9768_dapm_widgets, | ||
| 164 | .num_dapm_widgets = ARRAY_SIZE(max9768_dapm_widgets), | ||
| 165 | .dapm_routes = max9768_dapm_routes, | ||
| 166 | .num_dapm_routes = ARRAY_SIZE(max9768_dapm_routes), | ||
| 151 | }; | 167 | }; |
| 152 | 168 | ||
| 153 | static const struct regmap_config max9768_i2c_regmap_config = { | 169 | static const struct regmap_config max9768_i2c_regmap_config = { |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index ad5313f98f28..0569a4c3ae00 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
| @@ -2084,8 +2084,9 @@ static irqreturn_t max98090_interrupt(int irq, void *data) | |||
| 2084 | 2084 | ||
| 2085 | pm_wakeup_event(codec->dev, 100); | 2085 | pm_wakeup_event(codec->dev, 100); |
| 2086 | 2086 | ||
| 2087 | schedule_delayed_work(&max98090->jack_work, | 2087 | queue_delayed_work(system_power_efficient_wq, |
| 2088 | msecs_to_jiffies(100)); | 2088 | &max98090->jack_work, |
| 2089 | msecs_to_jiffies(100)); | ||
| 2089 | } | 2090 | } |
| 2090 | 2091 | ||
| 2091 | if (active & M98090_DRCACT_MASK) | 2092 | if (active & M98090_DRCACT_MASK) |
| @@ -2132,8 +2133,9 @@ int max98090_mic_detect(struct snd_soc_codec *codec, | |||
| 2132 | snd_soc_jack_report(max98090->jack, 0, | 2133 | snd_soc_jack_report(max98090->jack, 0, |
| 2133 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2134 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
| 2134 | 2135 | ||
| 2135 | schedule_delayed_work(&max98090->jack_work, | 2136 | queue_delayed_work(system_power_efficient_wq, |
| 2136 | msecs_to_jiffies(100)); | 2137 | &max98090->jack_work, |
| 2138 | msecs_to_jiffies(100)); | ||
| 2137 | 2139 | ||
| 2138 | return 0; | 2140 | return 0; |
| 2139 | } | 2141 | } |
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 6b6c74cd83e2..29549cdbf4c1 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c | |||
| @@ -14,170 +14,21 @@ | |||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 17 | #include <linux/regmap.h> | ||
| 17 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
| 18 | #include <sound/tlv.h> | 19 | #include <sound/tlv.h> |
| 19 | 20 | ||
| 20 | #include "max9877.h" | 21 | #include "max9877.h" |
| 21 | 22 | ||
| 22 | static struct i2c_client *i2c; | 23 | static struct regmap *regmap; |
| 23 | 24 | ||
| 24 | static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; | 25 | static struct reg_default max9877_regs[] = { |
| 25 | 26 | { 0, 0x40 }, | |
| 26 | static void max9877_write_regs(void) | 27 | { 1, 0x00 }, |
| 27 | { | 28 | { 2, 0x00 }, |
| 28 | unsigned int i; | 29 | { 3, 0x00 }, |
| 29 | u8 data[6]; | 30 | { 4, 0x49 }, |
| 30 | 31 | }; | |
| 31 | data[0] = MAX9877_INPUT_MODE; | ||
| 32 | for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) | ||
| 33 | data[i + 1] = max9877_regs[i]; | ||
| 34 | |||
| 35 | if (i2c_master_send(i2c, data, 6) != 6) | ||
| 36 | dev_err(&i2c->dev, "i2c write failed\n"); | ||
| 37 | } | ||
| 38 | |||
| 39 | static int max9877_get_reg(struct snd_kcontrol *kcontrol, | ||
| 40 | struct snd_ctl_elem_value *ucontrol) | ||
| 41 | { | ||
| 42 | struct soc_mixer_control *mc = | ||
| 43 | (struct soc_mixer_control *)kcontrol->private_value; | ||
| 44 | unsigned int reg = mc->reg; | ||
| 45 | unsigned int shift = mc->shift; | ||
| 46 | unsigned int mask = mc->max; | ||
| 47 | unsigned int invert = mc->invert; | ||
| 48 | |||
| 49 | ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; | ||
| 50 | |||
| 51 | if (invert) | ||
| 52 | ucontrol->value.integer.value[0] = | ||
| 53 | mask - ucontrol->value.integer.value[0]; | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int max9877_set_reg(struct snd_kcontrol *kcontrol, | ||
| 59 | struct snd_ctl_elem_value *ucontrol) | ||
| 60 | { | ||
| 61 | struct soc_mixer_control *mc = | ||
| 62 | (struct soc_mixer_control *)kcontrol->private_value; | ||
| 63 | unsigned int reg = mc->reg; | ||
| 64 | unsigned int shift = mc->shift; | ||
| 65 | unsigned int mask = mc->max; | ||
| 66 | unsigned int invert = mc->invert; | ||
| 67 | unsigned int val = (ucontrol->value.integer.value[0] & mask); | ||
| 68 | |||
| 69 | if (invert) | ||
| 70 | val = mask - val; | ||
| 71 | |||
| 72 | if (((max9877_regs[reg] >> shift) & mask) == val) | ||
| 73 | return 0; | ||
| 74 | |||
| 75 | max9877_regs[reg] &= ~(mask << shift); | ||
| 76 | max9877_regs[reg] |= val << shift; | ||
| 77 | max9877_write_regs(); | ||
| 78 | |||
| 79 | return 1; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int max9877_get_2reg(struct snd_kcontrol *kcontrol, | ||
| 83 | struct snd_ctl_elem_value *ucontrol) | ||
| 84 | { | ||
| 85 | struct soc_mixer_control *mc = | ||
| 86 | (struct soc_mixer_control *)kcontrol->private_value; | ||
| 87 | unsigned int reg = mc->reg; | ||
| 88 | unsigned int reg2 = mc->rreg; | ||
| 89 | unsigned int shift = mc->shift; | ||
| 90 | unsigned int mask = mc->max; | ||
| 91 | |||
| 92 | ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; | ||
| 93 | ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask; | ||
| 94 | |||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int max9877_set_2reg(struct snd_kcontrol *kcontrol, | ||
| 99 | struct snd_ctl_elem_value *ucontrol) | ||
| 100 | { | ||
| 101 | struct soc_mixer_control *mc = | ||
| 102 | (struct soc_mixer_control *)kcontrol->private_value; | ||
| 103 | unsigned int reg = mc->reg; | ||
| 104 | unsigned int reg2 = mc->rreg; | ||
| 105 | unsigned int shift = mc->shift; | ||
| 106 | unsigned int mask = mc->max; | ||
| 107 | unsigned int val = (ucontrol->value.integer.value[0] & mask); | ||
| 108 | unsigned int val2 = (ucontrol->value.integer.value[1] & mask); | ||
| 109 | unsigned int change = 0; | ||
| 110 | |||
| 111 | if (((max9877_regs[reg] >> shift) & mask) != val) | ||
| 112 | change = 1; | ||
| 113 | |||
| 114 | if (((max9877_regs[reg2] >> shift) & mask) != val2) | ||
| 115 | change = 1; | ||
| 116 | |||
| 117 | if (change) { | ||
| 118 | max9877_regs[reg] &= ~(mask << shift); | ||
| 119 | max9877_regs[reg] |= val << shift; | ||
| 120 | max9877_regs[reg2] &= ~(mask << shift); | ||
| 121 | max9877_regs[reg2] |= val2 << shift; | ||
| 122 | max9877_write_regs(); | ||
| 123 | } | ||
| 124 | |||
| 125 | return change; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int max9877_get_out_mode(struct snd_kcontrol *kcontrol, | ||
| 129 | struct snd_ctl_elem_value *ucontrol) | ||
| 130 | { | ||
| 131 | u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK; | ||
| 132 | |||
| 133 | if (value) | ||
| 134 | value -= 1; | ||
| 135 | |||
| 136 | ucontrol->value.integer.value[0] = value; | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int max9877_set_out_mode(struct snd_kcontrol *kcontrol, | ||
| 141 | struct snd_ctl_elem_value *ucontrol) | ||
| 142 | { | ||
| 143 | u8 value = ucontrol->value.integer.value[0]; | ||
| 144 | |||
| 145 | value += 1; | ||
| 146 | |||
| 147 | if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value) | ||
| 148 | return 0; | ||
| 149 | |||
| 150 | max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK; | ||
| 151 | max9877_regs[MAX9877_OUTPUT_MODE] |= value; | ||
| 152 | max9877_write_regs(); | ||
| 153 | return 1; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol, | ||
| 157 | struct snd_ctl_elem_value *ucontrol) | ||
| 158 | { | ||
| 159 | u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK); | ||
| 160 | |||
| 161 | value = value >> MAX9877_OSC_OFFSET; | ||
| 162 | |||
| 163 | ucontrol->value.integer.value[0] = value; | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol, | ||
| 168 | struct snd_ctl_elem_value *ucontrol) | ||
| 169 | { | ||
| 170 | u8 value = ucontrol->value.integer.value[0]; | ||
| 171 | |||
| 172 | value = value << MAX9877_OSC_OFFSET; | ||
| 173 | if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value) | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK; | ||
| 177 | max9877_regs[MAX9877_OUTPUT_MODE] |= value; | ||
| 178 | max9877_write_regs(); | ||
| 179 | return 1; | ||
| 180 | } | ||
| 181 | 32 | ||
| 182 | static const unsigned int max9877_pgain_tlv[] = { | 33 | static const unsigned int max9877_pgain_tlv[] = { |
| 183 | TLV_DB_RANGE_HEAD(2), | 34 | TLV_DB_RANGE_HEAD(2), |
| @@ -212,65 +63,104 @@ static const char *max9877_osc_mode[] = { | |||
| 212 | }; | 63 | }; |
| 213 | 64 | ||
| 214 | static const struct soc_enum max9877_enum[] = { | 65 | static const struct soc_enum max9877_enum[] = { |
| 215 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), | 66 | SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, 0, ARRAY_SIZE(max9877_out_mode), |
| 216 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), | 67 | max9877_out_mode), |
| 68 | SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, MAX9877_OSC_OFFSET, | ||
| 69 | ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), | ||
| 217 | }; | 70 | }; |
| 218 | 71 | ||
| 219 | static const struct snd_kcontrol_new max9877_controls[] = { | 72 | static const struct snd_kcontrol_new max9877_controls[] = { |
| 220 | SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", | 73 | SOC_SINGLE_TLV("MAX9877 PGAINA Playback Volume", |
| 221 | MAX9877_INPUT_MODE, 0, 2, 0, | 74 | MAX9877_INPUT_MODE, 0, 2, 0, max9877_pgain_tlv), |
| 222 | max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), | 75 | SOC_SINGLE_TLV("MAX9877 PGAINB Playback Volume", |
| 223 | SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", | 76 | MAX9877_INPUT_MODE, 2, 2, 0, max9877_pgain_tlv), |
| 224 | MAX9877_INPUT_MODE, 2, 2, 0, | 77 | SOC_SINGLE_TLV("MAX9877 Amp Speaker Playback Volume", |
| 225 | max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), | 78 | MAX9877_SPK_VOLUME, 0, 31, 0, max9877_output_tlv), |
| 226 | SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", | 79 | SOC_DOUBLE_R_TLV("MAX9877 Amp HP Playback Volume", |
| 227 | MAX9877_SPK_VOLUME, 0, 31, 0, | 80 | MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, |
| 228 | max9877_get_reg, max9877_set_reg, max9877_output_tlv), | 81 | max9877_output_tlv), |
| 229 | SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", | 82 | SOC_SINGLE("MAX9877 INB Stereo Switch", |
| 230 | MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, | 83 | MAX9877_INPUT_MODE, 4, 1, 1), |
| 231 | max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), | 84 | SOC_SINGLE("MAX9877 INA Stereo Switch", |
| 232 | SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", | 85 | MAX9877_INPUT_MODE, 5, 1, 1), |
| 233 | MAX9877_INPUT_MODE, 4, 1, 1, | 86 | SOC_SINGLE("MAX9877 Zero-crossing detection Switch", |
| 234 | max9877_get_reg, max9877_set_reg), | 87 | MAX9877_INPUT_MODE, 6, 1, 0), |
| 235 | SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", | 88 | SOC_SINGLE("MAX9877 Bypass Mode Switch", |
| 236 | MAX9877_INPUT_MODE, 5, 1, 1, | 89 | MAX9877_OUTPUT_MODE, 6, 1, 0), |
| 237 | max9877_get_reg, max9877_set_reg), | 90 | SOC_ENUM("MAX9877 Output Mode", max9877_enum[0]), |
| 238 | SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", | 91 | SOC_ENUM("MAX9877 Oscillator Mode", max9877_enum[1]), |
| 239 | MAX9877_INPUT_MODE, 6, 1, 0, | ||
| 240 | max9877_get_reg, max9877_set_reg), | ||
| 241 | SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch", | ||
| 242 | MAX9877_OUTPUT_MODE, 6, 1, 0, | ||
| 243 | max9877_get_reg, max9877_set_reg), | ||
| 244 | SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch", | ||
| 245 | MAX9877_OUTPUT_MODE, 7, 1, 1, | ||
| 246 | max9877_get_reg, max9877_set_reg), | ||
| 247 | SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0], | ||
| 248 | max9877_get_out_mode, max9877_set_out_mode), | ||
| 249 | SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1], | ||
| 250 | max9877_get_osc_mode, max9877_set_osc_mode), | ||
| 251 | }; | 92 | }; |
| 252 | 93 | ||
| 253 | /* This function is called from ASoC machine driver */ | 94 | static const struct snd_soc_dapm_widget max9877_dapm_widgets[] = { |
| 254 | int max9877_add_controls(struct snd_soc_codec *codec) | 95 | SND_SOC_DAPM_INPUT("INA1"), |
| 255 | { | 96 | SND_SOC_DAPM_INPUT("INA2"), |
| 256 | return snd_soc_add_codec_controls(codec, max9877_controls, | 97 | SND_SOC_DAPM_INPUT("INB1"), |
| 257 | ARRAY_SIZE(max9877_controls)); | 98 | SND_SOC_DAPM_INPUT("INB2"), |
| 258 | } | 99 | SND_SOC_DAPM_INPUT("RXIN+"), |
| 259 | EXPORT_SYMBOL_GPL(max9877_add_controls); | 100 | SND_SOC_DAPM_INPUT("RXIN-"), |
| 101 | |||
| 102 | SND_SOC_DAPM_PGA("SHDN", MAX9877_OUTPUT_MODE, 7, 1, NULL, 0), | ||
| 103 | |||
| 104 | SND_SOC_DAPM_OUTPUT("OUT+"), | ||
| 105 | SND_SOC_DAPM_OUTPUT("OUT-"), | ||
| 106 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
| 107 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
| 108 | }; | ||
| 109 | |||
| 110 | static const struct snd_soc_dapm_route max9877_dapm_routes[] = { | ||
| 111 | { "SHDN", NULL, "INA1" }, | ||
| 112 | { "SHDN", NULL, "INA2" }, | ||
| 113 | { "SHDN", NULL, "INB1" }, | ||
| 114 | { "SHDN", NULL, "INB2" }, | ||
| 115 | |||
| 116 | { "OUT+", NULL, "RXIN+" }, | ||
| 117 | { "OUT+", NULL, "SHDN" }, | ||
| 118 | |||
| 119 | { "OUT-", NULL, "SHDN" }, | ||
| 120 | { "OUT-", NULL, "RXIN-" }, | ||
| 121 | |||
| 122 | { "HPL", NULL, "SHDN" }, | ||
| 123 | { "HPR", NULL, "SHDN" }, | ||
| 124 | }; | ||
| 125 | |||
| 126 | static const struct snd_soc_codec_driver max9877_codec = { | ||
| 127 | .controls = max9877_controls, | ||
| 128 | .num_controls = ARRAY_SIZE(max9877_controls), | ||
| 129 | |||
| 130 | .dapm_widgets = max9877_dapm_widgets, | ||
| 131 | .num_dapm_widgets = ARRAY_SIZE(max9877_dapm_widgets), | ||
| 132 | .dapm_routes = max9877_dapm_routes, | ||
| 133 | .num_dapm_routes = ARRAY_SIZE(max9877_dapm_routes), | ||
| 134 | }; | ||
| 135 | |||
| 136 | static const struct regmap_config max9877_regmap = { | ||
| 137 | .reg_bits = 8, | ||
| 138 | .val_bits = 8, | ||
| 139 | |||
| 140 | .reg_defaults = max9877_regs, | ||
| 141 | .num_reg_defaults = ARRAY_SIZE(max9877_regs), | ||
| 142 | .cache_type = REGCACHE_RBTREE, | ||
| 143 | }; | ||
| 260 | 144 | ||
| 261 | static int max9877_i2c_probe(struct i2c_client *client, | 145 | static int max9877_i2c_probe(struct i2c_client *client, |
| 262 | const struct i2c_device_id *id) | 146 | const struct i2c_device_id *id) |
| 263 | { | 147 | { |
| 264 | i2c = client; | 148 | int i; |
| 265 | 149 | ||
| 266 | max9877_write_regs(); | 150 | regmap = devm_regmap_init_i2c(client, &max9877_regmap); |
| 151 | if (IS_ERR(regmap)) | ||
| 152 | return PTR_ERR(regmap); | ||
| 267 | 153 | ||
| 268 | return 0; | 154 | /* Ensure the device is in reset state */ |
| 155 | for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) | ||
| 156 | regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def); | ||
| 157 | |||
| 158 | return snd_soc_register_codec(&client->dev, &max9877_codec, NULL, 0); | ||
| 269 | } | 159 | } |
| 270 | 160 | ||
| 271 | static int max9877_i2c_remove(struct i2c_client *client) | 161 | static int max9877_i2c_remove(struct i2c_client *client) |
| 272 | { | 162 | { |
| 273 | i2c = NULL; | 163 | snd_soc_unregister_codec(&client->dev); |
| 274 | 164 | ||
| 275 | return 0; | 165 | return 0; |
| 276 | } | 166 | } |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 5402dfbbb716..4d3c8fd8c5db 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
| @@ -94,7 +94,6 @@ | |||
| 94 | #define AUDIO_DAC_CFS_DLY_B (1 << 10) | 94 | #define AUDIO_DAC_CFS_DLY_B (1 << 10) |
| 95 | 95 | ||
| 96 | struct mc13783_priv { | 96 | struct mc13783_priv { |
| 97 | struct snd_soc_codec codec; | ||
| 98 | struct mc13xxx *mc13xxx; | 97 | struct mc13xxx *mc13xxx; |
| 99 | 98 | ||
| 100 | enum mc13783_ssi_port adc_ssi_port; | 99 | enum mc13783_ssi_port adc_ssi_port; |
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c new file mode 100644 index 000000000000..651ce0923675 --- /dev/null +++ b/sound/soc/codecs/pcm1681.c | |||
| @@ -0,0 +1,339 @@ | |||
| 1 | /* | ||
| 2 | * PCM1681 ASoC codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) StreamUnlimited GmbH 2013 | ||
| 5 | * Marek Belisko <marek.belisko@streamunlimited.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version 2 | ||
| 10 | * of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/gpio.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/regmap.h> | ||
| 24 | #include <linux/of_device.h> | ||
| 25 | #include <linux/of_gpio.h> | ||
| 26 | #include <sound/pcm.h> | ||
| 27 | #include <sound/pcm_params.h> | ||
| 28 | #include <sound/soc.h> | ||
| 29 | #include <sound/tlv.h> | ||
| 30 | |||
| 31 | #define PCM1681_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
| 32 | SNDRV_PCM_FMTBIT_S24_LE) | ||
| 33 | |||
| 34 | #define PCM1681_PCM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ | ||
| 35 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
| 36 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ | ||
| 37 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) | ||
| 38 | |||
| 39 | #define PCM1681_SOFT_MUTE_ALL 0xff | ||
| 40 | #define PCM1681_DEEMPH_RATE_MASK 0x18 | ||
| 41 | #define PCM1681_DEEMPH_MASK 0x01 | ||
| 42 | |||
| 43 | #define PCM1681_ATT_CONTROL(X) (X <= 6 ? X : X + 9) /* Attenuation level */ | ||
| 44 | #define PCM1681_SOFT_MUTE 0x07 /* Soft mute control register */ | ||
| 45 | #define PCM1681_DAC_CONTROL 0x08 /* DAC operation control */ | ||
| 46 | #define PCM1681_FMT_CONTROL 0x09 /* Audio interface data format */ | ||
| 47 | #define PCM1681_DEEMPH_CONTROL 0x0a /* De-emphasis control */ | ||
| 48 | #define PCM1681_ZERO_DETECT_STATUS 0x0e /* Zero detect status reg */ | ||
| 49 | |||
| 50 | static const struct reg_default pcm1681_reg_defaults[] = { | ||
| 51 | { 0x01, 0xff }, | ||
| 52 | { 0x02, 0xff }, | ||
| 53 | { 0x03, 0xff }, | ||
| 54 | { 0x04, 0xff }, | ||
| 55 | { 0x05, 0xff }, | ||
| 56 | { 0x06, 0xff }, | ||
| 57 | { 0x07, 0x00 }, | ||
| 58 | { 0x08, 0x00 }, | ||
| 59 | { 0x09, 0x06 }, | ||
| 60 | { 0x0A, 0x00 }, | ||
| 61 | { 0x0B, 0xff }, | ||
| 62 | { 0x0C, 0x0f }, | ||
| 63 | { 0x0D, 0x00 }, | ||
| 64 | { 0x10, 0xff }, | ||
| 65 | { 0x11, 0xff }, | ||
| 66 | { 0x12, 0x00 }, | ||
| 67 | { 0x13, 0x00 }, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static bool pcm1681_accessible_reg(struct device *dev, unsigned int reg) | ||
| 71 | { | ||
| 72 | return !((reg == 0x00) || (reg == 0x0f)); | ||
| 73 | } | ||
| 74 | |||
| 75 | static bool pcm1681_writeable_reg(struct device *dev, unsigned register reg) | ||
| 76 | { | ||
| 77 | return pcm1681_accessible_reg(dev, reg) && | ||
| 78 | (reg != PCM1681_ZERO_DETECT_STATUS); | ||
| 79 | } | ||
| 80 | |||
| 81 | struct pcm1681_private { | ||
| 82 | struct regmap *regmap; | ||
| 83 | unsigned int format; | ||
| 84 | /* Current deemphasis status */ | ||
| 85 | unsigned int deemph; | ||
| 86 | /* Current rate for deemphasis control */ | ||
| 87 | unsigned int rate; | ||
| 88 | }; | ||
| 89 | |||
| 90 | static const int pcm1681_deemph[] = { 44100, 48000, 32000 }; | ||
| 91 | |||
| 92 | static int pcm1681_set_deemph(struct snd_soc_codec *codec) | ||
| 93 | { | ||
| 94 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 95 | int i = 0, val = -1, enable = 0; | ||
| 96 | |||
| 97 | if (priv->deemph) | ||
| 98 | for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) | ||
| 99 | if (pcm1681_deemph[i] == priv->rate) | ||
| 100 | val = i; | ||
| 101 | |||
| 102 | if (val != -1) { | ||
| 103 | regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, | ||
| 104 | PCM1681_DEEMPH_RATE_MASK, val); | ||
| 105 | enable = 1; | ||
| 106 | } else | ||
| 107 | enable = 0; | ||
| 108 | |||
| 109 | /* enable/disable deemphasis functionality */ | ||
| 110 | return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, | ||
| 111 | PCM1681_DEEMPH_MASK, enable); | ||
| 112 | } | ||
| 113 | |||
| 114 | static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol, | ||
| 115 | struct snd_ctl_elem_value *ucontrol) | ||
| 116 | { | ||
| 117 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 118 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 119 | |||
| 120 | ucontrol->value.enumerated.item[0] = priv->deemph; | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol, | ||
| 126 | struct snd_ctl_elem_value *ucontrol) | ||
| 127 | { | ||
| 128 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 129 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 130 | |||
| 131 | priv->deemph = ucontrol->value.enumerated.item[0]; | ||
| 132 | |||
| 133 | return pcm1681_set_deemph(codec); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
| 137 | unsigned int format) | ||
| 138 | { | ||
| 139 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 140 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 141 | |||
| 142 | /* The PCM1681 can only be slave to all clocks */ | ||
| 143 | if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
| 144 | dev_err(codec->dev, "Invalid clocking mode\n"); | ||
| 145 | return -EINVAL; | ||
| 146 | } | ||
| 147 | |||
| 148 | priv->format = format; | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute) | ||
| 154 | { | ||
| 155 | struct snd_soc_codec *codec = dai->codec; | ||
| 156 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 157 | int val; | ||
| 158 | |||
| 159 | if (mute) | ||
| 160 | val = PCM1681_SOFT_MUTE_ALL; | ||
| 161 | else | ||
| 162 | val = 0; | ||
| 163 | |||
| 164 | return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int pcm1681_hw_params(struct snd_pcm_substream *substream, | ||
| 168 | struct snd_pcm_hw_params *params, | ||
| 169 | struct snd_soc_dai *dai) | ||
| 170 | { | ||
| 171 | struct snd_soc_codec *codec = dai->codec; | ||
| 172 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 173 | int val = 0, ret; | ||
| 174 | int pcm_format = params_format(params); | ||
| 175 | |||
| 176 | priv->rate = params_rate(params); | ||
| 177 | |||
| 178 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 179 | case SND_SOC_DAIFMT_RIGHT_J: | ||
| 180 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) | ||
| 181 | val = 0x00; | ||
| 182 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | ||
| 183 | val = 0x03; | ||
| 184 | break; | ||
| 185 | case SND_SOC_DAIFMT_I2S: | ||
| 186 | val = 0x04; | ||
| 187 | break; | ||
| 188 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 189 | val = 0x05; | ||
| 190 | break; | ||
| 191 | default: | ||
| 192 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
| 193 | return -EINVAL; | ||
| 194 | } | ||
| 195 | |||
| 196 | ret = regmap_update_bits(priv->regmap, PCM1681_FMT_CONTROL, 0x0f, val); | ||
| 197 | if (ret < 0) | ||
| 198 | return ret; | ||
| 199 | |||
| 200 | return pcm1681_set_deemph(codec); | ||
| 201 | } | ||
| 202 | |||
| 203 | static const struct snd_soc_dai_ops pcm1681_dai_ops = { | ||
| 204 | .set_fmt = pcm1681_set_dai_fmt, | ||
| 205 | .hw_params = pcm1681_hw_params, | ||
| 206 | .digital_mute = pcm1681_digital_mute, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static const struct snd_soc_dapm_widget pcm1681_dapm_widgets[] = { | ||
| 210 | SND_SOC_DAPM_OUTPUT("VOUT1"), | ||
| 211 | SND_SOC_DAPM_OUTPUT("VOUT2"), | ||
| 212 | SND_SOC_DAPM_OUTPUT("VOUT3"), | ||
| 213 | SND_SOC_DAPM_OUTPUT("VOUT4"), | ||
| 214 | SND_SOC_DAPM_OUTPUT("VOUT5"), | ||
| 215 | SND_SOC_DAPM_OUTPUT("VOUT6"), | ||
| 216 | SND_SOC_DAPM_OUTPUT("VOUT7"), | ||
| 217 | SND_SOC_DAPM_OUTPUT("VOUT8"), | ||
| 218 | }; | ||
| 219 | |||
| 220 | static const struct snd_soc_dapm_route pcm1681_dapm_routes[] = { | ||
| 221 | { "VOUT1", NULL, "Playback" }, | ||
| 222 | { "VOUT2", NULL, "Playback" }, | ||
| 223 | { "VOUT3", NULL, "Playback" }, | ||
| 224 | { "VOUT4", NULL, "Playback" }, | ||
| 225 | { "VOUT5", NULL, "Playback" }, | ||
| 226 | { "VOUT6", NULL, "Playback" }, | ||
| 227 | { "VOUT7", NULL, "Playback" }, | ||
| 228 | { "VOUT8", NULL, "Playback" }, | ||
| 229 | }; | ||
| 230 | |||
| 231 | static const DECLARE_TLV_DB_SCALE(pcm1681_dac_tlv, -6350, 50, 1); | ||
| 232 | |||
| 233 | static const struct snd_kcontrol_new pcm1681_controls[] = { | ||
| 234 | SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume", | ||
| 235 | PCM1681_ATT_CONTROL(1), PCM1681_ATT_CONTROL(2), 0, | ||
| 236 | 0x7f, 0, pcm1681_dac_tlv), | ||
| 237 | SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume", | ||
| 238 | PCM1681_ATT_CONTROL(3), PCM1681_ATT_CONTROL(4), 0, | ||
| 239 | 0x7f, 0, pcm1681_dac_tlv), | ||
| 240 | SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume", | ||
| 241 | PCM1681_ATT_CONTROL(5), PCM1681_ATT_CONTROL(6), 0, | ||
| 242 | 0x7f, 0, pcm1681_dac_tlv), | ||
| 243 | SOC_DOUBLE_R_TLV("Channel 7/8 Playback Volume", | ||
| 244 | PCM1681_ATT_CONTROL(7), PCM1681_ATT_CONTROL(8), 0, | ||
| 245 | 0x7f, 0, pcm1681_dac_tlv), | ||
| 246 | SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0, | ||
| 247 | pcm1681_get_deemph, pcm1681_put_deemph), | ||
| 248 | }; | ||
| 249 | |||
| 250 | static struct snd_soc_dai_driver pcm1681_dai = { | ||
| 251 | .name = "pcm1681-hifi", | ||
| 252 | .playback = { | ||
| 253 | .stream_name = "Playback", | ||
| 254 | .channels_min = 2, | ||
| 255 | .channels_max = 8, | ||
| 256 | .rates = PCM1681_PCM_RATES, | ||
| 257 | .formats = PCM1681_PCM_FORMATS, | ||
| 258 | }, | ||
| 259 | .ops = &pcm1681_dai_ops, | ||
| 260 | }; | ||
| 261 | |||
| 262 | #ifdef CONFIG_OF | ||
| 263 | static const struct of_device_id pcm1681_dt_ids[] = { | ||
| 264 | { .compatible = "ti,pcm1681", }, | ||
| 265 | { } | ||
| 266 | }; | ||
| 267 | MODULE_DEVICE_TABLE(of, pcm1681_dt_ids); | ||
| 268 | #endif | ||
| 269 | |||
| 270 | static const struct regmap_config pcm1681_regmap = { | ||
| 271 | .reg_bits = 8, | ||
| 272 | .val_bits = 8, | ||
| 273 | .max_register = ARRAY_SIZE(pcm1681_reg_defaults) + 1, | ||
| 274 | .reg_defaults = pcm1681_reg_defaults, | ||
| 275 | .num_reg_defaults = ARRAY_SIZE(pcm1681_reg_defaults), | ||
| 276 | .writeable_reg = pcm1681_writeable_reg, | ||
| 277 | .readable_reg = pcm1681_accessible_reg, | ||
| 278 | }; | ||
| 279 | |||
| 280 | static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = { | ||
| 281 | .controls = pcm1681_controls, | ||
| 282 | .num_controls = ARRAY_SIZE(pcm1681_controls), | ||
| 283 | .dapm_widgets = pcm1681_dapm_widgets, | ||
| 284 | .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets), | ||
| 285 | .dapm_routes = pcm1681_dapm_routes, | ||
| 286 | .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes), | ||
| 287 | }; | ||
| 288 | |||
| 289 | static const struct i2c_device_id pcm1681_i2c_id[] = { | ||
| 290 | {"pcm1681", 0}, | ||
| 291 | {} | ||
| 292 | }; | ||
| 293 | MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id); | ||
| 294 | |||
| 295 | static int pcm1681_i2c_probe(struct i2c_client *client, | ||
| 296 | const struct i2c_device_id *id) | ||
| 297 | { | ||
| 298 | int ret; | ||
| 299 | struct pcm1681_private *priv; | ||
| 300 | |||
| 301 | priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); | ||
| 302 | if (!priv) | ||
| 303 | return -ENOMEM; | ||
| 304 | |||
| 305 | priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap); | ||
| 306 | if (IS_ERR(priv->regmap)) { | ||
| 307 | ret = PTR_ERR(priv->regmap); | ||
| 308 | dev_err(&client->dev, "Failed to create regmap: %d\n", ret); | ||
| 309 | return ret; | ||
| 310 | } | ||
| 311 | |||
| 312 | i2c_set_clientdata(client, priv); | ||
| 313 | |||
| 314 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_pcm1681, | ||
| 315 | &pcm1681_dai, 1); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int pcm1681_i2c_remove(struct i2c_client *client) | ||
| 319 | { | ||
| 320 | snd_soc_unregister_codec(&client->dev); | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct i2c_driver pcm1681_i2c_driver = { | ||
| 325 | .driver = { | ||
| 326 | .name = "pcm1681", | ||
| 327 | .owner = THIS_MODULE, | ||
| 328 | .of_match_table = of_match_ptr(pcm1681_dt_ids), | ||
| 329 | }, | ||
| 330 | .id_table = pcm1681_i2c_id, | ||
| 331 | .probe = pcm1681_i2c_probe, | ||
| 332 | .remove = pcm1681_i2c_remove, | ||
| 333 | }; | ||
| 334 | |||
| 335 | module_i2c_driver(pcm1681_i2c_driver); | ||
| 336 | |||
| 337 | MODULE_DESCRIPTION("Texas Instruments PCM1681 ALSA SoC Codec Driver"); | ||
| 338 | MODULE_AUTHOR("Marek Belisko <marek.belisko@streamunlimited.com>"); | ||
| 339 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c new file mode 100644 index 000000000000..2a8eccf64c76 --- /dev/null +++ b/sound/soc/codecs/pcm1792a.c | |||
| @@ -0,0 +1,257 @@ | |||
| 1 | /* | ||
| 2 | * PCM1792A ASoC codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Amarula Solutions B.V. 2013 | ||
| 5 | * | ||
| 6 | * Michael Trimarchi <michael@amarulasolutions.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/spi/spi.h> | ||
| 24 | |||
| 25 | #include <sound/core.h> | ||
| 26 | #include <sound/pcm.h> | ||
| 27 | #include <sound/pcm_params.h> | ||
| 28 | #include <sound/initval.h> | ||
| 29 | #include <sound/soc.h> | ||
| 30 | #include <sound/tlv.h> | ||
| 31 | #include <linux/of_device.h> | ||
| 32 | |||
| 33 | #include "pcm1792a.h" | ||
| 34 | |||
| 35 | #define PCM1792A_DAC_VOL_LEFT 0x10 | ||
| 36 | #define PCM1792A_DAC_VOL_RIGHT 0x11 | ||
| 37 | #define PCM1792A_FMT_CONTROL 0x12 | ||
| 38 | #define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL | ||
| 39 | |||
| 40 | #define PCM1792A_FMT_MASK 0x70 | ||
| 41 | #define PCM1792A_FMT_SHIFT 4 | ||
| 42 | #define PCM1792A_MUTE_MASK 0x01 | ||
| 43 | #define PCM1792A_MUTE_SHIFT 0 | ||
| 44 | #define PCM1792A_ATLD_ENABLE (1 << 7) | ||
| 45 | |||
| 46 | static const struct reg_default pcm1792a_reg_defaults[] = { | ||
| 47 | { 0x10, 0xff }, | ||
| 48 | { 0x11, 0xff }, | ||
| 49 | { 0x12, 0x50 }, | ||
| 50 | { 0x13, 0x00 }, | ||
| 51 | { 0x14, 0x00 }, | ||
| 52 | { 0x15, 0x01 }, | ||
| 53 | { 0x16, 0x00 }, | ||
| 54 | { 0x17, 0x00 }, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg) | ||
| 58 | { | ||
| 59 | return reg >= 0x10 && reg <= 0x17; | ||
| 60 | } | ||
| 61 | |||
| 62 | static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg) | ||
| 63 | { | ||
| 64 | bool accessible; | ||
| 65 | |||
| 66 | accessible = pcm1792a_accessible_reg(dev, reg); | ||
| 67 | |||
| 68 | return accessible && reg != 0x16 && reg != 0x17; | ||
| 69 | } | ||
| 70 | |||
| 71 | struct pcm1792a_private { | ||
| 72 | struct regmap *regmap; | ||
| 73 | unsigned int format; | ||
| 74 | unsigned int rate; | ||
| 75 | }; | ||
| 76 | |||
| 77 | static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
| 78 | unsigned int format) | ||
| 79 | { | ||
| 80 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 81 | struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 82 | |||
| 83 | priv->format = format; | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute) | ||
| 89 | { | ||
| 90 | struct snd_soc_codec *codec = dai->codec; | ||
| 91 | struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 92 | int ret; | ||
| 93 | |||
| 94 | ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE, | ||
| 95 | PCM1792A_MUTE_MASK, !!mute); | ||
| 96 | if (ret < 0) | ||
| 97 | return ret; | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int pcm1792a_hw_params(struct snd_pcm_substream *substream, | ||
| 103 | struct snd_pcm_hw_params *params, | ||
| 104 | struct snd_soc_dai *dai) | ||
| 105 | { | ||
| 106 | struct snd_soc_codec *codec = dai->codec; | ||
| 107 | struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); | ||
| 108 | int val = 0, ret; | ||
| 109 | int pcm_format = params_format(params); | ||
| 110 | |||
| 111 | priv->rate = params_rate(params); | ||
| 112 | |||
| 113 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 114 | case SND_SOC_DAIFMT_RIGHT_J: | ||
| 115 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || | ||
| 116 | pcm_format == SNDRV_PCM_FORMAT_S32_LE) | ||
| 117 | val = 0x02; | ||
| 118 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | ||
| 119 | val = 0x00; | ||
| 120 | break; | ||
| 121 | case SND_SOC_DAIFMT_I2S: | ||
| 122 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || | ||
| 123 | pcm_format == SNDRV_PCM_FORMAT_S32_LE) | ||
| 124 | val = 0x05; | ||
| 125 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | ||
| 126 | val = 0x04; | ||
| 127 | break; | ||
| 128 | default: | ||
| 129 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
| 130 | return -EINVAL; | ||
| 131 | } | ||
| 132 | |||
| 133 | val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE; | ||
| 134 | |||
| 135 | ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL, | ||
| 136 | PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val); | ||
| 137 | if (ret < 0) | ||
| 138 | return ret; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static const struct snd_soc_dai_ops pcm1792a_dai_ops = { | ||
| 144 | .set_fmt = pcm1792a_set_dai_fmt, | ||
| 145 | .hw_params = pcm1792a_hw_params, | ||
| 146 | .digital_mute = pcm1792a_digital_mute, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1); | ||
| 150 | |||
| 151 | static const struct snd_kcontrol_new pcm1792a_controls[] = { | ||
| 152 | SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT, | ||
| 153 | PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0, | ||
| 154 | pcm1792a_dac_tlv), | ||
| 155 | }; | ||
| 156 | |||
| 157 | static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = { | ||
| 158 | SND_SOC_DAPM_OUTPUT("IOUTL+"), | ||
| 159 | SND_SOC_DAPM_OUTPUT("IOUTL-"), | ||
| 160 | SND_SOC_DAPM_OUTPUT("IOUTR+"), | ||
| 161 | SND_SOC_DAPM_OUTPUT("IOUTR-"), | ||
| 162 | }; | ||
| 163 | |||
| 164 | static const struct snd_soc_dapm_route pcm1792a_dapm_routes[] = { | ||
| 165 | { "IOUTL+", NULL, "Playback" }, | ||
| 166 | { "IOUTL-", NULL, "Playback" }, | ||
| 167 | { "IOUTR+", NULL, "Playback" }, | ||
| 168 | { "IOUTR-", NULL, "Playback" }, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static struct snd_soc_dai_driver pcm1792a_dai = { | ||
| 172 | .name = "pcm1792a-hifi", | ||
| 173 | .playback = { | ||
| 174 | .stream_name = "Playback", | ||
| 175 | .channels_min = 2, | ||
| 176 | .channels_max = 2, | ||
| 177 | .rates = PCM1792A_RATES, | ||
| 178 | .formats = PCM1792A_FORMATS, }, | ||
| 179 | .ops = &pcm1792a_dai_ops, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static const struct of_device_id pcm1792a_of_match[] = { | ||
| 183 | { .compatible = "ti,pcm1792a", }, | ||
| 184 | { } | ||
| 185 | }; | ||
| 186 | MODULE_DEVICE_TABLE(of, pcm1792a_of_match); | ||
| 187 | |||
| 188 | static const struct regmap_config pcm1792a_regmap = { | ||
| 189 | .reg_bits = 8, | ||
| 190 | .val_bits = 8, | ||
| 191 | .max_register = 24, | ||
| 192 | .reg_defaults = pcm1792a_reg_defaults, | ||
| 193 | .num_reg_defaults = ARRAY_SIZE(pcm1792a_reg_defaults), | ||
| 194 | .writeable_reg = pcm1792a_writeable_reg, | ||
| 195 | .readable_reg = pcm1792a_accessible_reg, | ||
| 196 | }; | ||
| 197 | |||
| 198 | static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = { | ||
| 199 | .controls = pcm1792a_controls, | ||
| 200 | .num_controls = ARRAY_SIZE(pcm1792a_controls), | ||
| 201 | .dapm_widgets = pcm1792a_dapm_widgets, | ||
| 202 | .num_dapm_widgets = ARRAY_SIZE(pcm1792a_dapm_widgets), | ||
| 203 | .dapm_routes = pcm1792a_dapm_routes, | ||
| 204 | .num_dapm_routes = ARRAY_SIZE(pcm1792a_dapm_routes), | ||
| 205 | }; | ||
| 206 | |||
| 207 | static int pcm1792a_spi_probe(struct spi_device *spi) | ||
| 208 | { | ||
| 209 | struct pcm1792a_private *pcm1792a; | ||
| 210 | int ret; | ||
| 211 | |||
| 212 | pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private), | ||
| 213 | GFP_KERNEL); | ||
| 214 | if (!pcm1792a) | ||
| 215 | return -ENOMEM; | ||
| 216 | |||
| 217 | spi_set_drvdata(spi, pcm1792a); | ||
| 218 | |||
| 219 | pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap); | ||
| 220 | if (IS_ERR(pcm1792a->regmap)) { | ||
| 221 | ret = PTR_ERR(pcm1792a->regmap); | ||
| 222 | dev_err(&spi->dev, "Failed to register regmap: %d\n", ret); | ||
| 223 | return ret; | ||
| 224 | } | ||
| 225 | |||
| 226 | return snd_soc_register_codec(&spi->dev, | ||
| 227 | &soc_codec_dev_pcm1792a, &pcm1792a_dai, 1); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int pcm1792a_spi_remove(struct spi_device *spi) | ||
| 231 | { | ||
| 232 | snd_soc_unregister_codec(&spi->dev); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static const struct spi_device_id pcm1792a_spi_ids[] = { | ||
| 237 | { "pcm1792a", 0 }, | ||
| 238 | { }, | ||
| 239 | }; | ||
| 240 | MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids); | ||
| 241 | |||
| 242 | static struct spi_driver pcm1792a_codec_driver = { | ||
| 243 | .driver = { | ||
| 244 | .name = "pcm1792a", | ||
| 245 | .owner = THIS_MODULE, | ||
| 246 | .of_match_table = of_match_ptr(pcm1792a_of_match), | ||
| 247 | }, | ||
| 248 | .id_table = pcm1792a_spi_ids, | ||
| 249 | .probe = pcm1792a_spi_probe, | ||
| 250 | .remove = pcm1792a_spi_remove, | ||
| 251 | }; | ||
| 252 | |||
| 253 | module_spi_driver(pcm1792a_codec_driver); | ||
| 254 | |||
| 255 | MODULE_DESCRIPTION("ASoC PCM1792A driver"); | ||
| 256 | MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>"); | ||
| 257 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h new file mode 100644 index 000000000000..7a83d1fc102a --- /dev/null +++ b/sound/soc/codecs/pcm1792a.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * definitions for PCM1792A | ||
| 3 | * | ||
| 4 | * Copyright 2013 Amarula Solutions | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version 2 | ||
| 9 | * of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __PCM1792A_H__ | ||
| 18 | #define __PCM1792A_H__ | ||
| 19 | |||
| 20 | #define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ | ||
| 21 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) | ||
| 22 | |||
| 23 | #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
| 24 | SNDRV_PCM_FMTBIT_S16_LE) | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index f2a6282b41f4..b6618c4a7597 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
| @@ -28,7 +28,54 @@ | |||
| 28 | 28 | ||
| 29 | #include "pcm3008.h" | 29 | #include "pcm3008.h" |
| 30 | 30 | ||
| 31 | #define PCM3008_VERSION "0.2" | 31 | static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w, |
| 32 | struct snd_kcontrol *kcontrol, | ||
| 33 | int event) | ||
| 34 | { | ||
| 35 | struct snd_soc_codec *codec = w->codec; | ||
| 36 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | ||
| 37 | |||
| 38 | gpio_set_value_cansleep(setup->pdda_pin, | ||
| 39 | SND_SOC_DAPM_EVENT_ON(event)); | ||
| 40 | |||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w, | ||
| 45 | struct snd_kcontrol *kcontrol, | ||
| 46 | int event) | ||
| 47 | { | ||
| 48 | struct snd_soc_codec *codec = w->codec; | ||
| 49 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | ||
| 50 | |||
| 51 | gpio_set_value_cansleep(setup->pdad_pin, | ||
| 52 | SND_SOC_DAPM_EVENT_ON(event)); | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static const struct snd_soc_dapm_widget pcm3008_dapm_widgets[] = { | ||
| 58 | SND_SOC_DAPM_INPUT("VINL"), | ||
| 59 | SND_SOC_DAPM_INPUT("VINR"), | ||
| 60 | |||
| 61 | SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_dac_ev, | ||
| 62 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 63 | SND_SOC_DAPM_ADC_E("ADC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_adc_ev, | ||
| 64 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 65 | |||
| 66 | SND_SOC_DAPM_OUTPUT("VOUTL"), | ||
| 67 | SND_SOC_DAPM_OUTPUT("VOUTR"), | ||
| 68 | }; | ||
| 69 | |||
| 70 | static const struct snd_soc_dapm_route pcm3008_dapm_routes[] = { | ||
| 71 | { "PCM3008 Capture", NULL, "ADC" }, | ||
| 72 | { "ADC", NULL, "VINL" }, | ||
| 73 | { "ADC", NULL, "VINR" }, | ||
| 74 | |||
| 75 | { "DAC", NULL, "PCM3008 Playback" }, | ||
| 76 | { "VOUTL", NULL, "DAC" }, | ||
| 77 | { "VOUTR", NULL, "DAC" }, | ||
| 78 | }; | ||
| 32 | 79 | ||
| 33 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 80 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
| 34 | SNDRV_PCM_RATE_48000) | 81 | SNDRV_PCM_RATE_48000) |
| @@ -51,20 +98,20 @@ static struct snd_soc_dai_driver pcm3008_dai = { | |||
| 51 | }, | 98 | }, |
| 52 | }; | 99 | }; |
| 53 | 100 | ||
| 54 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | 101 | static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { |
| 55 | { | 102 | .dapm_widgets = pcm3008_dapm_widgets, |
| 56 | gpio_free(setup->dem0_pin); | 103 | .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets), |
| 57 | gpio_free(setup->dem1_pin); | 104 | .dapm_routes = pcm3008_dapm_routes, |
| 58 | gpio_free(setup->pdad_pin); | 105 | .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes), |
| 59 | gpio_free(setup->pdda_pin); | 106 | }; |
| 60 | } | ||
| 61 | 107 | ||
| 62 | static int pcm3008_soc_probe(struct snd_soc_codec *codec) | 108 | static int pcm3008_codec_probe(struct platform_device *pdev) |
| 63 | { | 109 | { |
| 64 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | 110 | struct pcm3008_setup_data *setup = pdev->dev.platform_data; |
| 65 | int ret = 0; | 111 | int ret; |
| 66 | 112 | ||
| 67 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); | 113 | if (!setup) |
| 114 | return -EINVAL; | ||
| 68 | 115 | ||
| 69 | /* DEM1 DEM0 DE-EMPHASIS_MODE | 116 | /* DEM1 DEM0 DE-EMPHASIS_MODE |
| 70 | * Low Low De-emphasis 44.1 kHz ON | 117 | * Low Low De-emphasis 44.1 kHz ON |
| @@ -74,83 +121,29 @@ static int pcm3008_soc_probe(struct snd_soc_codec *codec) | |||
| 74 | */ | 121 | */ |
| 75 | 122 | ||
| 76 | /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ | 123 | /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ |
| 77 | ret = gpio_request(setup->dem0_pin, "codec_dem0"); | 124 | ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin, |
| 78 | if (ret == 0) | 125 | GPIOF_OUT_INIT_HIGH, "codec_dem0"); |
| 79 | ret = gpio_direction_output(setup->dem0_pin, 1); | ||
| 80 | if (ret != 0) | 126 | if (ret != 0) |
| 81 | goto gpio_err; | 127 | return ret; |
| 82 | 128 | ||
| 83 | /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ | 129 | /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ |
| 84 | ret = gpio_request(setup->dem1_pin, "codec_dem1"); | 130 | ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin, |
| 85 | if (ret == 0) | 131 | GPIOF_OUT_INIT_LOW, "codec_dem1"); |
| 86 | ret = gpio_direction_output(setup->dem1_pin, 0); | ||
| 87 | if (ret != 0) | 132 | if (ret != 0) |
| 88 | goto gpio_err; | 133 | return ret; |
| 89 | 134 | ||
| 90 | /* Configure PDAD GPIO. */ | 135 | /* Configure PDAD GPIO. */ |
| 91 | ret = gpio_request(setup->pdad_pin, "codec_pdad"); | 136 | ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin, |
| 92 | if (ret == 0) | 137 | GPIOF_OUT_INIT_LOW, "codec_pdad"); |
| 93 | ret = gpio_direction_output(setup->pdad_pin, 1); | ||
| 94 | if (ret != 0) | 138 | if (ret != 0) |
| 95 | goto gpio_err; | 139 | return ret; |
| 96 | 140 | ||
| 97 | /* Configure PDDA GPIO. */ | 141 | /* Configure PDDA GPIO. */ |
| 98 | ret = gpio_request(setup->pdda_pin, "codec_pdda"); | 142 | ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin, |
| 99 | if (ret == 0) | 143 | GPIOF_OUT_INIT_LOW, "codec_pdda"); |
| 100 | ret = gpio_direction_output(setup->pdda_pin, 1); | ||
| 101 | if (ret != 0) | 144 | if (ret != 0) |
| 102 | goto gpio_err; | 145 | return ret; |
| 103 | |||
| 104 | return ret; | ||
| 105 | |||
| 106 | gpio_err: | ||
| 107 | pcm3008_gpio_free(setup); | ||
| 108 | 146 | ||
| 109 | return ret; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int pcm3008_soc_remove(struct snd_soc_codec *codec) | ||
| 113 | { | ||
| 114 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | ||
| 115 | |||
| 116 | pcm3008_gpio_free(setup); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | #ifdef CONFIG_PM | ||
| 121 | static int pcm3008_soc_suspend(struct snd_soc_codec *codec) | ||
| 122 | { | ||
| 123 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | ||
| 124 | |||
| 125 | gpio_set_value(setup->pdad_pin, 0); | ||
| 126 | gpio_set_value(setup->pdda_pin, 0); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int pcm3008_soc_resume(struct snd_soc_codec *codec) | ||
| 132 | { | ||
| 133 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | ||
| 134 | |||
| 135 | gpio_set_value(setup->pdad_pin, 1); | ||
| 136 | gpio_set_value(setup->pdda_pin, 1); | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | #else | ||
| 141 | #define pcm3008_soc_suspend NULL | ||
| 142 | #define pcm3008_soc_resume NULL | ||
| 143 | #endif | ||
| 144 | |||
| 145 | static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { | ||
| 146 | .probe = pcm3008_soc_probe, | ||
| 147 | .remove = pcm3008_soc_remove, | ||
| 148 | .suspend = pcm3008_soc_suspend, | ||
| 149 | .resume = pcm3008_soc_resume, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static int pcm3008_codec_probe(struct platform_device *pdev) | ||
| 153 | { | ||
| 154 | return snd_soc_register_codec(&pdev->dev, | 147 | return snd_soc_register_codec(&pdev->dev, |
| 155 | &soc_codec_dev_pcm3008, &pcm3008_dai, 1); | 148 | &soc_codec_dev_pcm3008, &pcm3008_dai, 1); |
| 156 | } | 149 | } |
| @@ -158,6 +151,7 @@ static int pcm3008_codec_probe(struct platform_device *pdev) | |||
| 158 | static int pcm3008_codec_remove(struct platform_device *pdev) | 151 | static int pcm3008_codec_remove(struct platform_device *pdev) |
| 159 | { | 152 | { |
| 160 | snd_soc_unregister_codec(&pdev->dev); | 153 | snd_soc_unregister_codec(&pdev->dev); |
| 154 | |||
| 161 | return 0; | 155 | return 0; |
| 162 | } | 156 | } |
| 163 | 157 | ||
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index ce585e37e38a..4db7314baabc 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
| @@ -737,29 +737,6 @@ static const struct snd_kcontrol_new rt5640_mono_mix[] = { | |||
| 737 | RT5640_M_BST1_MM_SFT, 1, 1), | 737 | RT5640_M_BST1_MM_SFT, 1, 1), |
| 738 | }; | 738 | }; |
| 739 | 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 */ | 740 | /* Stereo ADC source */ |
| 764 | static const char * const rt5640_stereo_adc1_src[] = { | 741 | static const char * const rt5640_stereo_adc1_src[] = { |
| 765 | "DIG MIX", "ADC" | 742 | "DIG MIX", "ADC" |
| @@ -1005,9 +982,6 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { | |||
| 1005 | RT5640_PWR_IN_L_BIT, 0, NULL, 0), | 982 | RT5640_PWR_IN_L_BIT, 0, NULL, 0), |
| 1006 | SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL, | 983 | SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL, |
| 1007 | RT5640_PWR_IN_R_BIT, 0, NULL, 0), | 984 | 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 */ | 985 | /* REC Mixer */ |
| 1012 | SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0, | 986 | 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)), | 987 | rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)), |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6c8a9e7bee25..1f4093f3f3a1 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
| @@ -153,6 +153,8 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
| 153 | static int power_vag_event(struct snd_soc_dapm_widget *w, | 153 | static int power_vag_event(struct snd_soc_dapm_widget *w, |
| 154 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
| 155 | { | 155 | { |
| 156 | const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; | ||
| 157 | |||
| 156 | switch (event) { | 158 | switch (event) { |
| 157 | case SND_SOC_DAPM_POST_PMU: | 159 | case SND_SOC_DAPM_POST_PMU: |
| 158 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 160 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, |
| @@ -160,9 +162,17 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, | |||
| 160 | break; | 162 | break; |
| 161 | 163 | ||
| 162 | case SND_SOC_DAPM_PRE_PMD: | 164 | case SND_SOC_DAPM_PRE_PMD: |
| 163 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 165 | /* |
| 164 | SGTL5000_VAG_POWERUP, 0); | 166 | * Don't clear VAG_POWERUP, when both DAC and ADC are |
| 165 | msleep(400); | 167 | * operational to prevent inadvertently starving the |
| 168 | * other one of them. | ||
| 169 | */ | ||
| 170 | if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) & | ||
| 171 | mask) != mask) { | ||
| 172 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | ||
| 173 | SGTL5000_VAG_POWERUP, 0); | ||
| 174 | msleep(400); | ||
| 175 | } | ||
| 166 | break; | 176 | break; |
| 167 | default: | 177 | default: |
| 168 | break; | 178 | break; |
| @@ -388,7 +398,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { | |||
| 388 | SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), | 398 | SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), |
| 389 | SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", | 399 | SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", |
| 390 | SGTL5000_CHIP_ANA_ADC_CTRL, | 400 | SGTL5000_CHIP_ANA_ADC_CTRL, |
| 391 | 8, 2, 0, capture_6db_attenuate), | 401 | 8, 1, 0, capture_6db_attenuate), |
| 392 | SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), | 402 | SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), |
| 393 | 403 | ||
| 394 | SOC_DOUBLE_TLV("Headphone Playback Volume", | 404 | SOC_DOUBLE_TLV("Headphone Playback Volume", |
| @@ -644,16 +654,19 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
| 644 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | 654 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, |
| 645 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, | 655 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, |
| 646 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); | 656 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); |
| 657 | |||
| 658 | /* if using pll, clk_ctrl must be set after pll power up */ | ||
| 659 | snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl); | ||
| 647 | } else { | 660 | } else { |
| 661 | /* otherwise, clk_ctrl must be set before pll power down */ | ||
| 662 | snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl); | ||
| 663 | |||
| 648 | /* power down pll */ | 664 | /* power down pll */ |
| 649 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | 665 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, |
| 650 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, | 666 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, |
| 651 | 0); | 667 | 0); |
| 652 | } | 668 | } |
| 653 | 669 | ||
| 654 | /* if using pll, clk_ctrl must be set after pll power up */ | ||
| 655 | snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl); | ||
| 656 | |||
| 657 | return 0; | 670 | return 0; |
| 658 | } | 671 | } |
| 659 | 672 | ||
| @@ -1470,6 +1483,7 @@ static struct snd_soc_codec_driver sgtl5000_driver = { | |||
| 1470 | static const struct regmap_config sgtl5000_regmap = { | 1483 | static const struct regmap_config sgtl5000_regmap = { |
| 1471 | .reg_bits = 16, | 1484 | .reg_bits = 16, |
| 1472 | .val_bits = 16, | 1485 | .val_bits = 16, |
| 1486 | .reg_stride = 2, | ||
| 1473 | 1487 | ||
| 1474 | .max_register = SGTL5000_MAX_REG_OFFSET, | 1488 | .max_register = SGTL5000_MAX_REG_OFFSET, |
| 1475 | .volatile_reg = sgtl5000_volatile, | 1489 | .volatile_reg = sgtl5000_volatile, |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 73e205c892a0..38f3b105c17d 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
| @@ -102,6 +102,16 @@ static int si476x_codec_write(struct snd_soc_codec *codec, | |||
| 102 | return err; | 102 | return err; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = { | ||
| 106 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
| 107 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
| 108 | }; | ||
| 109 | |||
| 110 | static const struct snd_soc_dapm_route si476x_dapm_routes[] = { | ||
| 111 | { "Capture", NULL, "LOUT" }, | ||
| 112 | { "Capture", NULL, "ROUT" }, | ||
| 113 | }; | ||
| 114 | |||
| 105 | static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, | 115 | static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, |
| 106 | unsigned int fmt) | 116 | unsigned int fmt) |
| 107 | { | 117 | { |
| @@ -260,6 +270,10 @@ static struct snd_soc_codec_driver soc_codec_dev_si476x = { | |||
| 260 | .probe = si476x_codec_probe, | 270 | .probe = si476x_codec_probe, |
| 261 | .read = si476x_codec_read, | 271 | .read = si476x_codec_read, |
| 262 | .write = si476x_codec_write, | 272 | .write = si476x_codec_write, |
| 273 | .dapm_widgets = si476x_dapm_widgets, | ||
| 274 | .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), | ||
| 275 | .dapm_routes = si476x_dapm_routes, | ||
| 276 | .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), | ||
| 263 | }; | 277 | }; |
| 264 | 278 | ||
| 265 | static int si476x_platform_probe(struct platform_device *pdev) | 279 | static int si476x_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index e9d7881ed2c8..e3501f40c7b3 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c | |||
| @@ -23,11 +23,26 @@ | |||
| 23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
| 24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
| 25 | 25 | ||
| 26 | static const struct snd_soc_dapm_widget dir_widgets[] = { | ||
| 27 | SND_SOC_DAPM_INPUT("spdif-in"), | ||
| 28 | }; | ||
| 29 | |||
| 30 | static const struct snd_soc_dapm_route dir_routes[] = { | ||
| 31 | { "Capture", NULL, "spdif-in" }, | ||
| 32 | }; | ||
| 33 | |||
| 26 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 | 34 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 |
| 27 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 35 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| 36 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
| 37 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
| 28 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) | 38 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) |
| 29 | 39 | ||
| 30 | static struct snd_soc_codec_driver soc_codec_spdif_dir; | 40 | static struct snd_soc_codec_driver soc_codec_spdif_dir = { |
| 41 | .dapm_widgets = dir_widgets, | ||
| 42 | .num_dapm_widgets = ARRAY_SIZE(dir_widgets), | ||
| 43 | .dapm_routes = dir_routes, | ||
| 44 | .num_dapm_routes = ARRAY_SIZE(dir_routes), | ||
| 45 | }; | ||
| 31 | 46 | ||
| 32 | static struct snd_soc_dai_driver dir_stub_dai = { | 47 | static struct snd_soc_dai_driver dir_stub_dai = { |
| 33 | .name = "dir-hifi", | 48 | .name = "dir-hifi", |
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index 18280499fd55..a078aa31052a 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c | |||
| @@ -25,10 +25,24 @@ | |||
| 25 | #define DRV_NAME "spdif-dit" | 25 | #define DRV_NAME "spdif-dit" |
| 26 | 26 | ||
| 27 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 | 27 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 |
| 28 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 28 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| 29 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
| 30 | SNDRV_PCM_FMTBIT_S24_LE) | ||
| 29 | 31 | ||
| 32 | static const struct snd_soc_dapm_widget dit_widgets[] = { | ||
| 33 | SND_SOC_DAPM_OUTPUT("spdif-out"), | ||
| 34 | }; | ||
| 35 | |||
| 36 | static const struct snd_soc_dapm_route dit_routes[] = { | ||
| 37 | { "spdif-out", NULL, "Playback" }, | ||
| 38 | }; | ||
| 30 | 39 | ||
| 31 | static struct snd_soc_codec_driver soc_codec_spdif_dit; | 40 | static struct snd_soc_codec_driver soc_codec_spdif_dit = { |
| 41 | .dapm_widgets = dit_widgets, | ||
| 42 | .num_dapm_widgets = ARRAY_SIZE(dit_widgets), | ||
| 43 | .dapm_routes = dit_routes, | ||
| 44 | .num_dapm_routes = ARRAY_SIZE(dit_routes), | ||
| 45 | }; | ||
| 32 | 46 | ||
| 33 | static struct snd_soc_dai_driver dit_stub_dai = { | 47 | static struct snd_soc_dai_driver dit_stub_dai = { |
| 34 | .name = "dit-hifi", | 48 | .name = "dit-hifi", |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index cfb55fe35e98..06edb396e733 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
| @@ -363,16 +363,18 @@ static void sta32x_watchdog(struct work_struct *work) | |||
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | if (!sta32x->shutdown) | 365 | if (!sta32x->shutdown) |
| 366 | schedule_delayed_work(&sta32x->watchdog_work, | 366 | queue_delayed_work(system_power_efficient_wq, |
| 367 | round_jiffies_relative(HZ)); | 367 | &sta32x->watchdog_work, |
| 368 | round_jiffies_relative(HZ)); | ||
| 368 | } | 369 | } |
| 369 | 370 | ||
| 370 | static void sta32x_watchdog_start(struct sta32x_priv *sta32x) | 371 | static void sta32x_watchdog_start(struct sta32x_priv *sta32x) |
| 371 | { | 372 | { |
| 372 | if (sta32x->pdata->needs_esd_watchdog) { | 373 | if (sta32x->pdata->needs_esd_watchdog) { |
| 373 | sta32x->shutdown = 0; | 374 | sta32x->shutdown = 0; |
| 374 | schedule_delayed_work(&sta32x->watchdog_work, | 375 | queue_delayed_work(system_power_efficient_wq, |
| 375 | round_jiffies_relative(HZ)); | 376 | &sta32x->watchdog_work, |
| 377 | round_jiffies_relative(HZ)); | ||
| 376 | } | 378 | } |
| 377 | } | 379 | } |
| 378 | 380 | ||
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index b1f6982c7c9c..7b8f3d965f43 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
| @@ -29,7 +29,7 @@ MODULE_LICENSE("GPL"); | |||
| 29 | /* AIC26 driver private data */ | 29 | /* AIC26 driver private data */ |
| 30 | struct aic26 { | 30 | struct aic26 { |
| 31 | struct spi_device *spi; | 31 | struct spi_device *spi; |
| 32 | struct snd_soc_codec codec; | 32 | struct snd_soc_codec *codec; |
| 33 | int master; | 33 | int master; |
| 34 | int datfm; | 34 | int datfm; |
| 35 | int mclk; | 35 | int mclk; |
| @@ -119,6 +119,22 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, | |||
| 119 | return 0; | 119 | return 0; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = { | ||
| 123 | SND_SOC_DAPM_INPUT("MICIN"), | ||
| 124 | SND_SOC_DAPM_INPUT("AUX"), | ||
| 125 | |||
| 126 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
| 127 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
| 128 | }; | ||
| 129 | |||
| 130 | static const struct snd_soc_dapm_route tlv320aic26_dapm_routes[] = { | ||
| 131 | { "Capture", NULL, "MICIN" }, | ||
| 132 | { "Capture", NULL, "AUX" }, | ||
| 133 | |||
| 134 | { "HPL", NULL, "Playback" }, | ||
| 135 | { "HPR", NULL, "Playback" }, | ||
| 136 | }; | ||
| 137 | |||
| 122 | /* --------------------------------------------------------------------- | 138 | /* --------------------------------------------------------------------- |
| 123 | * Digital Audio Interface Operations | 139 | * Digital Audio Interface Operations |
| 124 | */ | 140 | */ |
| @@ -174,9 +190,9 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
| 174 | dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); | 190 | dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); |
| 175 | qval = 0; | 191 | qval = 0; |
| 176 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; | 192 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; |
| 177 | aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); | 193 | snd_soc_write(codec, AIC26_REG_PLL_PROG1, reg); |
| 178 | reg = dval << 2; | 194 | reg = dval << 2; |
| 179 | aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg); | 195 | snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg); |
| 180 | 196 | ||
| 181 | /* Audio Control 3 (master mode, fsref rate) */ | 197 | /* Audio Control 3 (master mode, fsref rate) */ |
| 182 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); | 198 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); |
| @@ -185,13 +201,13 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
| 185 | reg |= 0x0800; | 201 | reg |= 0x0800; |
| 186 | if (fsref == 48000) | 202 | if (fsref == 48000) |
| 187 | reg |= 0x2000; | 203 | reg |= 0x2000; |
| 188 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); | 204 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg); |
| 189 | 205 | ||
| 190 | /* Audio Control 1 (FSref divisor) */ | 206 | /* Audio Control 1 (FSref divisor) */ |
| 191 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); | 207 | reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); |
| 192 | reg &= ~0x0fff; | 208 | reg &= ~0x0fff; |
| 193 | reg |= wlen | aic26->datfm | (divisor << 3) | divisor; | 209 | reg |= wlen | aic26->datfm | (divisor << 3) | divisor; |
| 194 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg); | 210 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg); |
| 195 | 211 | ||
| 196 | return 0; | 212 | return 0; |
| 197 | } | 213 | } |
| @@ -212,7 +228,7 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute) | |||
| 212 | reg |= 0x8080; | 228 | reg |= 0x8080; |
| 213 | else | 229 | else |
| 214 | reg &= ~0x8080; | 230 | reg &= ~0x8080; |
| 215 | aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg); | 231 | snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg); |
| 216 | 232 | ||
| 217 | return 0; | 233 | return 0; |
| 218 | } | 234 | } |
| @@ -330,7 +346,7 @@ static ssize_t aic26_keyclick_show(struct device *dev, | |||
| 330 | struct aic26 *aic26 = dev_get_drvdata(dev); | 346 | struct aic26 *aic26 = dev_get_drvdata(dev); |
| 331 | int val, amp, freq, len; | 347 | int val, amp, freq, len; |
| 332 | 348 | ||
| 333 | val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); | 349 | val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2); |
| 334 | amp = (val >> 12) & 0x7; | 350 | amp = (val >> 12) & 0x7; |
| 335 | freq = (125 << ((val >> 8) & 0x7)) >> 1; | 351 | freq = (125 << ((val >> 8) & 0x7)) >> 1; |
| 336 | len = 2 * (1 + ((val >> 4) & 0xf)); | 352 | len = 2 * (1 + ((val >> 4) & 0xf)); |
| @@ -346,9 +362,9 @@ static ssize_t aic26_keyclick_set(struct device *dev, | |||
| 346 | struct aic26 *aic26 = dev_get_drvdata(dev); | 362 | struct aic26 *aic26 = dev_get_drvdata(dev); |
| 347 | int val; | 363 | int val; |
| 348 | 364 | ||
| 349 | val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); | 365 | val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2); |
| 350 | val |= 0x8000; | 366 | val |= 0x8000; |
| 351 | aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val); | 367 | snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val); |
| 352 | 368 | ||
| 353 | return count; | 369 | return count; |
| 354 | } | 370 | } |
| @@ -360,25 +376,26 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | |||
| 360 | */ | 376 | */ |
| 361 | static int aic26_probe(struct snd_soc_codec *codec) | 377 | static int aic26_probe(struct snd_soc_codec *codec) |
| 362 | { | 378 | { |
| 379 | struct aic26 *aic26 = dev_get_drvdata(codec->dev); | ||
| 363 | int ret, err, i, reg; | 380 | int ret, err, i, reg; |
| 364 | 381 | ||
| 365 | dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); | 382 | aic26->codec = codec; |
| 366 | 383 | ||
| 367 | /* Reset the codec to power on defaults */ | 384 | /* Reset the codec to power on defaults */ |
| 368 | aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); | 385 | snd_soc_write(codec, AIC26_REG_RESET, 0xBB00); |
| 369 | 386 | ||
| 370 | /* Power up CODEC */ | 387 | /* Power up CODEC */ |
| 371 | aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); | 388 | snd_soc_write(codec, AIC26_REG_POWER_CTRL, 0); |
| 372 | 389 | ||
| 373 | /* Audio Control 3 (master mode, fsref rate) */ | 390 | /* Audio Control 3 (master mode, fsref rate) */ |
| 374 | reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); | 391 | reg = snd_soc_read(codec, AIC26_REG_AUDIO_CTRL3); |
| 375 | reg &= ~0xf800; | 392 | reg &= ~0xf800; |
| 376 | reg |= 0x0800; /* set master mode */ | 393 | reg |= 0x0800; /* set master mode */ |
| 377 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); | 394 | snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg); |
| 378 | 395 | ||
| 379 | /* Fill register cache */ | 396 | /* Fill register cache */ |
| 380 | for (i = 0; i < codec->driver->reg_cache_size; i++) | 397 | for (i = 0; i < codec->driver->reg_cache_size; i++) |
| 381 | aic26_reg_read(codec, i); | 398 | snd_soc_read(codec, i); |
| 382 | 399 | ||
| 383 | /* Register the sysfs files for debugging */ | 400 | /* Register the sysfs files for debugging */ |
| 384 | /* Create SysFS files */ | 401 | /* Create SysFS files */ |
| @@ -401,6 +418,10 @@ static struct snd_soc_codec_driver aic26_soc_codec_dev = { | |||
| 401 | .write = aic26_reg_write, | 418 | .write = aic26_reg_write, |
| 402 | .reg_cache_size = AIC26_NUM_REGS, | 419 | .reg_cache_size = AIC26_NUM_REGS, |
| 403 | .reg_word_size = sizeof(u16), | 420 | .reg_word_size = sizeof(u16), |
| 421 | .dapm_widgets = tlv320aic26_dapm_widgets, | ||
| 422 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), | ||
| 423 | .dapm_routes = tlv320aic26_dapm_routes, | ||
| 424 | .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), | ||
| 404 | }; | 425 | }; |
| 405 | 426 | ||
| 406 | /* --------------------------------------------------------------------- | 427 | /* --------------------------------------------------------------------- |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e5b926883131..6e3f269243e0 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
| @@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | |||
| 138 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | 138 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, |
| 139 | struct snd_ctl_elem_value *ucontrol) | 139 | struct snd_ctl_elem_value *ucontrol) |
| 140 | { | 140 | { |
| 141 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 141 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 142 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 143 | struct soc_mixer_control *mc = | 142 | struct soc_mixer_control *mc = |
| 144 | (struct soc_mixer_control *)kcontrol->private_value; | 143 | (struct soc_mixer_control *)kcontrol->private_value; |
| 145 | unsigned int reg = mc->reg; | 144 | unsigned int reg = mc->reg; |
| @@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
| 147 | int max = mc->max; | 146 | int max = mc->max; |
| 148 | unsigned int mask = (1 << fls(max)) - 1; | 147 | unsigned int mask = (1 << fls(max)) - 1; |
| 149 | unsigned int invert = mc->invert; | 148 | unsigned int invert = mc->invert; |
| 150 | unsigned short val, val_mask; | 149 | unsigned short val; |
| 151 | int ret; | 150 | struct snd_soc_dapm_update update; |
| 152 | struct snd_soc_dapm_path *path; | 151 | int connect, change; |
| 153 | int found = 0; | ||
| 154 | 152 | ||
| 155 | val = (ucontrol->value.integer.value[0] & mask); | 153 | val = (ucontrol->value.integer.value[0] & mask); |
| 156 | 154 | ||
| @@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
| 158 | if (val) | 156 | if (val) |
| 159 | val = mask; | 157 | val = mask; |
| 160 | 158 | ||
| 159 | connect = !!val; | ||
| 160 | |||
| 161 | if (invert) | 161 | if (invert) |
| 162 | val = mask - val; | 162 | val = mask - val; |
| 163 | val_mask = mask << shift; | ||
| 164 | val = val << shift; | ||
| 165 | |||
| 166 | mutex_lock(&widget->codec->mutex); | ||
| 167 | 163 | ||
| 168 | if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { | 164 | mask <<= shift; |
| 169 | /* find dapm widget path assoc with kcontrol */ | 165 | val <<= shift; |
| 170 | list_for_each_entry(path, &widget->dapm->card->paths, list) { | ||
| 171 | if (path->kcontrol != kcontrol) | ||
| 172 | continue; | ||
| 173 | 166 | ||
| 174 | /* found, now check type */ | 167 | change = snd_soc_test_bits(codec, val, mask, reg); |
| 175 | found = 1; | 168 | if (change) { |
| 176 | if (val) | 169 | update.kcontrol = kcontrol; |
| 177 | /* new connection */ | 170 | update.reg = reg; |
| 178 | path->connect = invert ? 0 : 1; | 171 | update.mask = mask; |
| 179 | else | 172 | update.val = val; |
| 180 | /* old connection must be powered down */ | ||
| 181 | path->connect = invert ? 1 : 0; | ||
| 182 | 173 | ||
| 183 | dapm_mark_dirty(path->source, "tlv320aic3x source"); | 174 | snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect, |
| 184 | dapm_mark_dirty(path->sink, "tlv320aic3x sink"); | 175 | &update); |
| 185 | |||
| 186 | break; | ||
| 187 | } | ||
| 188 | } | 176 | } |
| 189 | 177 | ||
| 190 | mutex_unlock(&widget->codec->mutex); | 178 | return change; |
| 191 | |||
| 192 | if (found) | ||
| 193 | snd_soc_dapm_sync(widget->dapm); | ||
| 194 | |||
| 195 | ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val); | ||
| 196 | return ret; | ||
| 197 | } | 179 | } |
| 198 | 180 | ||
| 199 | /* | 181 | /* |
| @@ -1492,6 +1474,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { | |||
| 1492 | { "tlv320aic3x", AIC3X_MODEL_3X }, | 1474 | { "tlv320aic3x", AIC3X_MODEL_3X }, |
| 1493 | { "tlv320aic33", AIC3X_MODEL_33 }, | 1475 | { "tlv320aic33", AIC3X_MODEL_33 }, |
| 1494 | { "tlv320aic3007", AIC3X_MODEL_3007 }, | 1476 | { "tlv320aic3007", AIC3X_MODEL_3007 }, |
| 1477 | { "tlv320aic3106", AIC3X_MODEL_3X }, | ||
| 1495 | { } | 1478 | { } |
| 1496 | }; | 1479 | }; |
| 1497 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1480 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
| @@ -1582,6 +1565,9 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
| 1582 | #if defined(CONFIG_OF) | 1565 | #if defined(CONFIG_OF) |
| 1583 | static const struct of_device_id tlv320aic3x_of_match[] = { | 1566 | static const struct of_device_id tlv320aic3x_of_match[] = { |
| 1584 | { .compatible = "ti,tlv320aic3x", }, | 1567 | { .compatible = "ti,tlv320aic3x", }, |
| 1568 | { .compatible = "ti,tlv320aic33" }, | ||
| 1569 | { .compatible = "ti,tlv320aic3007" }, | ||
| 1570 | { .compatible = "ti,tlv320aic3106" }, | ||
| 1585 | {}, | 1571 | {}, |
| 1586 | }; | 1572 | }; |
| 1587 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | 1573 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 44621ddc332d..d6c5bf14179a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
| @@ -437,9 +437,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data) | |||
| 437 | static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, | 437 | static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, |
| 438 | struct snd_ctl_elem_value *ucontrol) | 438 | struct snd_ctl_elem_value *ucontrol) |
| 439 | { | 439 | { |
| 440 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 440 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 441 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 442 | struct snd_soc_codec *codec = widget->codec; | ||
| 443 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 441 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 444 | unsigned int val; | 442 | unsigned int val; |
| 445 | 443 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 282fd232cdf7..8bbddc151aa8 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
| @@ -998,6 +998,8 @@ SND_SOC_DAPM_INPUT("IN2R"), | |||
| 998 | SND_SOC_DAPM_INPUT("IN3L"), | 998 | SND_SOC_DAPM_INPUT("IN3L"), |
| 999 | SND_SOC_DAPM_INPUT("IN3R"), | 999 | SND_SOC_DAPM_INPUT("IN3R"), |
| 1000 | 1000 | ||
| 1001 | SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), | ||
| 1002 | |||
| 1001 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | 1003 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, |
| 1002 | 0, NULL, 0, arizona_in_ev, | 1004 | 0, NULL, 0, arizona_in_ev, |
| 1003 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | 1005 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
| @@ -1421,9 +1423,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
| 1421 | { "Tone Generator 1", NULL, "TONE" }, | 1423 | { "Tone Generator 1", NULL, "TONE" }, |
| 1422 | { "Tone Generator 2", NULL, "TONE" }, | 1424 | { "Tone Generator 2", NULL, "TONE" }, |
| 1423 | 1425 | ||
| 1424 | { "Mic Mute Mixer", NULL, "Noise Mixer" }, | ||
| 1425 | { "Mic Mute Mixer", NULL, "Mic Mixer" }, | ||
| 1426 | |||
| 1427 | { "AIF1 Capture", NULL, "AIF1TX1" }, | 1426 | { "AIF1 Capture", NULL, "AIF1TX1" }, |
| 1428 | { "AIF1 Capture", NULL, "AIF1TX2" }, | 1427 | { "AIF1 Capture", NULL, "AIF1TX2" }, |
| 1429 | { "AIF1 Capture", NULL, "AIF1TX3" }, | 1428 | { "AIF1 Capture", NULL, "AIF1TX3" }, |
| @@ -1499,23 +1498,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
| 1499 | { "IN3L PGA", NULL, "IN3L" }, | 1498 | { "IN3L PGA", NULL, "IN3L" }, |
| 1500 | { "IN3R PGA", NULL, "IN3R" }, | 1499 | { "IN3R PGA", NULL, "IN3R" }, |
| 1501 | 1500 | ||
| 1502 | { "ASRC1L", NULL, "ASRC1L Input" }, | ||
| 1503 | { "ASRC1R", NULL, "ASRC1R Input" }, | ||
| 1504 | { "ASRC2L", NULL, "ASRC2L Input" }, | ||
| 1505 | { "ASRC2R", NULL, "ASRC2R Input" }, | ||
| 1506 | |||
| 1507 | { "ISRC1DEC1", NULL, "ISRC1DEC1 Input" }, | ||
| 1508 | { "ISRC1DEC2", NULL, "ISRC1DEC2 Input" }, | ||
| 1509 | |||
| 1510 | { "ISRC1INT1", NULL, "ISRC1INT1 Input" }, | ||
| 1511 | { "ISRC1INT2", NULL, "ISRC1INT2 Input" }, | ||
| 1512 | |||
| 1513 | { "ISRC2DEC1", NULL, "ISRC2DEC1 Input" }, | ||
| 1514 | { "ISRC2DEC2", NULL, "ISRC2DEC2 Input" }, | ||
| 1515 | |||
| 1516 | { "ISRC2INT1", NULL, "ISRC2INT1 Input" }, | ||
| 1517 | { "ISRC2INT2", NULL, "ISRC2INT2 Input" }, | ||
| 1518 | |||
| 1519 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | 1501 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), |
| 1520 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | 1502 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), |
| 1521 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | 1503 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), |
| @@ -1567,22 +1549,25 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
| 1567 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | 1549 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), |
| 1568 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | 1550 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), |
| 1569 | 1551 | ||
| 1570 | ARIZONA_MUX_ROUTES("ASRC1L"), | 1552 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"), |
| 1571 | ARIZONA_MUX_ROUTES("ASRC1R"), | 1553 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"), |
| 1572 | ARIZONA_MUX_ROUTES("ASRC2L"), | ||
| 1573 | ARIZONA_MUX_ROUTES("ASRC2R"), | ||
| 1574 | 1554 | ||
| 1575 | ARIZONA_MUX_ROUTES("ISRC1INT1"), | 1555 | ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"), |
| 1576 | ARIZONA_MUX_ROUTES("ISRC1INT2"), | 1556 | ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"), |
| 1557 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), | ||
| 1558 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), | ||
| 1577 | 1559 | ||
| 1578 | ARIZONA_MUX_ROUTES("ISRC1DEC1"), | 1560 | ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), |
| 1579 | ARIZONA_MUX_ROUTES("ISRC1DEC2"), | 1561 | ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), |
| 1580 | 1562 | ||
| 1581 | ARIZONA_MUX_ROUTES("ISRC2INT1"), | 1563 | ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), |
| 1582 | ARIZONA_MUX_ROUTES("ISRC2INT2"), | 1564 | ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), |
| 1583 | 1565 | ||
| 1584 | ARIZONA_MUX_ROUTES("ISRC2DEC1"), | 1566 | ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), |
| 1585 | ARIZONA_MUX_ROUTES("ISRC2DEC2"), | 1567 | ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), |
| 1568 | |||
| 1569 | ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
| 1570 | ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
| 1586 | 1571 | ||
| 1587 | ARIZONA_DSP_ROUTES("DSP1"), | 1572 | ARIZONA_DSP_ROUTES("DSP1"), |
| 1588 | 1573 | ||
| @@ -1614,6 +1599,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
| 1614 | { "SPKDAT1R", NULL, "OUT5R" }, | 1599 | { "SPKDAT1R", NULL, "OUT5R" }, |
| 1615 | 1600 | ||
| 1616 | { "MICSUPP", NULL, "SYSCLK" }, | 1601 | { "MICSUPP", NULL, "SYSCLK" }, |
| 1602 | |||
| 1603 | { "DRC1 Signal Activity", NULL, "DRC1L" }, | ||
| 1604 | { "DRC1 Signal Activity", NULL, "DRC1R" }, | ||
| 1617 | }; | 1605 | }; |
| 1618 | 1606 | ||
| 1619 | static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | 1607 | static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
| @@ -1781,6 +1769,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
| 1781 | return ret; | 1769 | return ret; |
| 1782 | 1770 | ||
| 1783 | arizona_init_spk(codec); | 1771 | arizona_init_spk(codec); |
| 1772 | arizona_init_gpio(codec); | ||
| 1784 | 1773 | ||
| 1785 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1774 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); |
| 1786 | 1775 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2e7cb4ba161a..bbd64384ca1c 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
| @@ -58,14 +58,10 @@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | |||
| 58 | SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0) | 58 | SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0) |
| 59 | 59 | ||
| 60 | static const struct snd_kcontrol_new wm5110_snd_controls[] = { | 60 | static const struct snd_kcontrol_new wm5110_snd_controls[] = { |
| 61 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | 61 | SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]), |
| 62 | ARIZONA_IN1_OSR_SHIFT, 1, 0), | 62 | SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]), |
| 63 | SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | 63 | SOC_ENUM("IN3 OSR", arizona_in_dmic_osr[2]), |
| 64 | ARIZONA_IN2_OSR_SHIFT, 1, 0), | 64 | SOC_ENUM("IN4 OSR", arizona_in_dmic_osr[3]), |
| 65 | SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, | ||
| 66 | ARIZONA_IN3_OSR_SHIFT, 1, 0), | ||
| 67 | SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL, | ||
| 68 | ARIZONA_IN4_OSR_SHIFT, 1, 0), | ||
| 69 | 65 | ||
| 70 | SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, | 66 | SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, |
| 71 | ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | 67 | ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), |
| @@ -432,6 +428,9 @@ SND_SOC_DAPM_INPUT("IN3R"), | |||
| 432 | SND_SOC_DAPM_INPUT("IN4L"), | 428 | SND_SOC_DAPM_INPUT("IN4L"), |
| 433 | SND_SOC_DAPM_INPUT("IN4R"), | 429 | SND_SOC_DAPM_INPUT("IN4R"), |
| 434 | 430 | ||
| 431 | SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), | ||
| 432 | SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), | ||
| 433 | |||
| 435 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | 434 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, |
| 436 | 0, NULL, 0, arizona_in_ev, | 435 | 0, NULL, 0, arizona_in_ev, |
| 437 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | 436 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
| @@ -842,9 +841,6 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 842 | { "Tone Generator 1", NULL, "TONE" }, | 841 | { "Tone Generator 1", NULL, "TONE" }, |
| 843 | { "Tone Generator 2", NULL, "TONE" }, | 842 | { "Tone Generator 2", NULL, "TONE" }, |
| 844 | 843 | ||
| 845 | { "Mic Mute Mixer", NULL, "Noise Mixer" }, | ||
| 846 | { "Mic Mute Mixer", NULL, "Mic Mixer" }, | ||
| 847 | |||
| 848 | { "AIF1 Capture", NULL, "AIF1TX1" }, | 844 | { "AIF1 Capture", NULL, "AIF1TX1" }, |
| 849 | { "AIF1 Capture", NULL, "AIF1TX2" }, | 845 | { "AIF1 Capture", NULL, "AIF1TX2" }, |
| 850 | { "AIF1 Capture", NULL, "AIF1TX3" }, | 846 | { "AIF1 Capture", NULL, "AIF1TX3" }, |
| @@ -979,10 +975,13 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 979 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | 975 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), |
| 980 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | 976 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), |
| 981 | 977 | ||
| 982 | ARIZONA_MUX_ROUTES("ASRC1L"), | 978 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"), |
| 983 | ARIZONA_MUX_ROUTES("ASRC1R"), | 979 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"), |
| 984 | ARIZONA_MUX_ROUTES("ASRC2L"), | 980 | |
| 985 | ARIZONA_MUX_ROUTES("ASRC2R"), | 981 | ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"), |
| 982 | ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"), | ||
| 983 | ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), | ||
| 984 | ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), | ||
| 986 | 985 | ||
| 987 | { "HPOUT1L", NULL, "OUT1L" }, | 986 | { "HPOUT1L", NULL, "OUT1L" }, |
| 988 | { "HPOUT1R", NULL, "OUT1R" }, | 987 | { "HPOUT1R", NULL, "OUT1R" }, |
| @@ -1006,6 +1005,11 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 1006 | { "SPKDAT2R", NULL, "OUT6R" }, | 1005 | { "SPKDAT2R", NULL, "OUT6R" }, |
| 1007 | 1006 | ||
| 1008 | { "MICSUPP", NULL, "SYSCLK" }, | 1007 | { "MICSUPP", NULL, "SYSCLK" }, |
| 1008 | |||
| 1009 | { "DRC1 Signal Activity", NULL, "DRC1L" }, | ||
| 1010 | { "DRC1 Signal Activity", NULL, "DRC1R" }, | ||
| 1011 | { "DRC2 Signal Activity", NULL, "DRC2L" }, | ||
| 1012 | { "DRC2 Signal Activity", NULL, "DRC2R" }, | ||
| 1009 | }; | 1013 | }; |
| 1010 | 1014 | ||
| 1011 | static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | 1015 | static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
| @@ -1170,6 +1174,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
| 1170 | return ret; | 1174 | return ret; |
| 1171 | 1175 | ||
| 1172 | arizona_init_spk(codec); | 1176 | arizona_init_spk(codec); |
| 1177 | arizona_init_gpio(codec); | ||
| 1173 | 1178 | ||
| 1174 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | 1179 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); |
| 1175 | 1180 | ||
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa24cedee687..eebcb1da3b7b 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
| @@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
| 364 | static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | 364 | static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, |
| 365 | struct snd_ctl_elem_value *ucontrol) | 365 | struct snd_ctl_elem_value *ucontrol) |
| 366 | { | 366 | { |
| 367 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 367 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 368 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 369 | struct snd_soc_codec *codec = widget->codec; | ||
| 370 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 368 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
| 371 | u16 reg; | 369 | u16 reg; |
| 372 | int ret; | 370 | int ret; |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 0a4ffdd1d2a7..5e5af898f7f8 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
| @@ -857,9 +857,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
| 857 | if (pll_div.k) { | 857 | if (pll_div.k) { |
| 858 | reg |= 0x20; | 858 | reg |= 0x20; |
| 859 | 859 | ||
| 860 | snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); | 860 | snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff); |
| 861 | snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); | 861 | snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff); |
| 862 | snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); | 862 | snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff); |
| 863 | } | 863 | } |
| 864 | snd_soc_write(codec, WM8960_PLL1, reg); | 864 | snd_soc_write(codec, WM8960_PLL1, reg); |
| 865 | 865 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index ba832b77c543..eee2a01f2691 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
| @@ -1437,9 +1437,7 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | |||
| 1437 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, | 1437 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, |
| 1438 | struct snd_ctl_elem_value *ucontrol) | 1438 | struct snd_ctl_elem_value *ucontrol) |
| 1439 | { | 1439 | { |
| 1440 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 1440 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 1441 | struct snd_soc_dapm_widget *w = wlist->widgets[0]; | ||
| 1442 | struct snd_soc_codec *codec = w->codec; | ||
| 1443 | int ret; | 1441 | int ret; |
| 1444 | 1442 | ||
| 1445 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | 1443 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 90a65c427541..da2899e6c401 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
| @@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, | |||
| 549 | static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, | 549 | static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, |
| 550 | struct snd_ctl_elem_value *ucontrol) | 550 | struct snd_ctl_elem_value *ucontrol) |
| 551 | { | 551 | { |
| 552 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 552 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 553 | struct snd_soc_dapm_widget *w = wlist->widgets[0]; | ||
| 554 | struct snd_soc_codec *codec; | ||
| 555 | int ret; | 553 | int ret; |
| 556 | 554 | ||
| 557 | codec = w->codec; | ||
| 558 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | 555 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); |
| 559 | wm8995_update_class_w(codec); | 556 | wm8995_update_class_w(codec); |
| 560 | return ret; | 557 | return ret; |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c new file mode 100644 index 000000000000..6ec3de3efa4f --- /dev/null +++ b/sound/soc/codecs/wm8997.c | |||
| @@ -0,0 +1,1175 @@ | |||
| 1 | /* | ||
| 2 | * wm8997.c -- WM8997 ALSA SoC Audio driver | ||
| 3 | * | ||
| 4 | * Copyright 2012 Wolfson Microelectronics plc | ||
| 5 | * | ||
| 6 | * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | ||
| 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/pm_runtime.h> | ||
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <sound/core.h> | ||
| 22 | #include <sound/pcm.h> | ||
| 23 | #include <sound/pcm_params.h> | ||
| 24 | #include <sound/soc.h> | ||
| 25 | #include <sound/jack.h> | ||
| 26 | #include <sound/initval.h> | ||
| 27 | #include <sound/tlv.h> | ||
| 28 | |||
| 29 | #include <linux/mfd/arizona/core.h> | ||
| 30 | #include <linux/mfd/arizona/registers.h> | ||
| 31 | |||
| 32 | #include "arizona.h" | ||
| 33 | #include "wm8997.h" | ||
| 34 | |||
| 35 | struct wm8997_priv { | ||
| 36 | struct arizona_priv core; | ||
| 37 | struct arizona_fll fll[2]; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | ||
| 41 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
| 42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | ||
| 43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | ||
| 44 | static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | ||
| 45 | |||
| 46 | static const struct reg_default wm8997_sysclk_reva_patch[] = { | ||
| 47 | { 0x301D, 0x7B15 }, | ||
| 48 | { 0x301B, 0x0050 }, | ||
| 49 | { 0x305D, 0x7B17 }, | ||
| 50 | { 0x305B, 0x0050 }, | ||
| 51 | { 0x3001, 0x08FE }, | ||
| 52 | { 0x3003, 0x00F4 }, | ||
| 53 | { 0x3041, 0x08FF }, | ||
| 54 | { 0x3043, 0x0005 }, | ||
| 55 | { 0x3020, 0x0225 }, | ||
| 56 | { 0x3021, 0x0A00 }, | ||
| 57 | { 0x3022, 0xE24D }, | ||
| 58 | { 0x3023, 0x0800 }, | ||
| 59 | { 0x3024, 0xE24D }, | ||
| 60 | { 0x3025, 0xF000 }, | ||
| 61 | { 0x3060, 0x0226 }, | ||
| 62 | { 0x3061, 0x0A00 }, | ||
| 63 | { 0x3062, 0xE252 }, | ||
| 64 | { 0x3063, 0x0800 }, | ||
| 65 | { 0x3064, 0xE252 }, | ||
| 66 | { 0x3065, 0xF000 }, | ||
| 67 | { 0x3116, 0x022B }, | ||
| 68 | { 0x3117, 0xFA00 }, | ||
| 69 | { 0x3110, 0x246C }, | ||
| 70 | { 0x3111, 0x0A03 }, | ||
| 71 | { 0x3112, 0x246E }, | ||
| 72 | { 0x3113, 0x0A03 }, | ||
| 73 | { 0x3114, 0x2470 }, | ||
| 74 | { 0x3115, 0x0A03 }, | ||
| 75 | { 0x3126, 0x246C }, | ||
| 76 | { 0x3127, 0x0A02 }, | ||
| 77 | { 0x3128, 0x246E }, | ||
| 78 | { 0x3129, 0x0A02 }, | ||
| 79 | { 0x312A, 0x2470 }, | ||
| 80 | { 0x312B, 0xFA02 }, | ||
| 81 | { 0x3125, 0x0800 }, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, | ||
| 85 | struct snd_kcontrol *kcontrol, int event) | ||
| 86 | { | ||
| 87 | struct snd_soc_codec *codec = w->codec; | ||
| 88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | ||
| 89 | struct regmap *regmap = codec->control_data; | ||
| 90 | const struct reg_default *patch = NULL; | ||
| 91 | int i, patch_size; | ||
| 92 | |||
| 93 | switch (arizona->rev) { | ||
| 94 | case 0: | ||
| 95 | patch = wm8997_sysclk_reva_patch; | ||
| 96 | patch_size = ARRAY_SIZE(wm8997_sysclk_reva_patch); | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | switch (event) { | ||
| 103 | case SND_SOC_DAPM_POST_PMU: | ||
| 104 | if (patch) | ||
| 105 | for (i = 0; i < patch_size; i++) | ||
| 106 | regmap_write(regmap, patch[i].reg, | ||
| 107 | patch[i].def); | ||
| 108 | break; | ||
| 109 | default: | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static const char *wm8997_osr_text[] = { | ||
| 117 | "Low power", "Normal", "High performance", | ||
| 118 | }; | ||
| 119 | |||
| 120 | static const unsigned int wm8997_osr_val[] = { | ||
| 121 | 0x0, 0x3, 0x5, | ||
| 122 | }; | ||
| 123 | |||
| 124 | static const struct soc_enum wm8997_hpout_osr[] = { | ||
| 125 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
| 126 | ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, | ||
| 127 | wm8997_osr_text, wm8997_osr_val), | ||
| 128 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
| 129 | ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, | ||
| 130 | wm8997_osr_text, wm8997_osr_val), | ||
| 131 | }; | ||
| 132 | |||
| 133 | #define WM8997_NG_SRC(name, base) \ | ||
| 134 | SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ | ||
| 135 | SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ | ||
| 136 | SOC_SINGLE(name " NG EPOUT Switch", base, 4, 1, 0), \ | ||
| 137 | SOC_SINGLE(name " NG SPKOUT Switch", base, 6, 1, 0), \ | ||
| 138 | SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ | ||
| 139 | SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) | ||
| 140 | |||
| 141 | static const struct snd_kcontrol_new wm8997_snd_controls[] = { | ||
| 142 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | ||
| 143 | ARIZONA_IN1_OSR_SHIFT, 1, 0), | ||
| 144 | SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | ||
| 145 | ARIZONA_IN2_OSR_SHIFT, 1, 0), | ||
| 146 | |||
| 147 | SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, | ||
| 148 | ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
| 149 | SOC_SINGLE_RANGE_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL, | ||
| 150 | ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
| 151 | SOC_SINGLE_RANGE_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL, | ||
| 152 | ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
| 153 | SOC_SINGLE_RANGE_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL, | ||
| 154 | ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
| 155 | |||
| 156 | SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
| 157 | ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 158 | SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R, | ||
| 159 | ARIZONA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 160 | SOC_SINGLE_TLV("IN2L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
| 161 | ARIZONA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 162 | SOC_SINGLE_TLV("IN2R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2R, | ||
| 163 | ARIZONA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 164 | |||
| 165 | SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp), | ||
| 166 | SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp), | ||
| 167 | |||
| 168 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | ||
| 169 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | ||
| 170 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | ||
| 171 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | ||
| 172 | |||
| 173 | SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21, | ||
| 174 | ARIZONA_EQ1_ENA_MASK), | ||
| 175 | SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21, | ||
| 176 | ARIZONA_EQ2_ENA_MASK), | ||
| 177 | SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21, | ||
| 178 | ARIZONA_EQ3_ENA_MASK), | ||
| 179 | SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21, | ||
| 180 | ARIZONA_EQ4_ENA_MASK), | ||
| 181 | |||
| 182 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | ||
| 183 | 24, 0, eq_tlv), | ||
| 184 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | ||
| 185 | 24, 0, eq_tlv), | ||
| 186 | SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, | ||
| 187 | 24, 0, eq_tlv), | ||
| 188 | SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | ||
| 189 | 24, 0, eq_tlv), | ||
| 190 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | ||
| 191 | 24, 0, eq_tlv), | ||
| 192 | |||
| 193 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | ||
| 194 | 24, 0, eq_tlv), | ||
| 195 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | ||
| 196 | 24, 0, eq_tlv), | ||
| 197 | SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, | ||
| 198 | 24, 0, eq_tlv), | ||
| 199 | SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | ||
| 200 | 24, 0, eq_tlv), | ||
| 201 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | ||
| 202 | 24, 0, eq_tlv), | ||
| 203 | |||
| 204 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | ||
| 205 | 24, 0, eq_tlv), | ||
| 206 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | ||
| 207 | 24, 0, eq_tlv), | ||
| 208 | SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, | ||
| 209 | 24, 0, eq_tlv), | ||
| 210 | SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | ||
| 211 | 24, 0, eq_tlv), | ||
| 212 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | ||
| 213 | 24, 0, eq_tlv), | ||
| 214 | |||
| 215 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | ||
| 216 | 24, 0, eq_tlv), | ||
| 217 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | ||
| 218 | 24, 0, eq_tlv), | ||
| 219 | SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, | ||
| 220 | 24, 0, eq_tlv), | ||
| 221 | SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, | ||
| 222 | 24, 0, eq_tlv), | ||
| 223 | SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, | ||
| 224 | 24, 0, eq_tlv), | ||
| 225 | |||
| 226 | ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), | ||
| 227 | ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), | ||
| 228 | |||
| 229 | SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, | ||
| 230 | ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), | ||
| 231 | |||
| 232 | ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), | ||
| 233 | ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | ||
| 234 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | ||
| 235 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | ||
| 236 | |||
| 237 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | ||
| 238 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | ||
| 239 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | ||
| 240 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | ||
| 241 | |||
| 242 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | ||
| 243 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | ||
| 244 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | ||
| 245 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | ||
| 246 | |||
| 247 | SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]), | ||
| 248 | SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]), | ||
| 249 | |||
| 250 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | ||
| 251 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | ||
| 252 | |||
| 253 | SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
| 254 | ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), | ||
| 255 | |||
| 256 | ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | ||
| 257 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | ||
| 258 | ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | ||
| 259 | ARIZONA_MIXER_CONTROLS("SPKOUT", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | ||
| 260 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | ||
| 261 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | ||
| 262 | |||
| 263 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
| 264 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
| 265 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | ||
| 266 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | ||
| 267 | |||
| 268 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
| 269 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | ||
| 270 | SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
| 271 | ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | ||
| 272 | SOC_SINGLE("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
| 273 | ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | ||
| 274 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
| 275 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), | ||
| 276 | |||
| 277 | SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
| 278 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, | ||
| 279 | 0xbf, 0, digital_tlv), | ||
| 280 | SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
| 281 | ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 282 | SOC_SINGLE_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
| 283 | ARIZONA_OUT4L_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
| 284 | SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
| 285 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | ||
| 286 | 0xbf, 0, digital_tlv), | ||
| 287 | |||
| 288 | SOC_VALUE_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]), | ||
| 289 | SOC_VALUE_ENUM("EPOUT OSR", wm8997_hpout_osr[1]), | ||
| 290 | |||
| 291 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | ||
| 292 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | ||
| 293 | |||
| 294 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | ||
| 295 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | ||
| 296 | |||
| 297 | SOC_SINGLE("Noise Gate Switch", ARIZONA_NOISE_GATE_CONTROL, | ||
| 298 | ARIZONA_NGATE_ENA_SHIFT, 1, 0), | ||
| 299 | SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL, | ||
| 300 | ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv), | ||
| 301 | SOC_ENUM("Noise Gate Hold", arizona_ng_hold), | ||
| 302 | |||
| 303 | WM8997_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L), | ||
| 304 | WM8997_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R), | ||
| 305 | WM8997_NG_SRC("EPOUT", ARIZONA_NOISE_GATE_SELECT_3L), | ||
| 306 | WM8997_NG_SRC("SPKOUT", ARIZONA_NOISE_GATE_SELECT_4L), | ||
| 307 | WM8997_NG_SRC("SPKDAT1L", ARIZONA_NOISE_GATE_SELECT_5L), | ||
| 308 | WM8997_NG_SRC("SPKDAT1R", ARIZONA_NOISE_GATE_SELECT_5R), | ||
| 309 | |||
| 310 | ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | ||
| 311 | ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | ||
| 312 | ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | ||
| 313 | ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), | ||
| 314 | ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), | ||
| 315 | ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), | ||
| 316 | ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), | ||
| 317 | ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | ||
| 318 | |||
| 319 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | ||
| 320 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | ||
| 321 | |||
| 322 | ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
| 323 | ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
| 324 | ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
| 325 | ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
| 326 | ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
| 327 | ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
| 328 | ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
| 329 | ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
| 330 | }; | ||
| 331 | |||
| 332 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | ||
| 333 | ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | ||
| 334 | ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | ||
| 335 | ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); | ||
| 336 | |||
| 337 | ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); | ||
| 338 | ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); | ||
| 339 | |||
| 340 | ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); | ||
| 341 | ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | ||
| 342 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | ||
| 343 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | ||
| 344 | |||
| 345 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | ||
| 346 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | ||
| 347 | |||
| 348 | ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); | ||
| 349 | ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); | ||
| 350 | |||
| 351 | ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | ||
| 352 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | ||
| 353 | ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | ||
| 354 | ARIZONA_MIXER_ENUMS(SPKOUT, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | ||
| 355 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | ||
| 356 | ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); | ||
| 357 | |||
| 358 | ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); | ||
| 359 | ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); | ||
| 360 | ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); | ||
| 361 | ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); | ||
| 362 | ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); | ||
| 363 | ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); | ||
| 364 | ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); | ||
| 365 | ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | ||
| 366 | |||
| 367 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | ||
| 368 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | ||
| 369 | |||
| 370 | ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
| 371 | ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
| 372 | ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
| 373 | ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
| 374 | ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
| 375 | ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
| 376 | ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
| 377 | ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
| 378 | |||
| 379 | ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE); | ||
| 380 | ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE); | ||
| 381 | |||
| 382 | ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE); | ||
| 383 | ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE); | ||
| 384 | |||
| 385 | ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE); | ||
| 386 | ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE); | ||
| 387 | |||
| 388 | ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE); | ||
| 389 | ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE); | ||
| 390 | |||
| 391 | static const char *wm8997_aec_loopback_texts[] = { | ||
| 392 | "HPOUT1L", "HPOUT1R", "EPOUT", "SPKOUT", "SPKDAT1L", "SPKDAT1R", | ||
| 393 | }; | ||
| 394 | |||
| 395 | static const unsigned int wm8997_aec_loopback_values[] = { | ||
| 396 | 0, 1, 4, 6, 8, 9, | ||
| 397 | }; | ||
| 398 | |||
| 399 | static const struct soc_enum wm8997_aec_loopback = | ||
| 400 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
| 401 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, | ||
| 402 | ARRAY_SIZE(wm8997_aec_loopback_texts), | ||
| 403 | wm8997_aec_loopback_texts, | ||
| 404 | wm8997_aec_loopback_values); | ||
| 405 | |||
| 406 | static const struct snd_kcontrol_new wm8997_aec_loopback_mux = | ||
| 407 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm8997_aec_loopback); | ||
| 408 | |||
| 409 | static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = { | ||
| 410 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | ||
| 411 | 0, wm8997_sysclk_ev, SND_SOC_DAPM_POST_PMU), | ||
| 412 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | ||
| 413 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | ||
| 414 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | ||
| 415 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), | ||
| 416 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, | ||
| 417 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), | ||
| 418 | |||
| 419 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), | ||
| 420 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | ||
| 421 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), | ||
| 422 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0), | ||
| 423 | |||
| 424 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
| 425 | SND_SOC_DAPM_SIGGEN("NOISE"), | ||
| 426 | SND_SOC_DAPM_SIGGEN("HAPTICS"), | ||
| 427 | |||
| 428 | SND_SOC_DAPM_INPUT("IN1L"), | ||
| 429 | SND_SOC_DAPM_INPUT("IN1R"), | ||
| 430 | SND_SOC_DAPM_INPUT("IN2L"), | ||
| 431 | SND_SOC_DAPM_INPUT("IN2R"), | ||
| 432 | |||
| 433 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | ||
| 434 | 0, NULL, 0, arizona_in_ev, | ||
| 435 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
| 436 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
| 437 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | ||
| 438 | 0, NULL, 0, arizona_in_ev, | ||
| 439 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
| 440 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
| 441 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | ||
| 442 | 0, NULL, 0, arizona_in_ev, | ||
| 443 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
| 444 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
| 445 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | ||
| 446 | 0, NULL, 0, arizona_in_ev, | ||
| 447 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
| 448 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
| 449 | |||
| 450 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | ||
| 451 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
| 452 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | ||
| 453 | ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0), | ||
| 454 | SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | ||
| 455 | ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0), | ||
| 456 | |||
| 457 | SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
| 458 | ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | ||
| 459 | |||
| 460 | SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, | ||
| 461 | ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), | ||
| 462 | SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, | ||
| 463 | ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), | ||
| 464 | |||
| 465 | SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, | ||
| 466 | ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), | ||
| 467 | |||
| 468 | SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), | ||
| 469 | SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), | ||
| 470 | SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), | ||
| 471 | SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), | ||
| 472 | |||
| 473 | SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, | ||
| 474 | NULL, 0), | ||
| 475 | SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, | ||
| 476 | NULL, 0), | ||
| 477 | |||
| 478 | SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, | ||
| 479 | NULL, 0), | ||
| 480 | SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, | ||
| 481 | NULL, 0), | ||
| 482 | SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, | ||
| 483 | NULL, 0), | ||
| 484 | SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, | ||
| 485 | NULL, 0), | ||
| 486 | |||
| 487 | SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, | ||
| 488 | 0, NULL, 0), | ||
| 489 | SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, | ||
| 490 | 0, NULL, 0), | ||
| 491 | |||
| 492 | SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, | ||
| 493 | ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), | ||
| 494 | SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3, | ||
| 495 | ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), | ||
| 496 | |||
| 497 | SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3, | ||
| 498 | ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
| 499 | SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3, | ||
| 500 | ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
| 501 | |||
| 502 | SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3, | ||
| 503 | ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0), | ||
| 504 | SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3, | ||
| 505 | ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), | ||
| 506 | |||
| 507 | SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3, | ||
| 508 | ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0), | ||
| 509 | SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3, | ||
| 510 | ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
| 511 | |||
| 512 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | ||
| 513 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | ||
| 514 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | ||
| 515 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), | ||
| 516 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | ||
| 517 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), | ||
| 518 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | ||
| 519 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), | ||
| 520 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | ||
| 521 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), | ||
| 522 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | ||
| 523 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), | ||
| 524 | SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | ||
| 525 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), | ||
| 526 | SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | ||
| 527 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), | ||
| 528 | |||
| 529 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | ||
| 530 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), | ||
| 531 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | ||
| 532 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), | ||
| 533 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | ||
| 534 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), | ||
| 535 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | ||
| 536 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), | ||
| 537 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | ||
| 538 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), | ||
| 539 | SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | ||
| 540 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), | ||
| 541 | SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | ||
| 542 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), | ||
| 543 | SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | ||
| 544 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), | ||
| 545 | |||
| 546 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | ||
| 547 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | ||
| 548 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | ||
| 549 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | ||
| 550 | |||
| 551 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | ||
| 552 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | ||
| 553 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | ||
| 554 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | ||
| 555 | |||
| 556 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
| 557 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 558 | ARIZONA_SLIMTX1_ENA_SHIFT, 0), | ||
| 559 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
| 560 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 561 | ARIZONA_SLIMTX2_ENA_SHIFT, 0), | ||
| 562 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
| 563 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 564 | ARIZONA_SLIMTX3_ENA_SHIFT, 0), | ||
| 565 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
| 566 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 567 | ARIZONA_SLIMTX4_ENA_SHIFT, 0), | ||
| 568 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
| 569 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 570 | ARIZONA_SLIMTX5_ENA_SHIFT, 0), | ||
| 571 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
| 572 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 573 | ARIZONA_SLIMTX6_ENA_SHIFT, 0), | ||
| 574 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
| 575 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 576 | ARIZONA_SLIMTX7_ENA_SHIFT, 0), | ||
| 577 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
| 578 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
| 579 | ARIZONA_SLIMTX8_ENA_SHIFT, 0), | ||
| 580 | |||
| 581 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | ||
| 582 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 583 | ARIZONA_SLIMRX1_ENA_SHIFT, 0), | ||
| 584 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, | ||
| 585 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 586 | ARIZONA_SLIMRX2_ENA_SHIFT, 0), | ||
| 587 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, | ||
| 588 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 589 | ARIZONA_SLIMRX3_ENA_SHIFT, 0), | ||
| 590 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, | ||
| 591 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 592 | ARIZONA_SLIMRX4_ENA_SHIFT, 0), | ||
| 593 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, | ||
| 594 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 595 | ARIZONA_SLIMRX5_ENA_SHIFT, 0), | ||
| 596 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, | ||
| 597 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 598 | ARIZONA_SLIMRX6_ENA_SHIFT, 0), | ||
| 599 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, | ||
| 600 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 601 | ARIZONA_SLIMRX7_ENA_SHIFT, 0), | ||
| 602 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, | ||
| 603 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
| 604 | ARIZONA_SLIMRX8_ENA_SHIFT, 0), | ||
| 605 | |||
| 606 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
| 607 | ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, | ||
| 608 | &wm8997_aec_loopback_mux), | ||
| 609 | |||
| 610 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | ||
| 611 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | ||
| 612 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 613 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | ||
| 614 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | ||
| 615 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 616 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | ||
| 617 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
| 618 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 619 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | ||
| 620 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
| 621 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 622 | SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, | ||
| 623 | ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
| 624 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 625 | |||
| 626 | ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), | ||
| 627 | ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), | ||
| 628 | ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), | ||
| 629 | ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), | ||
| 630 | |||
| 631 | ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), | ||
| 632 | ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), | ||
| 633 | |||
| 634 | ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), | ||
| 635 | ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), | ||
| 636 | ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), | ||
| 637 | ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), | ||
| 638 | |||
| 639 | ARIZONA_MIXER_WIDGETS(Mic, "Mic"), | ||
| 640 | ARIZONA_MIXER_WIDGETS(Noise, "Noise"), | ||
| 641 | |||
| 642 | ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), | ||
| 643 | ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), | ||
| 644 | |||
| 645 | ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | ||
| 646 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | ||
| 647 | ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | ||
| 648 | ARIZONA_MIXER_WIDGETS(SPKOUT, "SPKOUT"), | ||
| 649 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | ||
| 650 | ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | ||
| 651 | |||
| 652 | ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | ||
| 653 | ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | ||
| 654 | ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | ||
| 655 | ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | ||
| 656 | ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | ||
| 657 | ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | ||
| 658 | ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | ||
| 659 | ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | ||
| 660 | |||
| 661 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | ||
| 662 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | ||
| 663 | |||
| 664 | ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
| 665 | ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
| 666 | ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
| 667 | ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
| 668 | ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
| 669 | ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
| 670 | ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
| 671 | ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
| 672 | |||
| 673 | ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), | ||
| 674 | ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), | ||
| 675 | |||
| 676 | ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), | ||
| 677 | ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), | ||
| 678 | |||
| 679 | ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), | ||
| 680 | ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | ||
| 681 | |||
| 682 | ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | ||
| 683 | ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | ||
| 684 | |||
| 685 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | ||
| 686 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | ||
| 687 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | ||
| 688 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | ||
| 689 | SND_SOC_DAPM_OUTPUT("SPKOUTN"), | ||
| 690 | SND_SOC_DAPM_OUTPUT("SPKOUTP"), | ||
| 691 | SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | ||
| 692 | SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | ||
| 693 | |||
| 694 | SND_SOC_DAPM_OUTPUT("MICSUPP"), | ||
| 695 | }; | ||
| 696 | |||
| 697 | #define ARIZONA_MIXER_INPUT_ROUTES(name) \ | ||
| 698 | { name, "Noise Generator", "Noise Generator" }, \ | ||
| 699 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | ||
| 700 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | ||
| 701 | { name, "Haptics", "HAPTICS" }, \ | ||
| 702 | { name, "AEC", "AEC Loopback" }, \ | ||
| 703 | { name, "IN1L", "IN1L PGA" }, \ | ||
| 704 | { name, "IN1R", "IN1R PGA" }, \ | ||
| 705 | { name, "IN2L", "IN2L PGA" }, \ | ||
| 706 | { name, "IN2R", "IN2R PGA" }, \ | ||
| 707 | { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ | ||
| 708 | { name, "AIF1RX1", "AIF1RX1" }, \ | ||
| 709 | { name, "AIF1RX2", "AIF1RX2" }, \ | ||
| 710 | { name, "AIF1RX3", "AIF1RX3" }, \ | ||
| 711 | { name, "AIF1RX4", "AIF1RX4" }, \ | ||
| 712 | { name, "AIF1RX5", "AIF1RX5" }, \ | ||
| 713 | { name, "AIF1RX6", "AIF1RX6" }, \ | ||
| 714 | { name, "AIF1RX7", "AIF1RX7" }, \ | ||
| 715 | { name, "AIF1RX8", "AIF1RX8" }, \ | ||
| 716 | { name, "AIF2RX1", "AIF2RX1" }, \ | ||
| 717 | { name, "AIF2RX2", "AIF2RX2" }, \ | ||
| 718 | { name, "SLIMRX1", "SLIMRX1" }, \ | ||
| 719 | { name, "SLIMRX2", "SLIMRX2" }, \ | ||
| 720 | { name, "SLIMRX3", "SLIMRX3" }, \ | ||
| 721 | { name, "SLIMRX4", "SLIMRX4" }, \ | ||
| 722 | { name, "SLIMRX5", "SLIMRX5" }, \ | ||
| 723 | { name, "SLIMRX6", "SLIMRX6" }, \ | ||
| 724 | { name, "SLIMRX7", "SLIMRX7" }, \ | ||
| 725 | { name, "SLIMRX8", "SLIMRX8" }, \ | ||
| 726 | { name, "EQ1", "EQ1" }, \ | ||
| 727 | { name, "EQ2", "EQ2" }, \ | ||
| 728 | { name, "EQ3", "EQ3" }, \ | ||
| 729 | { name, "EQ4", "EQ4" }, \ | ||
| 730 | { name, "DRC1L", "DRC1L" }, \ | ||
| 731 | { name, "DRC1R", "DRC1R" }, \ | ||
| 732 | { name, "LHPF1", "LHPF1" }, \ | ||
| 733 | { name, "LHPF2", "LHPF2" }, \ | ||
| 734 | { name, "LHPF3", "LHPF3" }, \ | ||
| 735 | { name, "LHPF4", "LHPF4" }, \ | ||
| 736 | { name, "ISRC1DEC1", "ISRC1DEC1" }, \ | ||
| 737 | { name, "ISRC1DEC2", "ISRC1DEC2" }, \ | ||
| 738 | { name, "ISRC1INT1", "ISRC1INT1" }, \ | ||
| 739 | { name, "ISRC1INT2", "ISRC1INT2" }, \ | ||
| 740 | { name, "ISRC2DEC1", "ISRC2DEC1" }, \ | ||
| 741 | { name, "ISRC2DEC2", "ISRC2DEC2" }, \ | ||
| 742 | { name, "ISRC2INT1", "ISRC2INT1" }, \ | ||
| 743 | { name, "ISRC2INT2", "ISRC2INT2" } | ||
| 744 | |||
| 745 | static const struct snd_soc_dapm_route wm8997_dapm_routes[] = { | ||
| 746 | { "AIF2 Capture", NULL, "DBVDD2" }, | ||
| 747 | { "AIF2 Playback", NULL, "DBVDD2" }, | ||
| 748 | |||
| 749 | { "OUT1L", NULL, "CPVDD" }, | ||
| 750 | { "OUT1R", NULL, "CPVDD" }, | ||
| 751 | { "OUT3L", NULL, "CPVDD" }, | ||
| 752 | |||
| 753 | { "OUT4L", NULL, "SPKVDD" }, | ||
| 754 | |||
| 755 | { "OUT1L", NULL, "SYSCLK" }, | ||
| 756 | { "OUT1R", NULL, "SYSCLK" }, | ||
| 757 | { "OUT3L", NULL, "SYSCLK" }, | ||
| 758 | { "OUT4L", NULL, "SYSCLK" }, | ||
| 759 | |||
| 760 | { "IN1L", NULL, "SYSCLK" }, | ||
| 761 | { "IN1R", NULL, "SYSCLK" }, | ||
| 762 | { "IN2L", NULL, "SYSCLK" }, | ||
| 763 | { "IN2R", NULL, "SYSCLK" }, | ||
| 764 | |||
| 765 | { "MICBIAS1", NULL, "MICVDD" }, | ||
| 766 | { "MICBIAS2", NULL, "MICVDD" }, | ||
| 767 | { "MICBIAS3", NULL, "MICVDD" }, | ||
| 768 | |||
| 769 | { "Noise Generator", NULL, "SYSCLK" }, | ||
| 770 | { "Tone Generator 1", NULL, "SYSCLK" }, | ||
| 771 | { "Tone Generator 2", NULL, "SYSCLK" }, | ||
| 772 | |||
| 773 | { "Noise Generator", NULL, "NOISE" }, | ||
| 774 | { "Tone Generator 1", NULL, "TONE" }, | ||
| 775 | { "Tone Generator 2", NULL, "TONE" }, | ||
| 776 | |||
| 777 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
| 778 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
| 779 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
| 780 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
| 781 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
| 782 | { "AIF1 Capture", NULL, "AIF1TX6" }, | ||
| 783 | { "AIF1 Capture", NULL, "AIF1TX7" }, | ||
| 784 | { "AIF1 Capture", NULL, "AIF1TX8" }, | ||
| 785 | |||
| 786 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
| 787 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
| 788 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
| 789 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
| 790 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
| 791 | { "AIF1RX6", NULL, "AIF1 Playback" }, | ||
| 792 | { "AIF1RX7", NULL, "AIF1 Playback" }, | ||
| 793 | { "AIF1RX8", NULL, "AIF1 Playback" }, | ||
| 794 | |||
| 795 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
| 796 | { "AIF2 Capture", NULL, "AIF2TX2" }, | ||
| 797 | |||
| 798 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
| 799 | { "AIF2RX2", NULL, "AIF2 Playback" }, | ||
| 800 | |||
| 801 | { "Slim1 Capture", NULL, "SLIMTX1" }, | ||
| 802 | { "Slim1 Capture", NULL, "SLIMTX2" }, | ||
| 803 | { "Slim1 Capture", NULL, "SLIMTX3" }, | ||
| 804 | { "Slim1 Capture", NULL, "SLIMTX4" }, | ||
| 805 | |||
| 806 | { "SLIMRX1", NULL, "Slim1 Playback" }, | ||
| 807 | { "SLIMRX2", NULL, "Slim1 Playback" }, | ||
| 808 | { "SLIMRX3", NULL, "Slim1 Playback" }, | ||
| 809 | { "SLIMRX4", NULL, "Slim1 Playback" }, | ||
| 810 | |||
| 811 | { "Slim2 Capture", NULL, "SLIMTX5" }, | ||
| 812 | { "Slim2 Capture", NULL, "SLIMTX6" }, | ||
| 813 | |||
| 814 | { "SLIMRX5", NULL, "Slim2 Playback" }, | ||
| 815 | { "SLIMRX6", NULL, "Slim2 Playback" }, | ||
| 816 | |||
| 817 | { "Slim3 Capture", NULL, "SLIMTX7" }, | ||
| 818 | { "Slim3 Capture", NULL, "SLIMTX8" }, | ||
| 819 | |||
| 820 | { "SLIMRX7", NULL, "Slim3 Playback" }, | ||
| 821 | { "SLIMRX8", NULL, "Slim3 Playback" }, | ||
| 822 | |||
| 823 | { "AIF1 Playback", NULL, "SYSCLK" }, | ||
| 824 | { "AIF2 Playback", NULL, "SYSCLK" }, | ||
| 825 | { "Slim1 Playback", NULL, "SYSCLK" }, | ||
| 826 | { "Slim2 Playback", NULL, "SYSCLK" }, | ||
| 827 | { "Slim3 Playback", NULL, "SYSCLK" }, | ||
| 828 | |||
| 829 | { "AIF1 Capture", NULL, "SYSCLK" }, | ||
| 830 | { "AIF2 Capture", NULL, "SYSCLK" }, | ||
| 831 | { "Slim1 Capture", NULL, "SYSCLK" }, | ||
| 832 | { "Slim2 Capture", NULL, "SYSCLK" }, | ||
| 833 | { "Slim3 Capture", NULL, "SYSCLK" }, | ||
| 834 | |||
| 835 | { "IN1L PGA", NULL, "IN1L" }, | ||
| 836 | { "IN1R PGA", NULL, "IN1R" }, | ||
| 837 | |||
| 838 | { "IN2L PGA", NULL, "IN2L" }, | ||
| 839 | { "IN2R PGA", NULL, "IN2R" }, | ||
| 840 | |||
| 841 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | ||
| 842 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | ||
| 843 | ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | ||
| 844 | |||
| 845 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUT"), | ||
| 846 | ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | ||
| 847 | ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | ||
| 848 | |||
| 849 | ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | ||
| 850 | ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | ||
| 851 | |||
| 852 | ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | ||
| 853 | ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | ||
| 854 | ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | ||
| 855 | ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | ||
| 856 | ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | ||
| 857 | ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | ||
| 858 | ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | ||
| 859 | ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | ||
| 860 | |||
| 861 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | ||
| 862 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | ||
| 863 | |||
| 864 | ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), | ||
| 865 | ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), | ||
| 866 | ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), | ||
| 867 | ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), | ||
| 868 | ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), | ||
| 869 | ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), | ||
| 870 | ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), | ||
| 871 | ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), | ||
| 872 | |||
| 873 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | ||
| 874 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | ||
| 875 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | ||
| 876 | ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), | ||
| 877 | |||
| 878 | ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), | ||
| 879 | ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), | ||
| 880 | |||
| 881 | ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), | ||
| 882 | ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), | ||
| 883 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | ||
| 884 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | ||
| 885 | |||
| 886 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"), | ||
| 887 | ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"), | ||
| 888 | |||
| 889 | ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), | ||
| 890 | ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC2INT2"), | ||
| 891 | |||
| 892 | ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), | ||
| 893 | ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), | ||
| 894 | |||
| 895 | ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), | ||
| 896 | ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), | ||
| 897 | |||
| 898 | ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
| 899 | ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
| 900 | |||
| 901 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | ||
| 902 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | ||
| 903 | { "HPOUT1L", NULL, "OUT1L" }, | ||
| 904 | { "HPOUT1R", NULL, "OUT1R" }, | ||
| 905 | |||
| 906 | { "AEC Loopback", "EPOUT", "OUT3L" }, | ||
| 907 | { "EPOUTN", NULL, "OUT3L" }, | ||
| 908 | { "EPOUTP", NULL, "OUT3L" }, | ||
| 909 | |||
| 910 | { "AEC Loopback", "SPKOUT", "OUT4L" }, | ||
| 911 | { "SPKOUTN", NULL, "OUT4L" }, | ||
| 912 | { "SPKOUTP", NULL, "OUT4L" }, | ||
| 913 | |||
| 914 | { "AEC Loopback", "SPKDAT1L", "OUT5L" }, | ||
| 915 | { "AEC Loopback", "SPKDAT1R", "OUT5R" }, | ||
| 916 | { "SPKDAT1L", NULL, "OUT5L" }, | ||
| 917 | { "SPKDAT1R", NULL, "OUT5R" }, | ||
| 918 | |||
| 919 | { "MICSUPP", NULL, "SYSCLK" }, | ||
| 920 | }; | ||
| 921 | |||
| 922 | static int wm8997_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | ||
| 923 | unsigned int Fref, unsigned int Fout) | ||
| 924 | { | ||
| 925 | struct wm8997_priv *wm8997 = snd_soc_codec_get_drvdata(codec); | ||
| 926 | |||
| 927 | switch (fll_id) { | ||
| 928 | case WM8997_FLL1: | ||
| 929 | return arizona_set_fll(&wm8997->fll[0], source, Fref, Fout); | ||
| 930 | case WM8997_FLL2: | ||
| 931 | return arizona_set_fll(&wm8997->fll[1], source, Fref, Fout); | ||
| 932 | case WM8997_FLL1_REFCLK: | ||
| 933 | return arizona_set_fll_refclk(&wm8997->fll[0], source, Fref, | ||
| 934 | Fout); | ||
| 935 | case WM8997_FLL2_REFCLK: | ||
| 936 | return arizona_set_fll_refclk(&wm8997->fll[1], source, Fref, | ||
| 937 | Fout); | ||
| 938 | default: | ||
| 939 | return -EINVAL; | ||
| 940 | } | ||
| 941 | } | ||
| 942 | |||
| 943 | #define WM8997_RATES SNDRV_PCM_RATE_8000_192000 | ||
| 944 | |||
| 945 | #define WM8997_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
| 946 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 947 | |||
| 948 | static struct snd_soc_dai_driver wm8997_dai[] = { | ||
| 949 | { | ||
| 950 | .name = "wm8997-aif1", | ||
| 951 | .id = 1, | ||
| 952 | .base = ARIZONA_AIF1_BCLK_CTRL, | ||
| 953 | .playback = { | ||
| 954 | .stream_name = "AIF1 Playback", | ||
| 955 | .channels_min = 1, | ||
| 956 | .channels_max = 8, | ||
| 957 | .rates = WM8997_RATES, | ||
| 958 | .formats = WM8997_FORMATS, | ||
| 959 | }, | ||
| 960 | .capture = { | ||
| 961 | .stream_name = "AIF1 Capture", | ||
| 962 | .channels_min = 1, | ||
| 963 | .channels_max = 8, | ||
| 964 | .rates = WM8997_RATES, | ||
| 965 | .formats = WM8997_FORMATS, | ||
| 966 | }, | ||
| 967 | .ops = &arizona_dai_ops, | ||
| 968 | .symmetric_rates = 1, | ||
| 969 | }, | ||
| 970 | { | ||
| 971 | .name = "wm8997-aif2", | ||
| 972 | .id = 2, | ||
| 973 | .base = ARIZONA_AIF2_BCLK_CTRL, | ||
| 974 | .playback = { | ||
| 975 | .stream_name = "AIF2 Playback", | ||
| 976 | .channels_min = 1, | ||
| 977 | .channels_max = 2, | ||
| 978 | .rates = WM8997_RATES, | ||
| 979 | .formats = WM8997_FORMATS, | ||
| 980 | }, | ||
| 981 | .capture = { | ||
| 982 | .stream_name = "AIF2 Capture", | ||
| 983 | .channels_min = 1, | ||
| 984 | .channels_max = 2, | ||
| 985 | .rates = WM8997_RATES, | ||
| 986 | .formats = WM8997_FORMATS, | ||
| 987 | }, | ||
| 988 | .ops = &arizona_dai_ops, | ||
| 989 | .symmetric_rates = 1, | ||
| 990 | }, | ||
| 991 | { | ||
| 992 | .name = "wm8997-slim1", | ||
| 993 | .id = 3, | ||
| 994 | .playback = { | ||
| 995 | .stream_name = "Slim1 Playback", | ||
| 996 | .channels_min = 1, | ||
| 997 | .channels_max = 4, | ||
| 998 | .rates = WM8997_RATES, | ||
| 999 | .formats = WM8997_FORMATS, | ||
| 1000 | }, | ||
| 1001 | .capture = { | ||
| 1002 | .stream_name = "Slim1 Capture", | ||
| 1003 | .channels_min = 1, | ||
| 1004 | .channels_max = 4, | ||
| 1005 | .rates = WM8997_RATES, | ||
| 1006 | .formats = WM8997_FORMATS, | ||
| 1007 | }, | ||
| 1008 | .ops = &arizona_simple_dai_ops, | ||
| 1009 | }, | ||
| 1010 | { | ||
| 1011 | .name = "wm8997-slim2", | ||
| 1012 | .id = 4, | ||
| 1013 | .playback = { | ||
| 1014 | .stream_name = "Slim2 Playback", | ||
| 1015 | .channels_min = 1, | ||
| 1016 | .channels_max = 2, | ||
| 1017 | .rates = WM8997_RATES, | ||
| 1018 | .formats = WM8997_FORMATS, | ||
| 1019 | }, | ||
| 1020 | .capture = { | ||
| 1021 | .stream_name = "Slim2 Capture", | ||
| 1022 | .channels_min = 1, | ||
| 1023 | .channels_max = 2, | ||
| 1024 | .rates = WM8997_RATES, | ||
| 1025 | .formats = WM8997_FORMATS, | ||
| 1026 | }, | ||
| 1027 | .ops = &arizona_simple_dai_ops, | ||
| 1028 | }, | ||
| 1029 | { | ||
| 1030 | .name = "wm8997-slim3", | ||
| 1031 | .id = 5, | ||
| 1032 | .playback = { | ||
| 1033 | .stream_name = "Slim3 Playback", | ||
| 1034 | .channels_min = 1, | ||
| 1035 | .channels_max = 2, | ||
| 1036 | .rates = WM8997_RATES, | ||
| 1037 | .formats = WM8997_FORMATS, | ||
| 1038 | }, | ||
| 1039 | .capture = { | ||
| 1040 | .stream_name = "Slim3 Capture", | ||
| 1041 | .channels_min = 1, | ||
| 1042 | .channels_max = 2, | ||
| 1043 | .rates = WM8997_RATES, | ||
| 1044 | .formats = WM8997_FORMATS, | ||
| 1045 | }, | ||
| 1046 | .ops = &arizona_simple_dai_ops, | ||
| 1047 | }, | ||
| 1048 | }; | ||
| 1049 | |||
| 1050 | static int wm8997_codec_probe(struct snd_soc_codec *codec) | ||
| 1051 | { | ||
| 1052 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
| 1053 | int ret; | ||
| 1054 | |||
| 1055 | codec->control_data = priv->core.arizona->regmap; | ||
| 1056 | |||
| 1057 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
| 1058 | if (ret != 0) | ||
| 1059 | return ret; | ||
| 1060 | |||
| 1061 | arizona_init_spk(codec); | ||
| 1062 | |||
| 1063 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | ||
| 1064 | |||
| 1065 | priv->core.arizona->dapm = &codec->dapm; | ||
| 1066 | |||
| 1067 | return 0; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static int wm8997_codec_remove(struct snd_soc_codec *codec) | ||
| 1071 | { | ||
| 1072 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
| 1073 | |||
| 1074 | priv->core.arizona->dapm = NULL; | ||
| 1075 | |||
| 1076 | return 0; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | #define WM8997_DIG_VU 0x0200 | ||
| 1080 | |||
| 1081 | static unsigned int wm8997_digital_vu[] = { | ||
| 1082 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
| 1083 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | ||
| 1084 | ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
| 1085 | ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
| 1086 | ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
| 1087 | ARIZONA_DAC_DIGITAL_VOLUME_5R, | ||
| 1088 | }; | ||
| 1089 | |||
| 1090 | static struct snd_soc_codec_driver soc_codec_dev_wm8997 = { | ||
| 1091 | .probe = wm8997_codec_probe, | ||
| 1092 | .remove = wm8997_codec_remove, | ||
| 1093 | |||
| 1094 | .idle_bias_off = true, | ||
| 1095 | |||
| 1096 | .set_sysclk = arizona_set_sysclk, | ||
| 1097 | .set_pll = wm8997_set_fll, | ||
| 1098 | |||
| 1099 | .controls = wm8997_snd_controls, | ||
| 1100 | .num_controls = ARRAY_SIZE(wm8997_snd_controls), | ||
| 1101 | .dapm_widgets = wm8997_dapm_widgets, | ||
| 1102 | .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets), | ||
| 1103 | .dapm_routes = wm8997_dapm_routes, | ||
| 1104 | .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes), | ||
| 1105 | }; | ||
| 1106 | |||
| 1107 | static int wm8997_probe(struct platform_device *pdev) | ||
| 1108 | { | ||
| 1109 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | ||
| 1110 | struct wm8997_priv *wm8997; | ||
| 1111 | int i; | ||
| 1112 | |||
| 1113 | wm8997 = devm_kzalloc(&pdev->dev, sizeof(struct wm8997_priv), | ||
| 1114 | GFP_KERNEL); | ||
| 1115 | if (wm8997 == NULL) | ||
| 1116 | return -ENOMEM; | ||
| 1117 | platform_set_drvdata(pdev, wm8997); | ||
| 1118 | |||
| 1119 | wm8997->core.arizona = arizona; | ||
| 1120 | wm8997->core.num_inputs = 4; | ||
| 1121 | |||
| 1122 | for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++) | ||
| 1123 | wm8997->fll[i].vco_mult = 1; | ||
| 1124 | |||
| 1125 | arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, | ||
| 1126 | ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, | ||
| 1127 | &wm8997->fll[0]); | ||
| 1128 | arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, | ||
| 1129 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | ||
| 1130 | &wm8997->fll[1]); | ||
| 1131 | |||
| 1132 | /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */ | ||
| 1133 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2, | ||
| 1134 | ARIZONA_SAMPLE_RATE_2_MASK, 0x11); | ||
| 1135 | regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3, | ||
| 1136 | ARIZONA_SAMPLE_RATE_3_MASK, 0x12); | ||
| 1137 | |||
| 1138 | for (i = 0; i < ARRAY_SIZE(wm8997_dai); i++) | ||
| 1139 | arizona_init_dai(&wm8997->core, i); | ||
| 1140 | |||
| 1141 | /* Latch volume update bits */ | ||
| 1142 | for (i = 0; i < ARRAY_SIZE(wm8997_digital_vu); i++) | ||
| 1143 | regmap_update_bits(arizona->regmap, wm8997_digital_vu[i], | ||
| 1144 | WM8997_DIG_VU, WM8997_DIG_VU); | ||
| 1145 | |||
| 1146 | pm_runtime_enable(&pdev->dev); | ||
| 1147 | pm_runtime_idle(&pdev->dev); | ||
| 1148 | |||
| 1149 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8997, | ||
| 1150 | wm8997_dai, ARRAY_SIZE(wm8997_dai)); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | static int wm8997_remove(struct platform_device *pdev) | ||
| 1154 | { | ||
| 1155 | snd_soc_unregister_codec(&pdev->dev); | ||
| 1156 | pm_runtime_disable(&pdev->dev); | ||
| 1157 | |||
| 1158 | return 0; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | static struct platform_driver wm8997_codec_driver = { | ||
| 1162 | .driver = { | ||
| 1163 | .name = "wm8997-codec", | ||
| 1164 | .owner = THIS_MODULE, | ||
| 1165 | }, | ||
| 1166 | .probe = wm8997_probe, | ||
| 1167 | .remove = wm8997_remove, | ||
| 1168 | }; | ||
| 1169 | |||
| 1170 | module_platform_driver(wm8997_codec_driver); | ||
| 1171 | |||
| 1172 | MODULE_DESCRIPTION("ASoC WM8997 driver"); | ||
| 1173 | MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>"); | ||
| 1174 | MODULE_LICENSE("GPL"); | ||
| 1175 | MODULE_ALIAS("platform:wm8997-codec"); | ||
diff --git a/sound/soc/codecs/wm8997.h b/sound/soc/codecs/wm8997.h new file mode 100644 index 000000000000..5e91c6a7d567 --- /dev/null +++ b/sound/soc/codecs/wm8997.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | /* | ||
| 2 | * wm8997.h -- WM8997 ALSA SoC Audio driver | ||
| 3 | * | ||
| 4 | * Copyright 2012 Wolfson Microelectronics plc | ||
| 5 | * | ||
| 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
| 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 | #ifndef _WM8997_H | ||
| 14 | #define _WM8997_H | ||
| 15 | |||
| 16 | #include "arizona.h" | ||
| 17 | |||
| 18 | #define WM8997_FLL1 1 | ||
| 19 | #define WM8997_FLL2 2 | ||
| 20 | #define WM8997_FLL1_REFCLK 3 | ||
| 21 | #define WM8997_FLL2_REFCLK 4 | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 05252ac936a3..b38f3506418f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
| @@ -225,15 +225,8 @@ struct wm_coeff_ctl_ops { | |||
| 225 | struct snd_ctl_elem_info *uinfo); | 225 | struct snd_ctl_elem_info *uinfo); |
| 226 | }; | 226 | }; |
| 227 | 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 { | 228 | struct wm_coeff_ctl { |
| 235 | const char *name; | 229 | const char *name; |
| 236 | struct snd_card *card; | ||
| 237 | struct wm_adsp_alg_region region; | 230 | struct wm_adsp_alg_region region; |
| 238 | struct wm_coeff_ctl_ops ops; | 231 | struct wm_coeff_ctl_ops ops; |
| 239 | struct wm_adsp *adsp; | 232 | struct wm_adsp *adsp; |
| @@ -378,7 +371,6 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol, | |||
| 378 | static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, | 371 | static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, |
| 379 | const void *buf, size_t len) | 372 | const void *buf, size_t len) |
| 380 | { | 373 | { |
| 381 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
| 382 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | 374 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; |
| 383 | struct wm_adsp_alg_region *region = &ctl->region; | 375 | struct wm_adsp_alg_region *region = &ctl->region; |
| 384 | const struct wm_adsp_region *mem; | 376 | const struct wm_adsp_region *mem; |
| @@ -401,7 +393,7 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, | |||
| 401 | if (!scratch) | 393 | if (!scratch) |
| 402 | return -ENOMEM; | 394 | return -ENOMEM; |
| 403 | 395 | ||
| 404 | ret = regmap_raw_write(wm_coeff->regmap, reg, scratch, | 396 | ret = regmap_raw_write(adsp->regmap, reg, scratch, |
| 405 | ctl->len); | 397 | ctl->len); |
| 406 | if (ret) { | 398 | if (ret) { |
| 407 | adsp_err(adsp, "Failed to write %zu bytes to %x\n", | 399 | adsp_err(adsp, "Failed to write %zu bytes to %x\n", |
| @@ -434,7 +426,6 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol, | |||
| 434 | static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, | 426 | static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, |
| 435 | void *buf, size_t len) | 427 | void *buf, size_t len) |
| 436 | { | 428 | { |
| 437 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
| 438 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | 429 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; |
| 439 | struct wm_adsp_alg_region *region = &ctl->region; | 430 | struct wm_adsp_alg_region *region = &ctl->region; |
| 440 | const struct wm_adsp_region *mem; | 431 | const struct wm_adsp_region *mem; |
| @@ -457,7 +448,7 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, | |||
| 457 | if (!scratch) | 448 | if (!scratch) |
| 458 | return -ENOMEM; | 449 | return -ENOMEM; |
| 459 | 450 | ||
| 460 | ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len); | 451 | ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len); |
| 461 | if (ret) { | 452 | if (ret) { |
| 462 | adsp_err(adsp, "Failed to read %zu bytes from %x\n", | 453 | adsp_err(adsp, "Failed to read %zu bytes from %x\n", |
| 463 | ctl->len, reg); | 454 | ctl->len, reg); |
| @@ -481,37 +472,18 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol, | |||
| 481 | return 0; | 472 | return 0; |
| 482 | } | 473 | } |
| 483 | 474 | ||
| 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 { | 475 | struct wmfw_ctl_work { |
| 503 | struct wm_coeff *wm_coeff; | 476 | struct wm_adsp *adsp; |
| 504 | struct wm_coeff_ctl *ctl; | 477 | struct wm_coeff_ctl *ctl; |
| 505 | struct work_struct work; | 478 | struct work_struct work; |
| 506 | }; | 479 | }; |
| 507 | 480 | ||
| 508 | static int wmfw_add_ctl(struct wm_coeff *wm_coeff, | 481 | static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl) |
| 509 | struct wm_coeff_ctl *ctl) | ||
| 510 | { | 482 | { |
| 511 | struct snd_kcontrol_new *kcontrol; | 483 | struct snd_kcontrol_new *kcontrol; |
| 512 | int ret; | 484 | int ret; |
| 513 | 485 | ||
| 514 | if (!wm_coeff || !ctl || !ctl->name || !ctl->card) | 486 | if (!ctl || !ctl->name) |
| 515 | return -EINVAL; | 487 | return -EINVAL; |
| 516 | 488 | ||
| 517 | kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); | 489 | kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); |
| @@ -525,14 +497,17 @@ static int wmfw_add_ctl(struct wm_coeff *wm_coeff, | |||
| 525 | kcontrol->put = wm_coeff_put; | 497 | kcontrol->put = wm_coeff_put; |
| 526 | kcontrol->private_value = (unsigned long)ctl; | 498 | kcontrol->private_value = (unsigned long)ctl; |
| 527 | 499 | ||
| 528 | ret = wm_coeff_add_kcontrol(wm_coeff, | 500 | ret = snd_soc_add_card_controls(adsp->card, |
| 529 | ctl, kcontrol); | 501 | kcontrol, 1); |
| 530 | if (ret < 0) | 502 | if (ret < 0) |
| 531 | goto err_kcontrol; | 503 | goto err_kcontrol; |
| 532 | 504 | ||
| 533 | kfree(kcontrol); | 505 | kfree(kcontrol); |
| 534 | 506 | ||
| 535 | list_add(&ctl->list, &wm_coeff->ctl_list); | 507 | ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card, |
| 508 | ctl->name); | ||
| 509 | |||
| 510 | list_add(&ctl->list, &adsp->ctl_list); | ||
| 536 | return 0; | 511 | return 0; |
| 537 | 512 | ||
| 538 | err_kcontrol: | 513 | err_kcontrol: |
| @@ -753,13 +728,12 @@ out: | |||
| 753 | return ret; | 728 | return ret; |
| 754 | } | 729 | } |
| 755 | 730 | ||
| 756 | static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff) | 731 | static int wm_coeff_init_control_caches(struct wm_adsp *adsp) |
| 757 | { | 732 | { |
| 758 | struct wm_coeff_ctl *ctl; | 733 | struct wm_coeff_ctl *ctl; |
| 759 | int ret; | 734 | int ret; |
| 760 | 735 | ||
| 761 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | 736 | list_for_each_entry(ctl, &adsp->ctl_list, list) { |
| 762 | list) { | ||
| 763 | if (!ctl->enabled || ctl->set) | 737 | if (!ctl->enabled || ctl->set) |
| 764 | continue; | 738 | continue; |
| 765 | ret = wm_coeff_read_control(ctl->kcontrol, | 739 | ret = wm_coeff_read_control(ctl->kcontrol, |
| @@ -772,13 +746,12 @@ static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff) | |||
| 772 | return 0; | 746 | return 0; |
| 773 | } | 747 | } |
| 774 | 748 | ||
| 775 | static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff) | 749 | static int wm_coeff_sync_controls(struct wm_adsp *adsp) |
| 776 | { | 750 | { |
| 777 | struct wm_coeff_ctl *ctl; | 751 | struct wm_coeff_ctl *ctl; |
| 778 | int ret; | 752 | int ret; |
| 779 | 753 | ||
| 780 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | 754 | list_for_each_entry(ctl, &adsp->ctl_list, list) { |
| 781 | list) { | ||
| 782 | if (!ctl->enabled) | 755 | if (!ctl->enabled) |
| 783 | continue; | 756 | continue; |
| 784 | if (ctl->set) { | 757 | if (ctl->set) { |
| @@ -799,15 +772,14 @@ static void wm_adsp_ctl_work(struct work_struct *work) | |||
| 799 | struct wmfw_ctl_work, | 772 | struct wmfw_ctl_work, |
| 800 | work); | 773 | work); |
| 801 | 774 | ||
| 802 | wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl); | 775 | wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl); |
| 803 | kfree(ctl_work); | 776 | kfree(ctl_work); |
| 804 | } | 777 | } |
| 805 | 778 | ||
| 806 | static int wm_adsp_create_control(struct snd_soc_codec *codec, | 779 | static int wm_adsp_create_control(struct wm_adsp *dsp, |
| 807 | const struct wm_adsp_alg_region *region) | 780 | const struct wm_adsp_alg_region *region) |
| 808 | 781 | ||
| 809 | { | 782 | { |
| 810 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); | ||
| 811 | struct wm_coeff_ctl *ctl; | 783 | struct wm_coeff_ctl *ctl; |
| 812 | struct wmfw_ctl_work *ctl_work; | 784 | struct wmfw_ctl_work *ctl_work; |
| 813 | char *name; | 785 | char *name; |
| @@ -842,7 +814,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec, | |||
| 842 | snprintf(name, PAGE_SIZE, "DSP%d %s %x", | 814 | snprintf(name, PAGE_SIZE, "DSP%d %s %x", |
| 843 | dsp->num, region_name, region->alg); | 815 | dsp->num, region_name, region->alg); |
| 844 | 816 | ||
| 845 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | 817 | list_for_each_entry(ctl, &dsp->ctl_list, |
| 846 | list) { | 818 | list) { |
| 847 | if (!strcmp(ctl->name, name)) { | 819 | if (!strcmp(ctl->name, name)) { |
| 848 | if (!ctl->enabled) | 820 | if (!ctl->enabled) |
| @@ -866,7 +838,6 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec, | |||
| 866 | ctl->set = 0; | 838 | ctl->set = 0; |
| 867 | ctl->ops.xget = wm_coeff_get; | 839 | ctl->ops.xget = wm_coeff_get; |
| 868 | ctl->ops.xput = wm_coeff_put; | 840 | ctl->ops.xput = wm_coeff_put; |
| 869 | ctl->card = codec->card->snd_card; | ||
| 870 | ctl->adsp = dsp; | 841 | ctl->adsp = dsp; |
| 871 | 842 | ||
| 872 | ctl->len = region->len; | 843 | ctl->len = region->len; |
| @@ -882,7 +853,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec, | |||
| 882 | goto err_ctl_cache; | 853 | goto err_ctl_cache; |
| 883 | } | 854 | } |
| 884 | 855 | ||
| 885 | ctl_work->wm_coeff = dsp->wm_coeff; | 856 | ctl_work->adsp = dsp; |
| 886 | ctl_work->ctl = ctl; | 857 | ctl_work->ctl = ctl; |
| 887 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); | 858 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); |
| 888 | schedule_work(&ctl_work->work); | 859 | schedule_work(&ctl_work->work); |
| @@ -903,7 +874,7 @@ err_name: | |||
| 903 | return ret; | 874 | return ret; |
| 904 | } | 875 | } |
| 905 | 876 | ||
| 906 | static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | 877 | static int wm_adsp_setup_algs(struct wm_adsp *dsp) |
| 907 | { | 878 | { |
| 908 | struct regmap *regmap = dsp->regmap; | 879 | struct regmap *regmap = dsp->regmap; |
| 909 | struct wmfw_adsp1_id_hdr adsp1_id; | 880 | struct wmfw_adsp1_id_hdr adsp1_id; |
| @@ -1091,7 +1062,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | |||
| 1091 | if (i + 1 < algs) { | 1062 | if (i + 1 < algs) { |
| 1092 | region->len = be32_to_cpu(adsp1_alg[i + 1].dm); | 1063 | region->len = be32_to_cpu(adsp1_alg[i + 1].dm); |
| 1093 | region->len -= be32_to_cpu(adsp1_alg[i].dm); | 1064 | region->len -= be32_to_cpu(adsp1_alg[i].dm); |
| 1094 | wm_adsp_create_control(codec, region); | 1065 | wm_adsp_create_control(dsp, region); |
| 1095 | } else { | 1066 | } else { |
| 1096 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", | 1067 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", |
| 1097 | be32_to_cpu(adsp1_alg[i].alg.id)); | 1068 | be32_to_cpu(adsp1_alg[i].alg.id)); |
| @@ -1108,7 +1079,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | |||
| 1108 | if (i + 1 < algs) { | 1079 | if (i + 1 < algs) { |
| 1109 | region->len = be32_to_cpu(adsp1_alg[i + 1].zm); | 1080 | region->len = be32_to_cpu(adsp1_alg[i + 1].zm); |
| 1110 | region->len -= be32_to_cpu(adsp1_alg[i].zm); | 1081 | region->len -= be32_to_cpu(adsp1_alg[i].zm); |
| 1111 | wm_adsp_create_control(codec, region); | 1082 | wm_adsp_create_control(dsp, region); |
| 1112 | } else { | 1083 | } else { |
| 1113 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | 1084 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", |
| 1114 | be32_to_cpu(adsp1_alg[i].alg.id)); | 1085 | be32_to_cpu(adsp1_alg[i].alg.id)); |
| @@ -1137,7 +1108,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | |||
| 1137 | if (i + 1 < algs) { | 1108 | if (i + 1 < algs) { |
| 1138 | region->len = be32_to_cpu(adsp2_alg[i + 1].xm); | 1109 | region->len = be32_to_cpu(adsp2_alg[i + 1].xm); |
| 1139 | region->len -= be32_to_cpu(adsp2_alg[i].xm); | 1110 | region->len -= be32_to_cpu(adsp2_alg[i].xm); |
| 1140 | wm_adsp_create_control(codec, region); | 1111 | wm_adsp_create_control(dsp, region); |
| 1141 | } else { | 1112 | } else { |
| 1142 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", | 1113 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", |
| 1143 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1114 | be32_to_cpu(adsp2_alg[i].alg.id)); |
| @@ -1154,7 +1125,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | |||
| 1154 | if (i + 1 < algs) { | 1125 | if (i + 1 < algs) { |
| 1155 | region->len = be32_to_cpu(adsp2_alg[i + 1].ym); | 1126 | region->len = be32_to_cpu(adsp2_alg[i + 1].ym); |
| 1156 | region->len -= be32_to_cpu(adsp2_alg[i].ym); | 1127 | region->len -= be32_to_cpu(adsp2_alg[i].ym); |
| 1157 | wm_adsp_create_control(codec, region); | 1128 | wm_adsp_create_control(dsp, region); |
| 1158 | } else { | 1129 | } else { |
| 1159 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", | 1130 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", |
| 1160 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1131 | be32_to_cpu(adsp2_alg[i].alg.id)); |
| @@ -1171,7 +1142,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | |||
| 1171 | if (i + 1 < algs) { | 1142 | if (i + 1 < algs) { |
| 1172 | region->len = be32_to_cpu(adsp2_alg[i + 1].zm); | 1143 | region->len = be32_to_cpu(adsp2_alg[i + 1].zm); |
| 1173 | region->len -= be32_to_cpu(adsp2_alg[i].zm); | 1144 | region->len -= be32_to_cpu(adsp2_alg[i].zm); |
| 1174 | wm_adsp_create_control(codec, region); | 1145 | wm_adsp_create_control(dsp, region); |
| 1175 | } else { | 1146 | } else { |
| 1176 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | 1147 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", |
| 1177 | be32_to_cpu(adsp2_alg[i].alg.id)); | 1148 | be32_to_cpu(adsp2_alg[i].alg.id)); |
| @@ -1391,6 +1362,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1391 | int ret; | 1362 | int ret; |
| 1392 | int val; | 1363 | int val; |
| 1393 | 1364 | ||
| 1365 | dsp->card = codec->card; | ||
| 1366 | |||
| 1394 | switch (event) { | 1367 | switch (event) { |
| 1395 | case SND_SOC_DAPM_POST_PMU: | 1368 | case SND_SOC_DAPM_POST_PMU: |
| 1396 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1369 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
| @@ -1425,7 +1398,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1425 | if (ret != 0) | 1398 | if (ret != 0) |
| 1426 | goto err; | 1399 | goto err; |
| 1427 | 1400 | ||
| 1428 | ret = wm_adsp_setup_algs(dsp, codec); | 1401 | ret = wm_adsp_setup_algs(dsp); |
| 1429 | if (ret != 0) | 1402 | if (ret != 0) |
| 1430 | goto err; | 1403 | goto err; |
| 1431 | 1404 | ||
| @@ -1434,12 +1407,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1434 | goto err; | 1407 | goto err; |
| 1435 | 1408 | ||
| 1436 | /* Initialize caches for enabled and unset controls */ | 1409 | /* Initialize caches for enabled and unset controls */ |
| 1437 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | 1410 | ret = wm_coeff_init_control_caches(dsp); |
| 1438 | if (ret != 0) | 1411 | if (ret != 0) |
| 1439 | goto err; | 1412 | goto err; |
| 1440 | 1413 | ||
| 1441 | /* Sync set controls */ | 1414 | /* Sync set controls */ |
| 1442 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | 1415 | ret = wm_coeff_sync_controls(dsp); |
| 1443 | if (ret != 0) | 1416 | if (ret != 0) |
| 1444 | goto err; | 1417 | goto err; |
| 1445 | 1418 | ||
| @@ -1460,10 +1433,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
| 1460 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1433 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
| 1461 | ADSP1_SYS_ENA, 0); | 1434 | ADSP1_SYS_ENA, 0); |
| 1462 | 1435 | ||
| 1463 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | 1436 | list_for_each_entry(ctl, &dsp->ctl_list, list) |
| 1464 | list) { | ||
| 1465 | ctl->enabled = 0; | 1437 | ctl->enabled = 0; |
| 1466 | } | ||
| 1467 | break; | 1438 | break; |
| 1468 | 1439 | ||
| 1469 | default: | 1440 | default: |
| @@ -1520,6 +1491,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1520 | unsigned int val; | 1491 | unsigned int val; |
| 1521 | int ret; | 1492 | int ret; |
| 1522 | 1493 | ||
| 1494 | dsp->card = codec->card; | ||
| 1495 | |||
| 1523 | switch (event) { | 1496 | switch (event) { |
| 1524 | case SND_SOC_DAPM_POST_PMU: | 1497 | case SND_SOC_DAPM_POST_PMU: |
| 1525 | /* | 1498 | /* |
| @@ -1582,7 +1555,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1582 | if (ret != 0) | 1555 | if (ret != 0) |
| 1583 | goto err; | 1556 | goto err; |
| 1584 | 1557 | ||
| 1585 | ret = wm_adsp_setup_algs(dsp, codec); | 1558 | ret = wm_adsp_setup_algs(dsp); |
| 1586 | if (ret != 0) | 1559 | if (ret != 0) |
| 1587 | goto err; | 1560 | goto err; |
| 1588 | 1561 | ||
| @@ -1591,12 +1564,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1591 | goto err; | 1564 | goto err; |
| 1592 | 1565 | ||
| 1593 | /* Initialize caches for enabled and unset controls */ | 1566 | /* Initialize caches for enabled and unset controls */ |
| 1594 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | 1567 | ret = wm_coeff_init_control_caches(dsp); |
| 1595 | if (ret != 0) | 1568 | if (ret != 0) |
| 1596 | goto err; | 1569 | goto err; |
| 1597 | 1570 | ||
| 1598 | /* Sync set controls */ | 1571 | /* Sync set controls */ |
| 1599 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | 1572 | ret = wm_coeff_sync_controls(dsp); |
| 1600 | if (ret != 0) | 1573 | if (ret != 0) |
| 1601 | goto err; | 1574 | goto err; |
| 1602 | 1575 | ||
| @@ -1637,10 +1610,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
| 1637 | ret); | 1610 | ret); |
| 1638 | } | 1611 | } |
| 1639 | 1612 | ||
| 1640 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | 1613 | list_for_each_entry(ctl, &dsp->ctl_list, list) |
| 1641 | list) { | ||
| 1642 | ctl->enabled = 0; | 1614 | ctl->enabled = 0; |
| 1643 | } | ||
| 1644 | 1615 | ||
| 1645 | while (!list_empty(&dsp->alg_regions)) { | 1616 | while (!list_empty(&dsp->alg_regions)) { |
| 1646 | alg_region = list_first_entry(&dsp->alg_regions, | 1617 | alg_region = list_first_entry(&dsp->alg_regions, |
| @@ -1679,49 +1650,38 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
| 1679 | } | 1650 | } |
| 1680 | 1651 | ||
| 1681 | INIT_LIST_HEAD(&adsp->alg_regions); | 1652 | INIT_LIST_HEAD(&adsp->alg_regions); |
| 1682 | 1653 | INIT_LIST_HEAD(&adsp->ctl_list); | |
| 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 | 1654 | ||
| 1691 | if (dvfs) { | 1655 | if (dvfs) { |
| 1692 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | 1656 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); |
| 1693 | if (IS_ERR(adsp->dvfs)) { | 1657 | if (IS_ERR(adsp->dvfs)) { |
| 1694 | ret = PTR_ERR(adsp->dvfs); | 1658 | ret = PTR_ERR(adsp->dvfs); |
| 1695 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); | 1659 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); |
| 1696 | goto out_coeff; | 1660 | return ret; |
| 1697 | } | 1661 | } |
| 1698 | 1662 | ||
| 1699 | ret = regulator_enable(adsp->dvfs); | 1663 | ret = regulator_enable(adsp->dvfs); |
| 1700 | if (ret != 0) { | 1664 | if (ret != 0) { |
| 1701 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", | 1665 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", |
| 1702 | ret); | 1666 | ret); |
| 1703 | goto out_coeff; | 1667 | return ret; |
| 1704 | } | 1668 | } |
| 1705 | 1669 | ||
| 1706 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); | 1670 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); |
| 1707 | if (ret != 0) { | 1671 | if (ret != 0) { |
| 1708 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", | 1672 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", |
| 1709 | ret); | 1673 | ret); |
| 1710 | goto out_coeff; | 1674 | return ret; |
| 1711 | } | 1675 | } |
| 1712 | 1676 | ||
| 1713 | ret = regulator_disable(adsp->dvfs); | 1677 | ret = regulator_disable(adsp->dvfs); |
| 1714 | if (ret != 0) { | 1678 | if (ret != 0) { |
| 1715 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", | 1679 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", |
| 1716 | ret); | 1680 | ret); |
| 1717 | goto out_coeff; | 1681 | return ret; |
| 1718 | } | 1682 | } |
| 1719 | } | 1683 | } |
| 1720 | 1684 | ||
| 1721 | return 0; | 1685 | return 0; |
| 1722 | |||
| 1723 | out_coeff: | ||
| 1724 | kfree(adsp->wm_coeff); | ||
| 1725 | return ret; | ||
| 1726 | } | 1686 | } |
| 1727 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1687 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 9f922c82536c..d018dea6254d 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
| @@ -39,6 +39,7 @@ struct wm_adsp { | |||
| 39 | int type; | 39 | int type; |
| 40 | struct device *dev; | 40 | struct device *dev; |
| 41 | struct regmap *regmap; | 41 | struct regmap *regmap; |
| 42 | struct snd_soc_card *card; | ||
| 42 | 43 | ||
| 43 | int base; | 44 | int base; |
| 44 | int sysclk_reg; | 45 | int sysclk_reg; |
| @@ -57,7 +58,7 @@ struct wm_adsp { | |||
| 57 | 58 | ||
| 58 | struct regulator *dvfs; | 59 | struct regulator *dvfs; |
| 59 | 60 | ||
| 60 | struct wm_coeff *wm_coeff; | 61 | struct list_head ctl_list; |
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | #define WM_ADSP1(wname, num) \ | 64 | #define WM_ADSP1(wname, num) \ |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 2d9e099415a5..8b50e5958de5 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
| @@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); | |||
| 699 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, | 699 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, |
| 700 | struct snd_ctl_elem_value *ucontrol) | 700 | struct snd_ctl_elem_value *ucontrol) |
| 701 | { | 701 | { |
| 702 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 702 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 703 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 704 | struct snd_soc_codec *codec = widget->codec; | ||
| 705 | int ret; | 703 | int ret; |
| 706 | 704 | ||
| 707 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | 705 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); |
| @@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol, | |||
| 721 | static int class_w_put_double(struct snd_kcontrol *kcontrol, | 719 | static int class_w_put_double(struct snd_kcontrol *kcontrol, |
| 722 | struct snd_ctl_elem_value *ucontrol) | 720 | struct snd_ctl_elem_value *ucontrol) |
| 723 | { | 721 | { |
| 724 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 722 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 725 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 726 | struct snd_soc_codec *codec = widget->codec; | ||
| 727 | int ret; | 723 | int ret; |
| 728 | 724 | ||
| 729 | ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); | 725 | ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index aa438546c912..cd088cc8c866 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | config SND_SOC_FSL_SSI | 1 | config SND_SOC_FSL_SSI |
| 2 | tristate | 2 | tristate |
| 3 | 3 | ||
| 4 | config SND_SOC_FSL_SPDIF | ||
| 5 | tristate | ||
| 6 | |||
| 4 | config SND_SOC_FSL_UTILS | 7 | config SND_SOC_FSL_UTILS |
| 5 | tristate | 8 | tristate |
| 6 | 9 | ||
| @@ -98,7 +101,7 @@ endif # SND_POWERPC_SOC | |||
| 98 | 101 | ||
| 99 | menuconfig SND_IMX_SOC | 102 | menuconfig SND_IMX_SOC |
| 100 | tristate "SoC Audio for Freescale i.MX CPUs" | 103 | tristate "SoC Audio for Freescale i.MX CPUs" |
| 101 | depends on ARCH_MXC | 104 | depends on ARCH_MXC || COMPILE_TEST |
| 102 | help | 105 | help |
| 103 | Say Y or M if you want to add support for codecs attached to | 106 | Say Y or M if you want to add support for codecs attached to |
| 104 | the i.MX CPUs. | 107 | the i.MX CPUs. |
| @@ -109,11 +112,11 @@ config SND_SOC_IMX_SSI | |||
| 109 | tristate | 112 | tristate |
| 110 | 113 | ||
| 111 | config SND_SOC_IMX_PCM_FIQ | 114 | config SND_SOC_IMX_PCM_FIQ |
| 112 | bool | 115 | tristate |
| 113 | select FIQ | 116 | select FIQ |
| 114 | 117 | ||
| 115 | config SND_SOC_IMX_PCM_DMA | 118 | config SND_SOC_IMX_PCM_DMA |
| 116 | bool | 119 | tristate |
| 117 | select SND_SOC_GENERIC_DMAENGINE_PCM | 120 | select SND_SOC_GENERIC_DMAENGINE_PCM |
| 118 | 121 | ||
| 119 | config SND_SOC_IMX_AUDMUX | 122 | config SND_SOC_IMX_AUDMUX |
| @@ -175,7 +178,6 @@ config SND_SOC_IMX_WM8962 | |||
| 175 | select SND_SOC_IMX_PCM_DMA | 178 | select SND_SOC_IMX_PCM_DMA |
| 176 | select SND_SOC_IMX_AUDMUX | 179 | select SND_SOC_IMX_AUDMUX |
| 177 | select SND_SOC_FSL_SSI | 180 | select SND_SOC_FSL_SSI |
| 178 | select SND_SOC_FSL_UTILS | ||
| 179 | help | 181 | help |
| 180 | Say Y if you want to add support for SoC audio on an i.MX board with | 182 | Say Y if you want to add support for SoC audio on an i.MX board with |
| 181 | a wm8962 codec. | 183 | a wm8962 codec. |
| @@ -187,14 +189,13 @@ config SND_SOC_IMX_SGTL5000 | |||
| 187 | select SND_SOC_IMX_PCM_DMA | 189 | select SND_SOC_IMX_PCM_DMA |
| 188 | select SND_SOC_IMX_AUDMUX | 190 | select SND_SOC_IMX_AUDMUX |
| 189 | select SND_SOC_FSL_SSI | 191 | select SND_SOC_FSL_SSI |
| 190 | select SND_SOC_FSL_UTILS | ||
| 191 | help | 192 | help |
| 192 | Say Y if you want to add support for SoC audio on an i.MX board with | 193 | Say Y if you want to add support for SoC audio on an i.MX board with |
| 193 | a sgtl5000 codec. | 194 | a sgtl5000 codec. |
| 194 | 195 | ||
| 195 | config SND_SOC_IMX_MC13783 | 196 | config SND_SOC_IMX_MC13783 |
| 196 | tristate "SoC Audio support for I.MX boards with mc13783" | 197 | tristate "SoC Audio support for I.MX boards with mc13783" |
| 197 | depends on MFD_MC13783 | 198 | depends on MFD_MC13783 && ARM |
| 198 | select SND_SOC_IMX_SSI | 199 | select SND_SOC_IMX_SSI |
| 199 | select SND_SOC_IMX_AUDMUX | 200 | select SND_SOC_IMX_AUDMUX |
| 200 | select SND_SOC_MC13783 | 201 | select SND_SOC_MC13783 |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index d4b4aa8b5649..4b5970e014dd 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
| @@ -12,9 +12,11 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o | |||
| 12 | 12 | ||
| 13 | # Freescale PowerPC SSI/DMA Platform Support | 13 | # Freescale PowerPC SSI/DMA Platform Support |
| 14 | snd-soc-fsl-ssi-objs := fsl_ssi.o | 14 | snd-soc-fsl-ssi-objs := fsl_ssi.o |
| 15 | snd-soc-fsl-spdif-objs := fsl_spdif.o | ||
| 15 | snd-soc-fsl-utils-objs := fsl_utils.o | 16 | snd-soc-fsl-utils-objs := fsl_utils.o |
| 16 | snd-soc-fsl-dma-objs := fsl_dma.o | 17 | snd-soc-fsl-dma-objs := fsl_dma.o |
| 17 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 18 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
| 19 | obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o | ||
| 18 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o | 20 | obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o |
| 19 | obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o | 21 | obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o |
| 20 | 22 | ||
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c new file mode 100644 index 000000000000..42a43820d993 --- /dev/null +++ b/sound/soc/fsl/fsl_spdif.c | |||
| @@ -0,0 +1,1236 @@ | |||
| 1 | /* | ||
| 2 | * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
| 5 | * | ||
| 6 | * Based on stmp3xxx_spdif_dai.c | ||
| 7 | * Vladimir Barinov <vbarinov@embeddedalley.com> | ||
| 8 | * Copyright 2008 SigmaTel, Inc | ||
| 9 | * Copyright 2008 Embedded Alley Solutions, Inc | ||
| 10 | * | ||
| 11 | * This file is licensed under the terms of the GNU General Public License | ||
| 12 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 13 | * kind, whether express or implied. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/clk-private.h> | ||
| 19 | #include <linux/bitrev.h> | ||
| 20 | #include <linux/regmap.h> | ||
| 21 | #include <linux/of_address.h> | ||
| 22 | #include <linux/of_device.h> | ||
| 23 | #include <linux/of_irq.h> | ||
| 24 | |||
| 25 | #include <sound/asoundef.h> | ||
| 26 | #include <sound/soc.h> | ||
| 27 | #include <sound/dmaengine_pcm.h> | ||
| 28 | |||
| 29 | #include "fsl_spdif.h" | ||
| 30 | #include "imx-pcm.h" | ||
| 31 | |||
| 32 | #define FSL_SPDIF_TXFIFO_WML 0x8 | ||
| 33 | #define FSL_SPDIF_RXFIFO_WML 0x8 | ||
| 34 | |||
| 35 | #define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC) | ||
| 36 | #define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\ | ||
| 37 | INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\ | ||
| 38 | INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED) | ||
| 39 | |||
| 40 | /* Index list for the values that has if (DPLL Locked) condition */ | ||
| 41 | static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; | ||
| 42 | #define SRPC_NODPLL_START1 0x5 | ||
| 43 | #define SRPC_NODPLL_START2 0xc | ||
| 44 | |||
| 45 | #define DEFAULT_RXCLK_SRC 1 | ||
| 46 | |||
| 47 | /* | ||
| 48 | * SPDIF control structure | ||
| 49 | * Defines channel status, subcode and Q sub | ||
| 50 | */ | ||
| 51 | struct spdif_mixer_control { | ||
| 52 | /* spinlock to access control data */ | ||
| 53 | spinlock_t ctl_lock; | ||
| 54 | |||
| 55 | /* IEC958 channel tx status bit */ | ||
| 56 | unsigned char ch_status[4]; | ||
| 57 | |||
| 58 | /* User bits */ | ||
| 59 | unsigned char subcode[2 * SPDIF_UBITS_SIZE]; | ||
| 60 | |||
| 61 | /* Q subcode part of user bits */ | ||
| 62 | unsigned char qsub[2 * SPDIF_QSUB_SIZE]; | ||
| 63 | |||
| 64 | /* Buffer offset for U/Q */ | ||
| 65 | u32 upos; | ||
| 66 | u32 qpos; | ||
| 67 | |||
| 68 | /* Ready buffer index of the two buffers */ | ||
| 69 | u32 ready_buf; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct fsl_spdif_priv { | ||
| 73 | struct spdif_mixer_control fsl_spdif_control; | ||
| 74 | struct snd_soc_dai_driver cpu_dai_drv; | ||
| 75 | struct platform_device *pdev; | ||
| 76 | struct regmap *regmap; | ||
| 77 | bool dpll_locked; | ||
| 78 | u8 txclk_div[SPDIF_TXRATE_MAX]; | ||
| 79 | u8 txclk_src[SPDIF_TXRATE_MAX]; | ||
| 80 | u8 rxclk_src; | ||
| 81 | struct clk *txclk[SPDIF_TXRATE_MAX]; | ||
| 82 | struct clk *rxclk; | ||
| 83 | struct snd_dmaengine_dai_dma_data dma_params_tx; | ||
| 84 | struct snd_dmaengine_dai_dma_data dma_params_rx; | ||
| 85 | |||
| 86 | /* The name space will be allocated dynamically */ | ||
| 87 | char name[0]; | ||
| 88 | }; | ||
| 89 | |||
| 90 | |||
| 91 | /* DPLL locked and lock loss interrupt handler */ | ||
| 92 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) | ||
| 93 | { | ||
| 94 | struct regmap *regmap = spdif_priv->regmap; | ||
| 95 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 96 | u32 locked; | ||
| 97 | |||
| 98 | regmap_read(regmap, REG_SPDIF_SRPC, &locked); | ||
| 99 | locked &= SRPC_DPLL_LOCKED; | ||
| 100 | |||
| 101 | dev_dbg(&pdev->dev, "isr: Rx dpll %s \n", | ||
| 102 | locked ? "locked" : "loss lock"); | ||
| 103 | |||
| 104 | spdif_priv->dpll_locked = locked ? true : false; | ||
| 105 | } | ||
| 106 | |||
| 107 | /* Receiver found illegal symbol interrupt handler */ | ||
| 108 | static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv) | ||
| 109 | { | ||
| 110 | struct regmap *regmap = spdif_priv->regmap; | ||
| 111 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 112 | |||
| 113 | dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n"); | ||
| 114 | |||
| 115 | if (!spdif_priv->dpll_locked) { | ||
| 116 | /* DPLL unlocked seems no audio stream */ | ||
| 117 | regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | /* U/Q Channel receive register full */ | ||
| 122 | static void spdif_irq_uqrx_full(struct fsl_spdif_priv *spdif_priv, char name) | ||
| 123 | { | ||
| 124 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 125 | struct regmap *regmap = spdif_priv->regmap; | ||
| 126 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 127 | u32 *pos, size, val, reg; | ||
| 128 | |||
| 129 | switch (name) { | ||
| 130 | case 'U': | ||
| 131 | pos = &ctrl->upos; | ||
| 132 | size = SPDIF_UBITS_SIZE; | ||
| 133 | reg = REG_SPDIF_SRU; | ||
| 134 | break; | ||
| 135 | case 'Q': | ||
| 136 | pos = &ctrl->qpos; | ||
| 137 | size = SPDIF_QSUB_SIZE; | ||
| 138 | reg = REG_SPDIF_SRQ; | ||
| 139 | break; | ||
| 140 | default: | ||
| 141 | dev_err(&pdev->dev, "unsupported channel name\n"); | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | |||
| 145 | dev_dbg(&pdev->dev, "isr: %c Channel receive register full\n", name); | ||
| 146 | |||
| 147 | if (*pos >= size * 2) { | ||
| 148 | *pos = 0; | ||
| 149 | } else if (unlikely((*pos % size) + 3 > size)) { | ||
| 150 | dev_err(&pdev->dev, "User bit receivce buffer overflow\n"); | ||
| 151 | return; | ||
| 152 | } | ||
| 153 | |||
| 154 | regmap_read(regmap, reg, &val); | ||
| 155 | ctrl->subcode[*pos++] = val >> 16; | ||
| 156 | ctrl->subcode[*pos++] = val >> 8; | ||
| 157 | ctrl->subcode[*pos++] = val; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* U/Q Channel sync found */ | ||
| 161 | static void spdif_irq_uq_sync(struct fsl_spdif_priv *spdif_priv) | ||
| 162 | { | ||
| 163 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 164 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 165 | |||
| 166 | dev_dbg(&pdev->dev, "isr: U/Q Channel sync found\n"); | ||
| 167 | |||
| 168 | /* U/Q buffer reset */ | ||
| 169 | if (ctrl->qpos == 0) | ||
| 170 | return; | ||
| 171 | |||
| 172 | /* Set ready to this buffer */ | ||
| 173 | ctrl->ready_buf = (ctrl->qpos - 1) / SPDIF_QSUB_SIZE + 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* U/Q Channel framing error */ | ||
| 177 | static void spdif_irq_uq_err(struct fsl_spdif_priv *spdif_priv) | ||
| 178 | { | ||
| 179 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 180 | struct regmap *regmap = spdif_priv->regmap; | ||
| 181 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 182 | u32 val; | ||
| 183 | |||
| 184 | dev_dbg(&pdev->dev, "isr: U/Q Channel framing error\n"); | ||
| 185 | |||
| 186 | /* Read U/Q data to clear the irq and do buffer reset */ | ||
| 187 | regmap_read(regmap, REG_SPDIF_SRU, &val); | ||
| 188 | regmap_read(regmap, REG_SPDIF_SRQ, &val); | ||
| 189 | |||
| 190 | /* Drop this U/Q buffer */ | ||
| 191 | ctrl->ready_buf = 0; | ||
| 192 | ctrl->upos = 0; | ||
| 193 | ctrl->qpos = 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Get spdif interrupt status and clear the interrupt */ | ||
| 197 | static u32 spdif_intr_status_clear(struct fsl_spdif_priv *spdif_priv) | ||
| 198 | { | ||
| 199 | struct regmap *regmap = spdif_priv->regmap; | ||
| 200 | u32 val, val2; | ||
| 201 | |||
| 202 | regmap_read(regmap, REG_SPDIF_SIS, &val); | ||
| 203 | regmap_read(regmap, REG_SPDIF_SIE, &val2); | ||
| 204 | |||
| 205 | regmap_write(regmap, REG_SPDIF_SIC, val & val2); | ||
| 206 | |||
| 207 | return val; | ||
| 208 | } | ||
| 209 | |||
| 210 | static irqreturn_t spdif_isr(int irq, void *devid) | ||
| 211 | { | ||
| 212 | struct fsl_spdif_priv *spdif_priv = (struct fsl_spdif_priv *)devid; | ||
| 213 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 214 | u32 sis; | ||
| 215 | |||
| 216 | sis = spdif_intr_status_clear(spdif_priv); | ||
| 217 | |||
| 218 | if (sis & INT_DPLL_LOCKED) | ||
| 219 | spdif_irq_dpll_lock(spdif_priv); | ||
| 220 | |||
| 221 | if (sis & INT_TXFIFO_UNOV) | ||
| 222 | dev_dbg(&pdev->dev, "isr: Tx FIFO under/overrun\n"); | ||
| 223 | |||
| 224 | if (sis & INT_TXFIFO_RESYNC) | ||
| 225 | dev_dbg(&pdev->dev, "isr: Tx FIFO resync\n"); | ||
| 226 | |||
| 227 | if (sis & INT_CNEW) | ||
| 228 | dev_dbg(&pdev->dev, "isr: cstatus new\n"); | ||
| 229 | |||
| 230 | if (sis & INT_VAL_NOGOOD) | ||
| 231 | dev_dbg(&pdev->dev, "isr: validity flag no good\n"); | ||
| 232 | |||
| 233 | if (sis & INT_SYM_ERR) | ||
| 234 | spdif_irq_sym_error(spdif_priv); | ||
| 235 | |||
| 236 | if (sis & INT_BIT_ERR) | ||
| 237 | dev_dbg(&pdev->dev, "isr: receiver found parity bit error\n"); | ||
| 238 | |||
| 239 | if (sis & INT_URX_FUL) | ||
| 240 | spdif_irq_uqrx_full(spdif_priv, 'U'); | ||
| 241 | |||
| 242 | if (sis & INT_URX_OV) | ||
| 243 | dev_dbg(&pdev->dev, "isr: U Channel receive register overrun\n"); | ||
| 244 | |||
| 245 | if (sis & INT_QRX_FUL) | ||
| 246 | spdif_irq_uqrx_full(spdif_priv, 'Q'); | ||
| 247 | |||
| 248 | if (sis & INT_QRX_OV) | ||
| 249 | dev_dbg(&pdev->dev, "isr: Q Channel receive register overrun\n"); | ||
| 250 | |||
| 251 | if (sis & INT_UQ_SYNC) | ||
| 252 | spdif_irq_uq_sync(spdif_priv); | ||
| 253 | |||
| 254 | if (sis & INT_UQ_ERR) | ||
| 255 | spdif_irq_uq_err(spdif_priv); | ||
| 256 | |||
| 257 | if (sis & INT_RXFIFO_UNOV) | ||
| 258 | dev_dbg(&pdev->dev, "isr: Rx FIFO under/overrun\n"); | ||
| 259 | |||
| 260 | if (sis & INT_RXFIFO_RESYNC) | ||
| 261 | dev_dbg(&pdev->dev, "isr: Rx FIFO resync\n"); | ||
| 262 | |||
| 263 | if (sis & INT_LOSS_LOCK) | ||
| 264 | spdif_irq_dpll_lock(spdif_priv); | ||
| 265 | |||
| 266 | /* FIXME: Write Tx FIFO to clear TxEm */ | ||
| 267 | if (sis & INT_TX_EM) | ||
| 268 | dev_dbg(&pdev->dev, "isr: Tx FIFO empty\n"); | ||
| 269 | |||
| 270 | /* FIXME: Read Rx FIFO to clear RxFIFOFul */ | ||
| 271 | if (sis & INT_RXFIFO_FUL) | ||
| 272 | dev_dbg(&pdev->dev, "isr: Rx FIFO full\n"); | ||
| 273 | |||
| 274 | return IRQ_HANDLED; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int spdif_softreset(struct fsl_spdif_priv *spdif_priv) | ||
| 278 | { | ||
| 279 | struct regmap *regmap = spdif_priv->regmap; | ||
| 280 | u32 val, cycle = 1000; | ||
| 281 | |||
| 282 | regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET); | ||
| 283 | |||
| 284 | /* | ||
| 285 | * RESET bit would be cleared after finishing its reset procedure, | ||
| 286 | * which typically lasts 8 cycles. 1000 cycles will keep it safe. | ||
| 287 | */ | ||
| 288 | do { | ||
| 289 | regmap_read(regmap, REG_SPDIF_SCR, &val); | ||
| 290 | } while ((val & SCR_SOFT_RESET) && cycle--); | ||
| 291 | |||
| 292 | if (cycle) | ||
| 293 | return 0; | ||
| 294 | else | ||
| 295 | return -EBUSY; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void spdif_set_cstatus(struct spdif_mixer_control *ctrl, | ||
| 299 | u8 mask, u8 cstatus) | ||
| 300 | { | ||
| 301 | ctrl->ch_status[3] &= ~mask; | ||
| 302 | ctrl->ch_status[3] |= cstatus & mask; | ||
| 303 | } | ||
| 304 | |||
| 305 | static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv) | ||
| 306 | { | ||
| 307 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 308 | struct regmap *regmap = spdif_priv->regmap; | ||
| 309 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 310 | u32 ch_status; | ||
| 311 | |||
| 312 | ch_status = (bitrev8(ctrl->ch_status[0]) << 16) | | ||
| 313 | (bitrev8(ctrl->ch_status[1]) << 8) | | ||
| 314 | bitrev8(ctrl->ch_status[2]); | ||
| 315 | regmap_write(regmap, REG_SPDIF_STCSCH, ch_status); | ||
| 316 | |||
| 317 | dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status); | ||
| 318 | |||
| 319 | ch_status = bitrev8(ctrl->ch_status[3]) << 16; | ||
| 320 | regmap_write(regmap, REG_SPDIF_STCSCL, ch_status); | ||
| 321 | |||
| 322 | dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status); | ||
| 323 | } | ||
| 324 | |||
| 325 | /* Set SPDIF PhaseConfig register for rx clock */ | ||
| 326 | static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv, | ||
| 327 | enum spdif_gainsel gainsel, int dpll_locked) | ||
| 328 | { | ||
| 329 | struct regmap *regmap = spdif_priv->regmap; | ||
| 330 | u8 clksrc = spdif_priv->rxclk_src; | ||
| 331 | |||
| 332 | if (clksrc >= SRPC_CLKSRC_MAX || gainsel >= GAINSEL_MULTI_MAX) | ||
| 333 | return -EINVAL; | ||
| 334 | |||
| 335 | regmap_update_bits(regmap, REG_SPDIF_SRPC, | ||
| 336 | SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK, | ||
| 337 | SRPC_CLKSRC_SEL_SET(clksrc) | SRPC_GAINSEL_SET(gainsel)); | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | static int spdif_set_sample_rate(struct snd_pcm_substream *substream, | ||
| 343 | int sample_rate) | ||
| 344 | { | ||
| 345 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 346 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 347 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 348 | struct regmap *regmap = spdif_priv->regmap; | ||
| 349 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 350 | unsigned long csfs = 0; | ||
| 351 | u32 stc, mask, rate; | ||
| 352 | u8 clk, div; | ||
| 353 | int ret; | ||
| 354 | |||
| 355 | switch (sample_rate) { | ||
| 356 | case 32000: | ||
| 357 | rate = SPDIF_TXRATE_32000; | ||
| 358 | csfs = IEC958_AES3_CON_FS_32000; | ||
| 359 | break; | ||
| 360 | case 44100: | ||
| 361 | rate = SPDIF_TXRATE_44100; | ||
| 362 | csfs = IEC958_AES3_CON_FS_44100; | ||
| 363 | break; | ||
| 364 | case 48000: | ||
| 365 | rate = SPDIF_TXRATE_48000; | ||
| 366 | csfs = IEC958_AES3_CON_FS_48000; | ||
| 367 | break; | ||
| 368 | default: | ||
| 369 | dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate); | ||
| 370 | return -EINVAL; | ||
| 371 | } | ||
| 372 | |||
| 373 | clk = spdif_priv->txclk_src[rate]; | ||
| 374 | if (clk >= STC_TXCLK_SRC_MAX) { | ||
| 375 | dev_err(&pdev->dev, "tx clock source is out of range\n"); | ||
| 376 | return -EINVAL; | ||
| 377 | } | ||
| 378 | |||
| 379 | div = spdif_priv->txclk_div[rate]; | ||
| 380 | if (div == 0) { | ||
| 381 | dev_err(&pdev->dev, "the divisor can't be zero\n"); | ||
| 382 | return -EINVAL; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* | ||
| 386 | * The S/PDIF block needs a clock of 64 * fs * div. The S/PDIF block | ||
| 387 | * will divide by (div). So request 64 * fs * (div+1) which will | ||
| 388 | * get rounded. | ||
| 389 | */ | ||
| 390 | ret = clk_set_rate(spdif_priv->txclk[rate], 64 * sample_rate * (div + 1)); | ||
| 391 | if (ret) { | ||
| 392 | dev_err(&pdev->dev, "failed to set tx clock rate\n"); | ||
| 393 | return ret; | ||
| 394 | } | ||
| 395 | |||
| 396 | dev_dbg(&pdev->dev, "expected clock rate = %d\n", | ||
| 397 | (64 * sample_rate * div)); | ||
| 398 | dev_dbg(&pdev->dev, "actual clock rate = %ld\n", | ||
| 399 | clk_get_rate(spdif_priv->txclk[rate])); | ||
| 400 | |||
| 401 | /* set fs field in consumer channel status */ | ||
| 402 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); | ||
| 403 | |||
| 404 | /* select clock source and divisor */ | ||
| 405 | stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DIV(div); | ||
| 406 | mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DIV_MASK; | ||
| 407 | regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); | ||
| 408 | |||
| 409 | dev_dbg(&pdev->dev, "set sample rate to %d\n", sample_rate); | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | int fsl_spdif_startup(struct snd_pcm_substream *substream, | ||
| 415 | struct snd_soc_dai *cpu_dai) | ||
| 416 | { | ||
| 417 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 418 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 419 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 420 | struct regmap *regmap = spdif_priv->regmap; | ||
| 421 | u32 scr, mask, i; | ||
| 422 | int ret; | ||
| 423 | |||
| 424 | /* Reset module and interrupts only for first initialization */ | ||
| 425 | if (!cpu_dai->active) { | ||
| 426 | ret = spdif_softreset(spdif_priv); | ||
| 427 | if (ret) { | ||
| 428 | dev_err(&pdev->dev, "failed to soft reset\n"); | ||
| 429 | return ret; | ||
| 430 | } | ||
| 431 | |||
| 432 | /* Disable all the interrupts */ | ||
| 433 | regmap_update_bits(regmap, REG_SPDIF_SIE, 0xffffff, 0); | ||
| 434 | } | ||
| 435 | |||
| 436 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 437 | scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL | | ||
| 438 | SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP | | ||
| 439 | SCR_TXFIFO_FSEL_IF8; | ||
| 440 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | | ||
| 441 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | | ||
| 442 | SCR_TXFIFO_FSEL_MASK; | ||
| 443 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) | ||
| 444 | clk_prepare_enable(spdif_priv->txclk[i]); | ||
| 445 | } else { | ||
| 446 | scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; | ||
| 447 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| | ||
| 448 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; | ||
| 449 | clk_prepare_enable(spdif_priv->rxclk); | ||
| 450 | } | ||
| 451 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); | ||
| 452 | |||
| 453 | /* Power up SPDIF module */ | ||
| 454 | regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0); | ||
| 455 | |||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, | ||
| 460 | struct snd_soc_dai *cpu_dai) | ||
| 461 | { | ||
| 462 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 463 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 464 | struct regmap *regmap = spdif_priv->regmap; | ||
| 465 | u32 scr, mask, i; | ||
| 466 | |||
| 467 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 468 | scr = 0; | ||
| 469 | mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | | ||
| 470 | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | | ||
| 471 | SCR_TXFIFO_FSEL_MASK; | ||
| 472 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) | ||
| 473 | clk_disable_unprepare(spdif_priv->txclk[i]); | ||
| 474 | } else { | ||
| 475 | scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO; | ||
| 476 | mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| | ||
| 477 | SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; | ||
| 478 | clk_disable_unprepare(spdif_priv->rxclk); | ||
| 479 | } | ||
| 480 | regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); | ||
| 481 | |||
| 482 | /* Power down SPDIF module only if tx&rx are both inactive */ | ||
| 483 | if (!cpu_dai->active) { | ||
| 484 | spdif_intr_status_clear(spdif_priv); | ||
| 485 | regmap_update_bits(regmap, REG_SPDIF_SCR, | ||
| 486 | SCR_LOW_POWER, SCR_LOW_POWER); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, | ||
| 491 | struct snd_pcm_hw_params *params, | ||
| 492 | struct snd_soc_dai *dai) | ||
| 493 | { | ||
| 494 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 495 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 496 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 497 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 498 | u32 sample_rate = params_rate(params); | ||
| 499 | int ret = 0; | ||
| 500 | |||
| 501 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 502 | ret = spdif_set_sample_rate(substream, sample_rate); | ||
| 503 | if (ret) { | ||
| 504 | dev_err(&pdev->dev, "%s: set sample rate failed: %d\n", | ||
| 505 | __func__, sample_rate); | ||
| 506 | return ret; | ||
| 507 | } | ||
| 508 | spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK, | ||
| 509 | IEC958_AES3_CON_CLOCK_1000PPM); | ||
| 510 | spdif_write_channel_status(spdif_priv); | ||
| 511 | } else { | ||
| 512 | /* Setup rx clock source */ | ||
| 513 | ret = spdif_set_rx_clksrc(spdif_priv, SPDIF_DEFAULT_GAINSEL, 1); | ||
| 514 | } | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int fsl_spdif_trigger(struct snd_pcm_substream *substream, | ||
| 520 | int cmd, struct snd_soc_dai *dai) | ||
| 521 | { | ||
| 522 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 523 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 524 | struct regmap *regmap = spdif_priv->regmap; | ||
| 525 | int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
| 526 | u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE; | ||
| 527 | u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;; | ||
| 528 | |||
| 529 | switch (cmd) { | ||
| 530 | case SNDRV_PCM_TRIGGER_START: | ||
| 531 | case SNDRV_PCM_TRIGGER_RESUME: | ||
| 532 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
| 533 | regmap_update_bits(regmap, REG_SPDIF_SIE, intr, intr); | ||
| 534 | regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, dmaen); | ||
| 535 | break; | ||
| 536 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 537 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
| 538 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
| 539 | regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0); | ||
| 540 | regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0); | ||
| 541 | break; | ||
| 542 | default: | ||
| 543 | return -EINVAL; | ||
| 544 | } | ||
| 545 | |||
| 546 | return 0; | ||
| 547 | } | ||
| 548 | |||
| 549 | struct snd_soc_dai_ops fsl_spdif_dai_ops = { | ||
| 550 | .startup = fsl_spdif_startup, | ||
| 551 | .hw_params = fsl_spdif_hw_params, | ||
| 552 | .trigger = fsl_spdif_trigger, | ||
| 553 | .shutdown = fsl_spdif_shutdown, | ||
| 554 | }; | ||
| 555 | |||
| 556 | |||
| 557 | /* | ||
| 558 | * ============================================ | ||
| 559 | * FSL SPDIF IEC958 controller(mixer) functions | ||
| 560 | * | ||
| 561 | * Channel status get/put control | ||
| 562 | * User bit value get/put control | ||
| 563 | * Valid bit value get control | ||
| 564 | * DPLL lock status get control | ||
| 565 | * User bit sync mode selection control | ||
| 566 | * ============================================ | ||
| 567 | */ | ||
| 568 | |||
| 569 | static int fsl_spdif_info(struct snd_kcontrol *kcontrol, | ||
| 570 | struct snd_ctl_elem_info *uinfo) | ||
| 571 | { | ||
| 572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
| 573 | uinfo->count = 1; | ||
| 574 | |||
| 575 | return 0; | ||
| 576 | } | ||
| 577 | |||
| 578 | static int fsl_spdif_pb_get(struct snd_kcontrol *kcontrol, | ||
| 579 | struct snd_ctl_elem_value *uvalue) | ||
| 580 | { | ||
| 581 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 582 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 583 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 584 | |||
| 585 | uvalue->value.iec958.status[0] = ctrl->ch_status[0]; | ||
| 586 | uvalue->value.iec958.status[1] = ctrl->ch_status[1]; | ||
| 587 | uvalue->value.iec958.status[2] = ctrl->ch_status[2]; | ||
| 588 | uvalue->value.iec958.status[3] = ctrl->ch_status[3]; | ||
| 589 | |||
| 590 | return 0; | ||
| 591 | } | ||
| 592 | |||
| 593 | static int fsl_spdif_pb_put(struct snd_kcontrol *kcontrol, | ||
| 594 | struct snd_ctl_elem_value *uvalue) | ||
| 595 | { | ||
| 596 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 597 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 598 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 599 | |||
| 600 | ctrl->ch_status[0] = uvalue->value.iec958.status[0]; | ||
| 601 | ctrl->ch_status[1] = uvalue->value.iec958.status[1]; | ||
| 602 | ctrl->ch_status[2] = uvalue->value.iec958.status[2]; | ||
| 603 | ctrl->ch_status[3] = uvalue->value.iec958.status[3]; | ||
| 604 | |||
| 605 | spdif_write_channel_status(spdif_priv); | ||
| 606 | |||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | /* Get channel status from SPDIF_RX_CCHAN register */ | ||
| 611 | static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol, | ||
| 612 | struct snd_ctl_elem_value *ucontrol) | ||
| 613 | { | ||
| 614 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 615 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 616 | struct regmap *regmap = spdif_priv->regmap; | ||
| 617 | u32 cstatus, val; | ||
| 618 | |||
| 619 | regmap_read(regmap, REG_SPDIF_SIS, &val); | ||
| 620 | if (!(val & INT_CNEW)) { | ||
| 621 | return -EAGAIN; | ||
| 622 | } | ||
| 623 | |||
| 624 | regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus); | ||
| 625 | ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF; | ||
| 626 | ucontrol->value.iec958.status[1] = (cstatus >> 8) & 0xFF; | ||
| 627 | ucontrol->value.iec958.status[2] = cstatus & 0xFF; | ||
| 628 | |||
| 629 | regmap_read(regmap, REG_SPDIF_SRCSL, &cstatus); | ||
| 630 | ucontrol->value.iec958.status[3] = (cstatus >> 16) & 0xFF; | ||
| 631 | ucontrol->value.iec958.status[4] = (cstatus >> 8) & 0xFF; | ||
| 632 | ucontrol->value.iec958.status[5] = cstatus & 0xFF; | ||
| 633 | |||
| 634 | /* Clear intr */ | ||
| 635 | regmap_write(regmap, REG_SPDIF_SIC, INT_CNEW); | ||
| 636 | |||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | |||
| 640 | /* | ||
| 641 | * Get User bits (subcode) from chip value which readed out | ||
| 642 | * in UChannel register. | ||
| 643 | */ | ||
| 644 | static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol, | ||
| 645 | struct snd_ctl_elem_value *ucontrol) | ||
| 646 | { | ||
| 647 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 648 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 649 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 650 | unsigned long flags; | ||
| 651 | int ret = 0; | ||
| 652 | |||
| 653 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | ||
| 654 | if (ctrl->ready_buf) { | ||
| 655 | int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE; | ||
| 656 | memcpy(&ucontrol->value.iec958.subcode[0], | ||
| 657 | &ctrl->subcode[idx], SPDIF_UBITS_SIZE); | ||
| 658 | } else { | ||
| 659 | ret = -EAGAIN; | ||
| 660 | } | ||
| 661 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | ||
| 662 | |||
| 663 | return ret; | ||
| 664 | } | ||
| 665 | |||
| 666 | /* Q-subcode infomation. The byte size is SPDIF_UBITS_SIZE/8 */ | ||
| 667 | static int fsl_spdif_qinfo(struct snd_kcontrol *kcontrol, | ||
| 668 | struct snd_ctl_elem_info *uinfo) | ||
| 669 | { | ||
| 670 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
| 671 | uinfo->count = SPDIF_QSUB_SIZE; | ||
| 672 | |||
| 673 | return 0; | ||
| 674 | } | ||
| 675 | |||
| 676 | /* Get Q subcode from chip value which readed out in QChannel register */ | ||
| 677 | static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, | ||
| 678 | struct snd_ctl_elem_value *ucontrol) | ||
| 679 | { | ||
| 680 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 681 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 682 | struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; | ||
| 683 | unsigned long flags; | ||
| 684 | int ret = 0; | ||
| 685 | |||
| 686 | spin_lock_irqsave(&ctrl->ctl_lock, flags); | ||
| 687 | if (ctrl->ready_buf) { | ||
| 688 | int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE; | ||
| 689 | memcpy(&ucontrol->value.bytes.data[0], | ||
| 690 | &ctrl->qsub[idx], SPDIF_QSUB_SIZE); | ||
| 691 | } else { | ||
| 692 | ret = -EAGAIN; | ||
| 693 | } | ||
| 694 | spin_unlock_irqrestore(&ctrl->ctl_lock, flags); | ||
| 695 | |||
| 696 | return ret; | ||
| 697 | } | ||
| 698 | |||
| 699 | /* Valid bit infomation */ | ||
| 700 | static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, | ||
| 701 | struct snd_ctl_elem_info *uinfo) | ||
| 702 | { | ||
| 703 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
| 704 | uinfo->count = 1; | ||
| 705 | uinfo->value.integer.min = 0; | ||
| 706 | uinfo->value.integer.max = 1; | ||
| 707 | |||
| 708 | return 0; | ||
| 709 | } | ||
| 710 | |||
| 711 | /* Get valid good bit from interrupt status register */ | ||
| 712 | static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, | ||
| 713 | struct snd_ctl_elem_value *ucontrol) | ||
| 714 | { | ||
| 715 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 716 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 717 | struct regmap *regmap = spdif_priv->regmap; | ||
| 718 | u32 val; | ||
| 719 | |||
| 720 | val = regmap_read(regmap, REG_SPDIF_SIS, &val); | ||
| 721 | ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0; | ||
| 722 | regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD); | ||
| 723 | |||
| 724 | return 0; | ||
| 725 | } | ||
| 726 | |||
| 727 | /* DPLL lock infomation */ | ||
| 728 | static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, | ||
| 729 | struct snd_ctl_elem_info *uinfo) | ||
| 730 | { | ||
| 731 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 732 | uinfo->count = 1; | ||
| 733 | uinfo->value.integer.min = 16000; | ||
| 734 | uinfo->value.integer.max = 96000; | ||
| 735 | |||
| 736 | return 0; | ||
| 737 | } | ||
| 738 | |||
| 739 | static u32 gainsel_multi[GAINSEL_MULTI_MAX] = { | ||
| 740 | 24, 16, 12, 8, 6, 4, 3, | ||
| 741 | }; | ||
| 742 | |||
| 743 | /* Get RX data clock rate given the SPDIF bus_clk */ | ||
| 744 | static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv, | ||
| 745 | enum spdif_gainsel gainsel) | ||
| 746 | { | ||
| 747 | struct regmap *regmap = spdif_priv->regmap; | ||
| 748 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 749 | u64 tmpval64, busclk_freq = 0; | ||
| 750 | u32 freqmeas, phaseconf; | ||
| 751 | u8 clksrc; | ||
| 752 | |||
| 753 | regmap_read(regmap, REG_SPDIF_SRFM, &freqmeas); | ||
| 754 | regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf); | ||
| 755 | |||
| 756 | clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf; | ||
| 757 | if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) { | ||
| 758 | /* Get bus clock from system */ | ||
| 759 | busclk_freq = clk_get_rate(spdif_priv->rxclk); | ||
| 760 | } | ||
| 761 | |||
| 762 | /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */ | ||
| 763 | tmpval64 = (u64) busclk_freq * freqmeas; | ||
| 764 | do_div(tmpval64, gainsel_multi[gainsel] * 1024); | ||
| 765 | do_div(tmpval64, 128 * 1024); | ||
| 766 | |||
| 767 | dev_dbg(&pdev->dev, "FreqMeas: %d\n", freqmeas); | ||
| 768 | dev_dbg(&pdev->dev, "BusclkFreq: %lld\n", busclk_freq); | ||
| 769 | dev_dbg(&pdev->dev, "RxRate: %lld\n", tmpval64); | ||
| 770 | |||
| 771 | return (int)tmpval64; | ||
| 772 | } | ||
| 773 | |||
| 774 | /* | ||
| 775 | * Get DPLL lock or not info from stable interrupt status register. | ||
| 776 | * User application must use this control to get locked, | ||
| 777 | * then can do next PCM operation | ||
| 778 | */ | ||
| 779 | static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol, | ||
| 780 | struct snd_ctl_elem_value *ucontrol) | ||
| 781 | { | ||
| 782 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 783 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 784 | int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL); | ||
| 785 | |||
| 786 | if (spdif_priv->dpll_locked) | ||
| 787 | ucontrol->value.integer.value[0] = rate; | ||
| 788 | else | ||
| 789 | ucontrol->value.integer.value[0] = 0; | ||
| 790 | |||
| 791 | return 0; | ||
| 792 | } | ||
| 793 | |||
| 794 | /* User bit sync mode info */ | ||
| 795 | static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol, | ||
| 796 | struct snd_ctl_elem_info *uinfo) | ||
| 797 | { | ||
| 798 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
| 799 | uinfo->count = 1; | ||
| 800 | uinfo->value.integer.min = 0; | ||
| 801 | uinfo->value.integer.max = 1; | ||
| 802 | |||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | |||
| 806 | /* | ||
| 807 | * User bit sync mode: | ||
| 808 | * 1 CD User channel subcode | ||
| 809 | * 0 Non-CD data | ||
| 810 | */ | ||
| 811 | static int fsl_spdif_usync_get(struct snd_kcontrol *kcontrol, | ||
| 812 | struct snd_ctl_elem_value *ucontrol) | ||
| 813 | { | ||
| 814 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 815 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 816 | struct regmap *regmap = spdif_priv->regmap; | ||
| 817 | u32 val; | ||
| 818 | |||
| 819 | regmap_read(regmap, REG_SPDIF_SRCD, &val); | ||
| 820 | ucontrol->value.integer.value[0] = (val & SRCD_CD_USER) != 0; | ||
| 821 | |||
| 822 | return 0; | ||
| 823 | } | ||
| 824 | |||
| 825 | /* | ||
| 826 | * User bit sync mode: | ||
| 827 | * 1 CD User channel subcode | ||
| 828 | * 0 Non-CD data | ||
| 829 | */ | ||
| 830 | static int fsl_spdif_usync_put(struct snd_kcontrol *kcontrol, | ||
| 831 | struct snd_ctl_elem_value *ucontrol) | ||
| 832 | { | ||
| 833 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
| 834 | struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
| 835 | struct regmap *regmap = spdif_priv->regmap; | ||
| 836 | u32 val = ucontrol->value.integer.value[0] << SRCD_CD_USER_OFFSET; | ||
| 837 | |||
| 838 | regmap_update_bits(regmap, REG_SPDIF_SRCD, SRCD_CD_USER, val); | ||
| 839 | |||
| 840 | return 0; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* FSL SPDIF IEC958 controller defines */ | ||
| 844 | static struct snd_kcontrol_new fsl_spdif_ctrls[] = { | ||
| 845 | /* Status cchanel controller */ | ||
| 846 | { | ||
| 847 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 848 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), | ||
| 849 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 850 | SNDRV_CTL_ELEM_ACCESS_WRITE | | ||
| 851 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 852 | .info = fsl_spdif_info, | ||
| 853 | .get = fsl_spdif_pb_get, | ||
| 854 | .put = fsl_spdif_pb_put, | ||
| 855 | }, | ||
| 856 | { | ||
| 857 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 858 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | ||
| 859 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 860 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 861 | .info = fsl_spdif_info, | ||
| 862 | .get = fsl_spdif_capture_get, | ||
| 863 | }, | ||
| 864 | /* User bits controller */ | ||
| 865 | { | ||
| 866 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 867 | .name = "IEC958 Subcode Capture Default", | ||
| 868 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 869 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 870 | .info = fsl_spdif_info, | ||
| 871 | .get = fsl_spdif_subcode_get, | ||
| 872 | }, | ||
| 873 | { | ||
| 874 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 875 | .name = "IEC958 Q-subcode Capture Default", | ||
| 876 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 877 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 878 | .info = fsl_spdif_qinfo, | ||
| 879 | .get = fsl_spdif_qget, | ||
| 880 | }, | ||
| 881 | /* Valid bit error controller */ | ||
| 882 | { | ||
| 883 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 884 | .name = "IEC958 V-Bit Errors", | ||
| 885 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 886 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 887 | .info = fsl_spdif_vbit_info, | ||
| 888 | .get = fsl_spdif_vbit_get, | ||
| 889 | }, | ||
| 890 | /* DPLL lock info get controller */ | ||
| 891 | { | ||
| 892 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 893 | .name = "RX Sample Rate", | ||
| 894 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 895 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 896 | .info = fsl_spdif_rxrate_info, | ||
| 897 | .get = fsl_spdif_rxrate_get, | ||
| 898 | }, | ||
| 899 | /* User bit sync mode set/get controller */ | ||
| 900 | { | ||
| 901 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 902 | .name = "IEC958 USyncMode CDText", | ||
| 903 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 904 | SNDRV_CTL_ELEM_ACCESS_WRITE | | ||
| 905 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
| 906 | .info = fsl_spdif_usync_info, | ||
| 907 | .get = fsl_spdif_usync_get, | ||
| 908 | .put = fsl_spdif_usync_put, | ||
| 909 | }, | ||
| 910 | }; | ||
| 911 | |||
| 912 | static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) | ||
| 913 | { | ||
| 914 | struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); | ||
| 915 | |||
| 916 | dai->playback_dma_data = &spdif_private->dma_params_tx; | ||
| 917 | dai->capture_dma_data = &spdif_private->dma_params_rx; | ||
| 918 | |||
| 919 | snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); | ||
| 920 | |||
| 921 | return 0; | ||
| 922 | } | ||
| 923 | |||
| 924 | struct snd_soc_dai_driver fsl_spdif_dai = { | ||
| 925 | .probe = &fsl_spdif_dai_probe, | ||
| 926 | .playback = { | ||
| 927 | .channels_min = 2, | ||
| 928 | .channels_max = 2, | ||
| 929 | .rates = FSL_SPDIF_RATES_PLAYBACK, | ||
| 930 | .formats = FSL_SPDIF_FORMATS_PLAYBACK, | ||
| 931 | }, | ||
| 932 | .capture = { | ||
| 933 | .channels_min = 2, | ||
| 934 | .channels_max = 2, | ||
| 935 | .rates = FSL_SPDIF_RATES_CAPTURE, | ||
| 936 | .formats = FSL_SPDIF_FORMATS_CAPTURE, | ||
| 937 | }, | ||
| 938 | .ops = &fsl_spdif_dai_ops, | ||
| 939 | }; | ||
| 940 | |||
| 941 | static const struct snd_soc_component_driver fsl_spdif_component = { | ||
| 942 | .name = "fsl-spdif", | ||
| 943 | }; | ||
| 944 | |||
| 945 | /* | ||
| 946 | * ================ | ||
| 947 | * FSL SPDIF REGMAP | ||
| 948 | * ================ | ||
| 949 | */ | ||
| 950 | |||
| 951 | static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) | ||
| 952 | { | ||
| 953 | switch (reg) { | ||
| 954 | case REG_SPDIF_SCR: | ||
| 955 | case REG_SPDIF_SRCD: | ||
| 956 | case REG_SPDIF_SRPC: | ||
| 957 | case REG_SPDIF_SIE: | ||
| 958 | case REG_SPDIF_SIS: | ||
| 959 | case REG_SPDIF_SRL: | ||
| 960 | case REG_SPDIF_SRR: | ||
| 961 | case REG_SPDIF_SRCSH: | ||
| 962 | case REG_SPDIF_SRCSL: | ||
| 963 | case REG_SPDIF_SRU: | ||
| 964 | case REG_SPDIF_SRQ: | ||
| 965 | case REG_SPDIF_STCSCH: | ||
| 966 | case REG_SPDIF_STCSCL: | ||
| 967 | case REG_SPDIF_SRFM: | ||
| 968 | case REG_SPDIF_STC: | ||
| 969 | return true; | ||
| 970 | default: | ||
| 971 | return false; | ||
| 972 | }; | ||
| 973 | } | ||
| 974 | |||
| 975 | static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) | ||
| 976 | { | ||
| 977 | switch (reg) { | ||
| 978 | case REG_SPDIF_SCR: | ||
| 979 | case REG_SPDIF_SRCD: | ||
| 980 | case REG_SPDIF_SRPC: | ||
| 981 | case REG_SPDIF_SIE: | ||
| 982 | case REG_SPDIF_SIC: | ||
| 983 | case REG_SPDIF_STL: | ||
| 984 | case REG_SPDIF_STR: | ||
| 985 | case REG_SPDIF_STCSCH: | ||
| 986 | case REG_SPDIF_STCSCL: | ||
| 987 | case REG_SPDIF_STC: | ||
| 988 | return true; | ||
| 989 | default: | ||
| 990 | return false; | ||
| 991 | }; | ||
| 992 | } | ||
| 993 | |||
| 994 | static const struct regmap_config fsl_spdif_regmap_config = { | ||
| 995 | .reg_bits = 32, | ||
| 996 | .reg_stride = 4, | ||
| 997 | .val_bits = 32, | ||
| 998 | |||
| 999 | .max_register = REG_SPDIF_STC, | ||
| 1000 | .readable_reg = fsl_spdif_readable_reg, | ||
| 1001 | .writeable_reg = fsl_spdif_writeable_reg, | ||
| 1002 | }; | ||
| 1003 | |||
| 1004 | static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, | ||
| 1005 | struct clk *clk, u64 savesub, | ||
| 1006 | enum spdif_txrate index) | ||
| 1007 | { | ||
| 1008 | const u32 rate[] = { 32000, 44100, 48000 }; | ||
| 1009 | u64 rate_ideal, rate_actual, sub; | ||
| 1010 | u32 div, arate; | ||
| 1011 | |||
| 1012 | for (div = 1; div <= 128; div++) { | ||
| 1013 | rate_ideal = rate[index] * (div + 1) * 64; | ||
| 1014 | rate_actual = clk_round_rate(clk, rate_ideal); | ||
| 1015 | |||
| 1016 | arate = rate_actual / 64; | ||
| 1017 | arate /= div; | ||
| 1018 | |||
| 1019 | if (arate == rate[index]) { | ||
| 1020 | /* We are lucky */ | ||
| 1021 | savesub = 0; | ||
| 1022 | spdif_priv->txclk_div[index] = div; | ||
| 1023 | break; | ||
| 1024 | } else if (arate / rate[index] == 1) { | ||
| 1025 | /* A little bigger than expect */ | ||
| 1026 | sub = (arate - rate[index]) * 100000; | ||
| 1027 | do_div(sub, rate[index]); | ||
| 1028 | if (sub < savesub) { | ||
| 1029 | savesub = sub; | ||
| 1030 | spdif_priv->txclk_div[index] = div; | ||
| 1031 | } | ||
| 1032 | } else if (rate[index] / arate == 1) { | ||
| 1033 | /* A little smaller than expect */ | ||
| 1034 | sub = (rate[index] - arate) * 100000; | ||
| 1035 | do_div(sub, rate[index]); | ||
| 1036 | if (sub < savesub) { | ||
| 1037 | savesub = sub; | ||
| 1038 | spdif_priv->txclk_div[index] = div; | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | return savesub; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, | ||
| 1047 | enum spdif_txrate index) | ||
| 1048 | { | ||
| 1049 | const u32 rate[] = { 32000, 44100, 48000 }; | ||
| 1050 | struct platform_device *pdev = spdif_priv->pdev; | ||
| 1051 | struct device *dev = &pdev->dev; | ||
| 1052 | u64 savesub = 100000, ret; | ||
| 1053 | struct clk *clk; | ||
| 1054 | char tmp[16]; | ||
| 1055 | int i; | ||
| 1056 | |||
| 1057 | for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { | ||
| 1058 | sprintf(tmp, "rxtx%d", i); | ||
| 1059 | clk = devm_clk_get(&pdev->dev, tmp); | ||
| 1060 | if (IS_ERR(clk)) { | ||
| 1061 | dev_err(dev, "no rxtx%d clock in devicetree\n", i); | ||
| 1062 | return PTR_ERR(clk); | ||
| 1063 | } | ||
| 1064 | if (!clk_get_rate(clk)) | ||
| 1065 | continue; | ||
| 1066 | |||
| 1067 | ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index); | ||
| 1068 | if (savesub == ret) | ||
| 1069 | continue; | ||
| 1070 | |||
| 1071 | savesub = ret; | ||
| 1072 | spdif_priv->txclk[index] = clk; | ||
| 1073 | spdif_priv->txclk_src[index] = i; | ||
| 1074 | |||
| 1075 | /* To quick catch a divisor, we allow a 0.1% deviation */ | ||
| 1076 | if (savesub < 100) | ||
| 1077 | break; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate", | ||
| 1081 | spdif_priv->txclk_src[index], rate[index]); | ||
| 1082 | dev_dbg(&pdev->dev, "use divisor %d for %dHz sample rate", | ||
| 1083 | spdif_priv->txclk_div[index], rate[index]); | ||
| 1084 | |||
| 1085 | return 0; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | static int fsl_spdif_probe(struct platform_device *pdev) | ||
| 1089 | { | ||
| 1090 | struct device_node *np = pdev->dev.of_node; | ||
| 1091 | struct fsl_spdif_priv *spdif_priv; | ||
| 1092 | struct spdif_mixer_control *ctrl; | ||
| 1093 | struct resource *res; | ||
| 1094 | void __iomem *regs; | ||
| 1095 | int irq, ret, i; | ||
| 1096 | |||
| 1097 | if (!np) | ||
| 1098 | return -ENODEV; | ||
| 1099 | |||
| 1100 | spdif_priv = devm_kzalloc(&pdev->dev, | ||
| 1101 | sizeof(struct fsl_spdif_priv) + strlen(np->name) + 1, | ||
| 1102 | GFP_KERNEL); | ||
| 1103 | if (!spdif_priv) | ||
| 1104 | return -ENOMEM; | ||
| 1105 | |||
| 1106 | strcpy(spdif_priv->name, np->name); | ||
| 1107 | |||
| 1108 | spdif_priv->pdev = pdev; | ||
| 1109 | |||
| 1110 | /* Initialize this copy of the CPU DAI driver structure */ | ||
| 1111 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | ||
| 1112 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; | ||
| 1113 | |||
| 1114 | /* Get the addresses and IRQ */ | ||
| 1115 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1116 | if (IS_ERR(res)) { | ||
| 1117 | dev_err(&pdev->dev, "could not determine device resources\n"); | ||
| 1118 | return PTR_ERR(res); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
| 1122 | if (IS_ERR(regs)) { | ||
| 1123 | dev_err(&pdev->dev, "could not map device resources\n"); | ||
| 1124 | return PTR_ERR(regs); | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, | ||
| 1128 | "core", regs, &fsl_spdif_regmap_config); | ||
| 1129 | if (IS_ERR(spdif_priv->regmap)) { | ||
| 1130 | dev_err(&pdev->dev, "regmap init failed\n"); | ||
| 1131 | return PTR_ERR(spdif_priv->regmap); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | irq = platform_get_irq(pdev, 0); | ||
| 1135 | if (irq < 0) { | ||
| 1136 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
| 1137 | return irq; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, | ||
| 1141 | spdif_priv->name, spdif_priv); | ||
| 1142 | if (ret) { | ||
| 1143 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); | ||
| 1144 | return ret; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /* Select clock source for rx/tx clock */ | ||
| 1148 | spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1"); | ||
| 1149 | if (IS_ERR(spdif_priv->rxclk)) { | ||
| 1150 | dev_err(&pdev->dev, "no rxtx1 clock in devicetree\n"); | ||
| 1151 | return PTR_ERR(spdif_priv->rxclk); | ||
| 1152 | } | ||
| 1153 | spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC; | ||
| 1154 | |||
| 1155 | for (i = 0; i < SPDIF_TXRATE_MAX; i++) { | ||
| 1156 | ret = fsl_spdif_probe_txclk(spdif_priv, i); | ||
| 1157 | if (ret) | ||
| 1158 | return ret; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | /* Initial spinlock for control data */ | ||
| 1162 | ctrl = &spdif_priv->fsl_spdif_control; | ||
| 1163 | spin_lock_init(&ctrl->ctl_lock); | ||
| 1164 | |||
| 1165 | /* Init tx channel status default value */ | ||
| 1166 | ctrl->ch_status[0] = | ||
| 1167 | IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015; | ||
| 1168 | ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID; | ||
| 1169 | ctrl->ch_status[2] = 0x00; | ||
| 1170 | ctrl->ch_status[3] = | ||
| 1171 | IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM; | ||
| 1172 | |||
| 1173 | spdif_priv->dpll_locked = false; | ||
| 1174 | |||
| 1175 | spdif_priv->dma_params_tx.maxburst = FSL_SPDIF_TXFIFO_WML; | ||
| 1176 | spdif_priv->dma_params_rx.maxburst = FSL_SPDIF_RXFIFO_WML; | ||
| 1177 | spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL; | ||
| 1178 | spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL; | ||
| 1179 | |||
| 1180 | /* Register with ASoC */ | ||
| 1181 | dev_set_drvdata(&pdev->dev, spdif_priv); | ||
| 1182 | |||
| 1183 | ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component, | ||
| 1184 | &spdif_priv->cpu_dai_drv, 1); | ||
| 1185 | if (ret) { | ||
| 1186 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | ||
| 1187 | goto error_dev; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | ret = imx_pcm_dma_init(pdev); | ||
| 1191 | if (ret) { | ||
| 1192 | dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); | ||
| 1193 | goto error_component; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | return ret; | ||
| 1197 | |||
| 1198 | error_component: | ||
| 1199 | snd_soc_unregister_component(&pdev->dev); | ||
| 1200 | error_dev: | ||
| 1201 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 1202 | |||
| 1203 | return ret; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | static int fsl_spdif_remove(struct platform_device *pdev) | ||
| 1207 | { | ||
| 1208 | imx_pcm_dma_exit(pdev); | ||
| 1209 | snd_soc_unregister_component(&pdev->dev); | ||
| 1210 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 1211 | |||
| 1212 | return 0; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | static const struct of_device_id fsl_spdif_dt_ids[] = { | ||
| 1216 | { .compatible = "fsl,imx35-spdif", }, | ||
| 1217 | {} | ||
| 1218 | }; | ||
| 1219 | MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids); | ||
| 1220 | |||
| 1221 | static struct platform_driver fsl_spdif_driver = { | ||
| 1222 | .driver = { | ||
| 1223 | .name = "fsl-spdif-dai", | ||
| 1224 | .owner = THIS_MODULE, | ||
| 1225 | .of_match_table = fsl_spdif_dt_ids, | ||
| 1226 | }, | ||
| 1227 | .probe = fsl_spdif_probe, | ||
| 1228 | .remove = fsl_spdif_remove, | ||
| 1229 | }; | ||
| 1230 | |||
| 1231 | module_platform_driver(fsl_spdif_driver); | ||
| 1232 | |||
| 1233 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
| 1234 | MODULE_DESCRIPTION("Freescale S/PDIF CPU DAI Driver"); | ||
| 1235 | MODULE_LICENSE("GPL v2"); | ||
| 1236 | MODULE_ALIAS("platform:fsl-spdif-dai"); | ||
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h new file mode 100644 index 000000000000..b1266790d117 --- /dev/null +++ b/sound/soc/fsl/fsl_spdif.h | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | /* | ||
| 2 | * fsl_spdif.h - ALSA S/PDIF interface for the Freescale i.MX SoC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
| 5 | * | ||
| 6 | * Author: Nicolin Chen <b42378@freescale.com> | ||
| 7 | * | ||
| 8 | * Based on fsl_ssi.h | ||
| 9 | * Author: Timur Tabi <timur@freescale.com> | ||
| 10 | * Copyright 2007-2008 Freescale Semiconductor, Inc. | ||
| 11 | * | ||
| 12 | * This file is licensed under the terms of the GNU General Public License | ||
| 13 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 14 | * kind, whether express or implied. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _FSL_SPDIF_DAI_H | ||
| 18 | #define _FSL_SPDIF_DAI_H | ||
| 19 | |||
| 20 | /* S/PDIF Register Map */ | ||
| 21 | #define REG_SPDIF_SCR 0x0 /* SPDIF Configuration Register */ | ||
| 22 | #define REG_SPDIF_SRCD 0x4 /* CDText Control Register */ | ||
| 23 | #define REG_SPDIF_SRPC 0x8 /* PhaseConfig Register */ | ||
| 24 | #define REG_SPDIF_SIE 0xc /* InterruptEn Register */ | ||
| 25 | #define REG_SPDIF_SIS 0x10 /* InterruptStat Register */ | ||
| 26 | #define REG_SPDIF_SIC 0x10 /* InterruptClear Register */ | ||
| 27 | #define REG_SPDIF_SRL 0x14 /* SPDIFRxLeft Register */ | ||
| 28 | #define REG_SPDIF_SRR 0x18 /* SPDIFRxRight Register */ | ||
| 29 | #define REG_SPDIF_SRCSH 0x1c /* SPDIFRxCChannel_h Register */ | ||
| 30 | #define REG_SPDIF_SRCSL 0x20 /* SPDIFRxCChannel_l Register */ | ||
| 31 | #define REG_SPDIF_SRU 0x24 /* UchannelRx Register */ | ||
| 32 | #define REG_SPDIF_SRQ 0x28 /* QchannelRx Register */ | ||
| 33 | #define REG_SPDIF_STL 0x2C /* SPDIFTxLeft Register */ | ||
| 34 | #define REG_SPDIF_STR 0x30 /* SPDIFTxRight Register */ | ||
| 35 | #define REG_SPDIF_STCSCH 0x34 /* SPDIFTxCChannelCons_h Register */ | ||
| 36 | #define REG_SPDIF_STCSCL 0x38 /* SPDIFTxCChannelCons_l Register */ | ||
| 37 | #define REG_SPDIF_SRFM 0x44 /* FreqMeas Register */ | ||
| 38 | #define REG_SPDIF_STC 0x50 /* SPDIFTxClk Register */ | ||
| 39 | |||
| 40 | |||
| 41 | /* SPDIF Configuration register */ | ||
| 42 | #define SCR_RXFIFO_CTL_OFFSET 23 | ||
| 43 | #define SCR_RXFIFO_CTL_MASK (1 << SCR_RXFIFO_CTL_OFFSET) | ||
| 44 | #define SCR_RXFIFO_CTL_ZERO (1 << SCR_RXFIFO_CTL_OFFSET) | ||
| 45 | #define SCR_RXFIFO_OFF_OFFSET 22 | ||
| 46 | #define SCR_RXFIFO_OFF_MASK (1 << SCR_RXFIFO_OFF_OFFSET) | ||
| 47 | #define SCR_RXFIFO_OFF (1 << SCR_RXFIFO_OFF_OFFSET) | ||
| 48 | #define SCR_RXFIFO_RST_OFFSET 21 | ||
| 49 | #define SCR_RXFIFO_RST_MASK (1 << SCR_RXFIFO_RST_OFFSET) | ||
| 50 | #define SCR_RXFIFO_RST (1 << SCR_RXFIFO_RST_OFFSET) | ||
| 51 | #define SCR_RXFIFO_FSEL_OFFSET 19 | ||
| 52 | #define SCR_RXFIFO_FSEL_MASK (0x3 << SCR_RXFIFO_FSEL_OFFSET) | ||
| 53 | #define SCR_RXFIFO_FSEL_IF0 (0x0 << SCR_RXFIFO_FSEL_OFFSET) | ||
| 54 | #define SCR_RXFIFO_FSEL_IF4 (0x1 << SCR_RXFIFO_FSEL_OFFSET) | ||
| 55 | #define SCR_RXFIFO_FSEL_IF8 (0x2 << SCR_RXFIFO_FSEL_OFFSET) | ||
| 56 | #define SCR_RXFIFO_FSEL_IF12 (0x3 << SCR_RXFIFO_FSEL_OFFSET) | ||
| 57 | #define SCR_RXFIFO_AUTOSYNC_OFFSET 18 | ||
| 58 | #define SCR_RXFIFO_AUTOSYNC_MASK (1 << SCR_RXFIFO_AUTOSYNC_OFFSET) | ||
| 59 | #define SCR_RXFIFO_AUTOSYNC (1 << SCR_RXFIFO_AUTOSYNC_OFFSET) | ||
| 60 | #define SCR_TXFIFO_AUTOSYNC_OFFSET 17 | ||
| 61 | #define SCR_TXFIFO_AUTOSYNC_MASK (1 << SCR_TXFIFO_AUTOSYNC_OFFSET) | ||
| 62 | #define SCR_TXFIFO_AUTOSYNC (1 << SCR_TXFIFO_AUTOSYNC_OFFSET) | ||
| 63 | #define SCR_TXFIFO_FSEL_OFFSET 15 | ||
| 64 | #define SCR_TXFIFO_FSEL_MASK (0x3 << SCR_TXFIFO_FSEL_OFFSET) | ||
| 65 | #define SCR_TXFIFO_FSEL_IF0 (0x0 << SCR_TXFIFO_FSEL_OFFSET) | ||
| 66 | #define SCR_TXFIFO_FSEL_IF4 (0x1 << SCR_TXFIFO_FSEL_OFFSET) | ||
| 67 | #define SCR_TXFIFO_FSEL_IF8 (0x2 << SCR_TXFIFO_FSEL_OFFSET) | ||
| 68 | #define SCR_TXFIFO_FSEL_IF12 (0x3 << SCR_TXFIFO_FSEL_OFFSET) | ||
| 69 | #define SCR_LOW_POWER (1 << 13) | ||
| 70 | #define SCR_SOFT_RESET (1 << 12) | ||
| 71 | #define SCR_TXFIFO_CTRL_OFFSET 10 | ||
| 72 | #define SCR_TXFIFO_CTRL_MASK (0x3 << SCR_TXFIFO_CTRL_OFFSET) | ||
| 73 | #define SCR_TXFIFO_CTRL_ZERO (0x0 << SCR_TXFIFO_CTRL_OFFSET) | ||
| 74 | #define SCR_TXFIFO_CTRL_NORMAL (0x1 << SCR_TXFIFO_CTRL_OFFSET) | ||
| 75 | #define SCR_TXFIFO_CTRL_ONESAMPLE (0x2 << SCR_TXFIFO_CTRL_OFFSET) | ||
| 76 | #define SCR_DMA_RX_EN_OFFSET 9 | ||
| 77 | #define SCR_DMA_RX_EN_MASK (1 << SCR_DMA_RX_EN_OFFSET) | ||
| 78 | #define SCR_DMA_RX_EN (1 << SCR_DMA_RX_EN_OFFSET) | ||
| 79 | #define SCR_DMA_TX_EN_OFFSET 8 | ||
| 80 | #define SCR_DMA_TX_EN_MASK (1 << SCR_DMA_TX_EN_OFFSET) | ||
| 81 | #define SCR_DMA_TX_EN (1 << SCR_DMA_TX_EN_OFFSET) | ||
| 82 | #define SCR_VAL_OFFSET 5 | ||
| 83 | #define SCR_VAL_MASK (1 << SCR_VAL_OFFSET) | ||
| 84 | #define SCR_VAL_CLEAR (1 << SCR_VAL_OFFSET) | ||
| 85 | #define SCR_TXSEL_OFFSET 2 | ||
| 86 | #define SCR_TXSEL_MASK (0x7 << SCR_TXSEL_OFFSET) | ||
| 87 | #define SCR_TXSEL_OFF (0 << SCR_TXSEL_OFFSET) | ||
| 88 | #define SCR_TXSEL_RX (1 << SCR_TXSEL_OFFSET) | ||
| 89 | #define SCR_TXSEL_NORMAL (0x5 << SCR_TXSEL_OFFSET) | ||
| 90 | #define SCR_USRC_SEL_OFFSET 0x0 | ||
| 91 | #define SCR_USRC_SEL_MASK (0x3 << SCR_USRC_SEL_OFFSET) | ||
| 92 | #define SCR_USRC_SEL_NONE (0x0 << SCR_USRC_SEL_OFFSET) | ||
| 93 | #define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET) | ||
| 94 | #define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET) | ||
| 95 | |||
| 96 | /* SPDIF CDText control */ | ||
| 97 | #define SRCD_CD_USER_OFFSET 1 | ||
| 98 | #define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET) | ||
| 99 | |||
| 100 | /* SPDIF Phase Configuration register */ | ||
| 101 | #define SRPC_DPLL_LOCKED (1 << 6) | ||
| 102 | #define SRPC_CLKSRC_SEL_OFFSET 7 | ||
| 103 | #define SRPC_CLKSRC_SEL_MASK (0xf << SRPC_CLKSRC_SEL_OFFSET) | ||
| 104 | #define SRPC_CLKSRC_SEL_SET(x) ((x << SRPC_CLKSRC_SEL_OFFSET) & SRPC_CLKSRC_SEL_MASK) | ||
| 105 | #define SRPC_CLKSRC_SEL_LOCKED_OFFSET1 5 | ||
| 106 | #define SRPC_CLKSRC_SEL_LOCKED_OFFSET2 2 | ||
| 107 | #define SRPC_GAINSEL_OFFSET 3 | ||
| 108 | #define SRPC_GAINSEL_MASK (0x7 << SRPC_GAINSEL_OFFSET) | ||
| 109 | #define SRPC_GAINSEL_SET(x) ((x << SRPC_GAINSEL_OFFSET) & SRPC_GAINSEL_MASK) | ||
| 110 | |||
| 111 | #define SRPC_CLKSRC_MAX 16 | ||
| 112 | |||
| 113 | enum spdif_gainsel { | ||
| 114 | GAINSEL_MULTI_24 = 0, | ||
| 115 | GAINSEL_MULTI_16, | ||
| 116 | GAINSEL_MULTI_12, | ||
| 117 | GAINSEL_MULTI_8, | ||
| 118 | GAINSEL_MULTI_6, | ||
| 119 | GAINSEL_MULTI_4, | ||
| 120 | GAINSEL_MULTI_3, | ||
| 121 | }; | ||
| 122 | #define GAINSEL_MULTI_MAX (GAINSEL_MULTI_3 + 1) | ||
| 123 | #define SPDIF_DEFAULT_GAINSEL GAINSEL_MULTI_8 | ||
| 124 | |||
| 125 | /* SPDIF interrupt mask define */ | ||
| 126 | #define INT_DPLL_LOCKED (1 << 20) | ||
| 127 | #define INT_TXFIFO_UNOV (1 << 19) | ||
| 128 | #define INT_TXFIFO_RESYNC (1 << 18) | ||
| 129 | #define INT_CNEW (1 << 17) | ||
| 130 | #define INT_VAL_NOGOOD (1 << 16) | ||
| 131 | #define INT_SYM_ERR (1 << 15) | ||
| 132 | #define INT_BIT_ERR (1 << 14) | ||
| 133 | #define INT_URX_FUL (1 << 10) | ||
| 134 | #define INT_URX_OV (1 << 9) | ||
| 135 | #define INT_QRX_FUL (1 << 8) | ||
| 136 | #define INT_QRX_OV (1 << 7) | ||
| 137 | #define INT_UQ_SYNC (1 << 6) | ||
| 138 | #define INT_UQ_ERR (1 << 5) | ||
| 139 | #define INT_RXFIFO_UNOV (1 << 4) | ||
| 140 | #define INT_RXFIFO_RESYNC (1 << 3) | ||
| 141 | #define INT_LOSS_LOCK (1 << 2) | ||
| 142 | #define INT_TX_EM (1 << 1) | ||
| 143 | #define INT_RXFIFO_FUL (1 << 0) | ||
| 144 | |||
| 145 | /* SPDIF Clock register */ | ||
| 146 | #define STC_SYSCLK_DIV_OFFSET 11 | ||
| 147 | #define STC_SYSCLK_DIV_MASK (0x1ff << STC_TXCLK_SRC_OFFSET) | ||
| 148 | #define STC_SYSCLK_DIV(x) ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_SYSCLK_DIV_MASK) | ||
| 149 | #define STC_TXCLK_SRC_OFFSET 8 | ||
| 150 | #define STC_TXCLK_SRC_MASK (0x7 << STC_TXCLK_SRC_OFFSET) | ||
| 151 | #define STC_TXCLK_SRC_SET(x) ((x << STC_TXCLK_SRC_OFFSET) & STC_TXCLK_SRC_MASK) | ||
| 152 | #define STC_TXCLK_ALL_EN_OFFSET 7 | ||
| 153 | #define STC_TXCLK_ALL_EN_MASK (1 << STC_TXCLK_ALL_EN_OFFSET) | ||
| 154 | #define STC_TXCLK_ALL_EN (1 << STC_TXCLK_ALL_EN_OFFSET) | ||
| 155 | #define STC_TXCLK_DIV_OFFSET 0 | ||
| 156 | #define STC_TXCLK_DIV_MASK (0x7ff << STC_TXCLK_DIV_OFFSET) | ||
| 157 | #define STC_TXCLK_DIV(x) ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_TXCLK_DIV_MASK) | ||
| 158 | #define STC_TXCLK_SRC_MAX 8 | ||
| 159 | |||
| 160 | /* SPDIF tx rate */ | ||
| 161 | enum spdif_txrate { | ||
| 162 | SPDIF_TXRATE_32000 = 0, | ||
| 163 | SPDIF_TXRATE_44100, | ||
| 164 | SPDIF_TXRATE_48000, | ||
| 165 | }; | ||
| 166 | #define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1) | ||
| 167 | |||
| 168 | |||
| 169 | #define SPDIF_CSTATUS_BYTE 6 | ||
| 170 | #define SPDIF_UBITS_SIZE 96 | ||
| 171 | #define SPDIF_QSUB_SIZE (SPDIF_UBITS_SIZE / 8) | ||
| 172 | |||
| 173 | |||
| 174 | #define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ | ||
| 175 | SNDRV_PCM_RATE_44100 | \ | ||
| 176 | SNDRV_PCM_RATE_48000) | ||
| 177 | |||
| 178 | #define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \ | ||
| 179 | SNDRV_PCM_RATE_32000 | \ | ||
| 180 | SNDRV_PCM_RATE_44100 | \ | ||
| 181 | SNDRV_PCM_RATE_48000 | \ | ||
| 182 | SNDRV_PCM_RATE_64000 | \ | ||
| 183 | SNDRV_PCM_RATE_96000) | ||
| 184 | |||
| 185 | #define FSL_SPDIF_FORMATS_PLAYBACK (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
| 186 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
| 187 | SNDRV_PCM_FMTBIT_S24_LE) | ||
| 188 | |||
| 189 | #define FSL_SPDIF_FORMATS_CAPTURE (SNDRV_PCM_FMTBIT_S24_LE) | ||
| 190 | |||
| 191 | #endif /* _FSL_SPDIF_DAI_H */ | ||
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 2f2d837df07f..5cf626c4dc96 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
| @@ -8,6 +8,26 @@ | |||
| 8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
| 9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
| 10 | * kind, whether express or implied. | 10 | * kind, whether express or implied. |
| 11 | * | ||
| 12 | * | ||
| 13 | * Some notes why imx-pcm-fiq is used instead of DMA on some boards: | ||
| 14 | * | ||
| 15 | * The i.MX SSI core has some nasty limitations in AC97 mode. While most | ||
| 16 | * sane processor vendors have a FIFO per AC97 slot, the i.MX has only | ||
| 17 | * one FIFO which combines all valid receive slots. We cannot even select | ||
| 18 | * which slots we want to receive. The WM9712 with which this driver | ||
| 19 | * was developed with always sends GPIO status data in slot 12 which | ||
| 20 | * we receive in our (PCM-) data stream. The only chance we have is to | ||
| 21 | * manually skip this data in the FIQ handler. With sampling rates different | ||
| 22 | * from 48000Hz not every frame has valid receive data, so the ratio | ||
| 23 | * between pcm data and GPIO status data changes. Our FIQ handler is not | ||
| 24 | * able to handle this, hence this driver only works with 48000Hz sampling | ||
| 25 | * rate. | ||
| 26 | * Reading and writing AC97 registers is another challenge. The core | ||
| 27 | * provides us status bits when the read register is updated with *another* | ||
| 28 | * value. When we read the same register two times (and the register still | ||
| 29 | * contains the same value) these status bits are not set. We work | ||
| 30 | * around this by not polling these bits but only wait a fixed delay. | ||
| 11 | */ | 31 | */ |
| 12 | 32 | ||
| 13 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| @@ -36,7 +56,7 @@ | |||
| 36 | #define read_ssi(addr) in_be32(addr) | 56 | #define read_ssi(addr) in_be32(addr) |
| 37 | #define write_ssi(val, addr) out_be32(addr, val) | 57 | #define write_ssi(val, addr) out_be32(addr, val) |
| 38 | #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) | 58 | #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) |
| 39 | #elif defined ARM | 59 | #else |
| 40 | #define read_ssi(addr) readl(addr) | 60 | #define read_ssi(addr) readl(addr) |
| 41 | #define write_ssi(val, addr) writel(val, addr) | 61 | #define write_ssi(val, addr) writel(val, addr) |
| 42 | /* | 62 | /* |
| @@ -121,11 +141,14 @@ struct fsl_ssi_private { | |||
| 121 | 141 | ||
| 122 | bool new_binding; | 142 | bool new_binding; |
| 123 | bool ssi_on_imx; | 143 | bool ssi_on_imx; |
| 144 | bool imx_ac97; | ||
| 145 | bool use_dma; | ||
| 124 | struct clk *clk; | 146 | struct clk *clk; |
| 125 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 147 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
| 126 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 148 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
| 127 | struct imx_dma_data filter_data_tx; | 149 | struct imx_dma_data filter_data_tx; |
| 128 | struct imx_dma_data filter_data_rx; | 150 | struct imx_dma_data filter_data_rx; |
| 151 | struct imx_pcm_fiq_params fiq_params; | ||
| 129 | 152 | ||
| 130 | struct { | 153 | struct { |
| 131 | unsigned int rfrc; | 154 | unsigned int rfrc; |
| @@ -298,6 +321,102 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
| 298 | return ret; | 321 | return ret; |
| 299 | } | 322 | } |
| 300 | 323 | ||
| 324 | static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) | ||
| 325 | { | ||
| 326 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
| 327 | u8 i2s_mode; | ||
| 328 | u8 wm; | ||
| 329 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | ||
| 330 | |||
| 331 | if (ssi_private->imx_ac97) | ||
| 332 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; | ||
| 333 | else | ||
| 334 | i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; | ||
| 335 | |||
| 336 | /* | ||
| 337 | * Section 16.5 of the MPC8610 reference manual says that the SSI needs | ||
| 338 | * to be disabled before updating the registers we set here. | ||
| 339 | */ | ||
| 340 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
| 341 | |||
| 342 | /* | ||
| 343 | * Program the SSI into I2S Slave Non-Network Synchronous mode. Also | ||
| 344 | * enable the transmit and receive FIFO. | ||
| 345 | * | ||
| 346 | * FIXME: Little-endian samples require a different shift dir | ||
| 347 | */ | ||
| 348 | write_ssi_mask(&ssi->scr, | ||
| 349 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | ||
| 350 | CCSR_SSI_SCR_TFR_CLK_DIS | | ||
| 351 | i2s_mode | | ||
| 352 | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | ||
| 353 | |||
| 354 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
| 355 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | ||
| 356 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | ||
| 357 | |||
| 358 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
| 359 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
| 360 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
| 361 | /* | ||
| 362 | * The DC and PM bits are only used if the SSI is the clock master. | ||
| 363 | */ | ||
| 364 | |||
| 365 | /* | ||
| 366 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't | ||
| 367 | * use FIFO 1. We program the transmit water to signal a DMA transfer | ||
| 368 | * if there are only two (or fewer) elements left in the FIFO. Two | ||
| 369 | * elements equals one frame (left channel, right channel). This value, | ||
| 370 | * however, depends on the depth of the transmit buffer. | ||
| 371 | * | ||
| 372 | * We set the watermark on the same level as the DMA burstsize. For | ||
| 373 | * fiq it is probably better to use the biggest possible watermark | ||
| 374 | * size. | ||
| 375 | */ | ||
| 376 | if (ssi_private->use_dma) | ||
| 377 | wm = ssi_private->fifo_depth - 2; | ||
| 378 | else | ||
| 379 | wm = ssi_private->fifo_depth; | ||
| 380 | |||
| 381 | write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) | | ||
| 382 | CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm), | ||
| 383 | &ssi->sfcsr); | ||
| 384 | |||
| 385 | /* | ||
| 386 | * For ac97 interrupts are enabled with the startup of the substream | ||
| 387 | * because it is also running without an active substream. Normally SSI | ||
| 388 | * is only enabled when there is a substream. | ||
| 389 | */ | ||
| 390 | if (ssi_private->imx_ac97) { | ||
| 391 | /* | ||
| 392 | * Setup the clock control register | ||
| 393 | */ | ||
| 394 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
| 395 | &ssi->stccr); | ||
| 396 | write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), | ||
| 397 | &ssi->srccr); | ||
| 398 | |||
| 399 | /* | ||
| 400 | * Enable AC97 mode and startup the SSI | ||
| 401 | */ | ||
| 402 | write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, | ||
| 403 | &ssi->sacnt); | ||
| 404 | write_ssi(0xff, &ssi->saccdis); | ||
| 405 | write_ssi(0x300, &ssi->saccen); | ||
| 406 | |||
| 407 | /* | ||
| 408 | * Enable SSI, Transmit and Receive | ||
| 409 | */ | ||
| 410 | write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | | ||
| 411 | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); | ||
| 412 | |||
| 413 | write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); | ||
| 414 | } | ||
| 415 | |||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | |||
| 301 | /** | 420 | /** |
| 302 | * fsl_ssi_startup: create a new substream | 421 | * fsl_ssi_startup: create a new substream |
| 303 | * | 422 | * |
| @@ -319,70 +438,14 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
| 319 | * and initialize the SSI registers. | 438 | * and initialize the SSI registers. |
| 320 | */ | 439 | */ |
| 321 | if (!ssi_private->first_stream) { | 440 | if (!ssi_private->first_stream) { |
| 322 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
| 323 | |||
| 324 | ssi_private->first_stream = substream; | 441 | ssi_private->first_stream = substream; |
| 325 | 442 | ||
| 326 | /* | 443 | /* |
| 327 | * Section 16.5 of the MPC8610 reference manual says that the | 444 | * fsl_ssi_setup was already called by ac97_init earlier if |
| 328 | * SSI needs to be disabled before updating the registers we set | 445 | * the driver is in ac97 mode. |
| 329 | * here. | ||
| 330 | */ | ||
| 331 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
| 332 | |||
| 333 | /* | ||
| 334 | * Program the SSI into I2S Slave Non-Network Synchronous mode. | ||
| 335 | * Also enable the transmit and receive FIFO. | ||
| 336 | * | ||
| 337 | * FIXME: Little-endian samples require a different shift dir | ||
| 338 | */ | ||
| 339 | write_ssi_mask(&ssi->scr, | ||
| 340 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | ||
| 341 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | ||
| 342 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | ||
| 343 | |||
| 344 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
| 345 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | ||
| 346 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); | ||
| 347 | |||
| 348 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
| 349 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | ||
| 350 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); | ||
| 351 | |||
| 352 | /* | ||
| 353 | * The DC and PM bits are only used if the SSI is the clock | ||
| 354 | * master. | ||
| 355 | */ | ||
| 356 | |||
| 357 | /* Enable the interrupts and DMA requests */ | ||
| 358 | write_ssi(SIER_FLAGS, &ssi->sier); | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We | ||
| 362 | * don't use FIFO 1. We program the transmit water to signal a | ||
| 363 | * DMA transfer if there are only two (or fewer) elements left | ||
| 364 | * in the FIFO. Two elements equals one frame (left channel, | ||
| 365 | * right channel). This value, however, depends on the depth of | ||
| 366 | * the transmit buffer. | ||
| 367 | * | ||
| 368 | * We program the receive FIFO to notify us if at least two | ||
| 369 | * elements (one frame) have been written to the FIFO. We could | ||
| 370 | * make this value larger (and maybe we should), but this way | ||
| 371 | * data will be written to memory as soon as it's available. | ||
| 372 | */ | ||
| 373 | write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | | ||
| 374 | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2), | ||
| 375 | &ssi->sfcsr); | ||
| 376 | |||
| 377 | /* | ||
| 378 | * We keep the SSI disabled because if we enable it, then the | ||
| 379 | * DMA controller will start. It's not supposed to start until | ||
| 380 | * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The | ||
| 381 | * DMA controller will transfer one "BWC" of data (i.e. the | ||
| 382 | * amount of data that the MR.BWC bits are set to). The reason | ||
| 383 | * this is bad is because at this point, the PCM driver has not | ||
| 384 | * finished initializing the DMA controller. | ||
| 385 | */ | 446 | */ |
| 447 | if (!ssi_private->imx_ac97) | ||
| 448 | fsl_ssi_setup(ssi_private); | ||
| 386 | } else { | 449 | } else { |
| 387 | if (synchronous) { | 450 | if (synchronous) { |
| 388 | struct snd_pcm_runtime *first_runtime = | 451 | struct snd_pcm_runtime *first_runtime = |
| @@ -492,6 +555,27 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 492 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 555 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 493 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 556 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
| 494 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 557 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
| 558 | unsigned int sier_bits; | ||
| 559 | |||
| 560 | /* | ||
| 561 | * Enable only the interrupts and DMA requests | ||
| 562 | * that are needed for the channel. As the fiq | ||
| 563 | * is polling for this bits, we have to ensure | ||
| 564 | * that this are aligned with the preallocated | ||
| 565 | * buffers | ||
| 566 | */ | ||
| 567 | |||
| 568 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 569 | if (ssi_private->use_dma) | ||
| 570 | sier_bits = SIER_FLAGS; | ||
| 571 | else | ||
| 572 | sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; | ||
| 573 | } else { | ||
| 574 | if (ssi_private->use_dma) | ||
| 575 | sier_bits = SIER_FLAGS; | ||
| 576 | else | ||
| 577 | sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; | ||
| 578 | } | ||
| 495 | 579 | ||
| 496 | switch (cmd) { | 580 | switch (cmd) { |
| 497 | case SNDRV_PCM_TRIGGER_START: | 581 | case SNDRV_PCM_TRIGGER_START: |
| @@ -510,12 +594,18 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 510 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); | 594 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); |
| 511 | else | 595 | else |
| 512 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); | 596 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); |
| 597 | |||
| 598 | if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & | ||
| 599 | (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) | ||
| 600 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
| 513 | break; | 601 | break; |
| 514 | 602 | ||
| 515 | default: | 603 | default: |
| 516 | return -EINVAL; | 604 | return -EINVAL; |
| 517 | } | 605 | } |
| 518 | 606 | ||
| 607 | write_ssi(sier_bits, &ssi->sier); | ||
| 608 | |||
| 519 | return 0; | 609 | return 0; |
| 520 | } | 610 | } |
| 521 | 611 | ||
| @@ -534,22 +624,13 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
| 534 | ssi_private->first_stream = ssi_private->second_stream; | 624 | ssi_private->first_stream = ssi_private->second_stream; |
| 535 | 625 | ||
| 536 | ssi_private->second_stream = NULL; | 626 | ssi_private->second_stream = NULL; |
| 537 | |||
| 538 | /* | ||
| 539 | * If this is the last active substream, disable the SSI. | ||
| 540 | */ | ||
| 541 | if (!ssi_private->first_stream) { | ||
| 542 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
| 543 | |||
| 544 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); | ||
| 545 | } | ||
| 546 | } | 627 | } |
| 547 | 628 | ||
| 548 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | 629 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |
| 549 | { | 630 | { |
| 550 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 631 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
| 551 | 632 | ||
| 552 | if (ssi_private->ssi_on_imx) { | 633 | if (ssi_private->ssi_on_imx && ssi_private->use_dma) { |
| 553 | dai->playback_dma_data = &ssi_private->dma_params_tx; | 634 | dai->playback_dma_data = &ssi_private->dma_params_tx; |
| 554 | dai->capture_dma_data = &ssi_private->dma_params_rx; | 635 | dai->capture_dma_data = &ssi_private->dma_params_rx; |
| 555 | } | 636 | } |
| @@ -587,6 +668,133 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
| 587 | .name = "fsl-ssi", | 668 | .name = "fsl-ssi", |
| 588 | }; | 669 | }; |
| 589 | 670 | ||
| 671 | /** | ||
| 672 | * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. | ||
| 673 | * | ||
| 674 | * This function is called by ALSA to start, stop, pause, and resume the | ||
| 675 | * transfer of data. | ||
| 676 | */ | ||
| 677 | static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | ||
| 678 | struct snd_soc_dai *dai) | ||
| 679 | { | ||
| 680 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 681 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( | ||
| 682 | rtd->cpu_dai); | ||
| 683 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
| 684 | |||
| 685 | switch (cmd) { | ||
| 686 | case SNDRV_PCM_TRIGGER_START: | ||
| 687 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
| 688 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 689 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | | ||
| 690 | CCSR_SSI_SIER_TFE0_EN); | ||
| 691 | else | ||
| 692 | write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | | ||
| 693 | CCSR_SSI_SIER_RFF0_EN); | ||
| 694 | break; | ||
| 695 | |||
| 696 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 697 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
| 698 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 699 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | | ||
| 700 | CCSR_SSI_SIER_TFE0_EN, 0); | ||
| 701 | else | ||
| 702 | write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | | ||
| 703 | CCSR_SSI_SIER_RFF0_EN, 0); | ||
| 704 | break; | ||
| 705 | |||
| 706 | default: | ||
| 707 | return -EINVAL; | ||
| 708 | } | ||
| 709 | |||
| 710 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 711 | write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); | ||
| 712 | else | ||
| 713 | write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); | ||
| 714 | |||
| 715 | return 0; | ||
| 716 | } | ||
| 717 | |||
| 718 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | ||
| 719 | .startup = fsl_ssi_startup, | ||
| 720 | .shutdown = fsl_ssi_shutdown, | ||
| 721 | .trigger = fsl_ssi_ac97_trigger, | ||
| 722 | }; | ||
| 723 | |||
| 724 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | ||
| 725 | .ac97_control = 1, | ||
| 726 | .playback = { | ||
| 727 | .stream_name = "AC97 Playback", | ||
| 728 | .channels_min = 2, | ||
| 729 | .channels_max = 2, | ||
| 730 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
| 731 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 732 | }, | ||
| 733 | .capture = { | ||
| 734 | .stream_name = "AC97 Capture", | ||
| 735 | .channels_min = 2, | ||
| 736 | .channels_max = 2, | ||
| 737 | .rates = SNDRV_PCM_RATE_48000, | ||
| 738 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 739 | }, | ||
| 740 | .ops = &fsl_ssi_ac97_dai_ops, | ||
| 741 | }; | ||
| 742 | |||
| 743 | |||
| 744 | static struct fsl_ssi_private *fsl_ac97_data; | ||
| 745 | |||
| 746 | static void fsl_ssi_ac97_init(void) | ||
| 747 | { | ||
| 748 | fsl_ssi_setup(fsl_ac97_data); | ||
| 749 | } | ||
| 750 | |||
| 751 | void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
| 752 | unsigned short val) | ||
| 753 | { | ||
| 754 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
| 755 | unsigned int lreg; | ||
| 756 | unsigned int lval; | ||
| 757 | |||
| 758 | if (reg > 0x7f) | ||
| 759 | return; | ||
| 760 | |||
| 761 | |||
| 762 | lreg = reg << 12; | ||
| 763 | write_ssi(lreg, &ssi->sacadd); | ||
| 764 | |||
| 765 | lval = val << 4; | ||
| 766 | write_ssi(lval , &ssi->sacdat); | ||
| 767 | |||
| 768 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
| 769 | CCSR_SSI_SACNT_WR); | ||
| 770 | udelay(100); | ||
| 771 | } | ||
| 772 | |||
| 773 | unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, | ||
| 774 | unsigned short reg) | ||
| 775 | { | ||
| 776 | struct ccsr_ssi *ssi = fsl_ac97_data->ssi; | ||
| 777 | |||
| 778 | unsigned short val = -1; | ||
| 779 | unsigned int lreg; | ||
| 780 | |||
| 781 | lreg = (reg & 0x7f) << 12; | ||
| 782 | write_ssi(lreg, &ssi->sacadd); | ||
| 783 | write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK, | ||
| 784 | CCSR_SSI_SACNT_RD); | ||
| 785 | |||
| 786 | udelay(100); | ||
| 787 | |||
| 788 | val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff; | ||
| 789 | |||
| 790 | return val; | ||
| 791 | } | ||
| 792 | |||
| 793 | static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { | ||
| 794 | .read = fsl_ssi_ac97_read, | ||
| 795 | .write = fsl_ssi_ac97_write, | ||
| 796 | }; | ||
| 797 | |||
| 590 | /* Show the statistics of a flag only if its interrupt is enabled. The | 798 | /* Show the statistics of a flag only if its interrupt is enabled. The |
| 591 | * compiler will optimze this code to a no-op if the interrupt is not | 799 | * compiler will optimze this code to a no-op if the interrupt is not |
| 592 | * enabled. | 800 | * enabled. |
| @@ -663,6 +871,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 663 | struct resource res; | 871 | struct resource res; |
| 664 | char name[64]; | 872 | char name[64]; |
| 665 | bool shared; | 873 | bool shared; |
| 874 | bool ac97 = false; | ||
| 666 | 875 | ||
| 667 | /* SSIs that are not connected on the board should have a | 876 | /* SSIs that are not connected on the board should have a |
| 668 | * status = "disabled" | 877 | * status = "disabled" |
| @@ -673,14 +882,20 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 673 | 882 | ||
| 674 | /* We only support the SSI in "I2S Slave" mode */ | 883 | /* We only support the SSI in "I2S Slave" mode */ |
| 675 | sprop = of_get_property(np, "fsl,mode", NULL); | 884 | sprop = of_get_property(np, "fsl,mode", NULL); |
| 676 | if (!sprop || strcmp(sprop, "i2s-slave")) { | 885 | if (!sprop) { |
| 886 | dev_err(&pdev->dev, "fsl,mode property is necessary\n"); | ||
| 887 | return -EINVAL; | ||
| 888 | } | ||
| 889 | if (!strcmp(sprop, "ac97-slave")) { | ||
| 890 | ac97 = true; | ||
| 891 | } else if (strcmp(sprop, "i2s-slave")) { | ||
| 677 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); | 892 | dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); |
| 678 | return -ENODEV; | 893 | return -ENODEV; |
| 679 | } | 894 | } |
| 680 | 895 | ||
| 681 | /* The DAI name is the last part of the full name of the node. */ | 896 | /* The DAI name is the last part of the full name of the node. */ |
| 682 | p = strrchr(np->full_name, '/') + 1; | 897 | p = strrchr(np->full_name, '/') + 1; |
| 683 | ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), | 898 | ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p), |
| 684 | GFP_KERNEL); | 899 | GFP_KERNEL); |
| 685 | if (!ssi_private) { | 900 | if (!ssi_private) { |
| 686 | dev_err(&pdev->dev, "could not allocate DAI object\n"); | 901 | dev_err(&pdev->dev, "could not allocate DAI object\n"); |
| @@ -689,38 +904,41 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 689 | 904 | ||
| 690 | strcpy(ssi_private->name, p); | 905 | strcpy(ssi_private->name, p); |
| 691 | 906 | ||
| 692 | /* Initialize this copy of the CPU DAI driver structure */ | 907 | ssi_private->use_dma = !of_property_read_bool(np, |
| 693 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | 908 | "fsl,fiq-stream-filter"); |
| 694 | sizeof(fsl_ssi_dai_template)); | 909 | |
| 910 | if (ac97) { | ||
| 911 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, | ||
| 912 | sizeof(fsl_ssi_ac97_dai)); | ||
| 913 | |||
| 914 | fsl_ac97_data = ssi_private; | ||
| 915 | ssi_private->imx_ac97 = true; | ||
| 916 | |||
| 917 | snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev); | ||
| 918 | } else { | ||
| 919 | /* Initialize this copy of the CPU DAI driver structure */ | ||
| 920 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, | ||
| 921 | sizeof(fsl_ssi_dai_template)); | ||
| 922 | } | ||
| 695 | ssi_private->cpu_dai_drv.name = ssi_private->name; | 923 | ssi_private->cpu_dai_drv.name = ssi_private->name; |
| 696 | 924 | ||
| 697 | /* Get the addresses and IRQ */ | 925 | /* Get the addresses and IRQ */ |
| 698 | ret = of_address_to_resource(np, 0, &res); | 926 | ret = of_address_to_resource(np, 0, &res); |
| 699 | if (ret) { | 927 | if (ret) { |
| 700 | dev_err(&pdev->dev, "could not determine device resources\n"); | 928 | dev_err(&pdev->dev, "could not determine device resources\n"); |
| 701 | goto error_kmalloc; | 929 | return ret; |
| 702 | } | 930 | } |
| 703 | ssi_private->ssi = of_iomap(np, 0); | 931 | ssi_private->ssi = of_iomap(np, 0); |
| 704 | if (!ssi_private->ssi) { | 932 | if (!ssi_private->ssi) { |
| 705 | dev_err(&pdev->dev, "could not map device resources\n"); | 933 | dev_err(&pdev->dev, "could not map device resources\n"); |
| 706 | ret = -ENOMEM; | 934 | return -ENOMEM; |
| 707 | goto error_kmalloc; | ||
| 708 | } | 935 | } |
| 709 | ssi_private->ssi_phys = res.start; | 936 | ssi_private->ssi_phys = res.start; |
| 710 | 937 | ||
| 711 | ssi_private->irq = irq_of_parse_and_map(np, 0); | 938 | ssi_private->irq = irq_of_parse_and_map(np, 0); |
| 712 | if (ssi_private->irq == NO_IRQ) { | 939 | if (ssi_private->irq == NO_IRQ) { |
| 713 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 940 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); |
| 714 | ret = -ENXIO; | 941 | return -ENXIO; |
| 715 | goto error_iomap; | ||
| 716 | } | ||
| 717 | |||
| 718 | /* The 'name' should not have any slashes in it. */ | ||
| 719 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, | ||
| 720 | ssi_private); | ||
| 721 | if (ret < 0) { | ||
| 722 | dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); | ||
| 723 | goto error_irqmap; | ||
| 724 | } | 942 | } |
| 725 | 943 | ||
| 726 | /* Are the RX and the TX clocks locked? */ | 944 | /* Are the RX and the TX clocks locked? */ |
| @@ -739,13 +957,18 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 739 | u32 dma_events[2]; | 957 | u32 dma_events[2]; |
| 740 | ssi_private->ssi_on_imx = true; | 958 | ssi_private->ssi_on_imx = true; |
| 741 | 959 | ||
| 742 | ssi_private->clk = clk_get(&pdev->dev, NULL); | 960 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); |
| 743 | if (IS_ERR(ssi_private->clk)) { | 961 | if (IS_ERR(ssi_private->clk)) { |
| 744 | ret = PTR_ERR(ssi_private->clk); | 962 | ret = PTR_ERR(ssi_private->clk); |
| 745 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); | 963 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); |
| 746 | goto error_irq; | 964 | goto error_irqmap; |
| 965 | } | ||
| 966 | ret = clk_prepare_enable(ssi_private->clk); | ||
| 967 | if (ret) { | ||
| 968 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", | ||
| 969 | ret); | ||
| 970 | goto error_irqmap; | ||
| 747 | } | 971 | } |
| 748 | clk_prepare_enable(ssi_private->clk); | ||
| 749 | 972 | ||
| 750 | /* | 973 | /* |
| 751 | * We have burstsize be "fifo_depth - 2" to match the SSI | 974 | * We have burstsize be "fifo_depth - 2" to match the SSI |
| @@ -763,24 +986,38 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 763 | &ssi_private->filter_data_tx; | 986 | &ssi_private->filter_data_tx; |
| 764 | ssi_private->dma_params_rx.filter_data = | 987 | ssi_private->dma_params_rx.filter_data = |
| 765 | &ssi_private->filter_data_rx; | 988 | &ssi_private->filter_data_rx; |
| 766 | /* | 989 | if (!of_property_read_bool(pdev->dev.of_node, "dmas") && |
| 767 | * TODO: This is a temporary solution and should be changed | 990 | ssi_private->use_dma) { |
| 768 | * to use generic DMA binding later when the helplers get in. | 991 | /* |
| 769 | */ | 992 | * FIXME: This is a temporary solution until all |
| 770 | ret = of_property_read_u32_array(pdev->dev.of_node, | 993 | * necessary dma drivers support the generic dma |
| 994 | * bindings. | ||
| 995 | */ | ||
| 996 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
| 771 | "fsl,ssi-dma-events", dma_events, 2); | 997 | "fsl,ssi-dma-events", dma_events, 2); |
| 772 | if (ret) { | 998 | if (ret && ssi_private->use_dma) { |
| 773 | dev_err(&pdev->dev, "could not get dma events\n"); | 999 | dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n"); |
| 774 | goto error_clk; | 1000 | goto error_clk; |
| 1001 | } | ||
| 775 | } | 1002 | } |
| 776 | 1003 | ||
| 777 | shared = of_device_is_compatible(of_get_parent(np), | 1004 | shared = of_device_is_compatible(of_get_parent(np), |
| 778 | "fsl,spba-bus"); | 1005 | "fsl,spba-bus"); |
| 779 | 1006 | ||
| 780 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, | 1007 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, |
| 781 | dma_events[0], shared); | 1008 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
| 782 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, | 1009 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, |
| 783 | dma_events[1], shared); | 1010 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); |
| 1011 | } else if (ssi_private->use_dma) { | ||
| 1012 | /* The 'name' should not have any slashes in it. */ | ||
| 1013 | ret = devm_request_irq(&pdev->dev, ssi_private->irq, | ||
| 1014 | fsl_ssi_isr, 0, ssi_private->name, | ||
| 1015 | ssi_private); | ||
| 1016 | if (ret < 0) { | ||
| 1017 | dev_err(&pdev->dev, "could not claim irq %u\n", | ||
| 1018 | ssi_private->irq); | ||
| 1019 | goto error_irqmap; | ||
| 1020 | } | ||
| 784 | } | 1021 | } |
| 785 | 1022 | ||
| 786 | /* Initialize the the device_attribute structure */ | 1023 | /* Initialize the the device_attribute structure */ |
| @@ -794,7 +1031,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 794 | if (ret) { | 1031 | if (ret) { |
| 795 | dev_err(&pdev->dev, "could not create sysfs %s file\n", | 1032 | dev_err(&pdev->dev, "could not create sysfs %s file\n", |
| 796 | ssi_private->dev_attr.attr.name); | 1033 | ssi_private->dev_attr.attr.name); |
| 797 | goto error_irq; | 1034 | goto error_clk; |
| 798 | } | 1035 | } |
| 799 | 1036 | ||
| 800 | /* Register with ASoC */ | 1037 | /* Register with ASoC */ |
| @@ -808,9 +1045,30 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 808 | } | 1045 | } |
| 809 | 1046 | ||
| 810 | if (ssi_private->ssi_on_imx) { | 1047 | if (ssi_private->ssi_on_imx) { |
| 811 | ret = imx_pcm_dma_init(pdev); | 1048 | if (!ssi_private->use_dma) { |
| 812 | if (ret) | 1049 | |
| 813 | goto error_dev; | 1050 | /* |
| 1051 | * Some boards use an incompatible codec. To get it | ||
| 1052 | * working, we are using imx-fiq-pcm-audio, that | ||
| 1053 | * can handle those codecs. DMA is not possible in this | ||
| 1054 | * situation. | ||
| 1055 | */ | ||
| 1056 | |||
| 1057 | ssi_private->fiq_params.irq = ssi_private->irq; | ||
| 1058 | ssi_private->fiq_params.base = ssi_private->ssi; | ||
| 1059 | ssi_private->fiq_params.dma_params_rx = | ||
| 1060 | &ssi_private->dma_params_rx; | ||
| 1061 | ssi_private->fiq_params.dma_params_tx = | ||
| 1062 | &ssi_private->dma_params_tx; | ||
| 1063 | |||
| 1064 | ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params); | ||
| 1065 | if (ret) | ||
| 1066 | goto error_dev; | ||
| 1067 | } else { | ||
| 1068 | ret = imx_pcm_dma_init(pdev); | ||
| 1069 | if (ret) | ||
| 1070 | goto error_dev; | ||
| 1071 | } | ||
| 814 | } | 1072 | } |
| 815 | 1073 | ||
| 816 | /* | 1074 | /* |
| @@ -845,6 +1103,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
| 845 | } | 1103 | } |
| 846 | 1104 | ||
| 847 | done: | 1105 | done: |
| 1106 | if (ssi_private->imx_ac97) | ||
| 1107 | fsl_ssi_ac97_init(); | ||
| 1108 | |||
| 848 | return 0; | 1109 | return 0; |
| 849 | 1110 | ||
| 850 | error_dai: | 1111 | error_dai: |
| @@ -857,23 +1118,12 @@ error_dev: | |||
| 857 | device_remove_file(&pdev->dev, dev_attr); | 1118 | device_remove_file(&pdev->dev, dev_attr); |
| 858 | 1119 | ||
| 859 | error_clk: | 1120 | error_clk: |
| 860 | if (ssi_private->ssi_on_imx) { | 1121 | if (ssi_private->ssi_on_imx) |
| 861 | clk_disable_unprepare(ssi_private->clk); | 1122 | clk_disable_unprepare(ssi_private->clk); |
| 862 | clk_put(ssi_private->clk); | ||
| 863 | } | ||
| 864 | |||
| 865 | error_irq: | ||
| 866 | free_irq(ssi_private->irq, ssi_private); | ||
| 867 | 1123 | ||
| 868 | error_irqmap: | 1124 | error_irqmap: |
| 869 | irq_dispose_mapping(ssi_private->irq); | 1125 | irq_dispose_mapping(ssi_private->irq); |
| 870 | 1126 | ||
| 871 | error_iomap: | ||
| 872 | iounmap(ssi_private->ssi); | ||
| 873 | |||
| 874 | error_kmalloc: | ||
| 875 | kfree(ssi_private); | ||
| 876 | |||
| 877 | return ret; | 1127 | return ret; |
| 878 | } | 1128 | } |
| 879 | 1129 | ||
| @@ -883,20 +1133,15 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
| 883 | 1133 | ||
| 884 | if (!ssi_private->new_binding) | 1134 | if (!ssi_private->new_binding) |
| 885 | platform_device_unregister(ssi_private->pdev); | 1135 | platform_device_unregister(ssi_private->pdev); |
| 886 | if (ssi_private->ssi_on_imx) { | 1136 | if (ssi_private->ssi_on_imx) |
| 887 | imx_pcm_dma_exit(pdev); | 1137 | imx_pcm_dma_exit(pdev); |
| 888 | clk_disable_unprepare(ssi_private->clk); | ||
| 889 | clk_put(ssi_private->clk); | ||
| 890 | } | ||
| 891 | snd_soc_unregister_component(&pdev->dev); | 1138 | snd_soc_unregister_component(&pdev->dev); |
| 1139 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 892 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 1140 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); |
| 893 | 1141 | if (ssi_private->ssi_on_imx) | |
| 894 | free_irq(ssi_private->irq, ssi_private); | 1142 | clk_disable_unprepare(ssi_private->clk); |
| 895 | irq_dispose_mapping(ssi_private->irq); | 1143 | irq_dispose_mapping(ssi_private->irq); |
| 896 | 1144 | ||
| 897 | kfree(ssi_private); | ||
| 898 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 899 | |||
| 900 | return 0; | 1145 | return 0; |
| 901 | } | 1146 | } |
| 902 | 1147 | ||
| @@ -919,6 +1164,7 @@ static struct platform_driver fsl_ssi_driver = { | |||
| 919 | 1164 | ||
| 920 | module_platform_driver(fsl_ssi_driver); | 1165 | module_platform_driver(fsl_ssi_driver); |
| 921 | 1166 | ||
| 1167 | MODULE_ALIAS("platform:fsl-ssi-dai"); | ||
| 922 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 1168 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
| 923 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); | 1169 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); |
| 924 | MODULE_LICENSE("GPL v2"); | 1170 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index e260f1f899db..ab17381cc981 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
| @@ -73,8 +73,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, | |||
| 73 | if (!buf) | 73 | if (!buf) |
| 74 | return -ENOMEM; | 74 | return -ENOMEM; |
| 75 | 75 | ||
| 76 | if (audmux_clk) | 76 | if (audmux_clk) { |
| 77 | clk_prepare_enable(audmux_clk); | 77 | ret = clk_prepare_enable(audmux_clk); |
| 78 | if (ret) | ||
| 79 | return ret; | ||
| 80 | } | ||
| 78 | 81 | ||
| 79 | ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); | 82 | ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); |
| 80 | pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port)); | 83 | pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port)); |
| @@ -224,14 +227,19 @@ EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port); | |||
| 224 | int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, | 227 | int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, |
| 225 | unsigned int pdcr) | 228 | unsigned int pdcr) |
| 226 | { | 229 | { |
| 230 | int ret; | ||
| 231 | |||
| 227 | if (audmux_type != IMX31_AUDMUX) | 232 | if (audmux_type != IMX31_AUDMUX) |
| 228 | return -EINVAL; | 233 | return -EINVAL; |
| 229 | 234 | ||
| 230 | if (!audmux_base) | 235 | if (!audmux_base) |
| 231 | return -ENOSYS; | 236 | return -ENOSYS; |
| 232 | 237 | ||
| 233 | if (audmux_clk) | 238 | if (audmux_clk) { |
| 234 | clk_prepare_enable(audmux_clk); | 239 | ret = clk_prepare_enable(audmux_clk); |
| 240 | if (ret) | ||
| 241 | return ret; | ||
| 242 | } | ||
| 235 | 243 | ||
| 236 | writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); | 244 | writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); |
| 237 | writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port)); | 245 | writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port)); |
| @@ -243,6 +251,66 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, | |||
| 243 | } | 251 | } |
| 244 | EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); | 252 | EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); |
| 245 | 253 | ||
| 254 | static int imx_audmux_parse_dt_defaults(struct platform_device *pdev, | ||
| 255 | struct device_node *of_node) | ||
| 256 | { | ||
| 257 | struct device_node *child; | ||
| 258 | |||
| 259 | for_each_available_child_of_node(of_node, child) { | ||
| 260 | unsigned int port; | ||
| 261 | unsigned int ptcr = 0; | ||
| 262 | unsigned int pdcr = 0; | ||
| 263 | unsigned int pcr = 0; | ||
| 264 | unsigned int val; | ||
| 265 | int ret; | ||
| 266 | int i = 0; | ||
| 267 | |||
| 268 | ret = of_property_read_u32(child, "fsl,audmux-port", &port); | ||
| 269 | if (ret) { | ||
| 270 | dev_warn(&pdev->dev, "Failed to get fsl,audmux-port of child node \"%s\"\n", | ||
| 271 | child->full_name); | ||
| 272 | continue; | ||
| 273 | } | ||
| 274 | if (!of_property_read_bool(child, "fsl,port-config")) { | ||
| 275 | dev_warn(&pdev->dev, "child node \"%s\" does not have property fsl,port-config\n", | ||
| 276 | child->full_name); | ||
| 277 | continue; | ||
| 278 | } | ||
| 279 | |||
| 280 | for (i = 0; (ret = of_property_read_u32_index(child, | ||
| 281 | "fsl,port-config", i, &val)) == 0; | ||
| 282 | ++i) { | ||
| 283 | if (audmux_type == IMX31_AUDMUX) { | ||
| 284 | if (i % 2) | ||
| 285 | pdcr |= val; | ||
| 286 | else | ||
| 287 | ptcr |= val; | ||
| 288 | } else { | ||
| 289 | pcr |= val; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | if (ret != -EOVERFLOW) { | ||
| 294 | dev_err(&pdev->dev, "Failed to read u32 at index %d of child %s\n", | ||
| 295 | i, child->full_name); | ||
| 296 | continue; | ||
| 297 | } | ||
| 298 | |||
| 299 | if (audmux_type == IMX31_AUDMUX) { | ||
| 300 | if (i % 2) { | ||
| 301 | dev_err(&pdev->dev, "One pdcr value is missing in child node %s\n", | ||
| 302 | child->full_name); | ||
| 303 | continue; | ||
| 304 | } | ||
| 305 | imx_audmux_v2_configure_port(port, ptcr, pdcr); | ||
| 306 | } else { | ||
| 307 | imx_audmux_v1_configure_port(port, pcr); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 246 | static int imx_audmux_probe(struct platform_device *pdev) | 314 | static int imx_audmux_probe(struct platform_device *pdev) |
| 247 | { | 315 | { |
| 248 | struct resource *res; | 316 | struct resource *res; |
| @@ -267,6 +335,8 @@ static int imx_audmux_probe(struct platform_device *pdev) | |||
| 267 | if (audmux_type == IMX31_AUDMUX) | 335 | if (audmux_type == IMX31_AUDMUX) |
| 268 | audmux_debugfs_init(); | 336 | audmux_debugfs_init(); |
| 269 | 337 | ||
| 338 | imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node); | ||
| 339 | |||
| 270 | return 0; | 340 | return 0; |
| 271 | } | 341 | } |
| 272 | 342 | ||
diff --git a/sound/soc/fsl/imx-audmux.h b/sound/soc/fsl/imx-audmux.h index b8ff44b9dafa..38a4209af7c6 100644 --- a/sound/soc/fsl/imx-audmux.h +++ b/sound/soc/fsl/imx-audmux.h | |||
| @@ -1,57 +1,7 @@ | |||
| 1 | #ifndef __IMX_AUDMUX_H | 1 | #ifndef __IMX_AUDMUX_H |
| 2 | #define __IMX_AUDMUX_H | 2 | #define __IMX_AUDMUX_H |
| 3 | 3 | ||
| 4 | #define MX27_AUDMUX_HPCR1_SSI0 0 | 4 | #include <dt-bindings/sound/fsl-imx-audmux.h> |
| 5 | #define MX27_AUDMUX_HPCR2_SSI1 1 | ||
| 6 | #define MX27_AUDMUX_HPCR3_SSI_PINS_4 2 | ||
| 7 | #define MX27_AUDMUX_PPCR1_SSI_PINS_1 3 | ||
| 8 | #define MX27_AUDMUX_PPCR2_SSI_PINS_2 4 | ||
| 9 | #define MX27_AUDMUX_PPCR3_SSI_PINS_3 5 | ||
| 10 | |||
| 11 | #define MX31_AUDMUX_PORT1_SSI0 0 | ||
| 12 | #define MX31_AUDMUX_PORT2_SSI1 1 | ||
| 13 | #define MX31_AUDMUX_PORT3_SSI_PINS_3 2 | ||
| 14 | #define MX31_AUDMUX_PORT4_SSI_PINS_4 3 | ||
| 15 | #define MX31_AUDMUX_PORT5_SSI_PINS_5 4 | ||
| 16 | #define MX31_AUDMUX_PORT6_SSI_PINS_6 5 | ||
| 17 | #define MX31_AUDMUX_PORT7_SSI_PINS_7 6 | ||
| 18 | |||
| 19 | #define MX51_AUDMUX_PORT1_SSI0 0 | ||
| 20 | #define MX51_AUDMUX_PORT2_SSI1 1 | ||
| 21 | #define MX51_AUDMUX_PORT3 2 | ||
| 22 | #define MX51_AUDMUX_PORT4 3 | ||
| 23 | #define MX51_AUDMUX_PORT5 4 | ||
| 24 | #define MX51_AUDMUX_PORT6 5 | ||
| 25 | #define MX51_AUDMUX_PORT7 6 | ||
| 26 | |||
| 27 | /* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ | ||
| 28 | #define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) | ||
| 29 | #define IMX_AUDMUX_V1_PCR_INMEN (1 << 8) | ||
| 30 | #define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10) | ||
| 31 | #define IMX_AUDMUX_V1_PCR_SYN (1 << 12) | ||
| 32 | #define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) | ||
| 33 | #define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) | ||
| 34 | #define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24) | ||
| 35 | #define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25) | ||
| 36 | #define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) | ||
| 37 | #define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30) | ||
| 38 | #define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31) | ||
| 39 | |||
| 40 | /* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ | ||
| 41 | #define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31) | ||
| 42 | #define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) | ||
| 43 | #define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) | ||
| 44 | #define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) | ||
| 45 | #define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21) | ||
| 46 | #define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) | ||
| 47 | #define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) | ||
| 48 | #define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) | ||
| 49 | #define IMX_AUDMUX_V2_PTCR_SYN (1 << 11) | ||
| 50 | |||
| 51 | #define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) | ||
| 52 | #define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12) | ||
| 53 | #define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) | ||
| 54 | #define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) | ||
| 55 | 5 | ||
| 56 | int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr); | 6 | int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr); |
| 57 | 7 | ||
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 9df173c091a6..a3d60d4bea4c 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
| @@ -90,6 +90,7 @@ static const struct snd_soc_dapm_route imx_mc13783_routes[] = { | |||
| 90 | 90 | ||
| 91 | static struct snd_soc_card imx_mc13783 = { | 91 | static struct snd_soc_card imx_mc13783 = { |
| 92 | .name = "imx_mc13783", | 92 | .name = "imx_mc13783", |
| 93 | .owner = THIS_MODULE, | ||
| 93 | .dai_link = imx_mc13783_dai_mc13783, | 94 | .dai_link = imx_mc13783_dai_mc13783, |
| 94 | .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783), | 95 | .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783), |
| 95 | .dapm_widgets = imx_mc13783_widget, | 96 | .dapm_widgets = imx_mc13783_widget, |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index fde4d2ea68c8..4dc1296688e9 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
| 16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
| 17 | #include <linux/module.h> | ||
| 17 | 18 | ||
| 18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
| 19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
| @@ -64,7 +65,6 @@ int imx_pcm_dma_init(struct platform_device *pdev) | |||
| 64 | { | 65 | { |
| 65 | return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, | 66 | return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, |
| 66 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | | 67 | SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | |
| 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 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); |
| @@ -74,3 +74,5 @@ void imx_pcm_dma_exit(struct platform_device *pdev) | |||
| 74 | snd_dmaengine_pcm_unregister(&pdev->dev); | 74 | snd_dmaengine_pcm_unregister(&pdev->dev); |
| 75 | } | 75 | } |
| 76 | EXPORT_SYMBOL_GPL(imx_pcm_dma_exit); | 76 | EXPORT_SYMBOL_GPL(imx_pcm_dma_exit); |
| 77 | |||
| 78 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 310d90290320..34043c55f2a6 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | 23 | ||
| 24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
| 25 | #include <sound/dmaengine_pcm.h> | ||
| 25 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
| 26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
| 27 | #include <sound/pcm_params.h> | 28 | #include <sound/pcm_params.h> |
| @@ -32,6 +33,7 @@ | |||
| 32 | #include <linux/platform_data/asoc-imx-ssi.h> | 33 | #include <linux/platform_data/asoc-imx-ssi.h> |
| 33 | 34 | ||
| 34 | #include "imx-ssi.h" | 35 | #include "imx-ssi.h" |
| 36 | #include "imx-pcm.h" | ||
| 35 | 37 | ||
| 36 | struct imx_pcm_runtime_data { | 38 | struct imx_pcm_runtime_data { |
| 37 | unsigned int period; | 39 | unsigned int period; |
| @@ -366,9 +368,9 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = { | |||
| 366 | .pcm_free = imx_pcm_fiq_free, | 368 | .pcm_free = imx_pcm_fiq_free, |
| 367 | }; | 369 | }; |
| 368 | 370 | ||
| 369 | int imx_pcm_fiq_init(struct platform_device *pdev) | 371 | int imx_pcm_fiq_init(struct platform_device *pdev, |
| 372 | struct imx_pcm_fiq_params *params) | ||
| 370 | { | 373 | { |
| 371 | struct imx_ssi *ssi = platform_get_drvdata(pdev); | ||
| 372 | int ret; | 374 | int ret; |
| 373 | 375 | ||
| 374 | ret = claim_fiq(&fh); | 376 | ret = claim_fiq(&fh); |
| @@ -377,15 +379,15 @@ int imx_pcm_fiq_init(struct platform_device *pdev) | |||
| 377 | return ret; | 379 | return ret; |
| 378 | } | 380 | } |
| 379 | 381 | ||
| 380 | mxc_set_irq_fiq(ssi->irq, 1); | 382 | mxc_set_irq_fiq(params->irq, 1); |
| 381 | ssi_irq = ssi->irq; | 383 | ssi_irq = params->irq; |
| 382 | 384 | ||
| 383 | imx_pcm_fiq = ssi->irq; | 385 | imx_pcm_fiq = params->irq; |
| 384 | 386 | ||
| 385 | imx_ssi_fiq_base = (unsigned long)ssi->base; | 387 | imx_ssi_fiq_base = (unsigned long)params->base; |
| 386 | 388 | ||
| 387 | ssi->dma_params_tx.maxburst = 4; | 389 | params->dma_params_tx->maxburst = 4; |
| 388 | ssi->dma_params_rx.maxburst = 6; | 390 | params->dma_params_rx->maxburst = 6; |
| 389 | 391 | ||
| 390 | ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); | 392 | ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); |
| 391 | if (ret) | 393 | if (ret) |
| @@ -406,3 +408,5 @@ void imx_pcm_fiq_exit(struct platform_device *pdev) | |||
| 406 | snd_soc_unregister_platform(&pdev->dev); | 408 | snd_soc_unregister_platform(&pdev->dev); |
| 407 | } | 409 | } |
| 408 | EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit); | 410 | EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit); |
| 411 | |||
| 412 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index 67f656c7c320..5d5b73303e11 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h | |||
| @@ -22,17 +22,23 @@ | |||
| 22 | 22 | ||
| 23 | static inline void | 23 | static inline void |
| 24 | imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, | 24 | imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, |
| 25 | int dma, bool shared) | 25 | int dma, enum sdma_peripheral_type peripheral_type) |
| 26 | { | 26 | { |
| 27 | dma_data->dma_request = dma; | 27 | dma_data->dma_request = dma; |
| 28 | dma_data->priority = DMA_PRIO_HIGH; | 28 | dma_data->priority = DMA_PRIO_HIGH; |
| 29 | if (shared) | 29 | dma_data->peripheral_type = peripheral_type; |
| 30 | dma_data->peripheral_type = IMX_DMATYPE_SSI_SP; | ||
| 31 | else | ||
| 32 | dma_data->peripheral_type = IMX_DMATYPE_SSI; | ||
| 33 | } | 30 | } |
| 34 | 31 | ||
| 35 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA | 32 | struct imx_pcm_fiq_params { |
| 33 | int irq; | ||
| 34 | void __iomem *base; | ||
| 35 | |||
| 36 | /* Pointer to original ssi driver to setup tx rx sizes */ | ||
| 37 | struct snd_dmaengine_dai_dma_data *dma_params_rx; | ||
| 38 | struct snd_dmaengine_dai_dma_data *dma_params_tx; | ||
| 39 | }; | ||
| 40 | |||
| 41 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA) | ||
| 36 | int imx_pcm_dma_init(struct platform_device *pdev); | 42 | int imx_pcm_dma_init(struct platform_device *pdev); |
| 37 | void imx_pcm_dma_exit(struct platform_device *pdev); | 43 | void imx_pcm_dma_exit(struct platform_device *pdev); |
| 38 | #else | 44 | #else |
| @@ -46,11 +52,13 @@ static inline void imx_pcm_dma_exit(struct platform_device *pdev) | |||
| 46 | } | 52 | } |
| 47 | #endif | 53 | #endif |
| 48 | 54 | ||
| 49 | #ifdef CONFIG_SND_SOC_IMX_PCM_FIQ | 55 | #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ) |
| 50 | int imx_pcm_fiq_init(struct platform_device *pdev); | 56 | int imx_pcm_fiq_init(struct platform_device *pdev, |
| 57 | struct imx_pcm_fiq_params *params); | ||
| 51 | void imx_pcm_fiq_exit(struct platform_device *pdev); | 58 | void imx_pcm_fiq_exit(struct platform_device *pdev); |
| 52 | #else | 59 | #else |
| 53 | static inline int imx_pcm_fiq_init(struct platform_device *pdev) | 60 | static inline int imx_pcm_fiq_init(struct platform_device *pdev, |
| 61 | struct imx_pcm_fiq_params *params) | ||
| 54 | { | 62 | { |
| 55 | return -ENODEV; | 63 | return -ENODEV; |
| 56 | } | 64 | } |
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 3f726e4f88db..389cbfa6dca7 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c | |||
| @@ -129,8 +129,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | data->codec_clk = devm_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 | ret = PTR_ERR(data->codec_clk); | ||
| 133 | goto fail; | 134 | goto fail; |
| 135 | } | ||
| 134 | 136 | ||
| 135 | data->clk_frequency = clk_get_rate(data->codec_clk); | 137 | data->clk_frequency = clk_get_rate(data->codec_clk); |
| 136 | 138 | ||
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 51be3772cba9..f58bcd85c07f 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
| @@ -571,13 +571,13 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 571 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); | 571 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); |
| 572 | if (res) { | 572 | if (res) { |
| 573 | imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, | 573 | imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, |
| 574 | false); | 574 | IMX_DMATYPE_SSI); |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); | 577 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); |
| 578 | if (res) { | 578 | if (res) { |
| 579 | imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, | 579 | imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, |
| 580 | false); | 580 | IMX_DMATYPE_SSI); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | platform_set_drvdata(pdev, ssi); | 583 | platform_set_drvdata(pdev, ssi); |
| @@ -595,7 +595,12 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 595 | goto failed_register; | 595 | goto failed_register; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | ret = imx_pcm_fiq_init(pdev); | 598 | ssi->fiq_params.irq = ssi->irq; |
| 599 | ssi->fiq_params.base = ssi->base; | ||
| 600 | ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx; | ||
| 601 | ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx; | ||
| 602 | |||
| 603 | ret = imx_pcm_fiq_init(pdev, &ssi->fiq_params); | ||
| 599 | if (ret) | 604 | if (ret) |
| 600 | goto failed_pcm_fiq; | 605 | goto failed_pcm_fiq; |
| 601 | 606 | ||
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h index d5003cefca8d..fb1616ba8c59 100644 --- a/sound/soc/fsl/imx-ssi.h +++ b/sound/soc/fsl/imx-ssi.h | |||
| @@ -209,6 +209,7 @@ struct imx_ssi { | |||
| 209 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 209 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
| 210 | struct imx_dma_data filter_data_tx; | 210 | struct imx_dma_data filter_data_tx; |
| 211 | struct imx_dma_data filter_data_rx; | 211 | struct imx_dma_data filter_data_rx; |
| 212 | struct imx_pcm_fiq_params fiq_params; | ||
| 212 | 213 | ||
| 213 | int enabled; | 214 | int enabled; |
| 214 | }; | 215 | }; |
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 52a36a90f4f4..1d70e278e915 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c | |||
| @@ -217,7 +217,8 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
| 217 | codec_dev = of_find_i2c_device_by_node(codec_np); | 217 | codec_dev = of_find_i2c_device_by_node(codec_np); |
| 218 | if (!codec_dev || !codec_dev->driver) { | 218 | if (!codec_dev || !codec_dev->driver) { |
| 219 | dev_err(&pdev->dev, "failed to find codec platform device\n"); | 219 | dev_err(&pdev->dev, "failed to find codec platform device\n"); |
| 220 | return -EINVAL; | 220 | ret = -EINVAL; |
| 221 | goto fail; | ||
| 221 | } | 222 | } |
| 222 | 223 | ||
| 223 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 224 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index c62d715235e2..9e1970c44e86 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig | |||
| @@ -1,19 +1,15 @@ | |||
| 1 | config SND_KIRKWOOD_SOC | 1 | config SND_KIRKWOOD_SOC |
| 2 | tristate "SoC Audio for the Marvell Kirkwood chip" | 2 | tristate "SoC Audio for the Marvell Kirkwood chip" |
| 3 | depends on ARCH_KIRKWOOD | 3 | depends on ARCH_KIRKWOOD || COMPILE_TEST |
| 4 | help | 4 | help |
| 5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
| 6 | the Kirkwood I2S interface. You will also need to select the | 6 | the Kirkwood I2S interface. You will also need to select the |
| 7 | audio interfaces to support below. | 7 | audio interfaces to support below. |
| 8 | 8 | ||
| 9 | config SND_KIRKWOOD_SOC_I2S | ||
| 10 | tristate | ||
| 11 | |||
| 12 | config SND_KIRKWOOD_SOC_OPENRD | 9 | config SND_KIRKWOOD_SOC_OPENRD |
| 13 | tristate "SoC Audio support for Kirkwood Openrd Client" | 10 | tristate "SoC Audio support for Kirkwood Openrd Client" |
| 14 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE) | 11 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) |
| 15 | depends on I2C | 12 | depends on I2C |
| 16 | select SND_KIRKWOOD_SOC_I2S | ||
| 17 | select SND_SOC_CS42L51 | 13 | select SND_SOC_CS42L51 |
| 18 | help | 14 | help |
| 19 | Say Y if you want to add support for SoC audio on | 15 | Say Y if you want to add support for SoC audio on |
| @@ -21,8 +17,7 @@ config SND_KIRKWOOD_SOC_OPENRD | |||
| 21 | 17 | ||
| 22 | config SND_KIRKWOOD_SOC_T5325 | 18 | config SND_KIRKWOOD_SOC_T5325 |
| 23 | tristate "SoC Audio support for HP t5325" | 19 | tristate "SoC Audio support for HP t5325" |
| 24 | depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C | 20 | depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C |
| 25 | select SND_KIRKWOOD_SOC_I2S | ||
| 26 | select SND_SOC_ALC5623 | 21 | select SND_SOC_ALC5623 |
| 27 | help | 22 | help |
| 28 | Say Y if you want to add support for SoC audio on | 23 | Say Y if you want to add support for SoC audio on |
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 3e62ae9e7bbe..9e781385cb88 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | snd-soc-kirkwood-objs := kirkwood-dma.o | 1 | snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o |
| 2 | snd-soc-kirkwood-i2s-objs := kirkwood-i2s.o | ||
| 3 | 2 | ||
| 4 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o | 3 | obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o |
| 5 | obj-$(CONFIG_SND_KIRKWOOD_SOC_I2S) += snd-soc-kirkwood-i2s.o | ||
| 6 | 4 | ||
| 7 | snd-soc-openrd-objs := kirkwood-openrd.o | 5 | snd-soc-openrd-objs := kirkwood-openrd.o |
| 8 | snd-soc-t5325-objs := kirkwood-t5325.o | 6 | snd-soc-t5325-objs := kirkwood-t5325.o |
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index a9f14530c3db..b238434f92b0 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
| @@ -33,11 +33,11 @@ | |||
| 33 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \ | 33 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \ |
| 34 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE) | 34 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE) |
| 35 | 35 | ||
| 36 | struct kirkwood_dma_priv { | 36 | static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) |
| 37 | struct snd_pcm_substream *play_stream; | 37 | { |
| 38 | struct snd_pcm_substream *rec_stream; | 38 | struct snd_soc_pcm_runtime *soc_runtime = subs->private_data; |
| 39 | struct kirkwood_dma_data *data; | 39 | return snd_soc_dai_get_drvdata(soc_runtime->cpu_dai); |
| 40 | }; | 40 | } |
| 41 | 41 | ||
| 42 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { | 42 | static struct snd_pcm_hardware kirkwood_dma_snd_hw = { |
| 43 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | 43 | .info = (SNDRV_PCM_INFO_INTERLEAVED | |
| @@ -51,7 +51,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = { | |||
| 51 | .rate_max = 384000, | 51 | .rate_max = 384000, |
| 52 | .channels_min = 1, | 52 | .channels_min = 1, |
| 53 | .channels_max = 8, | 53 | .channels_max = 8, |
| 54 | .buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS, | 54 | .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, |
| 55 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, | 55 | .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, |
| 56 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, | 56 | .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, |
| 57 | .periods_min = KIRKWOOD_SND_MIN_PERIODS, | 57 | .periods_min = KIRKWOOD_SND_MIN_PERIODS, |
| @@ -63,8 +63,7 @@ static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32); | |||
| 63 | 63 | ||
| 64 | static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) | 64 | static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) |
| 65 | { | 65 | { |
| 66 | struct kirkwood_dma_priv *prdata = dev_id; | 66 | struct kirkwood_dma_data *priv = dev_id; |
| 67 | struct kirkwood_dma_data *priv = prdata->data; | ||
| 68 | unsigned long mask, status, cause; | 67 | unsigned long mask, status, cause; |
| 69 | 68 | ||
| 70 | mask = readl(priv->io + KIRKWOOD_INT_MASK); | 69 | mask = readl(priv->io + KIRKWOOD_INT_MASK); |
| @@ -89,10 +88,10 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) | |||
| 89 | writel(status, priv->io + KIRKWOOD_INT_CAUSE); | 88 | writel(status, priv->io + KIRKWOOD_INT_CAUSE); |
| 90 | 89 | ||
| 91 | if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES) | 90 | if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES) |
| 92 | snd_pcm_period_elapsed(prdata->play_stream); | 91 | snd_pcm_period_elapsed(priv->substream_play); |
| 93 | 92 | ||
| 94 | if (status & KIRKWOOD_INT_CAUSE_REC_BYTES) | 93 | if (status & KIRKWOOD_INT_CAUSE_REC_BYTES) |
| 95 | snd_pcm_period_elapsed(prdata->rec_stream); | 94 | snd_pcm_period_elapsed(priv->substream_rec); |
| 96 | 95 | ||
| 97 | return IRQ_HANDLED; | 96 | return IRQ_HANDLED; |
| 98 | } | 97 | } |
| @@ -126,15 +125,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
| 126 | { | 125 | { |
| 127 | int err; | 126 | int err; |
| 128 | struct snd_pcm_runtime *runtime = substream->runtime; | 127 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 129 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 128 | struct kirkwood_dma_data *priv = kirkwood_priv(substream); |
| 130 | struct snd_soc_platform *platform = soc_runtime->platform; | ||
| 131 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
| 132 | struct kirkwood_dma_data *priv; | ||
| 133 | struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); | ||
| 134 | const struct mbus_dram_target_info *dram; | 129 | const struct mbus_dram_target_info *dram; |
| 135 | unsigned long addr; | 130 | unsigned long addr; |
| 136 | 131 | ||
| 137 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | ||
| 138 | snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); | 132 | snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); |
| 139 | 133 | ||
| 140 | /* Ensure that all constraints linked to dma burst are fulfilled */ | 134 | /* Ensure that all constraints linked to dma burst are fulfilled */ |
| @@ -157,21 +151,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
| 157 | if (err < 0) | 151 | if (err < 0) |
| 158 | return err; | 152 | return err; |
| 159 | 153 | ||
| 160 | if (prdata == NULL) { | 154 | if (!priv->substream_play && !priv->substream_rec) { |
| 161 | prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); | ||
| 162 | if (prdata == NULL) | ||
| 163 | return -ENOMEM; | ||
| 164 | |||
| 165 | prdata->data = priv; | ||
| 166 | |||
| 167 | err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, | 155 | err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, |
| 168 | "kirkwood-i2s", prdata); | 156 | "kirkwood-i2s", priv); |
| 169 | if (err) { | 157 | if (err) |
| 170 | kfree(prdata); | ||
| 171 | return -EBUSY; | 158 | return -EBUSY; |
| 172 | } | ||
| 173 | |||
| 174 | snd_soc_platform_set_drvdata(platform, prdata); | ||
| 175 | 159 | ||
| 176 | /* | 160 | /* |
| 177 | * Enable Error interrupts. We're only ack'ing them but | 161 | * Enable Error interrupts. We're only ack'ing them but |
| @@ -183,11 +167,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
| 183 | dram = mv_mbus_dram_info(); | 167 | dram = mv_mbus_dram_info(); |
| 184 | addr = substream->dma_buffer.addr; | 168 | addr = substream->dma_buffer.addr; |
| 185 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 169 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 186 | prdata->play_stream = substream; | 170 | priv->substream_play = substream; |
| 187 | kirkwood_dma_conf_mbus_windows(priv->io, | 171 | kirkwood_dma_conf_mbus_windows(priv->io, |
| 188 | KIRKWOOD_PLAYBACK_WIN, addr, dram); | 172 | KIRKWOOD_PLAYBACK_WIN, addr, dram); |
| 189 | } else { | 173 | } else { |
| 190 | prdata->rec_stream = substream; | 174 | priv->substream_rec = substream; |
| 191 | kirkwood_dma_conf_mbus_windows(priv->io, | 175 | kirkwood_dma_conf_mbus_windows(priv->io, |
| 192 | KIRKWOOD_RECORD_WIN, addr, dram); | 176 | KIRKWOOD_RECORD_WIN, addr, dram); |
| 193 | } | 177 | } |
| @@ -197,27 +181,19 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
| 197 | 181 | ||
| 198 | static int kirkwood_dma_close(struct snd_pcm_substream *substream) | 182 | static int kirkwood_dma_close(struct snd_pcm_substream *substream) |
| 199 | { | 183 | { |
| 200 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 184 | struct kirkwood_dma_data *priv = kirkwood_priv(substream); |
| 201 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
| 202 | struct snd_soc_platform *platform = soc_runtime->platform; | ||
| 203 | struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); | ||
| 204 | struct kirkwood_dma_data *priv; | ||
| 205 | |||
| 206 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | ||
| 207 | 185 | ||
| 208 | if (!prdata || !priv) | 186 | if (!priv) |
| 209 | return 0; | 187 | return 0; |
| 210 | 188 | ||
| 211 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 189 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 212 | prdata->play_stream = NULL; | 190 | priv->substream_play = NULL; |
| 213 | else | 191 | else |
| 214 | prdata->rec_stream = NULL; | 192 | priv->substream_rec = NULL; |
| 215 | 193 | ||
| 216 | if (!prdata->play_stream && !prdata->rec_stream) { | 194 | if (!priv->substream_play && !priv->substream_rec) { |
| 217 | writel(0, priv->io + KIRKWOOD_ERR_MASK); | 195 | writel(0, priv->io + KIRKWOOD_ERR_MASK); |
| 218 | free_irq(priv->irq, prdata); | 196 | free_irq(priv->irq, priv); |
| 219 | kfree(prdata); | ||
| 220 | snd_soc_platform_set_drvdata(platform, NULL); | ||
| 221 | } | 197 | } |
| 222 | 198 | ||
| 223 | return 0; | 199 | return 0; |
| @@ -243,13 +219,9 @@ static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream) | |||
| 243 | static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) | 219 | static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) |
| 244 | { | 220 | { |
| 245 | struct snd_pcm_runtime *runtime = substream->runtime; | 221 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 246 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 222 | struct kirkwood_dma_data *priv = kirkwood_priv(substream); |
| 247 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
| 248 | struct kirkwood_dma_data *priv; | ||
| 249 | unsigned long size, count; | 223 | unsigned long size, count; |
| 250 | 224 | ||
| 251 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | ||
| 252 | |||
| 253 | /* compute buffer size in term of "words" as requested in specs */ | 225 | /* compute buffer size in term of "words" as requested in specs */ |
| 254 | size = frames_to_bytes(runtime, runtime->buffer_size); | 226 | size = frames_to_bytes(runtime, runtime->buffer_size); |
| 255 | size = (size>>2)-1; | 227 | size = (size>>2)-1; |
| @@ -272,13 +244,9 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) | |||
| 272 | static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream | 244 | static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream |
| 273 | *substream) | 245 | *substream) |
| 274 | { | 246 | { |
| 275 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 247 | struct kirkwood_dma_data *priv = kirkwood_priv(substream); |
| 276 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
| 277 | struct kirkwood_dma_data *priv; | ||
| 278 | snd_pcm_uframes_t count; | 248 | snd_pcm_uframes_t count; |
| 279 | 249 | ||
| 280 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | ||
| 281 | |||
| 282 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 250 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 283 | count = bytes_to_frames(substream->runtime, | 251 | count = bytes_to_frames(substream->runtime, |
| 284 | readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); | 252 | readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); |
| @@ -366,36 +334,8 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
| 366 | } | 334 | } |
| 367 | } | 335 | } |
| 368 | 336 | ||
| 369 | static struct snd_soc_platform_driver kirkwood_soc_platform = { | 337 | struct snd_soc_platform_driver kirkwood_soc_platform = { |
| 370 | .ops = &kirkwood_dma_ops, | 338 | .ops = &kirkwood_dma_ops, |
| 371 | .pcm_new = kirkwood_dma_new, | 339 | .pcm_new = kirkwood_dma_new, |
| 372 | .pcm_free = kirkwood_dma_free_dma_buffers, | 340 | .pcm_free = kirkwood_dma_free_dma_buffers, |
| 373 | }; | 341 | }; |
| 374 | |||
| 375 | static int kirkwood_soc_platform_probe(struct platform_device *pdev) | ||
| 376 | { | ||
| 377 | return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); | ||
| 378 | } | ||
| 379 | |||
| 380 | static int kirkwood_soc_platform_remove(struct platform_device *pdev) | ||
| 381 | { | ||
| 382 | snd_soc_unregister_platform(&pdev->dev); | ||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | static struct platform_driver kirkwood_pcm_driver = { | ||
| 387 | .driver = { | ||
| 388 | .name = "kirkwood-pcm-audio", | ||
| 389 | .owner = THIS_MODULE, | ||
| 390 | }, | ||
| 391 | |||
| 392 | .probe = kirkwood_soc_platform_probe, | ||
| 393 | .remove = kirkwood_soc_platform_remove, | ||
| 394 | }; | ||
| 395 | |||
| 396 | module_platform_driver(kirkwood_pcm_driver); | ||
| 397 | |||
| 398 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | ||
| 399 | MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); | ||
| 400 | MODULE_LICENSE("GPL"); | ||
| 401 | MODULE_ALIAS("platform:kirkwood-pcm-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 4c9dad3263c5..e5f3f7a9ea26 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
| @@ -24,11 +24,8 @@ | |||
| 24 | #include <linux/platform_data/asoc-kirkwood.h> | 24 | #include <linux/platform_data/asoc-kirkwood.h> |
| 25 | #include "kirkwood.h" | 25 | #include "kirkwood.h" |
| 26 | 26 | ||
| 27 | #define DRV_NAME "kirkwood-i2s" | 27 | #define DRV_NAME "mvebu-audio" |
| 28 | 28 | ||
| 29 | #define KIRKWOOD_I2S_RATES \ | ||
| 30 | (SNDRV_PCM_RATE_44100 | \ | ||
| 31 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | ||
| 32 | #define KIRKWOOD_I2S_FORMATS \ | 29 | #define KIRKWOOD_I2S_FORMATS \ |
| 33 | (SNDRV_PCM_FMTBIT_S16_LE | \ | 30 | (SNDRV_PCM_FMTBIT_S16_LE | \ |
| 34 | SNDRV_PCM_FMTBIT_S24_LE | \ | 31 | SNDRV_PCM_FMTBIT_S24_LE | \ |
| @@ -105,14 +102,16 @@ static void kirkwood_set_rate(struct snd_soc_dai *dai, | |||
| 105 | uint32_t clks_ctrl; | 102 | uint32_t clks_ctrl; |
| 106 | 103 | ||
| 107 | if (rate == 44100 || rate == 48000 || rate == 96000) { | 104 | if (rate == 44100 || rate == 48000 || rate == 96000) { |
| 108 | /* use internal dco for supported rates */ | 105 | /* use internal dco for the supported rates |
| 106 | * defined in kirkwood_i2s_dai */ | ||
| 109 | dev_dbg(dai->dev, "%s: dco set rate = %lu\n", | 107 | dev_dbg(dai->dev, "%s: dco set rate = %lu\n", |
| 110 | __func__, rate); | 108 | __func__, rate); |
| 111 | kirkwood_set_dco(priv->io, rate); | 109 | kirkwood_set_dco(priv->io, rate); |
| 112 | 110 | ||
| 113 | clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; | 111 | clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; |
| 114 | } else if (!IS_ERR(priv->extclk)) { | 112 | } else { |
| 115 | /* use optional external clk for other rates */ | 113 | /* use the external clock for the other rates |
| 114 | * defined in kirkwood_i2s_dai_extclk */ | ||
| 116 | dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", | 115 | dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", |
| 117 | __func__, rate, 256 * rate); | 116 | __func__, rate, 256 * rate); |
| 118 | clk_set_rate(priv->extclk, 256 * rate); | 117 | clk_set_rate(priv->extclk, 256 * rate); |
| @@ -199,8 +198,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
| 199 | ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; | 198 | ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; |
| 200 | 199 | ||
| 201 | priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | | 200 | priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | |
| 202 | KIRKWOOD_PLAYCTL_I2S_EN | | 201 | KIRKWOOD_PLAYCTL_ENABLE_MASK | |
| 203 | KIRKWOOD_PLAYCTL_SPDIF_EN | | ||
| 204 | KIRKWOOD_PLAYCTL_SIZE_MASK); | 202 | KIRKWOOD_PLAYCTL_SIZE_MASK); |
| 205 | priv->ctl_play |= ctl_play; | 203 | priv->ctl_play |= ctl_play; |
| 206 | } else { | 204 | } else { |
| @@ -244,8 +242,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
| 244 | case SNDRV_PCM_TRIGGER_START: | 242 | case SNDRV_PCM_TRIGGER_START: |
| 245 | /* configure */ | 243 | /* configure */ |
| 246 | ctl = priv->ctl_play; | 244 | ctl = priv->ctl_play; |
| 247 | value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN | | 245 | value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
| 248 | KIRKWOOD_PLAYCTL_SPDIF_EN); | ||
| 249 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 246 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
| 250 | 247 | ||
| 251 | /* enable interrupts */ | 248 | /* enable interrupts */ |
| @@ -267,7 +264,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
| 267 | writel(value, priv->io + KIRKWOOD_INT_MASK); | 264 | writel(value, priv->io + KIRKWOOD_INT_MASK); |
| 268 | 265 | ||
| 269 | /* disable all playbacks */ | 266 | /* disable all playbacks */ |
| 270 | ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); | 267 | ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
| 271 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); | 268 | writel(ctl, priv->io + KIRKWOOD_PLAYCTL); |
| 272 | break; | 269 | break; |
| 273 | 270 | ||
| @@ -387,7 +384,7 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai) | |||
| 387 | 384 | ||
| 388 | /* disable playback/record */ | 385 | /* disable playback/record */ |
| 389 | value = readl(priv->io + KIRKWOOD_PLAYCTL); | 386 | value = readl(priv->io + KIRKWOOD_PLAYCTL); |
| 390 | value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN); | 387 | value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK; |
| 391 | writel(value, priv->io + KIRKWOOD_PLAYCTL); | 388 | writel(value, priv->io + KIRKWOOD_PLAYCTL); |
| 392 | 389 | ||
| 393 | value = readl(priv->io + KIRKWOOD_RECCTL); | 390 | value = readl(priv->io + KIRKWOOD_RECCTL); |
| @@ -398,11 +395,6 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai) | |||
| 398 | 395 | ||
| 399 | } | 396 | } |
| 400 | 397 | ||
| 401 | static int kirkwood_i2s_remove(struct snd_soc_dai *dai) | ||
| 402 | { | ||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 406 | static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { | 398 | static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { |
| 407 | .startup = kirkwood_i2s_startup, | 399 | .startup = kirkwood_i2s_startup, |
| 408 | .trigger = kirkwood_i2s_trigger, | 400 | .trigger = kirkwood_i2s_trigger, |
| @@ -413,17 +405,18 @@ static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { | |||
| 413 | 405 | ||
| 414 | static struct snd_soc_dai_driver kirkwood_i2s_dai = { | 406 | static struct snd_soc_dai_driver kirkwood_i2s_dai = { |
| 415 | .probe = kirkwood_i2s_probe, | 407 | .probe = kirkwood_i2s_probe, |
| 416 | .remove = kirkwood_i2s_remove, | ||
| 417 | .playback = { | 408 | .playback = { |
| 418 | .channels_min = 1, | 409 | .channels_min = 1, |
| 419 | .channels_max = 2, | 410 | .channels_max = 2, |
| 420 | .rates = KIRKWOOD_I2S_RATES, | 411 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
| 412 | SNDRV_PCM_RATE_96000, | ||
| 421 | .formats = KIRKWOOD_I2S_FORMATS, | 413 | .formats = KIRKWOOD_I2S_FORMATS, |
| 422 | }, | 414 | }, |
| 423 | .capture = { | 415 | .capture = { |
| 424 | .channels_min = 1, | 416 | .channels_min = 1, |
| 425 | .channels_max = 2, | 417 | .channels_max = 2, |
| 426 | .rates = KIRKWOOD_I2S_RATES, | 418 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
| 419 | SNDRV_PCM_RATE_96000, | ||
| 427 | .formats = KIRKWOOD_I2S_FORMATS, | 420 | .formats = KIRKWOOD_I2S_FORMATS, |
| 428 | }, | 421 | }, |
| 429 | .ops = &kirkwood_i2s_dai_ops, | 422 | .ops = &kirkwood_i2s_dai_ops, |
| @@ -431,7 +424,6 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = { | |||
| 431 | 424 | ||
| 432 | static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { | 425 | static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { |
| 433 | .probe = kirkwood_i2s_probe, | 426 | .probe = kirkwood_i2s_probe, |
| 434 | .remove = kirkwood_i2s_remove, | ||
| 435 | .playback = { | 427 | .playback = { |
| 436 | .channels_min = 1, | 428 | .channels_min = 1, |
| 437 | .channels_max = 2, | 429 | .channels_max = 2, |
| @@ -498,10 +490,10 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
| 498 | if (err < 0) | 490 | if (err < 0) |
| 499 | return err; | 491 | return err; |
| 500 | 492 | ||
| 501 | priv->extclk = clk_get(&pdev->dev, "extclk"); | 493 | priv->extclk = devm_clk_get(&pdev->dev, "extclk"); |
| 502 | if (!IS_ERR(priv->extclk)) { | 494 | if (!IS_ERR(priv->extclk)) { |
| 503 | if (priv->extclk == priv->clk) { | 495 | if (priv->extclk == priv->clk) { |
| 504 | clk_put(priv->extclk); | 496 | devm_clk_put(&pdev->dev, priv->extclk); |
| 505 | priv->extclk = ERR_PTR(-EINVAL); | 497 | priv->extclk = ERR_PTR(-EINVAL); |
| 506 | } else { | 498 | } else { |
| 507 | dev_info(&pdev->dev, "found external clock\n"); | 499 | dev_info(&pdev->dev, "found external clock\n"); |
| @@ -525,14 +517,22 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
| 525 | 517 | ||
| 526 | err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, | 518 | err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, |
| 527 | soc_dai, 1); | 519 | soc_dai, 1); |
| 528 | if (!err) | 520 | if (err) { |
| 529 | return 0; | 521 | dev_err(&pdev->dev, "snd_soc_register_component failed\n"); |
| 530 | dev_err(&pdev->dev, "snd_soc_register_component failed\n"); | 522 | goto err_component; |
| 523 | } | ||
| 531 | 524 | ||
| 532 | if (!IS_ERR(priv->extclk)) { | 525 | err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); |
| 533 | clk_disable_unprepare(priv->extclk); | 526 | if (err) { |
| 534 | clk_put(priv->extclk); | 527 | dev_err(&pdev->dev, "snd_soc_register_platform failed\n"); |
| 528 | goto err_platform; | ||
| 535 | } | 529 | } |
| 530 | return 0; | ||
| 531 | err_platform: | ||
| 532 | snd_soc_unregister_component(&pdev->dev); | ||
| 533 | err_component: | ||
| 534 | if (!IS_ERR(priv->extclk)) | ||
| 535 | clk_disable_unprepare(priv->extclk); | ||
| 536 | clk_disable_unprepare(priv->clk); | 536 | clk_disable_unprepare(priv->clk); |
| 537 | 537 | ||
| 538 | return err; | 538 | return err; |
| @@ -542,12 +542,11 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) | |||
| 542 | { | 542 | { |
| 543 | struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); | 543 | struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); |
| 544 | 544 | ||
| 545 | snd_soc_unregister_platform(&pdev->dev); | ||
| 545 | snd_soc_unregister_component(&pdev->dev); | 546 | snd_soc_unregister_component(&pdev->dev); |
| 546 | 547 | ||
| 547 | if (!IS_ERR(priv->extclk)) { | 548 | if (!IS_ERR(priv->extclk)) |
| 548 | clk_disable_unprepare(priv->extclk); | 549 | clk_disable_unprepare(priv->extclk); |
| 549 | clk_put(priv->extclk); | ||
| 550 | } | ||
| 551 | clk_disable_unprepare(priv->clk); | 550 | clk_disable_unprepare(priv->clk); |
| 552 | 551 | ||
| 553 | return 0; | 552 | return 0; |
| @@ -568,4 +567,4 @@ module_platform_driver(kirkwood_i2s_driver); | |||
| 568 | MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); | 567 | MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); |
| 569 | MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); | 568 | MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); |
| 570 | MODULE_LICENSE("GPL"); | 569 | MODULE_LICENSE("GPL"); |
| 571 | MODULE_ALIAS("platform:kirkwood-i2s"); | 570 | MODULE_ALIAS("platform:mvebu-audio"); |
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c index b979c7154715..025be0e97164 100644 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ b/sound/soc/kirkwood/kirkwood-openrd.c | |||
| @@ -16,9 +16,7 @@ | |||
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
| 19 | #include <mach/kirkwood.h> | ||
| 20 | #include <linux/platform_data/asoc-kirkwood.h> | 19 | #include <linux/platform_data/asoc-kirkwood.h> |
| 21 | #include <asm/mach-types.h> | ||
| 22 | #include "../codecs/cs42l51.h" | 20 | #include "../codecs/cs42l51.h" |
| 23 | 21 | ||
| 24 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, | 22 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, |
| @@ -54,8 +52,8 @@ static struct snd_soc_dai_link openrd_client_dai[] = { | |||
| 54 | { | 52 | { |
| 55 | .name = "CS42L51", | 53 | .name = "CS42L51", |
| 56 | .stream_name = "CS42L51 HiFi", | 54 | .stream_name = "CS42L51 HiFi", |
| 57 | .cpu_dai_name = "kirkwood-i2s", | 55 | .cpu_dai_name = "mvebu-audio", |
| 58 | .platform_name = "kirkwood-pcm-audio", | 56 | .platform_name = "mvebu-audio", |
| 59 | .codec_dai_name = "cs42l51-hifi", | 57 | .codec_dai_name = "cs42l51-hifi", |
| 60 | .codec_name = "cs42l51-codec.0-004a", | 58 | .codec_name = "cs42l51-codec.0-004a", |
| 61 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | 59 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, |
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c index 1d0ed6f8add7..27545b0c4856 100644 --- a/sound/soc/kirkwood/kirkwood-t5325.c +++ b/sound/soc/kirkwood/kirkwood-t5325.c | |||
| @@ -15,9 +15,7 @@ | |||
| 15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <sound/soc.h> | 17 | #include <sound/soc.h> |
| 18 | #include <mach/kirkwood.h> | ||
| 19 | #include <linux/platform_data/asoc-kirkwood.h> | 18 | #include <linux/platform_data/asoc-kirkwood.h> |
| 20 | #include <asm/mach-types.h> | ||
| 21 | #include "../codecs/alc5623.h" | 19 | #include "../codecs/alc5623.h" |
| 22 | 20 | ||
| 23 | static int t5325_hw_params(struct snd_pcm_substream *substream, | 21 | static int t5325_hw_params(struct snd_pcm_substream *substream, |
| @@ -70,8 +68,8 @@ static struct snd_soc_dai_link t5325_dai[] = { | |||
| 70 | { | 68 | { |
| 71 | .name = "ALC5621", | 69 | .name = "ALC5621", |
| 72 | .stream_name = "ALC5621 HiFi", | 70 | .stream_name = "ALC5621 HiFi", |
| 73 | .cpu_dai_name = "kirkwood-i2s", | 71 | .cpu_dai_name = "mvebu-audio", |
| 74 | .platform_name = "kirkwood-pcm-audio", | 72 | .platform_name = "mvebu-audio", |
| 75 | .codec_dai_name = "alc5621-hifi", | 73 | .codec_dai_name = "alc5621-hifi", |
| 76 | .codec_name = "alc562x-codec.0-001a", | 74 | .codec_name = "alc562x-codec.0-001a", |
| 77 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | 75 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, |
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h index 4d92637ddb3f..f8e1ccc1c58c 100644 --- a/sound/soc/kirkwood/kirkwood.h +++ b/sound/soc/kirkwood/kirkwood.h | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | #define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5) | 54 | #define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5) |
| 55 | #define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7) | 55 | #define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7) |
| 56 | #define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4) | 56 | #define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4) |
| 57 | #define KIRKWOOD_PLAYCTL_I2S_EN (1<<3) | 57 | #define KIRKWOOD_PLAYCTL_I2S_EN (1<<3) |
| 58 | #define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0) | 58 | #define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0) |
| 59 | #define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0) | 59 | #define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0) |
| 60 | #define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0) | 60 | #define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0) |
| @@ -62,6 +62,9 @@ | |||
| 62 | #define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0) | 62 | #define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0) |
| 63 | #define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0) | 63 | #define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0) |
| 64 | 64 | ||
| 65 | #define KIRKWOOD_PLAYCTL_ENABLE_MASK (KIRKWOOD_PLAYCTL_SPDIF_EN | \ | ||
| 66 | KIRKWOOD_PLAYCTL_I2S_EN) | ||
| 67 | |||
| 65 | #define KIRKWOOD_PLAY_BUF_ADDR 0x1104 | 68 | #define KIRKWOOD_PLAY_BUF_ADDR 0x1104 |
| 66 | #define KIRKWOOD_PLAY_BUF_SIZE 0x1108 | 69 | #define KIRKWOOD_PLAY_BUF_SIZE 0x1108 |
| 67 | #define KIRKWOOD_PLAY_BYTE_COUNT 0x110C | 70 | #define KIRKWOOD_PLAY_BYTE_COUNT 0x110C |
| @@ -122,6 +125,8 @@ | |||
| 122 | #define KIRKWOOD_SND_MAX_PERIODS 16 | 125 | #define KIRKWOOD_SND_MAX_PERIODS 16 |
| 123 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000 | 126 | #define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000 |
| 124 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000 | 127 | #define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000 |
| 128 | #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ | ||
| 129 | * KIRKWOOD_SND_MAX_PERIODS) | ||
| 125 | 130 | ||
| 126 | struct kirkwood_dma_data { | 131 | struct kirkwood_dma_data { |
| 127 | void __iomem *io; | 132 | void __iomem *io; |
| @@ -129,8 +134,12 @@ struct kirkwood_dma_data { | |||
| 129 | struct clk *extclk; | 134 | struct clk *extclk; |
| 130 | uint32_t ctl_play; | 135 | uint32_t ctl_play; |
| 131 | uint32_t ctl_rec; | 136 | uint32_t ctl_rec; |
| 137 | struct snd_pcm_substream *substream_play; | ||
| 138 | struct snd_pcm_substream *substream_rec; | ||
| 132 | int irq; | 139 | int irq; |
| 133 | int burst; | 140 | int burst; |
| 134 | }; | 141 | }; |
| 135 | 142 | ||
| 143 | extern struct snd_soc_platform_driver kirkwood_soc_platform; | ||
| 144 | |||
| 136 | #endif | 145 | #endif |
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index 78d321cbe8b4..219235c02212 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | menuconfig SND_MXS_SOC | 1 | menuconfig SND_MXS_SOC |
| 2 | tristate "SoC Audio for Freescale MXS CPUs" | 2 | tristate "SoC Audio for Freescale MXS CPUs" |
| 3 | depends on ARCH_MXS | 3 | depends on ARCH_MXS || COMPILE_TEST |
| 4 | depends on COMMON_CLK | ||
| 4 | select SND_SOC_GENERIC_DMAENGINE_PCM | 5 | select SND_SOC_GENERIC_DMAENGINE_PCM |
| 5 | help | 6 | help |
| 6 | Say Y or M if you want to add support for codecs attached to | 7 | Say Y or M if you want to add support for codecs attached to |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 54511c5e6a7c..b56b8a0e8deb 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
| 32 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
| 33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
| 34 | #include <asm/mach-types.h> | ||
| 35 | 34 | ||
| 36 | #include "mxs-saif.h" | 35 | #include "mxs-saif.h" |
| 37 | 36 | ||
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 1b134d72f120..ce084eb10c49 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
| 26 | #include <sound/jack.h> | 26 | #include <sound/jack.h> |
| 27 | #include <sound/soc-dapm.h> | 27 | #include <sound/soc-dapm.h> |
| 28 | #include <asm/mach-types.h> | ||
| 29 | 28 | ||
| 30 | #include "../codecs/sgtl5000.h" | 29 | #include "../codecs/sgtl5000.h" |
| 31 | #include "mxs-saif.h" | 30 | #include "mxs-saif.h" |
| @@ -51,18 +50,27 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, | |||
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ | 52 | /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ |
| 54 | if (mclk < 8000000 || mclk > 27000000) | 53 | if (mclk < 8000000 || mclk > 27000000) { |
| 54 | dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n", | ||
| 55 | mclk / 1000000, mclk / 1000 % 1000); | ||
| 55 | return -EINVAL; | 56 | return -EINVAL; |
| 57 | } | ||
| 56 | 58 | ||
| 57 | /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ | 59 | /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ |
| 58 | ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); | 60 | ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); |
| 59 | if (ret) | 61 | if (ret) { |
| 62 | dev_err(codec_dai->dev, "Failed to set sysclk to %u.%03uMHz\n", | ||
| 63 | mclk / 1000000, mclk / 1000 % 1000); | ||
| 60 | return ret; | 64 | return ret; |
| 65 | } | ||
| 61 | 66 | ||
| 62 | /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */ | 67 | /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */ |
| 63 | ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0); | 68 | ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0); |
| 64 | if (ret) | 69 | if (ret) { |
| 70 | dev_err(cpu_dai->dev, "Failed to set sysclk to %u.%03uMHz\n", | ||
| 71 | mclk / 1000000, mclk / 1000 % 1000); | ||
| 65 | return ret; | 72 | return ret; |
| 73 | } | ||
| 66 | 74 | ||
| 67 | /* set codec to slave mode */ | 75 | /* set codec to slave mode */ |
| 68 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 76 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
| @@ -70,13 +78,19 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, | |||
| 70 | 78 | ||
| 71 | /* set codec DAI configuration */ | 79 | /* set codec DAI configuration */ |
| 72 | ret = snd_soc_dai_set_fmt(codec_dai, dai_format); | 80 | ret = snd_soc_dai_set_fmt(codec_dai, dai_format); |
| 73 | if (ret) | 81 | if (ret) { |
| 82 | dev_err(codec_dai->dev, "Failed to set dai format to %08x\n", | ||
| 83 | dai_format); | ||
| 74 | return ret; | 84 | return ret; |
| 85 | } | ||
| 75 | 86 | ||
| 76 | /* set cpu DAI configuration */ | 87 | /* set cpu DAI configuration */ |
| 77 | ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); | 88 | ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); |
| 78 | if (ret) | 89 | if (ret) { |
| 90 | dev_err(cpu_dai->dev, "Failed to set dai format to %08x\n", | ||
| 91 | dai_format); | ||
| 79 | return ret; | 92 | return ret; |
| 93 | } | ||
| 80 | 94 | ||
| 81 | return 0; | 95 | return 0; |
| 82 | } | 96 | } |
| @@ -154,8 +168,10 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) | |||
| 154 | * should be >= 8MHz and <= 27M. | 168 | * should be >= 8MHz and <= 27M. |
| 155 | */ | 169 | */ |
| 156 | ret = mxs_saif_get_mclk(0, 44100 * 256, 44100); | 170 | ret = mxs_saif_get_mclk(0, 44100 * 256, 44100); |
| 157 | if (ret) | 171 | if (ret) { |
| 172 | dev_err(&pdev->dev, "failed to get mclk\n"); | ||
| 158 | return ret; | 173 | return ret; |
| 174 | } | ||
| 159 | 175 | ||
| 160 | card->dev = &pdev->dev; | 176 | card->dev = &pdev->dev; |
| 161 | platform_set_drvdata(pdev, card); | 177 | platform_set_drvdata(pdev, card); |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index f4c2417a8730..8987bf987e58 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
| @@ -333,9 +333,6 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
| 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) | ||
| 337 | return ret; | ||
| 338 | |||
| 339 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, | 336 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, |
| 340 | nuc900_audio->res); | 337 | nuc900_audio->res); |
| 341 | if (IS_ERR(nuc900_audio->mmio)) | 338 | if (IS_ERR(nuc900_audio->mmio)) |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 9f5d55e6b17a..daa78a0095fa 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | config SND_OMAP_SOC | 1 | config SND_OMAP_SOC |
| 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" | 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" |
| 3 | depends on ARCH_OMAP && DMA_OMAP | 3 | depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST) |
| 4 | select SND_SOC_DMAENGINE_PCM | 4 | select SND_DMAENGINE_PCM |
| 5 | 5 | ||
| 6 | config SND_OMAP_SOC_DMIC | 6 | config SND_OMAP_SOC_DMIC |
| 7 | tristate | 7 | tristate |
| @@ -26,7 +26,7 @@ config SND_OMAP_SOC_N810 | |||
| 26 | 26 | ||
| 27 | config SND_OMAP_SOC_RX51 | 27 | config SND_OMAP_SOC_RX51 |
| 28 | tristate "SoC Audio support for Nokia RX-51" | 28 | tristate "SoC Audio support for Nokia RX-51" |
| 29 | depends on SND_OMAP_SOC && MACH_NOKIA_RX51 | 29 | depends on SND_OMAP_SOC && ARCH_ARM && (MACH_NOKIA_RX51 || COMPILE_TEST) |
| 30 | select SND_OMAP_SOC_MCBSP | 30 | select SND_OMAP_SOC_MCBSP |
| 31 | select SND_SOC_TLV320AIC3X | 31 | select SND_SOC_TLV320AIC3X |
| 32 | select SND_SOC_TPA6130A2 | 32 | select SND_SOC_TPA6130A2 |
| @@ -87,7 +87,7 @@ config SND_OMAP_SOC_OMAP_TWL4030 | |||
| 87 | 87 | ||
| 88 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 | 88 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 |
| 89 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" | 89 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" |
| 90 | depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 | 90 | depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST) |
| 91 | select SND_OMAP_SOC_DMIC | 91 | select SND_OMAP_SOC_DMIC |
| 92 | select SND_OMAP_SOC_MCPDM | 92 | select SND_OMAP_SOC_MCPDM |
| 93 | select SND_SOC_TWL6040 | 93 | select SND_SOC_TWL6040 |
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 70cd5c7b2e14..ebb13906b3a0 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | #include <linux/mfd/twl6040.h> | 25 | #include <linux/mfd/twl6040.h> |
| 26 | #include <linux/platform_data/omap-abe-twl6040.h> | ||
| 27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 28 | #include <linux/of.h> | 27 | #include <linux/of.h> |
| 29 | 28 | ||
| @@ -166,19 +165,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
| 166 | {"AFMR", NULL, "Line In"}, | 165 | {"AFMR", NULL, "Line In"}, |
| 167 | }; | 166 | }; |
| 168 | 167 | ||
| 169 | static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm, | ||
| 170 | int connected, char *pin) | ||
| 171 | { | ||
| 172 | if (!connected) | ||
| 173 | snd_soc_dapm_disable_pin(dapm, pin); | ||
| 174 | } | ||
| 175 | |||
| 176 | static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | 168 | static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) |
| 177 | { | 169 | { |
| 178 | struct snd_soc_codec *codec = rtd->codec; | 170 | struct snd_soc_codec *codec = rtd->codec; |
| 179 | struct snd_soc_card *card = codec->card; | 171 | struct snd_soc_card *card = codec->card; |
| 180 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
| 181 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev); | ||
| 182 | struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); | 172 | struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); |
| 183 | int hs_trim; | 173 | int hs_trim; |
| 184 | int ret = 0; | 174 | int ret = 0; |
| @@ -203,24 +193,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
| 203 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); | 193 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); |
| 204 | } | 194 | } |
| 205 | 195 | ||
| 206 | /* | ||
| 207 | * NULL pdata means we booted with DT. In this case the routing is | ||
| 208 | * provided and the card is fully routed, no need to mark pins. | ||
| 209 | */ | ||
| 210 | if (!pdata) | ||
| 211 | return ret; | ||
| 212 | |||
| 213 | /* Disable not connected paths if not used */ | ||
| 214 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
| 215 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
| 216 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
| 217 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
| 218 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); | ||
| 219 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
| 220 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
| 221 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
| 222 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
| 223 | |||
| 224 | return ret; | 196 | return ret; |
| 225 | } | 197 | } |
| 226 | 198 | ||
| @@ -274,13 +246,18 @@ static struct snd_soc_card omap_abe_card = { | |||
| 274 | 246 | ||
| 275 | static int omap_abe_probe(struct platform_device *pdev) | 247 | static int omap_abe_probe(struct platform_device *pdev) |
| 276 | { | 248 | { |
| 277 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 278 | struct device_node *node = pdev->dev.of_node; | 249 | struct device_node *node = pdev->dev.of_node; |
| 279 | struct snd_soc_card *card = &omap_abe_card; | 250 | struct snd_soc_card *card = &omap_abe_card; |
| 251 | struct device_node *dai_node; | ||
| 280 | struct abe_twl6040 *priv; | 252 | struct abe_twl6040 *priv; |
| 281 | int num_links = 0; | 253 | int num_links = 0; |
| 282 | int ret = 0; | 254 | int ret = 0; |
| 283 | 255 | ||
| 256 | if (!node) { | ||
| 257 | dev_err(&pdev->dev, "of node is missing.\n"); | ||
| 258 | return -ENODEV; | ||
| 259 | } | ||
| 260 | |||
| 284 | card->dev = &pdev->dev; | 261 | card->dev = &pdev->dev; |
| 285 | 262 | ||
| 286 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); | 263 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); |
| @@ -289,78 +266,50 @@ static int omap_abe_probe(struct platform_device *pdev) | |||
| 289 | 266 | ||
| 290 | priv->dmic_codec_dev = ERR_PTR(-EINVAL); | 267 | priv->dmic_codec_dev = ERR_PTR(-EINVAL); |
| 291 | 268 | ||
| 292 | if (node) { | 269 | if (snd_soc_of_parse_card_name(card, "ti,model")) { |
| 293 | struct device_node *dai_node; | 270 | dev_err(&pdev->dev, "Card name is not provided\n"); |
| 294 | 271 | return -ENODEV; | |
| 295 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | 272 | } |
| 296 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 297 | return -ENODEV; | ||
| 298 | } | ||
| 299 | 273 | ||
| 300 | ret = snd_soc_of_parse_audio_routing(card, | 274 | ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); |
| 301 | "ti,audio-routing"); | 275 | if (ret) { |
| 302 | if (ret) { | 276 | dev_err(&pdev->dev, "Error while parsing DAPM routing\n"); |
| 303 | dev_err(&pdev->dev, | 277 | return ret; |
| 304 | "Error while parsing DAPM routing\n"); | 278 | } |
| 305 | return ret; | ||
| 306 | } | ||
| 307 | 279 | ||
| 308 | dai_node = of_parse_phandle(node, "ti,mcpdm", 0); | 280 | dai_node = of_parse_phandle(node, "ti,mcpdm", 0); |
| 309 | if (!dai_node) { | 281 | if (!dai_node) { |
| 310 | dev_err(&pdev->dev, "McPDM node is not provided\n"); | 282 | dev_err(&pdev->dev, "McPDM node is not provided\n"); |
| 311 | return -EINVAL; | 283 | return -EINVAL; |
| 312 | } | 284 | } |
| 313 | abe_twl6040_dai_links[0].cpu_dai_name = NULL; | 285 | abe_twl6040_dai_links[0].cpu_dai_name = NULL; |
| 314 | abe_twl6040_dai_links[0].cpu_of_node = dai_node; | 286 | abe_twl6040_dai_links[0].cpu_of_node = dai_node; |
| 315 | 287 | ||
| 316 | dai_node = of_parse_phandle(node, "ti,dmic", 0); | 288 | dai_node = of_parse_phandle(node, "ti,dmic", 0); |
| 317 | if (dai_node) { | 289 | if (dai_node) { |
| 318 | num_links = 2; | 290 | num_links = 2; |
| 319 | abe_twl6040_dai_links[1].cpu_dai_name = NULL; | 291 | abe_twl6040_dai_links[1].cpu_dai_name = NULL; |
| 320 | abe_twl6040_dai_links[1].cpu_of_node = dai_node; | 292 | abe_twl6040_dai_links[1].cpu_of_node = dai_node; |
| 321 | 293 | ||
| 322 | priv->dmic_codec_dev = platform_device_register_simple( | 294 | priv->dmic_codec_dev = platform_device_register_simple( |
| 323 | "dmic-codec", -1, NULL, 0); | 295 | "dmic-codec", -1, NULL, 0); |
| 324 | if (IS_ERR(priv->dmic_codec_dev)) { | 296 | if (IS_ERR(priv->dmic_codec_dev)) { |
| 325 | dev_err(&pdev->dev, | 297 | dev_err(&pdev->dev, "Can't instantiate dmic-codec\n"); |
| 326 | "Can't instantiate dmic-codec\n"); | 298 | return PTR_ERR(priv->dmic_codec_dev); |
| 327 | return PTR_ERR(priv->dmic_codec_dev); | ||
| 328 | } | ||
| 329 | } else { | ||
| 330 | num_links = 1; | ||
| 331 | } | ||
| 332 | |||
| 333 | priv->jack_detection = of_property_read_bool(node, | ||
| 334 | "ti,jack-detection"); | ||
| 335 | of_property_read_u32(node, "ti,mclk-freq", | ||
| 336 | &priv->mclk_freq); | ||
| 337 | if (!priv->mclk_freq) { | ||
| 338 | dev_err(&pdev->dev, "MCLK frequency not provided\n"); | ||
| 339 | ret = -EINVAL; | ||
| 340 | goto err_unregister; | ||
| 341 | } | 299 | } |
| 342 | |||
| 343 | omap_abe_card.fully_routed = 1; | ||
| 344 | } else if (pdata) { | ||
| 345 | if (pdata->card_name) { | ||
| 346 | card->name = pdata->card_name; | ||
| 347 | } else { | ||
| 348 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 349 | return -ENODEV; | ||
| 350 | } | ||
| 351 | |||
| 352 | if (pdata->has_dmic) | ||
| 353 | num_links = 2; | ||
| 354 | else | ||
| 355 | num_links = 1; | ||
| 356 | |||
| 357 | priv->jack_detection = pdata->jack_detection; | ||
| 358 | priv->mclk_freq = pdata->mclk_freq; | ||
| 359 | } else { | 300 | } else { |
| 360 | dev_err(&pdev->dev, "Missing pdata\n"); | 301 | num_links = 1; |
| 361 | return -ENODEV; | 302 | } |
| 303 | |||
| 304 | priv->jack_detection = of_property_read_bool(node, "ti,jack-detection"); | ||
| 305 | of_property_read_u32(node, "ti,mclk-freq", &priv->mclk_freq); | ||
| 306 | if (!priv->mclk_freq) { | ||
| 307 | dev_err(&pdev->dev, "MCLK frequency not provided\n"); | ||
| 308 | ret = -EINVAL; | ||
| 309 | goto err_unregister; | ||
| 362 | } | 310 | } |
| 363 | 311 | ||
| 312 | card->fully_routed = 1; | ||
| 364 | 313 | ||
| 365 | if (!priv->mclk_freq) { | 314 | if (!priv->mclk_freq) { |
| 366 | dev_err(&pdev->dev, "MCLK frequency missing\n"); | 315 | dev_err(&pdev->dev, "MCLK frequency missing\n"); |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 4db1f8e6e172..12e566be3793 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
| @@ -480,15 +480,12 @@ static int asoc_dmic_probe(struct platform_device *pdev) | |||
| 480 | dmic->dma_data.filter_data = "up_link"; | 480 | dmic->dma_data.filter_data = "up_link"; |
| 481 | 481 | ||
| 482 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 482 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
| 483 | if (!res) { | 483 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); |
| 484 | dev_err(dmic->dev, "invalid memory resource\n"); | 484 | if (IS_ERR(dmic->io_base)) { |
| 485 | ret = -ENODEV; | 485 | ret = PTR_ERR(dmic->io_base); |
| 486 | goto err_put_clk; | 486 | goto err_put_clk; |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | dmic->io_base = devm_ioremap_resource(&pdev->dev, res); | ||
| 490 | if (IS_ERR(dmic->io_base)) | ||
| 491 | return PTR_ERR(dmic->io_base); | ||
| 492 | 489 | ||
| 493 | ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, | 490 | ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, |
| 494 | &omap_dmic_dai, 1); | 491 | &omap_dmic_dai, 1); |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 7483efb6dc67..6c19bba23570 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
| @@ -433,6 +433,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
| 433 | /* Sample rate generator drives the FS */ | 433 | /* Sample rate generator drives the FS */ |
| 434 | regs->srgr2 |= FSGM; | 434 | regs->srgr2 |= FSGM; |
| 435 | break; | 435 | break; |
| 436 | case SND_SOC_DAIFMT_CBM_CFS: | ||
| 437 | /* McBSP slave. FS clock as output */ | ||
| 438 | regs->srgr2 |= FSGM; | ||
| 439 | regs->pcr0 |= FSXM; | ||
| 440 | break; | ||
| 436 | case SND_SOC_DAIFMT_CBM_CFM: | 441 | case SND_SOC_DAIFMT_CBM_CFM: |
| 437 | /* McBSP slave */ | 442 | /* McBSP slave */ |
| 438 | break; | 443 | break; |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index a49dc52f8abc..90d2a7cd2563 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
| @@ -480,9 +480,6 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) | |||
| 480 | mcpdm->dma_data[1].filter_data = "up_link"; | 480 | mcpdm->dma_data[1].filter_data = "up_link"; |
| 481 | 481 | ||
| 482 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 482 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
| 483 | if (res == NULL) | ||
| 484 | return -ENOMEM; | ||
| 485 | |||
| 486 | mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); | 483 | mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); |
| 487 | if (IS_ERR(mcpdm->io_base)) | 484 | if (IS_ERR(mcpdm->io_base)) |
| 488 | return PTR_ERR(mcpdm->io_base); | 485 | return PTR_ERR(mcpdm->io_base); |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b35809467547..4db74a083db1 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
| @@ -11,7 +11,7 @@ config SND_PXA2XX_SOC | |||
| 11 | config SND_MMP_SOC | 11 | config SND_MMP_SOC |
| 12 | bool "Soc Audio for Marvell MMP chips" | 12 | bool "Soc Audio for Marvell MMP chips" |
| 13 | depends on ARCH_MMP | 13 | depends on ARCH_MMP |
| 14 | select SND_SOC_DMAENGINE_PCM | 14 | select SND_DMAENGINE_PCM |
| 15 | select SND_ARM | 15 | select SND_ARM |
| 16 | help | 16 | help |
| 17 | Say Y if you want to add support for codecs attached to | 17 | Say Y if you want to add support for codecs attached to |
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 4ad76099dd43..5b7d969f89a9 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c | |||
| @@ -129,6 +129,7 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = { | |||
| 129 | /* audio machine driver */ | 129 | /* audio machine driver */ |
| 130 | static struct snd_soc_card brownstone = { | 130 | static struct snd_soc_card brownstone = { |
| 131 | .name = "brownstone", | 131 | .name = "brownstone", |
| 132 | .owner = THIS_MODULE, | ||
| 132 | .dai_link = brownstone_wm8994_dai, | 133 | .dai_link = brownstone_wm8994_dai, |
| 133 | .num_links = ARRAY_SIZE(brownstone_wm8994_dai), | 134 | .num_links = ARRAY_SIZE(brownstone_wm8994_dai), |
| 134 | 135 | ||
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 97b711e12821..bbea7780eac6 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
| @@ -56,8 +56,6 @@ | |||
| 56 | #include "pxa2xx-ac97.h" | 56 | #include "pxa2xx-ac97.h" |
| 57 | #include "../codecs/wm9713.h" | 57 | #include "../codecs/wm9713.h" |
| 58 | 58 | ||
| 59 | #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) | ||
| 60 | |||
| 61 | #define AC97_GPIO_PULL 0x58 | 59 | #define AC97_GPIO_PULL 0x58 |
| 62 | 60 | ||
| 63 | /* Use GPIO8 for rear speaker amplifier */ | 61 | /* Use GPIO8 for rear speaker amplifier */ |
| @@ -133,10 +131,11 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) | |||
| 133 | unsigned short reg; | 131 | unsigned short reg; |
| 134 | 132 | ||
| 135 | /* Add mioa701 specific widgets */ | 133 | /* Add mioa701 specific widgets */ |
| 136 | snd_soc_dapm_new_controls(dapm, ARRAY_AND_SIZE(mioa701_dapm_widgets)); | 134 | snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, |
| 135 | ARRAY_SIZE(mioa701_dapm_widgets)); | ||
| 137 | 136 | ||
| 138 | /* Set up mioa701 specific audio path audio_mapnects */ | 137 | /* Set up mioa701 specific audio path audio_mapnects */ |
| 139 | snd_soc_dapm_add_routes(dapm, ARRAY_AND_SIZE(audio_map)); | 138 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
| 140 | 139 | ||
| 141 | /* Prepare GPIO8 for rear speaker amplifier */ | 140 | /* Prepare GPIO8 for rear speaker amplifier */ |
| 142 | reg = codec->driver->read(codec, AC97_GPIO_CFG); | 141 | reg = codec->driver->read(codec, AC97_GPIO_CFG); |
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 5d57e071cdf5..8235e231d89c 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/dmaengine.h> | 17 | #include <linux/dmaengine.h> |
| 18 | #include <linux/platform_data/dma-mmp_tdma.h> | 18 | #include <linux/platform_data/dma-mmp_tdma.h> |
| 19 | #include <linux/platform_data/mmp_audio.h> | 19 | #include <linux/platform_data/mmp_audio.h> |
| 20 | |||
| 20 | #include <sound/pxa2xx-lib.h> | 21 | #include <sound/pxa2xx-lib.h> |
| 21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
| 22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
| @@ -67,7 +68,7 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 67 | { | 68 | { |
| 68 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | 69 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); |
| 69 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 70 | struct pxa2xx_pcm_dma_params *dma_params; | 71 | struct snd_dmaengine_dai_dma_data *dma_params; |
| 71 | struct dma_slave_config slave_config; | 72 | struct dma_slave_config slave_config; |
| 72 | int ret; | 73 | int ret; |
| 73 | 74 | ||
| @@ -80,10 +81,10 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 80 | return ret; | 81 | return ret; |
| 81 | 82 | ||
| 82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 83 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 83 | slave_config.dst_addr = dma_params->dev_addr; | 84 | slave_config.dst_addr = dma_params->addr; |
| 84 | slave_config.dst_maxburst = 4; | 85 | slave_config.dst_maxburst = 4; |
| 85 | } else { | 86 | } else { |
| 86 | slave_config.src_addr = dma_params->dev_addr; | 87 | slave_config.src_addr = dma_params->addr; |
| 87 | slave_config.src_maxburst = 4; | 88 | slave_config.src_maxburst = 4; |
| 88 | } | 89 | } |
| 89 | 90 | ||
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 62142ce367c7..41752a5fe3b0 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c | |||
| @@ -27,12 +27,15 @@ | |||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/pxa2xx_ssp.h> | 28 | #include <linux/pxa2xx_ssp.h> |
| 29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
| 30 | #include <linux/dmaengine.h> | ||
| 31 | |||
| 30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
| 31 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
| 32 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
| 33 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
| 34 | #include <sound/soc.h> | 36 | #include <sound/soc.h> |
| 35 | #include <sound/pxa2xx-lib.h> | 37 | #include <sound/pxa2xx-lib.h> |
| 38 | #include <sound/dmaengine_pcm.h> | ||
| 36 | #include "mmp-sspa.h" | 39 | #include "mmp-sspa.h" |
| 37 | 40 | ||
| 38 | /* | 41 | /* |
| @@ -40,7 +43,7 @@ | |||
| 40 | */ | 43 | */ |
| 41 | struct sspa_priv { | 44 | struct sspa_priv { |
| 42 | struct ssp_device *sspa; | 45 | struct ssp_device *sspa; |
| 43 | struct pxa2xx_pcm_dma_params *dma_params; | 46 | struct snd_dmaengine_dai_dma_data *dma_params; |
| 44 | struct clk *audio_clk; | 47 | struct clk *audio_clk; |
| 45 | struct clk *sysclk; | 48 | struct clk *sysclk; |
| 46 | int dai_fmt; | 49 | int dai_fmt; |
| @@ -266,7 +269,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, | |||
| 266 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 269 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
| 267 | struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); | 270 | struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); |
| 268 | struct ssp_device *sspa = sspa_priv->sspa; | 271 | struct ssp_device *sspa = sspa_priv->sspa; |
| 269 | struct pxa2xx_pcm_dma_params *dma_params; | 272 | struct snd_dmaengine_dai_dma_data *dma_params; |
| 270 | u32 sspa_ctrl; | 273 | u32 sspa_ctrl; |
| 271 | 274 | ||
| 272 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 275 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| @@ -309,7 +312,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, | |||
| 309 | } | 312 | } |
| 310 | 313 | ||
| 311 | dma_params = &sspa_priv->dma_params[substream->stream]; | 314 | dma_params = &sspa_priv->dma_params[substream->stream]; |
| 312 | dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 315 | dma_params->addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
| 313 | (sspa->phys_base + SSPA_TXD) : | 316 | (sspa->phys_base + SSPA_TXD) : |
| 314 | (sspa->phys_base + SSPA_RXD); | 317 | (sspa->phys_base + SSPA_RXD); |
| 315 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); | 318 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); |
| @@ -425,14 +428,12 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) | |||
| 425 | return -ENOMEM; | 428 | return -ENOMEM; |
| 426 | 429 | ||
| 427 | priv->dma_params = devm_kzalloc(&pdev->dev, | 430 | priv->dma_params = devm_kzalloc(&pdev->dev, |
| 428 | 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL); | 431 | 2 * sizeof(struct snd_dmaengine_dai_dma_data), |
| 432 | GFP_KERNEL); | ||
| 429 | if (priv->dma_params == NULL) | 433 | if (priv->dma_params == NULL) |
| 430 | return -ENOMEM; | 434 | return -ENOMEM; |
| 431 | 435 | ||
| 432 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 436 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 433 | if (res == NULL) | ||
| 434 | return -ENOMEM; | ||
| 435 | |||
| 436 | priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res); | 437 | priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res); |
| 437 | if (IS_ERR(priv->sspa->mmio_base)) | 438 | if (IS_ERR(priv->sspa->mmio_base)) |
| 438 | return PTR_ERR(priv->sspa->mmio_base); | 439 | return PTR_ERR(priv->sspa->mmio_base); |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 6f4dd7543e82..a3119a00d8fa 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
| 22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 23 | #include <linux/pxa2xx_ssp.h> | 23 | #include <linux/pxa2xx_ssp.h> |
| 24 | #include <linux/of.h> | ||
| 25 | #include <linux/dmaengine.h> | ||
| 24 | 26 | ||
| 25 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
| 26 | 28 | ||
| @@ -30,9 +32,9 @@ | |||
| 30 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
| 31 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
| 32 | #include <sound/pxa2xx-lib.h> | 34 | #include <sound/pxa2xx-lib.h> |
| 35 | #include <sound/dmaengine_pcm.h> | ||
| 33 | 36 | ||
| 34 | #include <mach/hardware.h> | 37 | #include <mach/hardware.h> |
| 35 | #include <mach/dma.h> | ||
| 36 | 38 | ||
| 37 | #include "../../arm/pxa2xx-pcm.h" | 39 | #include "../../arm/pxa2xx-pcm.h" |
| 38 | #include "pxa-ssp.h" | 40 | #include "pxa-ssp.h" |
| @@ -79,27 +81,13 @@ static void pxa_ssp_disable(struct ssp_device *ssp) | |||
| 79 | __raw_writel(sscr0, ssp->mmio_base + SSCR0); | 81 | __raw_writel(sscr0, ssp->mmio_base + SSCR0); |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 82 | struct pxa2xx_pcm_dma_data { | ||
| 83 | struct pxa2xx_pcm_dma_params params; | ||
| 84 | char name[20]; | ||
| 85 | }; | ||
| 86 | |||
| 87 | static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4, | 84 | static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4, |
| 88 | int out, struct pxa2xx_pcm_dma_params *dma_data) | 85 | int out, struct snd_dmaengine_dai_dma_data *dma) |
| 89 | { | 86 | { |
| 90 | struct pxa2xx_pcm_dma_data *dma; | 87 | dma->addr_width = width4 ? DMA_SLAVE_BUSWIDTH_4_BYTES : |
| 91 | 88 | DMA_SLAVE_BUSWIDTH_2_BYTES; | |
| 92 | dma = container_of(dma_data, struct pxa2xx_pcm_dma_data, params); | 89 | dma->maxburst = 16; |
| 93 | 90 | dma->addr = ssp->phys_base + SSDR; | |
| 94 | snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id, | ||
| 95 | width4 ? "32-bit" : "16-bit", out ? "out" : "in"); | ||
| 96 | |||
| 97 | dma->params.name = dma->name; | ||
| 98 | dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx); | ||
| 99 | dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) : | ||
| 100 | (DCMD_INCTRGADDR | DCMD_FLOWSRC)) | | ||
| 101 | (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16; | ||
| 102 | dma->params.dev_addr = ssp->phys_base + SSDR; | ||
| 103 | } | 91 | } |
| 104 | 92 | ||
| 105 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, | 93 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, |
| @@ -107,7 +95,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
| 107 | { | 95 | { |
| 108 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); | 96 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
| 109 | struct ssp_device *ssp = priv->ssp; | 97 | struct ssp_device *ssp = priv->ssp; |
| 110 | struct pxa2xx_pcm_dma_data *dma; | 98 | struct snd_dmaengine_dai_dma_data *dma; |
| 111 | int ret = 0; | 99 | int ret = 0; |
| 112 | 100 | ||
| 113 | if (!cpu_dai->active) { | 101 | if (!cpu_dai->active) { |
| @@ -115,10 +103,14 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
| 115 | pxa_ssp_disable(ssp); | 103 | pxa_ssp_disable(ssp); |
| 116 | } | 104 | } |
| 117 | 105 | ||
| 118 | dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL); | 106 | dma = kzalloc(sizeof(struct snd_dmaengine_dai_dma_data), GFP_KERNEL); |
| 119 | if (!dma) | 107 | if (!dma) |
| 120 | return -ENOMEM; | 108 | return -ENOMEM; |
| 121 | snd_soc_dai_set_dma_data(cpu_dai, substream, &dma->params); | 109 | |
| 110 | dma->filter_data = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
| 111 | &ssp->drcmr_tx : &ssp->drcmr_rx; | ||
| 112 | |||
| 113 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma); | ||
| 122 | 114 | ||
| 123 | return ret; | 115 | return ret; |
| 124 | } | 116 | } |
| @@ -559,7 +551,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
| 559 | u32 sspsp; | 551 | u32 sspsp; |
| 560 | int width = snd_pcm_format_physical_width(params_format(params)); | 552 | int width = snd_pcm_format_physical_width(params_format(params)); |
| 561 | int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; | 553 | int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; |
| 562 | struct pxa2xx_pcm_dma_params *dma_data; | 554 | struct snd_dmaengine_dai_dma_data *dma_data; |
| 563 | 555 | ||
| 564 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); | 556 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); |
| 565 | 557 | ||
| @@ -719,6 +711,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 719 | 711 | ||
| 720 | static int pxa_ssp_probe(struct snd_soc_dai *dai) | 712 | static int pxa_ssp_probe(struct snd_soc_dai *dai) |
| 721 | { | 713 | { |
| 714 | struct device *dev = dai->dev; | ||
| 722 | struct ssp_priv *priv; | 715 | struct ssp_priv *priv; |
| 723 | int ret; | 716 | int ret; |
| 724 | 717 | ||
| @@ -726,10 +719,26 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) | |||
| 726 | if (!priv) | 719 | if (!priv) |
| 727 | return -ENOMEM; | 720 | return -ENOMEM; |
| 728 | 721 | ||
| 729 | priv->ssp = pxa_ssp_request(dai->id + 1, "SoC audio"); | 722 | if (dev->of_node) { |
| 730 | if (priv->ssp == NULL) { | 723 | struct device_node *ssp_handle; |
| 731 | ret = -ENODEV; | 724 | |
| 732 | goto err_priv; | 725 | ssp_handle = of_parse_phandle(dev->of_node, "port", 0); |
| 726 | if (!ssp_handle) { | ||
| 727 | dev_err(dev, "unable to get 'port' phandle\n"); | ||
| 728 | return -ENODEV; | ||
| 729 | } | ||
| 730 | |||
| 731 | priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); | ||
| 732 | if (priv->ssp == NULL) { | ||
| 733 | ret = -ENODEV; | ||
| 734 | goto err_priv; | ||
| 735 | } | ||
| 736 | } else { | ||
| 737 | priv->ssp = pxa_ssp_request(dai->id + 1, "SoC audio"); | ||
| 738 | if (priv->ssp == NULL) { | ||
| 739 | ret = -ENODEV; | ||
| 740 | goto err_priv; | ||
| 741 | } | ||
| 733 | } | 742 | } |
| 734 | 743 | ||
| 735 | priv->dai_fmt = (unsigned int) -1; | 744 | priv->dai_fmt = (unsigned int) -1; |
| @@ -798,6 +807,12 @@ static const struct snd_soc_component_driver pxa_ssp_component = { | |||
| 798 | .name = "pxa-ssp", | 807 | .name = "pxa-ssp", |
| 799 | }; | 808 | }; |
| 800 | 809 | ||
| 810 | #ifdef CONFIG_OF | ||
| 811 | static const struct of_device_id pxa_ssp_of_ids[] = { | ||
| 812 | { .compatible = "mrvl,pxa-ssp-dai" }, | ||
| 813 | }; | ||
| 814 | #endif | ||
| 815 | |||
| 801 | static int asoc_ssp_probe(struct platform_device *pdev) | 816 | static int asoc_ssp_probe(struct platform_device *pdev) |
| 802 | { | 817 | { |
| 803 | return snd_soc_register_component(&pdev->dev, &pxa_ssp_component, | 818 | return snd_soc_register_component(&pdev->dev, &pxa_ssp_component, |
| @@ -812,8 +827,9 @@ static int asoc_ssp_remove(struct platform_device *pdev) | |||
| 812 | 827 | ||
| 813 | static struct platform_driver asoc_ssp_driver = { | 828 | static struct platform_driver asoc_ssp_driver = { |
| 814 | .driver = { | 829 | .driver = { |
| 815 | .name = "pxa-ssp-dai", | 830 | .name = "pxa-ssp-dai", |
| 816 | .owner = THIS_MODULE, | 831 | .owner = THIS_MODULE, |
| 832 | .of_match_table = of_match_ptr(pxa_ssp_of_ids), | ||
| 817 | }, | 833 | }, |
| 818 | 834 | ||
| 819 | .probe = asoc_ssp_probe, | 835 | .probe = asoc_ssp_probe, |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 1475515712e6..f1059d999de6 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
| @@ -14,15 +14,16 @@ | |||
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/dmaengine.h> | ||
| 17 | 18 | ||
| 18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
| 19 | #include <sound/ac97_codec.h> | 20 | #include <sound/ac97_codec.h> |
| 20 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
| 21 | #include <sound/pxa2xx-lib.h> | 22 | #include <sound/pxa2xx-lib.h> |
| 23 | #include <sound/dmaengine_pcm.h> | ||
| 22 | 24 | ||
| 23 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
| 24 | #include <mach/regs-ac97.h> | 26 | #include <mach/regs-ac97.h> |
| 25 | #include <mach/dma.h> | ||
| 26 | #include <mach/audio.h> | 27 | #include <mach/audio.h> |
| 27 | 28 | ||
| 28 | #include "pxa2xx-ac97.h" | 29 | #include "pxa2xx-ac97.h" |
| @@ -48,44 +49,44 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { | |||
| 48 | .reset = pxa2xx_ac97_cold_reset, | 49 | .reset = pxa2xx_ac97_cold_reset, |
| 49 | }; | 50 | }; |
| 50 | 51 | ||
| 51 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { | 52 | static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12; |
| 52 | .name = "AC97 PCM Stereo out", | 53 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { |
| 53 | .dev_addr = __PREG(PCDR), | 54 | .addr = __PREG(PCDR), |
| 54 | .drcmr = &DRCMR(12), | 55 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 55 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | 56 | .maxburst = 32, |
| 56 | DCMD_BURST32 | DCMD_WIDTH4, | 57 | .filter_data = &pxa2xx_ac97_pcm_stereo_in_req, |
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 59 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { | 60 | static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11; |
| 60 | .name = "AC97 PCM Stereo in", | 61 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = { |
| 61 | .dev_addr = __PREG(PCDR), | 62 | .addr = __PREG(PCDR), |
| 62 | .drcmr = &DRCMR(11), | 63 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 63 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | 64 | .maxburst = 32, |
| 64 | DCMD_BURST32 | DCMD_WIDTH4, | 65 | .filter_data = &pxa2xx_ac97_pcm_stereo_out_req, |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { | 68 | static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10; |
| 68 | .name = "AC97 Aux PCM (Slot 5) Mono out", | 69 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = { |
| 69 | .dev_addr = __PREG(MODR), | 70 | .addr = __PREG(MODR), |
| 70 | .drcmr = &DRCMR(10), | 71 | .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, |
| 71 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | 72 | .maxburst = 16, |
| 72 | DCMD_BURST16 | DCMD_WIDTH2, | 73 | .filter_data = &pxa2xx_ac97_pcm_aux_mono_out_req, |
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| 75 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { | 76 | static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9; |
| 76 | .name = "AC97 Aux PCM (Slot 5) Mono in", | 77 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = { |
| 77 | .dev_addr = __PREG(MODR), | 78 | .addr = __PREG(MODR), |
| 78 | .drcmr = &DRCMR(9), | 79 | .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, |
| 79 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | 80 | .maxburst = 16, |
| 80 | DCMD_BURST16 | DCMD_WIDTH2, | 81 | .filter_data = &pxa2xx_ac97_pcm_aux_mono_in_req, |
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { | 84 | static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8; |
| 84 | .name = "AC97 Mic PCM (Slot 6) Mono in", | 85 | static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = { |
| 85 | .dev_addr = __PREG(MCDR), | 86 | .addr = __PREG(MCDR), |
| 86 | .drcmr = &DRCMR(8), | 87 | .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, |
| 87 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | 88 | .maxburst = 16, |
| 88 | DCMD_BURST16 | DCMD_WIDTH2, | 89 | .filter_data = &pxa2xx_ac97_pcm_aux_mic_mono_req, |
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | #ifdef CONFIG_PM | 92 | #ifdef CONFIG_PM |
| @@ -119,7 +120,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | |||
| 119 | struct snd_pcm_hw_params *params, | 120 | struct snd_pcm_hw_params *params, |
| 120 | struct snd_soc_dai *cpu_dai) | 121 | struct snd_soc_dai *cpu_dai) |
| 121 | { | 122 | { |
| 122 | struct pxa2xx_pcm_dma_params *dma_data; | 123 | struct snd_dmaengine_dai_dma_data *dma_data; |
| 123 | 124 | ||
| 124 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 125 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 125 | dma_data = &pxa2xx_ac97_pcm_stereo_out; | 126 | dma_data = &pxa2xx_ac97_pcm_stereo_out; |
| @@ -135,7 +136,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | |||
| 135 | struct snd_pcm_hw_params *params, | 136 | struct snd_pcm_hw_params *params, |
| 136 | struct snd_soc_dai *cpu_dai) | 137 | struct snd_soc_dai *cpu_dai) |
| 137 | { | 138 | { |
| 138 | struct pxa2xx_pcm_dma_params *dma_data; | 139 | struct snd_dmaengine_dai_dma_data *dma_data; |
| 139 | 140 | ||
| 140 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 141 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 141 | dma_data = &pxa2xx_ac97_pcm_aux_mono_out; | 142 | dma_data = &pxa2xx_ac97_pcm_aux_mono_out; |
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index f7ca71664112..d5340a088858 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
| @@ -23,9 +23,9 @@ | |||
| 23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
| 24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
| 25 | #include <sound/pxa2xx-lib.h> | 25 | #include <sound/pxa2xx-lib.h> |
| 26 | #include <sound/dmaengine_pcm.h> | ||
| 26 | 27 | ||
| 27 | #include <mach/hardware.h> | 28 | #include <mach/hardware.h> |
| 28 | #include <mach/dma.h> | ||
| 29 | #include <mach/audio.h> | 29 | #include <mach/audio.h> |
| 30 | 30 | ||
| 31 | #include "pxa2xx-i2s.h" | 31 | #include "pxa2xx-i2s.h" |
| @@ -82,20 +82,20 @@ static struct pxa_i2s_port pxa_i2s; | |||
| 82 | static struct clk *clk_i2s; | 82 | static struct clk *clk_i2s; |
| 83 | static int clk_ena = 0; | 83 | static int clk_ena = 0; |
| 84 | 84 | ||
| 85 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { | 85 | static unsigned long pxa2xx_i2s_pcm_stereo_out_req = 3; |
| 86 | .name = "I2S PCM Stereo out", | 86 | static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_out = { |
| 87 | .dev_addr = __PREG(SADR), | 87 | .addr = __PREG(SADR), |
| 88 | .drcmr = &DRCMR(3), | 88 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 89 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | 89 | .maxburst = 32, |
| 90 | DCMD_BURST32 | DCMD_WIDTH4, | 90 | .filter_data = &pxa2xx_i2s_pcm_stereo_out_req, |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { | 93 | static unsigned long pxa2xx_i2s_pcm_stereo_in_req = 2; |
| 94 | .name = "I2S PCM Stereo in", | 94 | static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = { |
| 95 | .dev_addr = __PREG(SADR), | 95 | .addr = __PREG(SADR), |
| 96 | .drcmr = &DRCMR(2), | 96 | .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 97 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | 97 | .maxburst = 32, |
| 98 | DCMD_BURST32 | DCMD_WIDTH4, | 98 | .filter_data = &pxa2xx_i2s_pcm_stereo_in_req, |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, | 101 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, |
| @@ -163,7 +163,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
| 163 | struct snd_pcm_hw_params *params, | 163 | struct snd_pcm_hw_params *params, |
| 164 | struct snd_soc_dai *dai) | 164 | struct snd_soc_dai *dai) |
| 165 | { | 165 | { |
| 166 | struct pxa2xx_pcm_dma_params *dma_data; | 166 | struct snd_dmaengine_dai_dma_data *dma_data; |
| 167 | 167 | ||
| 168 | BUG_ON(IS_ERR(clk_i2s)); | 168 | BUG_ON(IS_ERR(clk_i2s)); |
| 169 | clk_prepare_enable(clk_i2s); | 169 | clk_prepare_enable(clk_i2s); |
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index ecff116cb7b0..806da27b8b67 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c | |||
| @@ -12,10 +12,13 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/dma-mapping.h> | 13 | #include <linux/dma-mapping.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/dmaengine.h> | ||
| 16 | #include <linux/of.h> | ||
| 15 | 17 | ||
| 16 | #include <sound/core.h> | 18 | #include <sound/core.h> |
| 17 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
| 18 | #include <sound/pxa2xx-lib.h> | 20 | #include <sound/pxa2xx-lib.h> |
| 21 | #include <sound/dmaengine_pcm.h> | ||
| 19 | 22 | ||
| 20 | #include "../../arm/pxa2xx-pcm.h" | 23 | #include "../../arm/pxa2xx-pcm.h" |
| 21 | 24 | ||
| @@ -25,7 +28,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 25 | struct snd_pcm_runtime *runtime = substream->runtime; | 28 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 26 | struct pxa2xx_runtime_data *prtd = runtime->private_data; | 29 | struct pxa2xx_runtime_data *prtd = runtime->private_data; |
| 27 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 30 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 28 | struct pxa2xx_pcm_dma_params *dma; | 31 | struct snd_dmaengine_dai_dma_data *dma; |
| 29 | int ret; | 32 | int ret; |
| 30 | 33 | ||
| 31 | dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 34 | dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| @@ -39,7 +42,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 39 | * with different params */ | 42 | * with different params */ |
| 40 | if (prtd->params == NULL) { | 43 | if (prtd->params == NULL) { |
| 41 | prtd->params = dma; | 44 | prtd->params = dma; |
| 42 | ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, | 45 | ret = pxa_request_dma("name", DMA_PRIO_LOW, |
| 43 | pxa2xx_pcm_dma_irq, substream); | 46 | pxa2xx_pcm_dma_irq, substream); |
| 44 | if (ret < 0) | 47 | if (ret < 0) |
| 45 | return ret; | 48 | return ret; |
| @@ -47,7 +50,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 47 | } else if (prtd->params != dma) { | 50 | } else if (prtd->params != dma) { |
| 48 | pxa_free_dma(prtd->dma_ch); | 51 | pxa_free_dma(prtd->dma_ch); |
| 49 | prtd->params = dma; | 52 | prtd->params = dma; |
| 50 | ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, | 53 | ret = pxa_request_dma("name", DMA_PRIO_LOW, |
| 51 | pxa2xx_pcm_dma_irq, substream); | 54 | pxa2xx_pcm_dma_irq, substream); |
| 52 | if (ret < 0) | 55 | if (ret < 0) |
| 53 | return ret; | 56 | return ret; |
| @@ -131,10 +134,18 @@ static int pxa2xx_soc_platform_remove(struct platform_device *pdev) | |||
| 131 | return 0; | 134 | return 0; |
| 132 | } | 135 | } |
| 133 | 136 | ||
| 137 | #ifdef CONFIG_OF | ||
| 138 | static const struct of_device_id snd_soc_pxa_audio_match[] = { | ||
| 139 | { .compatible = "mrvl,pxa-pcm-audio" }, | ||
| 140 | { } | ||
| 141 | }; | ||
| 142 | #endif | ||
| 143 | |||
| 134 | static struct platform_driver pxa_pcm_driver = { | 144 | static struct platform_driver pxa_pcm_driver = { |
| 135 | .driver = { | 145 | .driver = { |
| 136 | .name = "pxa-pcm-audio", | 146 | .name = "pxa-pcm-audio", |
| 137 | .owner = THIS_MODULE, | 147 | .owner = THIS_MODULE, |
| 148 | .of_match_table = of_match_ptr(snd_soc_pxa_audio_match), | ||
| 138 | }, | 149 | }, |
| 139 | 150 | ||
| 140 | .probe = pxa2xx_soc_platform_probe, | 151 | .probe = pxa2xx_soc_platform_probe, |
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c index f4ea4f6663a2..13c9ee0cb83b 100644 --- a/sound/soc/pxa/ttc-dkb.c +++ b/sound/soc/pxa/ttc-dkb.c | |||
| @@ -122,6 +122,7 @@ static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = { | |||
| 122 | /* ttc/td audio machine driver */ | 122 | /* ttc/td audio machine driver */ |
| 123 | static struct snd_soc_card ttc_dkb_card = { | 123 | static struct snd_soc_card ttc_dkb_card = { |
| 124 | .name = "ttc-dkb-hifi", | 124 | .name = "ttc-dkb-hifi", |
| 125 | .owner = THIS_MODULE, | ||
| 125 | .dai_link = ttc_pm860x_hifi_dai, | 126 | .dai_link = ttc_pm860x_hifi_dai, |
| 126 | .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), | 127 | .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), |
| 127 | 128 | ||
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 58cfb1eb7dd3..945e8abdc10f 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c | |||
| @@ -192,7 +192,7 @@ static struct snd_soc_card snd_soc_card_s6105 = { | |||
| 192 | .num_links = 1, | 192 | .num_links = 1, |
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | static struct s6000_snd_platform_data __initdata s6105_snd_data = { | 195 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { |
| 196 | .wide = 0, | 196 | .wide = 0, |
| 197 | .channel_in = 0, | 197 | .channel_in = 0, |
| 198 | .channel_out = 1, | 198 | .channel_out = 1, |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 2dd623fa3882..2acf987844e8 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
| @@ -404,18 +404,13 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
| 404 | return -ENXIO; | 404 | return -ENXIO; |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 408 | if (!mem_res) { | ||
| 409 | dev_err(&pdev->dev, "Unable to get register resource\n"); | ||
| 410 | return -ENXIO; | ||
| 411 | } | ||
| 412 | |||
| 413 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 407 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 414 | if (!irq_res) { | 408 | if (!irq_res) { |
| 415 | dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); | 409 | dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); |
| 416 | return -ENXIO; | 410 | return -ENXIO; |
| 417 | } | 411 | } |
| 418 | 412 | ||
| 413 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 419 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); | 414 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); |
| 420 | if (IS_ERR(s3c_ac97.regs)) | 415 | if (IS_ERR(s3c_ac97.regs)) |
| 421 | return PTR_ERR(s3c_ac97.regs); | 416 | return PTR_ERR(s3c_ac97.regs); |
| @@ -462,7 +457,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
| 462 | if (ret) | 457 | if (ret) |
| 463 | goto err5; | 458 | goto err5; |
| 464 | 459 | ||
| 465 | ret = asoc_dma_platform_register(&pdev->dev); | 460 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
| 466 | if (ret) { | 461 | if (ret) { |
| 467 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); | 462 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); |
| 468 | goto err6; | 463 | goto err6; |
| @@ -485,7 +480,7 @@ static int s3c_ac97_remove(struct platform_device *pdev) | |||
| 485 | { | 480 | { |
| 486 | struct resource *irq_res; | 481 | struct resource *irq_res; |
| 487 | 482 | ||
| 488 | asoc_dma_platform_unregister(&pdev->dev); | 483 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 489 | snd_soc_unregister_component(&pdev->dev); | 484 | snd_soc_unregister_component(&pdev->dev); |
| 490 | 485 | ||
| 491 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 486 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 21b79262010e..a0c67f60f594 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c | |||
| @@ -176,6 +176,10 @@ static int dma_hw_params(struct snd_pcm_substream *substream, | |||
| 176 | prtd->params->ch = prtd->params->ops->request( | 176 | prtd->params->ch = prtd->params->ops->request( |
| 177 | prtd->params->channel, &req, rtd->cpu_dai->dev, | 177 | prtd->params->channel, &req, rtd->cpu_dai->dev, |
| 178 | prtd->params->ch_name); | 178 | prtd->params->ch_name); |
| 179 | if (!prtd->params->ch) { | ||
| 180 | pr_err("Failed to allocate DMA channel\n"); | ||
| 181 | return -ENXIO; | ||
| 182 | } | ||
| 179 | prtd->params->ops->config(prtd->params->ch, &config); | 183 | prtd->params->ops->config(prtd->params->ch, &config); |
| 180 | } | 184 | } |
| 181 | 185 | ||
| @@ -433,17 +437,17 @@ static struct snd_soc_platform_driver samsung_asoc_platform = { | |||
| 433 | .pcm_free = dma_free_dma_buffers, | 437 | .pcm_free = dma_free_dma_buffers, |
| 434 | }; | 438 | }; |
| 435 | 439 | ||
| 436 | int asoc_dma_platform_register(struct device *dev) | 440 | int samsung_asoc_dma_platform_register(struct device *dev) |
| 437 | { | 441 | { |
| 438 | return snd_soc_register_platform(dev, &samsung_asoc_platform); | 442 | return snd_soc_register_platform(dev, &samsung_asoc_platform); |
| 439 | } | 443 | } |
| 440 | EXPORT_SYMBOL_GPL(asoc_dma_platform_register); | 444 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); |
| 441 | 445 | ||
| 442 | void asoc_dma_platform_unregister(struct device *dev) | 446 | void samsung_asoc_dma_platform_unregister(struct device *dev) |
| 443 | { | 447 | { |
| 444 | snd_soc_unregister_platform(dev); | 448 | snd_soc_unregister_platform(dev); |
| 445 | } | 449 | } |
| 446 | EXPORT_SYMBOL_GPL(asoc_dma_platform_unregister); | 450 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); |
| 447 | 451 | ||
| 448 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 452 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
| 449 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); | 453 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); |
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 189a7a6d5020..0e86315a3eaf 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
| @@ -22,7 +22,7 @@ struct s3c_dma_params { | |||
| 22 | char *ch_name; | 22 | char *ch_name; |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | int asoc_dma_platform_register(struct device *dev); | 25 | int samsung_asoc_dma_platform_register(struct device *dev); |
| 26 | void asoc_dma_platform_unregister(struct device *dev); | 26 | void samsung_asoc_dma_platform_unregister(struct device *dev); |
| 27 | 27 | ||
| 28 | #endif | 28 | #endif |
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h index c0e6d9a19efc..821a50231002 100644 --- a/sound/soc/samsung/i2s-regs.h +++ b/sound/soc/samsung/i2s-regs.h | |||
| @@ -31,6 +31,10 @@ | |||
| 31 | #define I2SLVL1ADDR 0x34 | 31 | #define I2SLVL1ADDR 0x34 |
| 32 | #define I2SLVL2ADDR 0x38 | 32 | #define I2SLVL2ADDR 0x38 |
| 33 | #define I2SLVL3ADDR 0x3c | 33 | #define I2SLVL3ADDR 0x3c |
| 34 | #define I2SSTR1 0x40 | ||
| 35 | #define I2SVER 0x44 | ||
| 36 | #define I2SFIC2 0x48 | ||
| 37 | #define I2STDM 0x4c | ||
| 34 | 38 | ||
| 35 | #define CON_RSTCLR (1 << 31) | 39 | #define CON_RSTCLR (1 << 31) |
| 36 | #define CON_FRXOFSTATUS (1 << 26) | 40 | #define CON_FRXOFSTATUS (1 << 26) |
| @@ -95,24 +99,39 @@ | |||
| 95 | #define MOD_RXONLY (1 << 8) | 99 | #define MOD_RXONLY (1 << 8) |
| 96 | #define MOD_TXRX (2 << 8) | 100 | #define MOD_TXRX (2 << 8) |
| 97 | #define MOD_MASK (3 << 8) | 101 | #define MOD_MASK (3 << 8) |
| 98 | #define MOD_LR_LLOW (0 << 7) | 102 | #define MOD_LRP_SHIFT 7 |
| 99 | #define MOD_LR_RLOW (1 << 7) | 103 | #define MOD_LR_LLOW 0 |
| 100 | #define MOD_SDF_IIS (0 << 5) | 104 | #define MOD_LR_RLOW 1 |
| 101 | #define MOD_SDF_MSB (1 << 5) | 105 | #define MOD_SDF_SHIFT 5 |
| 102 | #define MOD_SDF_LSB (2 << 5) | 106 | #define MOD_SDF_IIS 0 |
| 103 | #define MOD_SDF_MASK (3 << 5) | 107 | #define MOD_SDF_MSB 1 |
| 104 | #define MOD_RCLK_256FS (0 << 3) | 108 | #define MOD_SDF_LSB 2 |
| 105 | #define MOD_RCLK_512FS (1 << 3) | 109 | #define MOD_SDF_MASK 3 |
| 106 | #define MOD_RCLK_384FS (2 << 3) | 110 | #define MOD_RCLK_SHIFT 3 |
| 107 | #define MOD_RCLK_768FS (3 << 3) | 111 | #define MOD_RCLK_256FS 0 |
| 108 | #define MOD_RCLK_MASK (3 << 3) | 112 | #define MOD_RCLK_512FS 1 |
| 109 | #define MOD_BCLK_32FS (0 << 1) | 113 | #define MOD_RCLK_384FS 2 |
| 110 | #define MOD_BCLK_48FS (1 << 1) | 114 | #define MOD_RCLK_768FS 3 |
| 111 | #define MOD_BCLK_16FS (2 << 1) | 115 | #define MOD_RCLK_MASK 3 |
| 112 | #define MOD_BCLK_24FS (3 << 1) | 116 | #define MOD_BCLK_SHIFT 1 |
| 113 | #define MOD_BCLK_MASK (3 << 1) | 117 | #define MOD_BCLK_32FS 0 |
| 118 | #define MOD_BCLK_48FS 1 | ||
| 119 | #define MOD_BCLK_16FS 2 | ||
| 120 | #define MOD_BCLK_24FS 3 | ||
| 121 | #define MOD_BCLK_MASK 3 | ||
| 114 | #define MOD_8BIT (1 << 0) | 122 | #define MOD_8BIT (1 << 0) |
| 115 | 123 | ||
| 124 | #define EXYNOS5420_MOD_LRP_SHIFT 15 | ||
| 125 | #define EXYNOS5420_MOD_SDF_SHIFT 6 | ||
| 126 | #define EXYNOS5420_MOD_RCLK_SHIFT 4 | ||
| 127 | #define EXYNOS5420_MOD_BCLK_SHIFT 0 | ||
| 128 | #define EXYNOS5420_MOD_BCLK_64FS 4 | ||
| 129 | #define EXYNOS5420_MOD_BCLK_96FS 5 | ||
| 130 | #define EXYNOS5420_MOD_BCLK_128FS 6 | ||
| 131 | #define EXYNOS5420_MOD_BCLK_192FS 7 | ||
| 132 | #define EXYNOS5420_MOD_BCLK_256FS 8 | ||
| 133 | #define EXYNOS5420_MOD_BCLK_MASK 0xf | ||
| 134 | |||
| 116 | #define MOD_CDCLKCON (1 << 12) | 135 | #define MOD_CDCLKCON (1 << 12) |
| 117 | 136 | ||
| 118 | #define PSR_PSREN (1 << 15) | 137 | #define PSR_PSREN (1 << 15) |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 959c702235c8..b302f3b7a587 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
| @@ -40,6 +40,7 @@ enum samsung_dai_type { | |||
| 40 | 40 | ||
| 41 | struct samsung_i2s_dai_data { | 41 | struct samsung_i2s_dai_data { |
| 42 | int dai_type; | 42 | int dai_type; |
| 43 | u32 quirks; | ||
| 43 | }; | 44 | }; |
| 44 | 45 | ||
| 45 | struct i2s_dai { | 46 | struct i2s_dai { |
| @@ -198,7 +199,13 @@ static inline bool is_manager(struct i2s_dai *i2s) | |||
| 198 | /* Read RCLK of I2S (in multiples of LRCLK) */ | 199 | /* Read RCLK of I2S (in multiples of LRCLK) */ |
| 199 | static inline unsigned get_rfs(struct i2s_dai *i2s) | 200 | static inline unsigned get_rfs(struct i2s_dai *i2s) |
| 200 | { | 201 | { |
| 201 | u32 rfs = (readl(i2s->addr + I2SMOD) >> 3) & 0x3; | 202 | u32 rfs; |
| 203 | |||
| 204 | if (i2s->quirks & QUIRK_SUPPORTS_TDM) | ||
| 205 | rfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_RCLK_SHIFT; | ||
| 206 | else | ||
| 207 | rfs = (readl(i2s->addr + I2SMOD) >> MOD_RCLK_SHIFT); | ||
| 208 | rfs &= MOD_RCLK_MASK; | ||
| 202 | 209 | ||
| 203 | switch (rfs) { | 210 | switch (rfs) { |
| 204 | case 3: return 768; | 211 | case 3: return 768; |
| @@ -212,21 +219,26 @@ static inline unsigned get_rfs(struct i2s_dai *i2s) | |||
| 212 | static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) | 219 | static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) |
| 213 | { | 220 | { |
| 214 | u32 mod = readl(i2s->addr + I2SMOD); | 221 | u32 mod = readl(i2s->addr + I2SMOD); |
| 222 | int rfs_shift; | ||
| 215 | 223 | ||
| 216 | mod &= ~MOD_RCLK_MASK; | 224 | if (i2s->quirks & QUIRK_SUPPORTS_TDM) |
| 225 | rfs_shift = EXYNOS5420_MOD_RCLK_SHIFT; | ||
| 226 | else | ||
| 227 | rfs_shift = MOD_RCLK_SHIFT; | ||
| 228 | mod &= ~(MOD_RCLK_MASK << rfs_shift); | ||
| 217 | 229 | ||
| 218 | switch (rfs) { | 230 | switch (rfs) { |
| 219 | case 768: | 231 | case 768: |
| 220 | mod |= MOD_RCLK_768FS; | 232 | mod |= (MOD_RCLK_768FS << rfs_shift); |
| 221 | break; | 233 | break; |
| 222 | case 512: | 234 | case 512: |
| 223 | mod |= MOD_RCLK_512FS; | 235 | mod |= (MOD_RCLK_512FS << rfs_shift); |
| 224 | break; | 236 | break; |
| 225 | case 384: | 237 | case 384: |
| 226 | mod |= MOD_RCLK_384FS; | 238 | mod |= (MOD_RCLK_384FS << rfs_shift); |
| 227 | break; | 239 | break; |
| 228 | default: | 240 | default: |
| 229 | mod |= MOD_RCLK_256FS; | 241 | mod |= (MOD_RCLK_256FS << rfs_shift); |
| 230 | break; | 242 | break; |
| 231 | } | 243 | } |
| 232 | 244 | ||
| @@ -236,9 +248,22 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) | |||
| 236 | /* Read Bit-Clock of I2S (in multiples of LRCLK) */ | 248 | /* Read Bit-Clock of I2S (in multiples of LRCLK) */ |
| 237 | static inline unsigned get_bfs(struct i2s_dai *i2s) | 249 | static inline unsigned get_bfs(struct i2s_dai *i2s) |
| 238 | { | 250 | { |
| 239 | u32 bfs = (readl(i2s->addr + I2SMOD) >> 1) & 0x3; | 251 | u32 bfs; |
| 252 | |||
| 253 | if (i2s->quirks & QUIRK_SUPPORTS_TDM) { | ||
| 254 | bfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_BCLK_SHIFT; | ||
| 255 | bfs &= EXYNOS5420_MOD_BCLK_MASK; | ||
| 256 | } else { | ||
| 257 | bfs = readl(i2s->addr + I2SMOD) >> MOD_BCLK_SHIFT; | ||
| 258 | bfs &= MOD_BCLK_MASK; | ||
| 259 | } | ||
| 240 | 260 | ||
| 241 | switch (bfs) { | 261 | switch (bfs) { |
| 262 | case 8: return 256; | ||
| 263 | case 7: return 192; | ||
| 264 | case 6: return 128; | ||
| 265 | case 5: return 96; | ||
| 266 | case 4: return 64; | ||
| 242 | case 3: return 24; | 267 | case 3: return 24; |
| 243 | case 2: return 16; | 268 | case 2: return 16; |
| 244 | case 1: return 48; | 269 | case 1: return 48; |
| @@ -250,21 +275,50 @@ static inline unsigned get_bfs(struct i2s_dai *i2s) | |||
| 250 | static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) | 275 | static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) |
| 251 | { | 276 | { |
| 252 | u32 mod = readl(i2s->addr + I2SMOD); | 277 | u32 mod = readl(i2s->addr + I2SMOD); |
| 278 | int bfs_shift; | ||
| 279 | int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM; | ||
| 253 | 280 | ||
| 254 | mod &= ~MOD_BCLK_MASK; | 281 | if (i2s->quirks & QUIRK_SUPPORTS_TDM) { |
| 282 | bfs_shift = EXYNOS5420_MOD_BCLK_SHIFT; | ||
| 283 | mod &= ~(EXYNOS5420_MOD_BCLK_MASK << bfs_shift); | ||
| 284 | } else { | ||
| 285 | bfs_shift = MOD_BCLK_SHIFT; | ||
| 286 | mod &= ~(MOD_BCLK_MASK << bfs_shift); | ||
| 287 | } | ||
| 288 | |||
| 289 | /* Non-TDM I2S controllers do not support BCLK > 48 * FS */ | ||
| 290 | if (!tdm && bfs > 48) { | ||
| 291 | dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n"); | ||
| 292 | return; | ||
| 293 | } | ||
| 255 | 294 | ||
| 256 | switch (bfs) { | 295 | switch (bfs) { |
| 257 | case 48: | 296 | case 48: |
| 258 | mod |= MOD_BCLK_48FS; | 297 | mod |= (MOD_BCLK_48FS << bfs_shift); |
| 259 | break; | 298 | break; |
| 260 | case 32: | 299 | case 32: |
| 261 | mod |= MOD_BCLK_32FS; | 300 | mod |= (MOD_BCLK_32FS << bfs_shift); |
| 262 | break; | 301 | break; |
| 263 | case 24: | 302 | case 24: |
| 264 | mod |= MOD_BCLK_24FS; | 303 | mod |= (MOD_BCLK_24FS << bfs_shift); |
| 265 | break; | 304 | break; |
| 266 | case 16: | 305 | case 16: |
| 267 | mod |= MOD_BCLK_16FS; | 306 | mod |= (MOD_BCLK_16FS << bfs_shift); |
| 307 | break; | ||
| 308 | case 64: | ||
| 309 | mod |= (EXYNOS5420_MOD_BCLK_64FS << bfs_shift); | ||
| 310 | break; | ||
| 311 | case 96: | ||
| 312 | mod |= (EXYNOS5420_MOD_BCLK_96FS << bfs_shift); | ||
| 313 | break; | ||
| 314 | case 128: | ||
| 315 | mod |= (EXYNOS5420_MOD_BCLK_128FS << bfs_shift); | ||
| 316 | break; | ||
| 317 | case 192: | ||
| 318 | mod |= (EXYNOS5420_MOD_BCLK_192FS << bfs_shift); | ||
| 319 | break; | ||
| 320 | case 256: | ||
| 321 | mod |= (EXYNOS5420_MOD_BCLK_256FS << bfs_shift); | ||
| 268 | break; | 322 | break; |
| 269 | default: | 323 | default: |
| 270 | dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); | 324 | dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); |
| @@ -491,20 +545,32 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
| 491 | { | 545 | { |
| 492 | struct i2s_dai *i2s = to_info(dai); | 546 | struct i2s_dai *i2s = to_info(dai); |
| 493 | u32 mod = readl(i2s->addr + I2SMOD); | 547 | u32 mod = readl(i2s->addr + I2SMOD); |
| 548 | int lrp_shift, sdf_shift, sdf_mask, lrp_rlow; | ||
| 494 | u32 tmp = 0; | 549 | u32 tmp = 0; |
| 495 | 550 | ||
| 551 | if (i2s->quirks & QUIRK_SUPPORTS_TDM) { | ||
| 552 | lrp_shift = EXYNOS5420_MOD_LRP_SHIFT; | ||
| 553 | sdf_shift = EXYNOS5420_MOD_SDF_SHIFT; | ||
| 554 | } else { | ||
| 555 | lrp_shift = MOD_LRP_SHIFT; | ||
| 556 | sdf_shift = MOD_SDF_SHIFT; | ||
| 557 | } | ||
| 558 | |||
| 559 | sdf_mask = MOD_SDF_MASK << sdf_shift; | ||
| 560 | lrp_rlow = MOD_LR_RLOW << lrp_shift; | ||
| 561 | |||
| 496 | /* Format is priority */ | 562 | /* Format is priority */ |
| 497 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 563 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
| 498 | case SND_SOC_DAIFMT_RIGHT_J: | 564 | case SND_SOC_DAIFMT_RIGHT_J: |
| 499 | tmp |= MOD_LR_RLOW; | 565 | tmp |= lrp_rlow; |
| 500 | tmp |= MOD_SDF_MSB; | 566 | tmp |= (MOD_SDF_MSB << sdf_shift); |
| 501 | break; | 567 | break; |
| 502 | case SND_SOC_DAIFMT_LEFT_J: | 568 | case SND_SOC_DAIFMT_LEFT_J: |
| 503 | tmp |= MOD_LR_RLOW; | 569 | tmp |= lrp_rlow; |
| 504 | tmp |= MOD_SDF_LSB; | 570 | tmp |= (MOD_SDF_LSB << sdf_shift); |
| 505 | break; | 571 | break; |
| 506 | case SND_SOC_DAIFMT_I2S: | 572 | case SND_SOC_DAIFMT_I2S: |
| 507 | tmp |= MOD_SDF_IIS; | 573 | tmp |= (MOD_SDF_IIS << sdf_shift); |
| 508 | break; | 574 | break; |
| 509 | default: | 575 | default: |
| 510 | dev_err(&i2s->pdev->dev, "Format not supported\n"); | 576 | dev_err(&i2s->pdev->dev, "Format not supported\n"); |
| @@ -519,10 +585,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
| 519 | case SND_SOC_DAIFMT_NB_NF: | 585 | case SND_SOC_DAIFMT_NB_NF: |
| 520 | break; | 586 | break; |
| 521 | case SND_SOC_DAIFMT_NB_IF: | 587 | case SND_SOC_DAIFMT_NB_IF: |
| 522 | if (tmp & MOD_LR_RLOW) | 588 | if (tmp & lrp_rlow) |
| 523 | tmp &= ~MOD_LR_RLOW; | 589 | tmp &= ~lrp_rlow; |
| 524 | else | 590 | else |
| 525 | tmp |= MOD_LR_RLOW; | 591 | tmp |= lrp_rlow; |
| 526 | break; | 592 | break; |
| 527 | default: | 593 | default: |
| 528 | dev_err(&i2s->pdev->dev, "Polarity not supported\n"); | 594 | dev_err(&i2s->pdev->dev, "Polarity not supported\n"); |
| @@ -544,15 +610,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
| 544 | return -EINVAL; | 610 | return -EINVAL; |
| 545 | } | 611 | } |
| 546 | 612 | ||
| 613 | /* | ||
| 614 | * Don't change the I2S mode if any controller is active on this | ||
| 615 | * channel. | ||
| 616 | */ | ||
| 547 | if (any_active(i2s) && | 617 | if (any_active(i2s) && |
| 548 | ((mod & (MOD_SDF_MASK | MOD_LR_RLOW | 618 | ((mod & (sdf_mask | lrp_rlow | MOD_SLAVE)) != tmp)) { |
| 549 | | MOD_SLAVE)) != tmp)) { | ||
| 550 | dev_err(&i2s->pdev->dev, | 619 | dev_err(&i2s->pdev->dev, |
| 551 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 620 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
| 552 | return -EAGAIN; | 621 | return -EAGAIN; |
| 553 | } | 622 | } |
| 554 | 623 | ||
| 555 | mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE); | 624 | mod &= ~(sdf_mask | lrp_rlow | MOD_SLAVE); |
| 556 | mod |= tmp; | 625 | mod |= tmp; |
| 557 | writel(mod, i2s->addr + I2SMOD); | 626 | writel(mod, i2s->addr + I2SMOD); |
| 558 | 627 | ||
| @@ -1007,6 +1076,8 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) | |||
| 1007 | if (IS_ERR(i2s->pdev)) | 1076 | if (IS_ERR(i2s->pdev)) |
| 1008 | return NULL; | 1077 | return NULL; |
| 1009 | 1078 | ||
| 1079 | i2s->pdev->dev.parent = &pdev->dev; | ||
| 1080 | |||
| 1010 | platform_set_drvdata(i2s->pdev, i2s); | 1081 | platform_set_drvdata(i2s->pdev, i2s); |
| 1011 | ret = platform_device_add(i2s->pdev); | 1082 | ret = platform_device_add(i2s->pdev); |
| 1012 | if (ret < 0) | 1083 | if (ret < 0) |
| @@ -1018,18 +1089,18 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) | |||
| 1018 | 1089 | ||
| 1019 | static const struct of_device_id exynos_i2s_match[]; | 1090 | static const struct of_device_id exynos_i2s_match[]; |
| 1020 | 1091 | ||
| 1021 | static inline int samsung_i2s_get_driver_data(struct platform_device *pdev) | 1092 | static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data( |
| 1093 | struct platform_device *pdev) | ||
| 1022 | { | 1094 | { |
| 1023 | #ifdef CONFIG_OF | 1095 | #ifdef CONFIG_OF |
| 1024 | struct samsung_i2s_dai_data *data; | ||
| 1025 | if (pdev->dev.of_node) { | 1096 | if (pdev->dev.of_node) { |
| 1026 | const struct of_device_id *match; | 1097 | const struct of_device_id *match; |
| 1027 | match = of_match_node(exynos_i2s_match, pdev->dev.of_node); | 1098 | match = of_match_node(exynos_i2s_match, pdev->dev.of_node); |
| 1028 | data = (struct samsung_i2s_dai_data *) match->data; | 1099 | return match->data; |
| 1029 | return data->dai_type; | ||
| 1030 | } else | 1100 | } else |
| 1031 | #endif | 1101 | #endif |
| 1032 | return platform_get_device_id(pdev)->driver_data; | 1102 | return (struct samsung_i2s_dai_data *) |
| 1103 | platform_get_device_id(pdev)->driver_data; | ||
| 1033 | } | 1104 | } |
| 1034 | 1105 | ||
| 1035 | #ifdef CONFIG_PM_RUNTIME | 1106 | #ifdef CONFIG_PM_RUNTIME |
| @@ -1060,13 +1131,13 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
| 1060 | struct resource *res; | 1131 | struct resource *res; |
| 1061 | u32 regs_base, quirks = 0, idma_addr = 0; | 1132 | u32 regs_base, quirks = 0, idma_addr = 0; |
| 1062 | struct device_node *np = pdev->dev.of_node; | 1133 | struct device_node *np = pdev->dev.of_node; |
| 1063 | enum samsung_dai_type samsung_dai_type; | 1134 | const struct samsung_i2s_dai_data *i2s_dai_data; |
| 1064 | int ret = 0; | 1135 | int ret = 0; |
| 1065 | 1136 | ||
| 1066 | /* Call during Seconday interface registration */ | 1137 | /* Call during Seconday interface registration */ |
| 1067 | samsung_dai_type = samsung_i2s_get_driver_data(pdev); | 1138 | i2s_dai_data = samsung_i2s_get_driver_data(pdev); |
| 1068 | 1139 | ||
| 1069 | if (samsung_dai_type == TYPE_SEC) { | 1140 | if (i2s_dai_data->dai_type == TYPE_SEC) { |
| 1070 | sec_dai = dev_get_drvdata(&pdev->dev); | 1141 | sec_dai = dev_get_drvdata(&pdev->dev); |
| 1071 | if (!sec_dai) { | 1142 | if (!sec_dai) { |
| 1072 | dev_err(&pdev->dev, "Unable to get drvdata\n"); | 1143 | dev_err(&pdev->dev, "Unable to get drvdata\n"); |
| @@ -1075,7 +1146,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
| 1075 | snd_soc_register_component(&sec_dai->pdev->dev, | 1146 | snd_soc_register_component(&sec_dai->pdev->dev, |
| 1076 | &samsung_i2s_component, | 1147 | &samsung_i2s_component, |
| 1077 | &sec_dai->i2s_dai_drv, 1); | 1148 | &sec_dai->i2s_dai_drv, 1); |
| 1078 | asoc_dma_platform_register(&pdev->dev); | 1149 | samsung_asoc_dma_platform_register(&pdev->dev); |
| 1079 | return 0; | 1150 | return 0; |
| 1080 | } | 1151 | } |
| 1081 | 1152 | ||
| @@ -1115,15 +1186,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
| 1115 | idma_addr = i2s_cfg->idma_addr; | 1186 | idma_addr = i2s_cfg->idma_addr; |
| 1116 | } | 1187 | } |
| 1117 | } else { | 1188 | } else { |
| 1118 | if (of_find_property(np, "samsung,supports-6ch", NULL)) | 1189 | quirks = i2s_dai_data->quirks; |
| 1119 | quirks |= QUIRK_PRI_6CHAN; | ||
| 1120 | |||
| 1121 | if (of_find_property(np, "samsung,supports-secdai", NULL)) | ||
| 1122 | quirks |= QUIRK_SEC_DAI; | ||
| 1123 | |||
| 1124 | if (of_find_property(np, "samsung,supports-rstclr", NULL)) | ||
| 1125 | quirks |= QUIRK_NEED_RSTCLR; | ||
| 1126 | |||
| 1127 | if (of_property_read_u32(np, "samsung,idma-addr", | 1190 | if (of_property_read_u32(np, "samsung,idma-addr", |
| 1128 | &idma_addr)) { | 1191 | &idma_addr)) { |
| 1129 | if (quirks & QUIRK_SEC_DAI) { | 1192 | if (quirks & QUIRK_SEC_DAI) { |
| @@ -1200,7 +1263,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
| 1200 | 1263 | ||
| 1201 | pm_runtime_enable(&pdev->dev); | 1264 | pm_runtime_enable(&pdev->dev); |
| 1202 | 1265 | ||
| 1203 | asoc_dma_platform_register(&pdev->dev); | 1266 | samsung_asoc_dma_platform_register(&pdev->dev); |
| 1204 | 1267 | ||
| 1205 | return 0; | 1268 | return 0; |
| 1206 | err: | 1269 | err: |
| @@ -1230,33 +1293,59 @@ static int samsung_i2s_remove(struct platform_device *pdev) | |||
| 1230 | i2s->pri_dai = NULL; | 1293 | i2s->pri_dai = NULL; |
| 1231 | i2s->sec_dai = NULL; | 1294 | i2s->sec_dai = NULL; |
| 1232 | 1295 | ||
| 1233 | asoc_dma_platform_unregister(&pdev->dev); | 1296 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 1234 | snd_soc_unregister_component(&pdev->dev); | 1297 | snd_soc_unregister_component(&pdev->dev); |
| 1235 | 1298 | ||
| 1236 | return 0; | 1299 | return 0; |
| 1237 | } | 1300 | } |
| 1238 | 1301 | ||
| 1302 | static const struct samsung_i2s_dai_data i2sv3_dai_type = { | ||
| 1303 | .dai_type = TYPE_PRI, | ||
| 1304 | .quirks = QUIRK_NO_MUXPSR, | ||
| 1305 | }; | ||
| 1306 | |||
| 1307 | static const struct samsung_i2s_dai_data i2sv5_dai_type = { | ||
| 1308 | .dai_type = TYPE_PRI, | ||
| 1309 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR, | ||
| 1310 | }; | ||
| 1311 | |||
| 1312 | static const struct samsung_i2s_dai_data i2sv6_dai_type = { | ||
| 1313 | .dai_type = TYPE_PRI, | ||
| 1314 | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | | ||
| 1315 | QUIRK_SUPPORTS_TDM, | ||
| 1316 | }; | ||
| 1317 | |||
| 1318 | static const struct samsung_i2s_dai_data samsung_dai_type_pri = { | ||
| 1319 | .dai_type = TYPE_PRI, | ||
| 1320 | }; | ||
| 1321 | |||
| 1322 | static const struct samsung_i2s_dai_data samsung_dai_type_sec = { | ||
| 1323 | .dai_type = TYPE_SEC, | ||
| 1324 | }; | ||
| 1325 | |||
| 1239 | static struct platform_device_id samsung_i2s_driver_ids[] = { | 1326 | static struct platform_device_id samsung_i2s_driver_ids[] = { |
| 1240 | { | 1327 | { |
| 1241 | .name = "samsung-i2s", | 1328 | .name = "samsung-i2s", |
| 1242 | .driver_data = TYPE_PRI, | 1329 | .driver_data = (kernel_ulong_t)&samsung_dai_type_pri, |
| 1243 | }, { | 1330 | }, { |
| 1244 | .name = "samsung-i2s-sec", | 1331 | .name = "samsung-i2s-sec", |
| 1245 | .driver_data = TYPE_SEC, | 1332 | .driver_data = (kernel_ulong_t)&samsung_dai_type_sec, |
| 1246 | }, | 1333 | }, |
| 1247 | {}, | 1334 | {}, |
| 1248 | }; | 1335 | }; |
| 1249 | MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids); | 1336 | MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids); |
| 1250 | 1337 | ||
| 1251 | #ifdef CONFIG_OF | 1338 | #ifdef CONFIG_OF |
| 1252 | static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = { | ||
| 1253 | [TYPE_PRI] = { TYPE_PRI }, | ||
| 1254 | [TYPE_SEC] = { TYPE_SEC }, | ||
| 1255 | }; | ||
| 1256 | |||
| 1257 | static const struct of_device_id exynos_i2s_match[] = { | 1339 | static const struct of_device_id exynos_i2s_match[] = { |
| 1258 | { .compatible = "samsung,i2s-v5", | 1340 | { |
| 1259 | .data = &samsung_i2s_dai_data_array[TYPE_PRI], | 1341 | .compatible = "samsung,s3c6410-i2s", |
| 1342 | .data = &i2sv3_dai_type, | ||
| 1343 | }, { | ||
| 1344 | .compatible = "samsung,s5pv210-i2s", | ||
| 1345 | .data = &i2sv5_dai_type, | ||
| 1346 | }, { | ||
| 1347 | .compatible = "samsung,exynos5420-i2s", | ||
| 1348 | .data = &i2sv6_dai_type, | ||
| 1260 | }, | 1349 | }, |
| 1261 | {}, | 1350 | {}, |
| 1262 | }; | 1351 | }; |
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 1566afe9ef52..e54256fc4b2c 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
| @@ -594,7 +594,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
| 594 | goto err5; | 594 | goto err5; |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | ret = asoc_dma_platform_register(&pdev->dev); | 597 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
| 598 | if (ret) { | 598 | if (ret) { |
| 599 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); | 599 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); |
| 600 | goto err6; | 600 | goto err6; |
| @@ -623,7 +623,7 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) | |||
| 623 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; | 623 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; |
| 624 | struct resource *mem_res; | 624 | struct resource *mem_res; |
| 625 | 625 | ||
| 626 | asoc_dma_platform_unregister(&pdev->dev); | 626 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 627 | snd_soc_unregister_component(&pdev->dev); | 627 | snd_soc_unregister_component(&pdev->dev); |
| 628 | 628 | ||
| 629 | pm_runtime_disable(&pdev->dev); | 629 | pm_runtime_disable(&pdev->dev); |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 47e23864ea72..ea885cb9f76c 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
| @@ -176,7 +176,7 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) | |||
| 176 | return ret; | 176 | return ret; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | ret = asoc_dma_platform_register(&pdev->dev); | 179 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
| 180 | if (ret) { | 180 | if (ret) { |
| 181 | pr_err("failed to register the DMA: %d\n", ret); | 181 | pr_err("failed to register the DMA: %d\n", ret); |
| 182 | goto err; | 182 | goto err; |
| @@ -190,7 +190,7 @@ err: | |||
| 190 | 190 | ||
| 191 | static int s3c2412_iis_dev_remove(struct platform_device *pdev) | 191 | static int s3c2412_iis_dev_remove(struct platform_device *pdev) |
| 192 | { | 192 | { |
| 193 | asoc_dma_platform_unregister(&pdev->dev); | 193 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 194 | snd_soc_unregister_component(&pdev->dev); | 194 | snd_soc_unregister_component(&pdev->dev); |
| 195 | return 0; | 195 | return 0; |
| 196 | } | 196 | } |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 8b3414551a62..9c8ebd872fac 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
| @@ -480,7 +480,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | |||
| 480 | return ret; | 480 | return ret; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | ret = asoc_dma_platform_register(&pdev->dev); | 483 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
| 484 | if (ret) { | 484 | if (ret) { |
| 485 | pr_err("failed to register the dma: %d\n", ret); | 485 | pr_err("failed to register the dma: %d\n", ret); |
| 486 | goto err; | 486 | goto err; |
| @@ -494,7 +494,7 @@ err: | |||
| 494 | 494 | ||
| 495 | static int s3c24xx_iis_dev_remove(struct platform_device *pdev) | 495 | static int s3c24xx_iis_dev_remove(struct platform_device *pdev) |
| 496 | { | 496 | { |
| 497 | asoc_dma_platform_unregister(&pdev->dev); | 497 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 498 | snd_soc_unregister_component(&pdev->dev); | 498 | snd_soc_unregister_component(&pdev->dev); |
| 499 | return 0; | 499 | return 0; |
| 500 | } | 500 | } |
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 581ea4a06fc6..5fd7a05a9b9e 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <sound/pcm_params.h> | 11 | #include <sound/pcm_params.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
| 14 | #include <linux/of_device.h> | ||
| 14 | 15 | ||
| 15 | /* | 16 | /* |
| 16 | * Default CFG switch settings to use this driver: | 17 | * Default CFG switch settings to use this driver: |
| @@ -37,11 +38,19 @@ | |||
| 37 | /* SMDK has a 16.934MHZ crystal attached to WM8994 */ | 38 | /* SMDK has a 16.934MHZ crystal attached to WM8994 */ |
| 38 | #define SMDK_WM8994_FREQ 16934000 | 39 | #define SMDK_WM8994_FREQ 16934000 |
| 39 | 40 | ||
| 41 | struct smdk_wm8994_data { | ||
| 42 | int mclk1_rate; | ||
| 43 | }; | ||
| 44 | |||
| 45 | /* Default SMDKs */ | ||
| 46 | static struct smdk_wm8994_data smdk_board_data = { | ||
| 47 | .mclk1_rate = SMDK_WM8994_FREQ, | ||
| 48 | }; | ||
| 49 | |||
| 40 | static int smdk_hw_params(struct snd_pcm_substream *substream, | 50 | static int smdk_hw_params(struct snd_pcm_substream *substream, |
| 41 | struct snd_pcm_hw_params *params) | 51 | struct snd_pcm_hw_params *params) |
| 42 | { | 52 | { |
| 43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 45 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 54 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 46 | unsigned int pll_out; | 55 | unsigned int pll_out; |
| 47 | int ret; | 56 | int ret; |
| @@ -54,18 +63,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, | |||
| 54 | else | 63 | else |
| 55 | pll_out = params_rate(params) * 256; | 64 | pll_out = params_rate(params) * 256; |
| 56 | 65 | ||
| 57 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ||
| 58 | | SND_SOC_DAIFMT_NB_NF | ||
| 59 | | SND_SOC_DAIFMT_CBM_CFM); | ||
| 60 | if (ret < 0) | ||
| 61 | return ret; | ||
| 62 | |||
| 63 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ||
| 64 | | SND_SOC_DAIFMT_NB_NF | ||
| 65 | | SND_SOC_DAIFMT_CBM_CFM); | ||
| 66 | if (ret < 0) | ||
| 67 | return ret; | ||
| 68 | |||
| 69 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, | 66 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, |
| 70 | SMDK_WM8994_FREQ, pll_out); | 67 | SMDK_WM8994_FREQ, pll_out); |
| 71 | if (ret < 0) | 68 | if (ret < 0) |
| @@ -131,6 +128,8 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
| 131 | .platform_name = "samsung-i2s.0", | 128 | .platform_name = "samsung-i2s.0", |
| 132 | .codec_name = "wm8994-codec", | 129 | .codec_name = "wm8994-codec", |
| 133 | .init = smdk_wm8994_init_paiftx, | 130 | .init = smdk_wm8994_init_paiftx, |
| 131 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 132 | SND_SOC_DAIFMT_CBM_CFM, | ||
| 134 | .ops = &smdk_ops, | 133 | .ops = &smdk_ops, |
| 135 | }, { /* Sec_Fifo Playback i/f */ | 134 | }, { /* Sec_Fifo Playback i/f */ |
| 136 | .name = "Sec_FIFO TX", | 135 | .name = "Sec_FIFO TX", |
| @@ -139,6 +138,8 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
| 139 | .codec_dai_name = "wm8994-aif1", | 138 | .codec_dai_name = "wm8994-aif1", |
| 140 | .platform_name = "samsung-i2s-sec", | 139 | .platform_name = "samsung-i2s-sec", |
| 141 | .codec_name = "wm8994-codec", | 140 | .codec_name = "wm8994-codec", |
| 141 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 142 | SND_SOC_DAIFMT_CBM_CFM, | ||
| 142 | .ops = &smdk_ops, | 143 | .ops = &smdk_ops, |
| 143 | }, | 144 | }, |
| 144 | }; | 145 | }; |
| @@ -150,15 +151,28 @@ static struct snd_soc_card smdk = { | |||
| 150 | .num_links = ARRAY_SIZE(smdk_dai), | 151 | .num_links = ARRAY_SIZE(smdk_dai), |
| 151 | }; | 152 | }; |
| 152 | 153 | ||
| 154 | #ifdef CONFIG_OF | ||
| 155 | static const struct of_device_id samsung_wm8994_of_match[] = { | ||
| 156 | { .compatible = "samsung,smdk-wm8994", .data = &smdk_board_data }, | ||
| 157 | {}, | ||
| 158 | }; | ||
| 159 | MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match); | ||
| 160 | #endif /* CONFIG_OF */ | ||
| 153 | 161 | ||
| 154 | static int smdk_audio_probe(struct platform_device *pdev) | 162 | static int smdk_audio_probe(struct platform_device *pdev) |
| 155 | { | 163 | { |
| 156 | int ret; | 164 | int ret; |
| 157 | struct device_node *np = pdev->dev.of_node; | 165 | struct device_node *np = pdev->dev.of_node; |
| 158 | struct snd_soc_card *card = &smdk; | 166 | struct snd_soc_card *card = &smdk; |
| 167 | struct smdk_wm8994_data *board; | ||
| 168 | const struct of_device_id *id; | ||
| 159 | 169 | ||
| 160 | card->dev = &pdev->dev; | 170 | card->dev = &pdev->dev; |
| 161 | 171 | ||
| 172 | board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL); | ||
| 173 | if (!board) | ||
| 174 | return -ENOMEM; | ||
| 175 | |||
| 162 | if (np) { | 176 | if (np) { |
| 163 | smdk_dai[0].cpu_dai_name = NULL; | 177 | smdk_dai[0].cpu_dai_name = NULL; |
| 164 | smdk_dai[0].cpu_of_node = of_parse_phandle(np, | 178 | smdk_dai[0].cpu_of_node = of_parse_phandle(np, |
| @@ -173,6 +187,12 @@ static int smdk_audio_probe(struct platform_device *pdev) | |||
| 173 | smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; | 187 | smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; |
| 174 | } | 188 | } |
| 175 | 189 | ||
| 190 | id = of_match_device(samsung_wm8994_of_match, &pdev->dev); | ||
| 191 | if (id) | ||
| 192 | *board = *((struct smdk_wm8994_data *)id->data); | ||
| 193 | |||
| 194 | platform_set_drvdata(pdev, board); | ||
| 195 | |||
| 176 | ret = snd_soc_register_card(card); | 196 | ret = snd_soc_register_card(card); |
| 177 | 197 | ||
| 178 | if (ret) | 198 | if (ret) |
| @@ -190,17 +210,9 @@ static int smdk_audio_remove(struct platform_device *pdev) | |||
| 190 | return 0; | 210 | return 0; |
| 191 | } | 211 | } |
| 192 | 212 | ||
| 193 | #ifdef CONFIG_OF | ||
| 194 | static const struct of_device_id samsung_wm8994_of_match[] = { | ||
| 195 | { .compatible = "samsung,smdk-wm8994", }, | ||
| 196 | {}, | ||
| 197 | }; | ||
| 198 | MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match); | ||
| 199 | #endif /* CONFIG_OF */ | ||
| 200 | |||
| 201 | static struct platform_driver smdk_audio_driver = { | 213 | static struct platform_driver smdk_audio_driver = { |
| 202 | .driver = { | 214 | .driver = { |
| 203 | .name = "smdk-audio", | 215 | .name = "smdk-audio-wm8894", |
| 204 | .owner = THIS_MODULE, | 216 | .owner = THIS_MODULE, |
| 205 | .of_match_table = of_match_ptr(samsung_wm8994_of_match), | 217 | .of_match_table = of_match_ptr(samsung_wm8994_of_match), |
| 206 | }, | 218 | }, |
| @@ -212,4 +224,4 @@ module_platform_driver(smdk_audio_driver); | |||
| 212 | 224 | ||
| 213 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); | 225 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); |
| 214 | MODULE_LICENSE("GPL"); | 226 | MODULE_LICENSE("GPL"); |
| 215 | MODULE_ALIAS("platform:smdk-audio"); | 227 | MODULE_ALIAS("platform:smdk-audio-wm8994"); |
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 2e5ebb2f1982..28487dcc4538 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c | |||
| @@ -395,7 +395,7 @@ static int spdif_probe(struct platform_device *pdev) | |||
| 395 | 395 | ||
| 396 | spin_lock_init(&spdif->lock); | 396 | spin_lock_init(&spdif->lock); |
| 397 | 397 | ||
| 398 | spdif->pclk = clk_get(&pdev->dev, "spdif"); | 398 | spdif->pclk = devm_clk_get(&pdev->dev, "spdif"); |
| 399 | if (IS_ERR(spdif->pclk)) { | 399 | if (IS_ERR(spdif->pclk)) { |
| 400 | dev_err(&pdev->dev, "failed to get peri-clock\n"); | 400 | dev_err(&pdev->dev, "failed to get peri-clock\n"); |
| 401 | ret = -ENOENT; | 401 | ret = -ENOENT; |
| @@ -403,7 +403,7 @@ static int spdif_probe(struct platform_device *pdev) | |||
| 403 | } | 403 | } |
| 404 | clk_prepare_enable(spdif->pclk); | 404 | clk_prepare_enable(spdif->pclk); |
| 405 | 405 | ||
| 406 | spdif->sclk = clk_get(&pdev->dev, "sclk_spdif"); | 406 | spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif"); |
| 407 | if (IS_ERR(spdif->sclk)) { | 407 | if (IS_ERR(spdif->sclk)) { |
| 408 | dev_err(&pdev->dev, "failed to get internal source clock\n"); | 408 | dev_err(&pdev->dev, "failed to get internal source clock\n"); |
| 409 | ret = -ENOENT; | 409 | ret = -ENOENT; |
| @@ -442,7 +442,7 @@ static int spdif_probe(struct platform_device *pdev) | |||
| 442 | 442 | ||
| 443 | spdif->dma_playback = &spdif_stereo_out; | 443 | spdif->dma_playback = &spdif_stereo_out; |
| 444 | 444 | ||
| 445 | ret = asoc_dma_platform_register(&pdev->dev); | 445 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
| 446 | if (ret) { | 446 | if (ret) { |
| 447 | dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); | 447 | dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); |
| 448 | goto err5; | 448 | goto err5; |
| @@ -457,10 +457,8 @@ err3: | |||
| 457 | release_mem_region(mem_res->start, resource_size(mem_res)); | 457 | release_mem_region(mem_res->start, resource_size(mem_res)); |
| 458 | err2: | 458 | err2: |
| 459 | clk_disable_unprepare(spdif->sclk); | 459 | clk_disable_unprepare(spdif->sclk); |
| 460 | clk_put(spdif->sclk); | ||
| 461 | err1: | 460 | err1: |
| 462 | clk_disable_unprepare(spdif->pclk); | 461 | clk_disable_unprepare(spdif->pclk); |
| 463 | clk_put(spdif->pclk); | ||
| 464 | err0: | 462 | err0: |
| 465 | return ret; | 463 | return ret; |
| 466 | } | 464 | } |
| @@ -470,7 +468,7 @@ static int spdif_remove(struct platform_device *pdev) | |||
| 470 | struct samsung_spdif_info *spdif = &spdif_info; | 468 | struct samsung_spdif_info *spdif = &spdif_info; |
| 471 | struct resource *mem_res; | 469 | struct resource *mem_res; |
| 472 | 470 | ||
| 473 | asoc_dma_platform_unregister(&pdev->dev); | 471 | samsung_asoc_dma_platform_unregister(&pdev->dev); |
| 474 | snd_soc_unregister_component(&pdev->dev); | 472 | snd_soc_unregister_component(&pdev->dev); |
| 475 | 473 | ||
| 476 | iounmap(spdif->regs); | 474 | iounmap(spdif->regs); |
| @@ -480,9 +478,7 @@ static int spdif_remove(struct platform_device *pdev) | |||
| 480 | release_mem_region(mem_res->start, resource_size(mem_res)); | 478 | release_mem_region(mem_res->start, resource_size(mem_res)); |
| 481 | 479 | ||
| 482 | clk_disable_unprepare(spdif->sclk); | 480 | clk_disable_unprepare(spdif->sclk); |
| 483 | clk_put(spdif->sclk); | ||
| 484 | clk_disable_unprepare(spdif->pclk); | 481 | clk_disable_unprepare(spdif->pclk); |
| 485 | clk_put(spdif->pclk); | ||
| 486 | 482 | ||
| 487 | return 0; | 483 | return 0; |
| 488 | } | 484 | } |
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 6bcb1164d599..56d8ff6a402d 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
| @@ -34,6 +34,13 @@ config SND_SOC_SH4_SIU | |||
| 34 | select SH_DMAE | 34 | select SH_DMAE |
| 35 | select FW_LOADER | 35 | select FW_LOADER |
| 36 | 36 | ||
| 37 | config SND_SOC_RCAR | ||
| 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | ||
| 39 | select SND_SIMPLE_CARD | ||
| 40 | select RCAR_CLK_ADG | ||
| 41 | help | ||
| 42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support | ||
| 43 | |||
| 37 | ## | 44 | ## |
| 38 | ## Boards | 45 | ## Boards |
| 39 | ## | 46 | ## |
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 849b387d17d9..aaf3dcd1ee2a 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile | |||
| @@ -12,6 +12,9 @@ obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o | |||
| 12 | obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o | 12 | obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o |
| 13 | obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o | 13 | obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o |
| 14 | 14 | ||
| 15 | ## audio units for R-Car | ||
| 16 | obj-$(CONFIG_SND_SOC_RCAR) += rcar/ | ||
| 17 | |||
| 15 | ## boards | 18 | ## boards |
| 16 | snd-soc-sh7760-ac97-objs := sh7760-ac97.o | 19 | snd-soc-sh7760-ac97-objs := sh7760-ac97.o |
| 17 | snd-soc-migor-objs := migor.o | 20 | snd-soc-migor-objs := migor.o |
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile new file mode 100644 index 000000000000..0ff492df7929 --- /dev/null +++ b/sound/soc/sh/rcar/Makefile | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o | ||
| 2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file | ||
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c new file mode 100644 index 000000000000..d80deb7ccf13 --- /dev/null +++ b/sound/soc/sh/rcar/adg.c | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | /* | ||
| 2 | * Helper routines for R-Car sound ADG. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | #include <linux/sh_clk.h> | ||
| 11 | #include <mach/clock.h> | ||
| 12 | #include "rsnd.h" | ||
| 13 | |||
| 14 | #define CLKA 0 | ||
| 15 | #define CLKB 1 | ||
| 16 | #define CLKC 2 | ||
| 17 | #define CLKI 3 | ||
| 18 | #define CLKMAX 4 | ||
| 19 | |||
| 20 | struct rsnd_adg { | ||
| 21 | struct clk *clk[CLKMAX]; | ||
| 22 | |||
| 23 | int rate_of_441khz_div_6; | ||
| 24 | int rate_of_48khz_div_6; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #define for_each_rsnd_clk(pos, adg, i) \ | ||
| 28 | for (i = 0, (pos) = adg->clk[i]; \ | ||
| 29 | i < CLKMAX; \ | ||
| 30 | i++, (pos) = adg->clk[i]) | ||
| 31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | ||
| 32 | |||
| 33 | static enum rsnd_reg rsnd_adg_ssi_reg_get(int id) | ||
| 34 | { | ||
| 35 | enum rsnd_reg reg; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * SSI 8 is not connected to ADG. | ||
| 39 | * it works with SSI 7 | ||
| 40 | */ | ||
| 41 | if (id == 8) | ||
| 42 | return RSND_REG_MAX; | ||
| 43 | |||
| 44 | if (0 <= id && id <= 3) | ||
| 45 | reg = RSND_REG_AUDIO_CLK_SEL0; | ||
| 46 | else if (4 <= id && id <= 7) | ||
| 47 | reg = RSND_REG_AUDIO_CLK_SEL1; | ||
| 48 | else | ||
| 49 | reg = RSND_REG_AUDIO_CLK_SEL2; | ||
| 50 | |||
| 51 | return reg; | ||
| 52 | } | ||
| 53 | |||
| 54 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) | ||
| 55 | { | ||
| 56 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 57 | enum rsnd_reg reg; | ||
| 58 | int id; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * "mod" = "ssi" here. | ||
| 62 | * we can get "ssi id" from mod | ||
| 63 | */ | ||
| 64 | id = rsnd_mod_id(mod); | ||
| 65 | reg = rsnd_adg_ssi_reg_get(id); | ||
| 66 | |||
| 67 | rsnd_write(priv, mod, reg, 0); | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) | ||
| 73 | { | ||
| 74 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 75 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | ||
| 76 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 77 | struct clk *clk; | ||
| 78 | enum rsnd_reg reg; | ||
| 79 | int id, shift, i; | ||
| 80 | u32 data; | ||
| 81 | int sel_table[] = { | ||
| 82 | [CLKA] = 0x1, | ||
| 83 | [CLKB] = 0x2, | ||
| 84 | [CLKC] = 0x3, | ||
| 85 | [CLKI] = 0x0, | ||
| 86 | }; | ||
| 87 | |||
| 88 | dev_dbg(dev, "request clock = %d\n", rate); | ||
| 89 | |||
| 90 | /* | ||
| 91 | * find suitable clock from | ||
| 92 | * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. | ||
| 93 | */ | ||
| 94 | data = 0; | ||
| 95 | for_each_rsnd_clk(clk, adg, i) { | ||
| 96 | if (rate == clk_get_rate(clk)) { | ||
| 97 | data = sel_table[i]; | ||
| 98 | goto found_clock; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * find 1/6 clock from BRGA/BRGB | ||
| 104 | */ | ||
| 105 | if (rate == adg->rate_of_441khz_div_6) { | ||
| 106 | data = 0x10; | ||
| 107 | goto found_clock; | ||
| 108 | } | ||
| 109 | |||
| 110 | if (rate == adg->rate_of_48khz_div_6) { | ||
| 111 | data = 0x20; | ||
| 112 | goto found_clock; | ||
| 113 | } | ||
| 114 | |||
| 115 | return -EIO; | ||
| 116 | |||
| 117 | found_clock: | ||
| 118 | |||
| 119 | /* | ||
| 120 | * This "mod" = "ssi" here. | ||
| 121 | * we can get "ssi id" from mod | ||
| 122 | */ | ||
| 123 | id = rsnd_mod_id(mod); | ||
| 124 | reg = rsnd_adg_ssi_reg_get(id); | ||
| 125 | |||
| 126 | dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Enable SSIx clock | ||
| 130 | */ | ||
| 131 | shift = (id % 4) * 8; | ||
| 132 | |||
| 133 | rsnd_bset(priv, mod, reg, | ||
| 134 | 0xFF << shift, | ||
| 135 | data << shift); | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | ||
| 141 | { | ||
| 142 | struct clk *clk; | ||
| 143 | unsigned long rate; | ||
| 144 | u32 ckr; | ||
| 145 | int i; | ||
| 146 | int brg_table[] = { | ||
| 147 | [CLKA] = 0x0, | ||
| 148 | [CLKB] = 0x1, | ||
| 149 | [CLKC] = 0x4, | ||
| 150 | [CLKI] = 0x2, | ||
| 151 | }; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC | ||
| 155 | * have 44.1kHz or 48kHz base clocks for now. | ||
| 156 | * | ||
| 157 | * SSI itself can divide parent clock by 1/1 - 1/16 | ||
| 158 | * So, BRGA outputs 44.1kHz base parent clock 1/32, | ||
| 159 | * and, BRGB outputs 48.0kHz base parent clock 1/32 here. | ||
| 160 | * see | ||
| 161 | * rsnd_adg_ssi_clk_try_start() | ||
| 162 | */ | ||
| 163 | ckr = 0; | ||
| 164 | adg->rate_of_441khz_div_6 = 0; | ||
| 165 | adg->rate_of_48khz_div_6 = 0; | ||
| 166 | for_each_rsnd_clk(clk, adg, i) { | ||
| 167 | rate = clk_get_rate(clk); | ||
| 168 | |||
| 169 | if (0 == rate) /* not used */ | ||
| 170 | continue; | ||
| 171 | |||
| 172 | /* RBGA */ | ||
| 173 | if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { | ||
| 174 | adg->rate_of_441khz_div_6 = rate / 6; | ||
| 175 | ckr |= brg_table[i] << 20; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* RBGB */ | ||
| 179 | if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { | ||
| 180 | adg->rate_of_48khz_div_6 = rate / 6; | ||
| 181 | ckr |= brg_table[i] << 16; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr); | ||
| 186 | rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */ | ||
| 187 | rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */ | ||
| 188 | } | ||
| 189 | |||
| 190 | int rsnd_adg_probe(struct platform_device *pdev, | ||
| 191 | struct rcar_snd_info *info, | ||
| 192 | struct rsnd_priv *priv) | ||
| 193 | { | ||
| 194 | struct rsnd_adg *adg; | ||
| 195 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 196 | struct clk *clk; | ||
| 197 | int i; | ||
| 198 | |||
| 199 | adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); | ||
| 200 | if (!adg) { | ||
| 201 | dev_err(dev, "ADG allocate failed\n"); | ||
| 202 | return -ENOMEM; | ||
| 203 | } | ||
| 204 | |||
| 205 | adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); | ||
| 206 | adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); | ||
| 207 | adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); | ||
| 208 | adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); | ||
| 209 | for_each_rsnd_clk(clk, adg, i) { | ||
| 210 | if (IS_ERR(clk)) { | ||
| 211 | dev_err(dev, "Audio clock failed\n"); | ||
| 212 | return -EIO; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | rsnd_adg_ssi_clk_init(priv, adg); | ||
| 217 | |||
| 218 | priv->adg = adg; | ||
| 219 | |||
| 220 | dev_dbg(dev, "adg probed\n"); | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | void rsnd_adg_remove(struct platform_device *pdev, | ||
| 226 | struct rsnd_priv *priv) | ||
| 227 | { | ||
| 228 | struct rsnd_adg *adg = priv->adg; | ||
| 229 | struct clk *clk; | ||
| 230 | int i; | ||
| 231 | |||
| 232 | for_each_rsnd_clk(clk, adg, i) | ||
| 233 | clk_put(clk); | ||
| 234 | } | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c new file mode 100644 index 000000000000..a35706028514 --- /dev/null +++ b/sound/soc/sh/rcar/core.c | |||
| @@ -0,0 +1,861 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car SRU/SCU/SSIU/SSI support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
| 6 | * | ||
| 7 | * Based on fsi.c | ||
| 8 | * Kuninori Morimoto <morimoto.kuninori@renesas.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 | /* | ||
| 16 | * Renesas R-Car sound device structure | ||
| 17 | * | ||
| 18 | * Gen1 | ||
| 19 | * | ||
| 20 | * SRU : Sound Routing Unit | ||
| 21 | * - SRC : Sampling Rate Converter | ||
| 22 | * - CMD | ||
| 23 | * - CTU : Channel Count Conversion Unit | ||
| 24 | * - MIX : Mixer | ||
| 25 | * - DVC : Digital Volume and Mute Function | ||
| 26 | * - SSI : Serial Sound Interface | ||
| 27 | * | ||
| 28 | * Gen2 | ||
| 29 | * | ||
| 30 | * SCU : Sampling Rate Converter Unit | ||
| 31 | * - SRC : Sampling Rate Converter | ||
| 32 | * - CMD | ||
| 33 | * - CTU : Channel Count Conversion Unit | ||
| 34 | * - MIX : Mixer | ||
| 35 | * - DVC : Digital Volume and Mute Function | ||
| 36 | * SSIU : Serial Sound Interface Unit | ||
| 37 | * - SSI : Serial Sound Interface | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | * driver data Image | ||
| 42 | * | ||
| 43 | * rsnd_priv | ||
| 44 | * | | ||
| 45 | * | ** this depends on Gen1/Gen2 | ||
| 46 | * | | ||
| 47 | * +- gen | ||
| 48 | * | | ||
| 49 | * | ** these depend on data path | ||
| 50 | * | ** gen and platform data control it | ||
| 51 | * | | ||
| 52 | * +- rdai[0] | ||
| 53 | * | | sru ssiu ssi | ||
| 54 | * | +- playback -> [mod] -> [mod] -> [mod] -> ... | ||
| 55 | * | | | ||
| 56 | * | | sru ssiu ssi | ||
| 57 | * | +- capture -> [mod] -> [mod] -> [mod] -> ... | ||
| 58 | * | | ||
| 59 | * +- rdai[1] | ||
| 60 | * | | sru ssiu ssi | ||
| 61 | * | +- playback -> [mod] -> [mod] -> [mod] -> ... | ||
| 62 | * | | | ||
| 63 | * | | sru ssiu ssi | ||
| 64 | * | +- capture -> [mod] -> [mod] -> [mod] -> ... | ||
| 65 | * ... | ||
| 66 | * | | ||
| 67 | * | ** these control ssi | ||
| 68 | * | | ||
| 69 | * +- ssi | ||
| 70 | * | | | ||
| 71 | * | +- ssi[0] | ||
| 72 | * | +- ssi[1] | ||
| 73 | * | +- ssi[2] | ||
| 74 | * | ... | ||
| 75 | * | | ||
| 76 | * | ** these control scu | ||
| 77 | * | | ||
| 78 | * +- scu | ||
| 79 | * | | ||
| 80 | * +- scu[0] | ||
| 81 | * +- scu[1] | ||
| 82 | * +- scu[2] | ||
| 83 | * ... | ||
| 84 | * | ||
| 85 | * | ||
| 86 | * for_each_rsnd_dai(xx, priv, xx) | ||
| 87 | * rdai[0] => rdai[1] => rdai[2] => ... | ||
| 88 | * | ||
| 89 | * for_each_rsnd_mod(xx, rdai, xx) | ||
| 90 | * [mod] => [mod] => [mod] => ... | ||
| 91 | * | ||
| 92 | * rsnd_dai_call(xxx, fn ) | ||
| 93 | * [mod]->fn() -> [mod]->fn() -> [mod]->fn()... | ||
| 94 | * | ||
| 95 | */ | ||
| 96 | #include <linux/pm_runtime.h> | ||
| 97 | #include "rsnd.h" | ||
| 98 | |||
| 99 | #define RSND_RATES SNDRV_PCM_RATE_8000_96000 | ||
| 100 | #define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | ||
| 101 | |||
| 102 | /* | ||
| 103 | * rsnd_platform functions | ||
| 104 | */ | ||
| 105 | #define rsnd_platform_call(priv, dai, func, param...) \ | ||
| 106 | (!(priv->info->func) ? -ENODEV : \ | ||
| 107 | priv->info->func(param)) | ||
| 108 | |||
| 109 | |||
| 110 | /* | ||
| 111 | * basic function | ||
| 112 | */ | ||
| 113 | u32 rsnd_read(struct rsnd_priv *priv, | ||
| 114 | struct rsnd_mod *mod, enum rsnd_reg reg) | ||
| 115 | { | ||
| 116 | void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); | ||
| 117 | |||
| 118 | BUG_ON(!base); | ||
| 119 | |||
| 120 | return ioread32(base); | ||
| 121 | } | ||
| 122 | |||
| 123 | void rsnd_write(struct rsnd_priv *priv, | ||
| 124 | struct rsnd_mod *mod, | ||
| 125 | enum rsnd_reg reg, u32 data) | ||
| 126 | { | ||
| 127 | void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); | ||
| 128 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 129 | |||
| 130 | BUG_ON(!base); | ||
| 131 | |||
| 132 | dev_dbg(dev, "w %p : %08x\n", base, data); | ||
| 133 | |||
| 134 | iowrite32(data, base); | ||
| 135 | } | ||
| 136 | |||
| 137 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | ||
| 138 | enum rsnd_reg reg, u32 mask, u32 data) | ||
| 139 | { | ||
| 140 | void __iomem *base = rsnd_gen_reg_get(priv, mod, reg); | ||
| 141 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 142 | u32 val; | ||
| 143 | |||
| 144 | BUG_ON(!base); | ||
| 145 | |||
| 146 | val = ioread32(base); | ||
| 147 | val &= ~mask; | ||
| 148 | val |= data & mask; | ||
| 149 | iowrite32(val, base); | ||
| 150 | |||
| 151 | dev_dbg(dev, "s %p : %08x\n", base, val); | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | * rsnd_mod functions | ||
| 156 | */ | ||
| 157 | char *rsnd_mod_name(struct rsnd_mod *mod) | ||
| 158 | { | ||
| 159 | if (!mod || !mod->ops) | ||
| 160 | return "unknown"; | ||
| 161 | |||
| 162 | return mod->ops->name; | ||
| 163 | } | ||
| 164 | |||
| 165 | void rsnd_mod_init(struct rsnd_priv *priv, | ||
| 166 | struct rsnd_mod *mod, | ||
| 167 | struct rsnd_mod_ops *ops, | ||
| 168 | int id) | ||
| 169 | { | ||
| 170 | mod->priv = priv; | ||
| 171 | mod->id = id; | ||
| 172 | mod->ops = ops; | ||
| 173 | INIT_LIST_HEAD(&mod->list); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * rsnd_dma functions | ||
| 178 | */ | ||
| 179 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
| 180 | { | ||
| 181 | /* push next A or B plane */ | ||
| 182 | dma->submit_loop = 1; | ||
| 183 | schedule_work(&dma->work); | ||
| 184 | } | ||
| 185 | |||
| 186 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
| 187 | { | ||
| 188 | /* push both A and B plane*/ | ||
| 189 | dma->submit_loop = 2; | ||
| 190 | schedule_work(&dma->work); | ||
| 191 | } | ||
| 192 | |||
| 193 | void rsnd_dma_stop(struct rsnd_dma *dma) | ||
| 194 | { | ||
| 195 | dma->submit_loop = 0; | ||
| 196 | cancel_work_sync(&dma->work); | ||
| 197 | dmaengine_terminate_all(dma->chan); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void rsnd_dma_complete(void *data) | ||
| 201 | { | ||
| 202 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | ||
| 203 | struct rsnd_priv *priv = dma->priv; | ||
| 204 | unsigned long flags; | ||
| 205 | |||
| 206 | rsnd_lock(priv, flags); | ||
| 207 | |||
| 208 | dma->complete(dma); | ||
| 209 | |||
| 210 | if (dma->submit_loop) | ||
| 211 | rsnd_dma_continue(dma); | ||
| 212 | |||
| 213 | rsnd_unlock(priv, flags); | ||
| 214 | } | ||
| 215 | |||
| 216 | static void rsnd_dma_do_work(struct work_struct *work) | ||
| 217 | { | ||
| 218 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
| 219 | struct rsnd_priv *priv = dma->priv; | ||
| 220 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 221 | struct dma_async_tx_descriptor *desc; | ||
| 222 | dma_addr_t buf; | ||
| 223 | size_t len; | ||
| 224 | int i; | ||
| 225 | |||
| 226 | for (i = 0; i < dma->submit_loop; i++) { | ||
| 227 | |||
| 228 | if (dma->inquiry(dma, &buf, &len) < 0) | ||
| 229 | return; | ||
| 230 | |||
| 231 | desc = dmaengine_prep_slave_single( | ||
| 232 | dma->chan, buf, len, dma->dir, | ||
| 233 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 234 | if (!desc) { | ||
| 235 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
| 236 | return; | ||
| 237 | } | ||
| 238 | |||
| 239 | desc->callback = rsnd_dma_complete; | ||
| 240 | desc->callback_param = dma; | ||
| 241 | |||
| 242 | if (dmaengine_submit(desc) < 0) { | ||
| 243 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
| 244 | return; | ||
| 245 | } | ||
| 246 | |||
| 247 | } | ||
| 248 | |||
| 249 | dma_async_issue_pending(dma->chan); | ||
| 250 | } | ||
| 251 | |||
| 252 | int rsnd_dma_available(struct rsnd_dma *dma) | ||
| 253 | { | ||
| 254 | return !!dma->chan; | ||
| 255 | } | ||
| 256 | |||
| 257 | static bool rsnd_dma_filter(struct dma_chan *chan, void *param) | ||
| 258 | { | ||
| 259 | chan->private = param; | ||
| 260 | |||
| 261 | return true; | ||
| 262 | } | ||
| 263 | |||
| 264 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | ||
| 265 | int is_play, int id, | ||
| 266 | int (*inquiry)(struct rsnd_dma *dma, | ||
| 267 | dma_addr_t *buf, int *len), | ||
| 268 | int (*complete)(struct rsnd_dma *dma)) | ||
| 269 | { | ||
| 270 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 271 | dma_cap_mask_t mask; | ||
| 272 | |||
| 273 | if (dma->chan) { | ||
| 274 | dev_err(dev, "it already has dma channel\n"); | ||
| 275 | return -EIO; | ||
| 276 | } | ||
| 277 | |||
| 278 | dma_cap_zero(mask); | ||
| 279 | dma_cap_set(DMA_SLAVE, mask); | ||
| 280 | |||
| 281 | dma->slave.shdma_slave.slave_id = id; | ||
| 282 | |||
| 283 | dma->chan = dma_request_channel(mask, rsnd_dma_filter, | ||
| 284 | &dma->slave.shdma_slave); | ||
| 285 | if (!dma->chan) { | ||
| 286 | dev_err(dev, "can't get dma channel\n"); | ||
| 287 | return -EIO; | ||
| 288 | } | ||
| 289 | |||
| 290 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
| 291 | dma->priv = priv; | ||
| 292 | dma->inquiry = inquiry; | ||
| 293 | dma->complete = complete; | ||
| 294 | INIT_WORK(&dma->work, rsnd_dma_do_work); | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | void rsnd_dma_quit(struct rsnd_priv *priv, | ||
| 300 | struct rsnd_dma *dma) | ||
| 301 | { | ||
| 302 | if (dma->chan) | ||
| 303 | dma_release_channel(dma->chan); | ||
| 304 | |||
| 305 | dma->chan = NULL; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* | ||
| 309 | * rsnd_dai functions | ||
| 310 | */ | ||
| 311 | #define rsnd_dai_call(rdai, io, fn) \ | ||
| 312 | ({ \ | ||
| 313 | struct rsnd_mod *mod, *n; \ | ||
| 314 | int ret = 0; \ | ||
| 315 | for_each_rsnd_mod(mod, n, io) { \ | ||
| 316 | ret = rsnd_mod_call(mod, fn, rdai, io); \ | ||
| 317 | if (ret < 0) \ | ||
| 318 | break; \ | ||
| 319 | } \ | ||
| 320 | ret; \ | ||
| 321 | }) | ||
| 322 | |||
| 323 | int rsnd_dai_connect(struct rsnd_dai *rdai, | ||
| 324 | struct rsnd_mod *mod, | ||
| 325 | struct rsnd_dai_stream *io) | ||
| 326 | { | ||
| 327 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 328 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 329 | |||
| 330 | if (!mod) { | ||
| 331 | dev_err(dev, "NULL mod\n"); | ||
| 332 | return -EIO; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (!list_empty(&mod->list)) { | ||
| 336 | dev_err(dev, "%s%d is not empty\n", | ||
| 337 | rsnd_mod_name(mod), | ||
| 338 | rsnd_mod_id(mod)); | ||
| 339 | return -EIO; | ||
| 340 | } | ||
| 341 | |||
| 342 | list_add_tail(&mod->list, &io->head); | ||
| 343 | |||
| 344 | return 0; | ||
| 345 | } | ||
| 346 | |||
| 347 | int rsnd_dai_disconnect(struct rsnd_mod *mod) | ||
| 348 | { | ||
| 349 | list_del_init(&mod->list); | ||
| 350 | |||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) | ||
| 355 | { | ||
| 356 | int id = rdai - priv->rdai; | ||
| 357 | |||
| 358 | if ((id < 0) || (id >= rsnd_dai_nr(priv))) | ||
| 359 | return -EINVAL; | ||
| 360 | |||
| 361 | return id; | ||
| 362 | } | ||
| 363 | |||
| 364 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) | ||
| 365 | { | ||
| 366 | return priv->rdai + id; | ||
| 367 | } | ||
| 368 | |||
| 369 | static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) | ||
| 370 | { | ||
| 371 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); | ||
| 372 | |||
| 373 | return rsnd_dai_get(priv, dai->id); | ||
| 374 | } | ||
| 375 | |||
| 376 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io) | ||
| 377 | { | ||
| 378 | return &rdai->playback == io; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* | ||
| 382 | * rsnd_soc_dai functions | ||
| 383 | */ | ||
| 384 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional) | ||
| 385 | { | ||
| 386 | struct snd_pcm_substream *substream = io->substream; | ||
| 387 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 388 | int pos = io->byte_pos + additional; | ||
| 389 | |||
| 390 | pos %= (runtime->periods * io->byte_per_period); | ||
| 391 | |||
| 392 | return pos; | ||
| 393 | } | ||
| 394 | |||
| 395 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) | ||
| 396 | { | ||
| 397 | io->byte_pos += byte; | ||
| 398 | |||
| 399 | if (io->byte_pos >= io->next_period_byte) { | ||
| 400 | struct snd_pcm_substream *substream = io->substream; | ||
| 401 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 402 | |||
| 403 | io->period_pos++; | ||
| 404 | io->next_period_byte += io->byte_per_period; | ||
| 405 | |||
| 406 | if (io->period_pos >= runtime->periods) { | ||
| 407 | io->byte_pos = 0; | ||
| 408 | io->period_pos = 0; | ||
| 409 | io->next_period_byte = io->byte_per_period; | ||
| 410 | } | ||
| 411 | |||
| 412 | snd_pcm_period_elapsed(substream); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, | ||
| 417 | struct snd_pcm_substream *substream) | ||
| 418 | { | ||
| 419 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 420 | |||
| 421 | if (!list_empty(&io->head)) | ||
| 422 | return -EIO; | ||
| 423 | |||
| 424 | INIT_LIST_HEAD(&io->head); | ||
| 425 | io->substream = substream; | ||
| 426 | io->byte_pos = 0; | ||
| 427 | io->period_pos = 0; | ||
| 428 | io->byte_per_period = runtime->period_size * | ||
| 429 | runtime->channels * | ||
| 430 | samples_to_bytes(runtime, 1); | ||
| 431 | io->next_period_byte = io->byte_per_period; | ||
| 432 | |||
| 433 | return 0; | ||
| 434 | } | ||
| 435 | |||
| 436 | static | ||
| 437 | struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream) | ||
| 438 | { | ||
| 439 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 440 | |||
| 441 | return rtd->cpu_dai; | ||
| 442 | } | ||
| 443 | |||
| 444 | static | ||
| 445 | struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai, | ||
| 446 | struct snd_pcm_substream *substream) | ||
| 447 | { | ||
| 448 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 449 | return &rdai->playback; | ||
| 450 | else | ||
| 451 | return &rdai->capture; | ||
| 452 | } | ||
| 453 | |||
| 454 | static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
| 455 | struct snd_soc_dai *dai) | ||
| 456 | { | ||
| 457 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); | ||
| 458 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
| 459 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | ||
| 460 | struct rsnd_mod *mod = rsnd_ssi_mod_get_frm_dai(priv, | ||
| 461 | rsnd_dai_id(priv, rdai), | ||
| 462 | rsnd_dai_is_play(rdai, io)); | ||
| 463 | int ssi_id = rsnd_mod_id(mod); | ||
| 464 | int ret; | ||
| 465 | unsigned long flags; | ||
| 466 | |||
| 467 | rsnd_lock(priv, flags); | ||
| 468 | |||
| 469 | switch (cmd) { | ||
| 470 | case SNDRV_PCM_TRIGGER_START: | ||
| 471 | ret = rsnd_dai_stream_init(io, substream); | ||
| 472 | if (ret < 0) | ||
| 473 | goto dai_trigger_end; | ||
| 474 | |||
| 475 | ret = rsnd_platform_call(priv, dai, start, ssi_id); | ||
| 476 | if (ret < 0) | ||
| 477 | goto dai_trigger_end; | ||
| 478 | |||
| 479 | ret = rsnd_gen_path_init(priv, rdai, io); | ||
| 480 | if (ret < 0) | ||
| 481 | goto dai_trigger_end; | ||
| 482 | |||
| 483 | ret = rsnd_dai_call(rdai, io, init); | ||
| 484 | if (ret < 0) | ||
| 485 | goto dai_trigger_end; | ||
| 486 | |||
| 487 | ret = rsnd_dai_call(rdai, io, start); | ||
| 488 | if (ret < 0) | ||
| 489 | goto dai_trigger_end; | ||
| 490 | break; | ||
| 491 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 492 | ret = rsnd_dai_call(rdai, io, stop); | ||
| 493 | if (ret < 0) | ||
| 494 | goto dai_trigger_end; | ||
| 495 | |||
| 496 | ret = rsnd_dai_call(rdai, io, quit); | ||
| 497 | if (ret < 0) | ||
| 498 | goto dai_trigger_end; | ||
| 499 | |||
| 500 | ret = rsnd_gen_path_exit(priv, rdai, io); | ||
| 501 | if (ret < 0) | ||
| 502 | goto dai_trigger_end; | ||
| 503 | |||
| 504 | ret = rsnd_platform_call(priv, dai, stop, ssi_id); | ||
| 505 | if (ret < 0) | ||
| 506 | goto dai_trigger_end; | ||
| 507 | break; | ||
| 508 | default: | ||
| 509 | ret = -EINVAL; | ||
| 510 | } | ||
| 511 | |||
| 512 | dai_trigger_end: | ||
| 513 | rsnd_unlock(priv, flags); | ||
| 514 | |||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
| 519 | { | ||
| 520 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
| 521 | |||
| 522 | /* set master/slave audio interface */ | ||
| 523 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
| 524 | case SND_SOC_DAIFMT_CBM_CFM: | ||
| 525 | rdai->clk_master = 1; | ||
| 526 | break; | ||
| 527 | case SND_SOC_DAIFMT_CBS_CFS: | ||
| 528 | rdai->clk_master = 0; | ||
| 529 | break; | ||
| 530 | default: | ||
| 531 | return -EINVAL; | ||
| 532 | } | ||
| 533 | |||
| 534 | /* set clock inversion */ | ||
| 535 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
| 536 | case SND_SOC_DAIFMT_NB_IF: | ||
| 537 | rdai->bit_clk_inv = 0; | ||
| 538 | rdai->frm_clk_inv = 1; | ||
| 539 | break; | ||
| 540 | case SND_SOC_DAIFMT_IB_NF: | ||
| 541 | rdai->bit_clk_inv = 1; | ||
| 542 | rdai->frm_clk_inv = 0; | ||
| 543 | break; | ||
| 544 | case SND_SOC_DAIFMT_IB_IF: | ||
| 545 | rdai->bit_clk_inv = 1; | ||
| 546 | rdai->frm_clk_inv = 1; | ||
| 547 | break; | ||
| 548 | case SND_SOC_DAIFMT_NB_NF: | ||
| 549 | default: | ||
| 550 | rdai->bit_clk_inv = 0; | ||
| 551 | rdai->frm_clk_inv = 0; | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | |||
| 555 | /* set format */ | ||
| 556 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 557 | case SND_SOC_DAIFMT_I2S: | ||
| 558 | rdai->sys_delay = 0; | ||
| 559 | rdai->data_alignment = 0; | ||
| 560 | break; | ||
| 561 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 562 | rdai->sys_delay = 1; | ||
| 563 | rdai->data_alignment = 0; | ||
| 564 | break; | ||
| 565 | case SND_SOC_DAIFMT_RIGHT_J: | ||
| 566 | rdai->sys_delay = 1; | ||
| 567 | rdai->data_alignment = 1; | ||
| 568 | break; | ||
| 569 | } | ||
| 570 | |||
| 571 | return 0; | ||
| 572 | } | ||
| 573 | |||
| 574 | static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | ||
| 575 | .trigger = rsnd_soc_dai_trigger, | ||
| 576 | .set_fmt = rsnd_soc_dai_set_fmt, | ||
| 577 | }; | ||
| 578 | |||
| 579 | static int rsnd_dai_probe(struct platform_device *pdev, | ||
| 580 | struct rcar_snd_info *info, | ||
| 581 | struct rsnd_priv *priv) | ||
| 582 | { | ||
| 583 | struct snd_soc_dai_driver *drv; | ||
| 584 | struct rsnd_dai *rdai; | ||
| 585 | struct rsnd_mod *pmod, *cmod; | ||
| 586 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 587 | int dai_nr; | ||
| 588 | int i; | ||
| 589 | |||
| 590 | /* get max dai nr */ | ||
| 591 | for (dai_nr = 0; dai_nr < 32; dai_nr++) { | ||
| 592 | pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); | ||
| 593 | cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); | ||
| 594 | |||
| 595 | if (!pmod && !cmod) | ||
| 596 | break; | ||
| 597 | } | ||
| 598 | |||
| 599 | if (!dai_nr) { | ||
| 600 | dev_err(dev, "no dai\n"); | ||
| 601 | return -EIO; | ||
| 602 | } | ||
| 603 | |||
| 604 | drv = devm_kzalloc(dev, sizeof(*drv) * dai_nr, GFP_KERNEL); | ||
| 605 | rdai = devm_kzalloc(dev, sizeof(*rdai) * dai_nr, GFP_KERNEL); | ||
| 606 | if (!drv || !rdai) { | ||
| 607 | dev_err(dev, "dai allocate failed\n"); | ||
| 608 | return -ENOMEM; | ||
| 609 | } | ||
| 610 | |||
| 611 | for (i = 0; i < dai_nr; i++) { | ||
| 612 | |||
| 613 | pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); | ||
| 614 | cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); | ||
| 615 | |||
| 616 | /* | ||
| 617 | * init rsnd_dai | ||
| 618 | */ | ||
| 619 | INIT_LIST_HEAD(&rdai[i].playback.head); | ||
| 620 | INIT_LIST_HEAD(&rdai[i].capture.head); | ||
| 621 | |||
| 622 | snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); | ||
| 623 | |||
| 624 | /* | ||
| 625 | * init snd_soc_dai_driver | ||
| 626 | */ | ||
| 627 | drv[i].name = rdai[i].name; | ||
| 628 | drv[i].ops = &rsnd_soc_dai_ops; | ||
| 629 | if (pmod) { | ||
| 630 | drv[i].playback.rates = RSND_RATES; | ||
| 631 | drv[i].playback.formats = RSND_FMTS; | ||
| 632 | drv[i].playback.channels_min = 2; | ||
| 633 | drv[i].playback.channels_max = 2; | ||
| 634 | } | ||
| 635 | if (cmod) { | ||
| 636 | drv[i].capture.rates = RSND_RATES; | ||
| 637 | drv[i].capture.formats = RSND_FMTS; | ||
| 638 | drv[i].capture.channels_min = 2; | ||
| 639 | drv[i].capture.channels_max = 2; | ||
| 640 | } | ||
| 641 | |||
| 642 | dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, | ||
| 643 | pmod ? "play" : " -- ", | ||
| 644 | cmod ? "capture" : " -- "); | ||
| 645 | } | ||
| 646 | |||
| 647 | priv->dai_nr = dai_nr; | ||
| 648 | priv->daidrv = drv; | ||
| 649 | priv->rdai = rdai; | ||
| 650 | |||
| 651 | return 0; | ||
| 652 | } | ||
| 653 | |||
| 654 | static void rsnd_dai_remove(struct platform_device *pdev, | ||
| 655 | struct rsnd_priv *priv) | ||
| 656 | { | ||
| 657 | } | ||
| 658 | |||
| 659 | /* | ||
| 660 | * pcm ops | ||
| 661 | */ | ||
| 662 | static struct snd_pcm_hardware rsnd_pcm_hardware = { | ||
| 663 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
| 664 | SNDRV_PCM_INFO_MMAP | | ||
| 665 | SNDRV_PCM_INFO_MMAP_VALID | | ||
| 666 | SNDRV_PCM_INFO_PAUSE, | ||
| 667 | .formats = RSND_FMTS, | ||
| 668 | .rates = RSND_RATES, | ||
| 669 | .rate_min = 8000, | ||
| 670 | .rate_max = 192000, | ||
| 671 | .channels_min = 2, | ||
| 672 | .channels_max = 2, | ||
| 673 | .buffer_bytes_max = 64 * 1024, | ||
| 674 | .period_bytes_min = 32, | ||
| 675 | .period_bytes_max = 8192, | ||
| 676 | .periods_min = 1, | ||
| 677 | .periods_max = 32, | ||
| 678 | .fifo_size = 256, | ||
| 679 | }; | ||
| 680 | |||
| 681 | static int rsnd_pcm_open(struct snd_pcm_substream *substream) | ||
| 682 | { | ||
| 683 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 684 | int ret = 0; | ||
| 685 | |||
| 686 | snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware); | ||
| 687 | |||
| 688 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
| 689 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
| 690 | |||
| 691 | return ret; | ||
| 692 | } | ||
| 693 | |||
| 694 | static int rsnd_hw_params(struct snd_pcm_substream *substream, | ||
| 695 | struct snd_pcm_hw_params *hw_params) | ||
| 696 | { | ||
| 697 | return snd_pcm_lib_malloc_pages(substream, | ||
| 698 | params_buffer_bytes(hw_params)); | ||
| 699 | } | ||
| 700 | |||
| 701 | static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) | ||
| 702 | { | ||
| 703 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 704 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); | ||
| 705 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
| 706 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | ||
| 707 | |||
| 708 | return bytes_to_frames(runtime, io->byte_pos); | ||
| 709 | } | ||
| 710 | |||
| 711 | static struct snd_pcm_ops rsnd_pcm_ops = { | ||
| 712 | .open = rsnd_pcm_open, | ||
| 713 | .ioctl = snd_pcm_lib_ioctl, | ||
| 714 | .hw_params = rsnd_hw_params, | ||
| 715 | .hw_free = snd_pcm_lib_free_pages, | ||
| 716 | .pointer = rsnd_pointer, | ||
| 717 | }; | ||
| 718 | |||
| 719 | /* | ||
| 720 | * snd_soc_platform | ||
| 721 | */ | ||
| 722 | |||
| 723 | #define PREALLOC_BUFFER (32 * 1024) | ||
| 724 | #define PREALLOC_BUFFER_MAX (32 * 1024) | ||
| 725 | |||
| 726 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
| 727 | { | ||
| 728 | return snd_pcm_lib_preallocate_pages_for_all( | ||
| 729 | rtd->pcm, | ||
| 730 | SNDRV_DMA_TYPE_DEV, | ||
| 731 | rtd->card->snd_card->dev, | ||
| 732 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | ||
| 733 | } | ||
| 734 | |||
| 735 | static void rsnd_pcm_free(struct snd_pcm *pcm) | ||
| 736 | { | ||
| 737 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
| 738 | } | ||
| 739 | |||
| 740 | static struct snd_soc_platform_driver rsnd_soc_platform = { | ||
| 741 | .ops = &rsnd_pcm_ops, | ||
| 742 | .pcm_new = rsnd_pcm_new, | ||
| 743 | .pcm_free = rsnd_pcm_free, | ||
| 744 | }; | ||
| 745 | |||
| 746 | static const struct snd_soc_component_driver rsnd_soc_component = { | ||
| 747 | .name = "rsnd", | ||
| 748 | }; | ||
| 749 | |||
| 750 | /* | ||
| 751 | * rsnd probe | ||
| 752 | */ | ||
| 753 | static int rsnd_probe(struct platform_device *pdev) | ||
| 754 | { | ||
| 755 | struct rcar_snd_info *info; | ||
| 756 | struct rsnd_priv *priv; | ||
| 757 | struct device *dev = &pdev->dev; | ||
| 758 | int ret; | ||
| 759 | |||
| 760 | info = pdev->dev.platform_data; | ||
| 761 | if (!info) { | ||
| 762 | dev_err(dev, "driver needs R-Car sound information\n"); | ||
| 763 | return -ENODEV; | ||
| 764 | } | ||
| 765 | |||
| 766 | /* | ||
| 767 | * init priv data | ||
| 768 | */ | ||
| 769 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 770 | if (!priv) { | ||
| 771 | dev_err(dev, "priv allocate failed\n"); | ||
| 772 | return -ENODEV; | ||
| 773 | } | ||
| 774 | |||
| 775 | priv->dev = dev; | ||
| 776 | priv->info = info; | ||
| 777 | spin_lock_init(&priv->lock); | ||
| 778 | |||
| 779 | /* | ||
| 780 | * init each module | ||
| 781 | */ | ||
| 782 | ret = rsnd_gen_probe(pdev, info, priv); | ||
| 783 | if (ret < 0) | ||
| 784 | return ret; | ||
| 785 | |||
| 786 | ret = rsnd_scu_probe(pdev, info, priv); | ||
| 787 | if (ret < 0) | ||
| 788 | return ret; | ||
| 789 | |||
| 790 | ret = rsnd_adg_probe(pdev, info, priv); | ||
| 791 | if (ret < 0) | ||
| 792 | return ret; | ||
| 793 | |||
| 794 | ret = rsnd_ssi_probe(pdev, info, priv); | ||
| 795 | if (ret < 0) | ||
| 796 | return ret; | ||
| 797 | |||
| 798 | ret = rsnd_dai_probe(pdev, info, priv); | ||
| 799 | if (ret < 0) | ||
| 800 | return ret; | ||
| 801 | |||
| 802 | /* | ||
| 803 | * asoc register | ||
| 804 | */ | ||
| 805 | ret = snd_soc_register_platform(dev, &rsnd_soc_platform); | ||
| 806 | if (ret < 0) { | ||
| 807 | dev_err(dev, "cannot snd soc register\n"); | ||
| 808 | return ret; | ||
| 809 | } | ||
| 810 | |||
| 811 | ret = snd_soc_register_component(dev, &rsnd_soc_component, | ||
| 812 | priv->daidrv, rsnd_dai_nr(priv)); | ||
| 813 | if (ret < 0) { | ||
| 814 | dev_err(dev, "cannot snd dai register\n"); | ||
| 815 | goto exit_snd_soc; | ||
| 816 | } | ||
| 817 | |||
| 818 | dev_set_drvdata(dev, priv); | ||
| 819 | |||
| 820 | pm_runtime_enable(dev); | ||
| 821 | |||
| 822 | dev_info(dev, "probed\n"); | ||
| 823 | return ret; | ||
| 824 | |||
| 825 | exit_snd_soc: | ||
| 826 | snd_soc_unregister_platform(dev); | ||
| 827 | |||
| 828 | return ret; | ||
| 829 | } | ||
| 830 | |||
| 831 | static int rsnd_remove(struct platform_device *pdev) | ||
| 832 | { | ||
| 833 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | ||
| 834 | |||
| 835 | pm_runtime_disable(&pdev->dev); | ||
| 836 | |||
| 837 | /* | ||
| 838 | * remove each module | ||
| 839 | */ | ||
| 840 | rsnd_ssi_remove(pdev, priv); | ||
| 841 | rsnd_adg_remove(pdev, priv); | ||
| 842 | rsnd_scu_remove(pdev, priv); | ||
| 843 | rsnd_dai_remove(pdev, priv); | ||
| 844 | rsnd_gen_remove(pdev, priv); | ||
| 845 | |||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | static struct platform_driver rsnd_driver = { | ||
| 850 | .driver = { | ||
| 851 | .name = "rcar_sound", | ||
| 852 | }, | ||
| 853 | .probe = rsnd_probe, | ||
| 854 | .remove = rsnd_remove, | ||
| 855 | }; | ||
| 856 | module_platform_driver(rsnd_driver); | ||
| 857 | |||
| 858 | MODULE_LICENSE("GPL"); | ||
| 859 | MODULE_DESCRIPTION("Renesas R-Car audio driver"); | ||
| 860 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
| 861 | MODULE_ALIAS("platform:rcar-pcm-audio"); | ||
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c new file mode 100644 index 000000000000..babb203b43b7 --- /dev/null +++ b/sound/soc/sh/rcar/gen.c | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car Gen1 SRU/SSI support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 | #include "rsnd.h" | ||
| 12 | |||
| 13 | struct rsnd_gen_ops { | ||
| 14 | int (*path_init)(struct rsnd_priv *priv, | ||
| 15 | struct rsnd_dai *rdai, | ||
| 16 | struct rsnd_dai_stream *io); | ||
| 17 | int (*path_exit)(struct rsnd_priv *priv, | ||
| 18 | struct rsnd_dai *rdai, | ||
| 19 | struct rsnd_dai_stream *io); | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct rsnd_gen_reg_map { | ||
| 23 | int index; /* -1 : not supported */ | ||
| 24 | u32 offset_id; /* offset of ssi0, ssi1, ssi2... */ | ||
| 25 | u32 offset_adr; /* offset of SSICR, SSISR, ... */ | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct rsnd_gen { | ||
| 29 | void __iomem *base[RSND_BASE_MAX]; | ||
| 30 | |||
| 31 | struct rsnd_gen_reg_map reg_map[RSND_REG_MAX]; | ||
| 32 | struct rsnd_gen_ops *ops; | ||
| 33 | }; | ||
| 34 | |||
| 35 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Gen2 | ||
| 39 | * will be filled in the future | ||
| 40 | */ | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Gen1 | ||
| 44 | */ | ||
| 45 | static int rsnd_gen1_path_init(struct rsnd_priv *priv, | ||
| 46 | struct rsnd_dai *rdai, | ||
| 47 | struct rsnd_dai_stream *io) | ||
| 48 | { | ||
| 49 | struct rsnd_mod *mod; | ||
| 50 | int ret; | ||
| 51 | int id; | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Gen1 is created by SRU/SSI, and this SRU is base module of | ||
| 55 | * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) | ||
| 56 | * | ||
| 57 | * Easy image is.. | ||
| 58 | * Gen1 SRU = Gen2 SCU + SSIU + etc | ||
| 59 | * | ||
| 60 | * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is | ||
| 61 | * using fixed path. | ||
| 62 | * | ||
| 63 | * Then, SSI id = SCU id here | ||
| 64 | */ | ||
| 65 | |||
| 66 | /* get SSI's ID */ | ||
| 67 | mod = rsnd_ssi_mod_get_frm_dai(priv, | ||
| 68 | rsnd_dai_id(priv, rdai), | ||
| 69 | rsnd_dai_is_play(rdai, io)); | ||
| 70 | id = rsnd_mod_id(mod); | ||
| 71 | |||
| 72 | /* SSI */ | ||
| 73 | mod = rsnd_ssi_mod_get(priv, id); | ||
| 74 | ret = rsnd_dai_connect(rdai, mod, io); | ||
| 75 | if (ret < 0) | ||
| 76 | return ret; | ||
| 77 | |||
| 78 | /* SCU */ | ||
| 79 | mod = rsnd_scu_mod_get(priv, id); | ||
| 80 | ret = rsnd_dai_connect(rdai, mod, io); | ||
| 81 | |||
| 82 | return ret; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int rsnd_gen1_path_exit(struct rsnd_priv *priv, | ||
| 86 | struct rsnd_dai *rdai, | ||
| 87 | struct rsnd_dai_stream *io) | ||
| 88 | { | ||
| 89 | struct rsnd_mod *mod, *n; | ||
| 90 | int ret = 0; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * remove all mod from rdai | ||
| 94 | */ | ||
| 95 | for_each_rsnd_mod(mod, n, io) | ||
| 96 | ret |= rsnd_dai_disconnect(mod); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | static struct rsnd_gen_ops rsnd_gen1_ops = { | ||
| 102 | .path_init = rsnd_gen1_path_init, | ||
| 103 | .path_exit = rsnd_gen1_path_exit, | ||
| 104 | }; | ||
| 105 | |||
| 106 | #define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \ | ||
| 107 | do { \ | ||
| 108 | (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \ | ||
| 109 | (g)->reg_map[RSND_REG_##i].offset_id = oi; \ | ||
| 110 | (g)->reg_map[RSND_REG_##i].offset_adr = oa; \ | ||
| 111 | } while (0) | ||
| 112 | |||
| 113 | static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen) | ||
| 114 | { | ||
| 115 | RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00); | ||
| 116 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08); | ||
| 117 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c); | ||
| 118 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10); | ||
| 119 | RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0); | ||
| 120 | RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0); | ||
| 121 | RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4); | ||
| 122 | RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20); | ||
| 123 | RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214); | ||
| 124 | |||
| 125 | RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00); | ||
| 126 | RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04); | ||
| 127 | RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08); | ||
| 128 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c); | ||
| 129 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10); | ||
| 130 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18); | ||
| 131 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c); | ||
| 132 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20); | ||
| 133 | |||
| 134 | RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00); | ||
| 135 | RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04); | ||
| 136 | RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08); | ||
| 137 | RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c); | ||
| 138 | RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int rsnd_gen1_probe(struct platform_device *pdev, | ||
| 142 | struct rcar_snd_info *info, | ||
| 143 | struct rsnd_priv *priv) | ||
| 144 | { | ||
| 145 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 146 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
| 147 | struct resource *sru_res; | ||
| 148 | struct resource *adg_res; | ||
| 149 | struct resource *ssi_res; | ||
| 150 | |||
| 151 | /* | ||
| 152 | * map address | ||
| 153 | */ | ||
| 154 | sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); | ||
| 155 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); | ||
| 156 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); | ||
| 157 | |||
| 158 | gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); | ||
| 159 | gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); | ||
| 160 | gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); | ||
| 161 | if (IS_ERR(gen->base[RSND_GEN1_SRU]) || | ||
| 162 | IS_ERR(gen->base[RSND_GEN1_ADG]) || | ||
| 163 | IS_ERR(gen->base[RSND_GEN1_SSI])) | ||
| 164 | return -ENODEV; | ||
| 165 | |||
| 166 | gen->ops = &rsnd_gen1_ops; | ||
| 167 | rsnd_gen1_reg_map_init(gen); | ||
| 168 | |||
| 169 | dev_dbg(dev, "Gen1 device probed\n"); | ||
| 170 | dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, | ||
| 171 | gen->base[RSND_GEN1_SRU]); | ||
| 172 | dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, | ||
| 173 | gen->base[RSND_GEN1_ADG]); | ||
| 174 | dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, | ||
| 175 | gen->base[RSND_GEN1_SSI]); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | |||
| 179 | } | ||
| 180 | |||
| 181 | static void rsnd_gen1_remove(struct platform_device *pdev, | ||
| 182 | struct rsnd_priv *priv) | ||
| 183 | { | ||
| 184 | } | ||
| 185 | |||
| 186 | /* | ||
| 187 | * Gen | ||
| 188 | */ | ||
| 189 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
| 190 | struct rsnd_dai *rdai, | ||
| 191 | struct rsnd_dai_stream *io) | ||
| 192 | { | ||
| 193 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
| 194 | |||
| 195 | return gen->ops->path_init(priv, rdai, io); | ||
| 196 | } | ||
| 197 | |||
| 198 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | ||
| 199 | struct rsnd_dai *rdai, | ||
| 200 | struct rsnd_dai_stream *io) | ||
| 201 | { | ||
| 202 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
| 203 | |||
| 204 | return gen->ops->path_exit(priv, rdai, io); | ||
| 205 | } | ||
| 206 | |||
| 207 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | ||
| 208 | struct rsnd_mod *mod, | ||
| 209 | enum rsnd_reg reg) | ||
| 210 | { | ||
| 211 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
| 212 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 213 | int index; | ||
| 214 | u32 offset_id, offset_adr; | ||
| 215 | |||
| 216 | if (reg >= RSND_REG_MAX) { | ||
| 217 | dev_err(dev, "rsnd_reg reg error\n"); | ||
| 218 | return NULL; | ||
| 219 | } | ||
| 220 | |||
| 221 | index = gen->reg_map[reg].index; | ||
| 222 | offset_id = gen->reg_map[reg].offset_id; | ||
| 223 | offset_adr = gen->reg_map[reg].offset_adr; | ||
| 224 | |||
| 225 | if (index < 0) { | ||
| 226 | dev_err(dev, "unsupported reg access %d\n", reg); | ||
| 227 | return NULL; | ||
| 228 | } | ||
| 229 | |||
| 230 | if (offset_id && mod) | ||
| 231 | offset_id *= rsnd_mod_id(mod); | ||
| 232 | |||
| 233 | /* | ||
| 234 | * index/offset were set on gen1/gen2 | ||
| 235 | */ | ||
| 236 | |||
| 237 | return gen->base[index] + offset_id + offset_adr; | ||
| 238 | } | ||
| 239 | |||
| 240 | int rsnd_gen_probe(struct platform_device *pdev, | ||
| 241 | struct rcar_snd_info *info, | ||
| 242 | struct rsnd_priv *priv) | ||
| 243 | { | ||
| 244 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 245 | struct rsnd_gen *gen; | ||
| 246 | int i; | ||
| 247 | |||
| 248 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); | ||
| 249 | if (!gen) { | ||
| 250 | dev_err(dev, "GEN allocate failed\n"); | ||
| 251 | return -ENOMEM; | ||
| 252 | } | ||
| 253 | |||
| 254 | priv->gen = gen; | ||
| 255 | |||
| 256 | /* | ||
| 257 | * see | ||
| 258 | * rsnd_reg_get() | ||
| 259 | * rsnd_gen_probe() | ||
| 260 | */ | ||
| 261 | for (i = 0; i < RSND_REG_MAX; i++) | ||
| 262 | gen->reg_map[i].index = -1; | ||
| 263 | |||
| 264 | /* | ||
| 265 | * init each module | ||
| 266 | */ | ||
| 267 | if (rsnd_is_gen1(priv)) | ||
| 268 | return rsnd_gen1_probe(pdev, info, priv); | ||
| 269 | |||
| 270 | dev_err(dev, "unknown generation R-Car sound device\n"); | ||
| 271 | |||
| 272 | return -ENODEV; | ||
| 273 | } | ||
| 274 | |||
| 275 | void rsnd_gen_remove(struct platform_device *pdev, | ||
| 276 | struct rsnd_priv *priv) | ||
| 277 | { | ||
| 278 | if (rsnd_is_gen1(priv)) | ||
| 279 | rsnd_gen1_remove(pdev, priv); | ||
| 280 | } | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h new file mode 100644 index 000000000000..9cc6986a8cfb --- /dev/null +++ b/sound/soc/sh/rcar/rsnd.h | |||
| @@ -0,0 +1,302 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 | #ifndef RSND_H | ||
| 12 | #define RSND_H | ||
| 13 | |||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/dma-mapping.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/list.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/sh_dma.h> | ||
| 21 | #include <linux/workqueue.h> | ||
| 22 | #include <sound/rcar_snd.h> | ||
| 23 | #include <sound/soc.h> | ||
| 24 | #include <sound/pcm_params.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * pseudo register | ||
| 28 | * | ||
| 29 | * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different. | ||
| 30 | * This driver uses pseudo register in order to hide it. | ||
| 31 | * see gen1/gen2 for detail | ||
| 32 | */ | ||
| 33 | enum rsnd_reg { | ||
| 34 | /* SRU/SCU */ | ||
| 35 | RSND_REG_SRC_ROUTE_SEL, | ||
| 36 | RSND_REG_SRC_TMG_SEL0, | ||
| 37 | RSND_REG_SRC_TMG_SEL1, | ||
| 38 | RSND_REG_SRC_TMG_SEL2, | ||
| 39 | RSND_REG_SRC_CTRL, | ||
| 40 | RSND_REG_SSI_MODE0, | ||
| 41 | RSND_REG_SSI_MODE1, | ||
| 42 | RSND_REG_BUSIF_MODE, | ||
| 43 | RSND_REG_BUSIF_ADINR, | ||
| 44 | |||
| 45 | /* ADG */ | ||
| 46 | RSND_REG_BRRA, | ||
| 47 | RSND_REG_BRRB, | ||
| 48 | RSND_REG_SSICKR, | ||
| 49 | RSND_REG_AUDIO_CLK_SEL0, | ||
| 50 | RSND_REG_AUDIO_CLK_SEL1, | ||
| 51 | RSND_REG_AUDIO_CLK_SEL2, | ||
| 52 | RSND_REG_AUDIO_CLK_SEL3, | ||
| 53 | RSND_REG_AUDIO_CLK_SEL4, | ||
| 54 | RSND_REG_AUDIO_CLK_SEL5, | ||
| 55 | |||
| 56 | /* SSI */ | ||
| 57 | RSND_REG_SSICR, | ||
| 58 | RSND_REG_SSISR, | ||
| 59 | RSND_REG_SSITDR, | ||
| 60 | RSND_REG_SSIRDR, | ||
| 61 | RSND_REG_SSIWSR, | ||
| 62 | |||
| 63 | RSND_REG_MAX, | ||
| 64 | }; | ||
| 65 | |||
| 66 | struct rsnd_priv; | ||
| 67 | struct rsnd_mod; | ||
| 68 | struct rsnd_dai; | ||
| 69 | struct rsnd_dai_stream; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * R-Car basic functions | ||
| 73 | */ | ||
| 74 | #define rsnd_mod_read(m, r) \ | ||
| 75 | rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r) | ||
| 76 | #define rsnd_mod_write(m, r, d) \ | ||
| 77 | rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) | ||
| 78 | #define rsnd_mod_bset(m, r, s, d) \ | ||
| 79 | rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) | ||
| 80 | |||
| 81 | #define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r) | ||
| 82 | #define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d) | ||
| 83 | #define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d) | ||
| 84 | |||
| 85 | u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); | ||
| 86 | void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, | ||
| 87 | enum rsnd_reg reg, u32 data); | ||
| 88 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, | ||
| 89 | u32 mask, u32 data); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * R-Car DMA | ||
| 93 | */ | ||
| 94 | struct rsnd_dma { | ||
| 95 | struct rsnd_priv *priv; | ||
| 96 | struct sh_dmae_slave slave; | ||
| 97 | struct work_struct work; | ||
| 98 | struct dma_chan *chan; | ||
| 99 | enum dma_data_direction dir; | ||
| 100 | int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); | ||
| 101 | int (*complete)(struct rsnd_dma *dma); | ||
| 102 | |||
| 103 | int submit_loop; | ||
| 104 | }; | ||
| 105 | |||
| 106 | void rsnd_dma_start(struct rsnd_dma *dma); | ||
| 107 | void rsnd_dma_stop(struct rsnd_dma *dma); | ||
| 108 | int rsnd_dma_available(struct rsnd_dma *dma); | ||
| 109 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | ||
| 110 | int is_play, int id, | ||
| 111 | int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), | ||
| 112 | int (*complete)(struct rsnd_dma *dma)); | ||
| 113 | void rsnd_dma_quit(struct rsnd_priv *priv, | ||
| 114 | struct rsnd_dma *dma); | ||
| 115 | |||
| 116 | |||
| 117 | /* | ||
| 118 | * R-Car sound mod | ||
| 119 | */ | ||
| 120 | |||
| 121 | struct rsnd_mod_ops { | ||
| 122 | char *name; | ||
| 123 | int (*init)(struct rsnd_mod *mod, | ||
| 124 | struct rsnd_dai *rdai, | ||
| 125 | struct rsnd_dai_stream *io); | ||
| 126 | int (*quit)(struct rsnd_mod *mod, | ||
| 127 | struct rsnd_dai *rdai, | ||
| 128 | struct rsnd_dai_stream *io); | ||
| 129 | int (*start)(struct rsnd_mod *mod, | ||
| 130 | struct rsnd_dai *rdai, | ||
| 131 | struct rsnd_dai_stream *io); | ||
| 132 | int (*stop)(struct rsnd_mod *mod, | ||
| 133 | struct rsnd_dai *rdai, | ||
| 134 | struct rsnd_dai_stream *io); | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct rsnd_mod { | ||
| 138 | int id; | ||
| 139 | struct rsnd_priv *priv; | ||
| 140 | struct rsnd_mod_ops *ops; | ||
| 141 | struct list_head list; /* connect to rsnd_dai playback/capture */ | ||
| 142 | struct rsnd_dma dma; | ||
| 143 | }; | ||
| 144 | |||
| 145 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | ||
| 146 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | ||
| 147 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) | ||
| 148 | #define rsnd_mod_id(mod) ((mod)->id) | ||
| 149 | #define for_each_rsnd_mod(pos, n, io) \ | ||
| 150 | list_for_each_entry_safe(pos, n, &(io)->head, list) | ||
| 151 | #define rsnd_mod_call(mod, func, rdai, io) \ | ||
| 152 | (!(mod) ? -ENODEV : \ | ||
| 153 | !((mod)->ops->func) ? 0 : \ | ||
| 154 | (mod)->ops->func(mod, rdai, io)) | ||
| 155 | |||
| 156 | void rsnd_mod_init(struct rsnd_priv *priv, | ||
| 157 | struct rsnd_mod *mod, | ||
| 158 | struct rsnd_mod_ops *ops, | ||
| 159 | int id); | ||
| 160 | char *rsnd_mod_name(struct rsnd_mod *mod); | ||
| 161 | |||
| 162 | /* | ||
| 163 | * R-Car sound DAI | ||
| 164 | */ | ||
| 165 | #define RSND_DAI_NAME_SIZE 16 | ||
| 166 | struct rsnd_dai_stream { | ||
| 167 | struct list_head head; /* head of rsnd_mod list */ | ||
| 168 | struct snd_pcm_substream *substream; | ||
| 169 | int byte_pos; | ||
| 170 | int period_pos; | ||
| 171 | int byte_per_period; | ||
| 172 | int next_period_byte; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct rsnd_dai { | ||
| 176 | char name[RSND_DAI_NAME_SIZE]; | ||
| 177 | struct rsnd_dai_platform_info *info; /* rcar_snd.h */ | ||
| 178 | struct rsnd_dai_stream playback; | ||
| 179 | struct rsnd_dai_stream capture; | ||
| 180 | |||
| 181 | int clk_master:1; | ||
| 182 | int bit_clk_inv:1; | ||
| 183 | int frm_clk_inv:1; | ||
| 184 | int sys_delay:1; | ||
| 185 | int data_alignment:1; | ||
| 186 | }; | ||
| 187 | |||
| 188 | #define rsnd_dai_nr(priv) ((priv)->dai_nr) | ||
| 189 | #define for_each_rsnd_dai(rdai, priv, i) \ | ||
| 190 | for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ | ||
| 191 | i < rsnd_dai_nr(priv); \ | ||
| 192 | i++, (rdai) = rsnd_dai_get(priv, i)) | ||
| 193 | |||
| 194 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); | ||
| 195 | int rsnd_dai_disconnect(struct rsnd_mod *mod); | ||
| 196 | int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, | ||
| 197 | struct rsnd_dai_stream *io); | ||
| 198 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); | ||
| 199 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); | ||
| 200 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) | ||
| 201 | #define rsnd_io_to_runtime(io) ((io)->substream->runtime) | ||
| 202 | |||
| 203 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | ||
| 204 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | ||
| 205 | |||
| 206 | /* | ||
| 207 | * R-Car Gen1/Gen2 | ||
| 208 | */ | ||
| 209 | int rsnd_gen_probe(struct platform_device *pdev, | ||
| 210 | struct rcar_snd_info *info, | ||
| 211 | struct rsnd_priv *priv); | ||
| 212 | void rsnd_gen_remove(struct platform_device *pdev, | ||
| 213 | struct rsnd_priv *priv); | ||
| 214 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
| 215 | struct rsnd_dai *rdai, | ||
| 216 | struct rsnd_dai_stream *io); | ||
| 217 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | ||
| 218 | struct rsnd_dai *rdai, | ||
| 219 | struct rsnd_dai_stream *io); | ||
| 220 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | ||
| 221 | struct rsnd_mod *mod, | ||
| 222 | enum rsnd_reg reg); | ||
| 223 | #define rsnd_is_gen1(s) ((s)->info->flags & RSND_GEN1) | ||
| 224 | #define rsnd_is_gen2(s) ((s)->info->flags & RSND_GEN2) | ||
| 225 | |||
| 226 | /* | ||
| 227 | * R-Car ADG | ||
| 228 | */ | ||
| 229 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); | ||
| 230 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); | ||
| 231 | int rsnd_adg_probe(struct platform_device *pdev, | ||
| 232 | struct rcar_snd_info *info, | ||
| 233 | struct rsnd_priv *priv); | ||
| 234 | void rsnd_adg_remove(struct platform_device *pdev, | ||
| 235 | struct rsnd_priv *priv); | ||
| 236 | |||
| 237 | /* | ||
| 238 | * R-Car sound priv | ||
| 239 | */ | ||
| 240 | struct rsnd_priv { | ||
| 241 | |||
| 242 | struct device *dev; | ||
| 243 | struct rcar_snd_info *info; | ||
| 244 | spinlock_t lock; | ||
| 245 | |||
| 246 | /* | ||
| 247 | * below value will be filled on rsnd_gen_probe() | ||
| 248 | */ | ||
| 249 | void *gen; | ||
| 250 | |||
| 251 | /* | ||
| 252 | * below value will be filled on rsnd_scu_probe() | ||
| 253 | */ | ||
| 254 | void *scu; | ||
| 255 | int scu_nr; | ||
| 256 | |||
| 257 | /* | ||
| 258 | * below value will be filled on rsnd_adg_probe() | ||
| 259 | */ | ||
| 260 | void *adg; | ||
| 261 | |||
| 262 | /* | ||
| 263 | * below value will be filled on rsnd_ssi_probe() | ||
| 264 | */ | ||
| 265 | void *ssiu; | ||
| 266 | |||
| 267 | /* | ||
| 268 | * below value will be filled on rsnd_dai_probe() | ||
| 269 | */ | ||
| 270 | struct snd_soc_dai_driver *daidrv; | ||
| 271 | struct rsnd_dai *rdai; | ||
| 272 | int dai_nr; | ||
| 273 | }; | ||
| 274 | |||
| 275 | #define rsnd_priv_to_dev(priv) ((priv)->dev) | ||
| 276 | #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) | ||
| 277 | #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) | ||
| 278 | |||
| 279 | /* | ||
| 280 | * R-Car SCU | ||
| 281 | */ | ||
| 282 | int rsnd_scu_probe(struct platform_device *pdev, | ||
| 283 | struct rcar_snd_info *info, | ||
| 284 | struct rsnd_priv *priv); | ||
| 285 | void rsnd_scu_remove(struct platform_device *pdev, | ||
| 286 | struct rsnd_priv *priv); | ||
| 287 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); | ||
| 288 | #define rsnd_scu_nr(priv) ((priv)->scu_nr) | ||
| 289 | |||
| 290 | /* | ||
| 291 | * R-Car SSI | ||
| 292 | */ | ||
| 293 | int rsnd_ssi_probe(struct platform_device *pdev, | ||
| 294 | struct rcar_snd_info *info, | ||
| 295 | struct rsnd_priv *priv); | ||
| 296 | void rsnd_ssi_remove(struct platform_device *pdev, | ||
| 297 | struct rsnd_priv *priv); | ||
| 298 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | ||
| 299 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, | ||
| 300 | int dai_id, int is_play); | ||
| 301 | |||
| 302 | #endif | ||
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c new file mode 100644 index 000000000000..184d9008cecd --- /dev/null +++ b/sound/soc/sh/rcar/scu.c | |||
| @@ -0,0 +1,236 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car SCU support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 | #include "rsnd.h" | ||
| 12 | |||
| 13 | struct rsnd_scu { | ||
| 14 | struct rsnd_scu_platform_info *info; /* rcar_snd.h */ | ||
| 15 | struct rsnd_mod mod; | ||
| 16 | }; | ||
| 17 | |||
| 18 | #define rsnd_scu_mode_flags(p) ((p)->info->flags) | ||
| 19 | |||
| 20 | /* | ||
| 21 | * ADINR | ||
| 22 | */ | ||
| 23 | #define OTBL_24 (0 << 16) | ||
| 24 | #define OTBL_22 (2 << 16) | ||
| 25 | #define OTBL_20 (4 << 16) | ||
| 26 | #define OTBL_18 (6 << 16) | ||
| 27 | #define OTBL_16 (8 << 16) | ||
| 28 | |||
| 29 | |||
| 30 | #define rsnd_mod_to_scu(_mod) \ | ||
| 31 | container_of((_mod), struct rsnd_scu, mod) | ||
| 32 | |||
| 33 | #define for_each_rsnd_scu(pos, priv, i) \ | ||
| 34 | for ((i) = 0; \ | ||
| 35 | ((i) < rsnd_scu_nr(priv)) && \ | ||
| 36 | ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ | ||
| 37 | i++) | ||
| 38 | |||
| 39 | static int rsnd_scu_set_route(struct rsnd_priv *priv, | ||
| 40 | struct rsnd_mod *mod, | ||
| 41 | struct rsnd_dai *rdai, | ||
| 42 | struct rsnd_dai_stream *io) | ||
| 43 | { | ||
| 44 | struct scu_route_config { | ||
| 45 | u32 mask; | ||
| 46 | int shift; | ||
| 47 | } routes[] = { | ||
| 48 | { 0xF, 0, }, /* 0 */ | ||
| 49 | { 0xF, 4, }, /* 1 */ | ||
| 50 | { 0xF, 8, }, /* 2 */ | ||
| 51 | { 0x7, 12, }, /* 3 */ | ||
| 52 | { 0x7, 16, }, /* 4 */ | ||
| 53 | { 0x7, 20, }, /* 5 */ | ||
| 54 | { 0x7, 24, }, /* 6 */ | ||
| 55 | { 0x3, 28, }, /* 7 */ | ||
| 56 | { 0x3, 30, }, /* 8 */ | ||
| 57 | }; | ||
| 58 | |||
| 59 | u32 mask; | ||
| 60 | u32 val; | ||
| 61 | int shift; | ||
| 62 | int id; | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Gen1 only | ||
| 66 | */ | ||
| 67 | if (!rsnd_is_gen1(priv)) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | id = rsnd_mod_id(mod); | ||
| 71 | if (id < 0 || id > ARRAY_SIZE(routes)) | ||
| 72 | return -EIO; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * SRC_ROUTE_SELECT | ||
| 76 | */ | ||
| 77 | val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; | ||
| 78 | val = val << routes[id].shift; | ||
| 79 | mask = routes[id].mask << routes[id].shift; | ||
| 80 | |||
| 81 | rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); | ||
| 82 | |||
| 83 | /* | ||
| 84 | * SRC_TIMING_SELECT | ||
| 85 | */ | ||
| 86 | shift = (id % 4) * 8; | ||
| 87 | mask = 0x1F << shift; | ||
| 88 | if (8 == id) /* SRU8 is very special */ | ||
| 89 | val = id << shift; | ||
| 90 | else | ||
| 91 | val = (id + 1) << shift; | ||
| 92 | |||
| 93 | switch (id / 4) { | ||
| 94 | case 0: | ||
| 95 | rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); | ||
| 96 | break; | ||
| 97 | case 1: | ||
| 98 | rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); | ||
| 99 | break; | ||
| 100 | case 2: | ||
| 101 | rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int rsnd_scu_set_mode(struct rsnd_priv *priv, | ||
| 109 | struct rsnd_mod *mod, | ||
| 110 | struct rsnd_dai *rdai, | ||
| 111 | struct rsnd_dai_stream *io) | ||
| 112 | { | ||
| 113 | int id = rsnd_mod_id(mod); | ||
| 114 | u32 val; | ||
| 115 | |||
| 116 | if (rsnd_is_gen1(priv)) { | ||
| 117 | val = (1 << id); | ||
| 118 | rsnd_mod_bset(mod, SRC_CTRL, val, val); | ||
| 119 | } | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, | ||
| 125 | struct rsnd_mod *mod, | ||
| 126 | struct rsnd_dai *rdai, | ||
| 127 | struct rsnd_dai_stream *io) | ||
| 128 | { | ||
| 129 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
| 130 | u32 adinr = runtime->channels; | ||
| 131 | |||
| 132 | switch (runtime->sample_bits) { | ||
| 133 | case 16: | ||
| 134 | adinr |= OTBL_16; | ||
| 135 | break; | ||
| 136 | case 32: | ||
| 137 | adinr |= OTBL_24; | ||
| 138 | break; | ||
| 139 | default: | ||
| 140 | return -EIO; | ||
| 141 | } | ||
| 142 | |||
| 143 | rsnd_mod_write(mod, BUSIF_MODE, 1); | ||
| 144 | rsnd_mod_write(mod, BUSIF_ADINR, adinr); | ||
| 145 | |||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int rsnd_scu_start(struct rsnd_mod *mod, | ||
| 150 | struct rsnd_dai *rdai, | ||
| 151 | struct rsnd_dai_stream *io) | ||
| 152 | { | ||
| 153 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 154 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
| 155 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 156 | u32 flags = rsnd_scu_mode_flags(scu); | ||
| 157 | int ret; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * SCU will be used if it has RSND_SCU_USB_HPBIF flags | ||
| 161 | */ | ||
| 162 | if (!(flags & RSND_SCU_USB_HPBIF)) { | ||
| 163 | /* it use PIO transter */ | ||
| 164 | dev_dbg(dev, "%s%d is not used\n", | ||
| 165 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* it use DMA transter */ | ||
| 171 | ret = rsnd_scu_set_route(priv, mod, rdai, io); | ||
| 172 | if (ret < 0) | ||
| 173 | return ret; | ||
| 174 | |||
| 175 | ret = rsnd_scu_set_mode(priv, mod, rdai, io); | ||
| 176 | if (ret < 0) | ||
| 177 | return ret; | ||
| 178 | |||
| 179 | ret = rsnd_scu_set_hpbif(priv, mod, rdai, io); | ||
| 180 | if (ret < 0) | ||
| 181 | return ret; | ||
| 182 | |||
| 183 | dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static struct rsnd_mod_ops rsnd_scu_ops = { | ||
| 189 | .name = "scu", | ||
| 190 | .start = rsnd_scu_start, | ||
| 191 | }; | ||
| 192 | |||
| 193 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) | ||
| 194 | { | ||
| 195 | BUG_ON(id < 0 || id >= rsnd_scu_nr(priv)); | ||
| 196 | |||
| 197 | return &((struct rsnd_scu *)(priv->scu) + id)->mod; | ||
| 198 | } | ||
| 199 | |||
| 200 | int rsnd_scu_probe(struct platform_device *pdev, | ||
| 201 | struct rcar_snd_info *info, | ||
| 202 | struct rsnd_priv *priv) | ||
| 203 | { | ||
| 204 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 205 | struct rsnd_scu *scu; | ||
| 206 | int i, nr; | ||
| 207 | |||
| 208 | /* | ||
| 209 | * init SCU | ||
| 210 | */ | ||
| 211 | nr = info->scu_info_nr; | ||
| 212 | scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); | ||
| 213 | if (!scu) { | ||
| 214 | dev_err(dev, "SCU allocate failed\n"); | ||
| 215 | return -ENOMEM; | ||
| 216 | } | ||
| 217 | |||
| 218 | priv->scu_nr = nr; | ||
| 219 | priv->scu = scu; | ||
| 220 | |||
| 221 | for_each_rsnd_scu(scu, priv, i) { | ||
| 222 | rsnd_mod_init(priv, &scu->mod, | ||
| 223 | &rsnd_scu_ops, i); | ||
| 224 | scu->info = &info->scu_info[i]; | ||
| 225 | |||
| 226 | dev_dbg(dev, "SCU%d probed\n", i); | ||
| 227 | } | ||
| 228 | dev_dbg(dev, "scu probed\n"); | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | void rsnd_scu_remove(struct platform_device *pdev, | ||
| 234 | struct rsnd_priv *priv) | ||
| 235 | { | ||
| 236 | } | ||
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c new file mode 100644 index 000000000000..fae26d3f79d2 --- /dev/null +++ b/sound/soc/sh/rcar/ssi.c | |||
| @@ -0,0 +1,728 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car SSIU/SSI support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
| 6 | * | ||
| 7 | * Based on fsi.c | ||
| 8 | * Kuninori Morimoto <morimoto.kuninori@renesas.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 | #include <linux/delay.h> | ||
| 15 | #include "rsnd.h" | ||
| 16 | #define RSND_SSI_NAME_SIZE 16 | ||
| 17 | |||
| 18 | /* | ||
| 19 | * SSICR | ||
| 20 | */ | ||
| 21 | #define FORCE (1 << 31) /* Fixed */ | ||
| 22 | #define DMEN (1 << 28) /* DMA Enable */ | ||
| 23 | #define UIEN (1 << 27) /* Underflow Interrupt Enable */ | ||
| 24 | #define OIEN (1 << 26) /* Overflow Interrupt Enable */ | ||
| 25 | #define IIEN (1 << 25) /* Idle Mode Interrupt Enable */ | ||
| 26 | #define DIEN (1 << 24) /* Data Interrupt Enable */ | ||
| 27 | |||
| 28 | #define DWL_8 (0 << 19) /* Data Word Length */ | ||
| 29 | #define DWL_16 (1 << 19) /* Data Word Length */ | ||
| 30 | #define DWL_18 (2 << 19) /* Data Word Length */ | ||
| 31 | #define DWL_20 (3 << 19) /* Data Word Length */ | ||
| 32 | #define DWL_22 (4 << 19) /* Data Word Length */ | ||
| 33 | #define DWL_24 (5 << 19) /* Data Word Length */ | ||
| 34 | #define DWL_32 (6 << 19) /* Data Word Length */ | ||
| 35 | |||
| 36 | #define SWL_32 (3 << 16) /* R/W System Word Length */ | ||
| 37 | #define SCKD (1 << 15) /* Serial Bit Clock Direction */ | ||
| 38 | #define SWSD (1 << 14) /* Serial WS Direction */ | ||
| 39 | #define SCKP (1 << 13) /* Serial Bit Clock Polarity */ | ||
| 40 | #define SWSP (1 << 12) /* Serial WS Polarity */ | ||
| 41 | #define SDTA (1 << 10) /* Serial Data Alignment */ | ||
| 42 | #define DEL (1 << 8) /* Serial Data Delay */ | ||
| 43 | #define CKDV(v) (v << 4) /* Serial Clock Division Ratio */ | ||
| 44 | #define TRMD (1 << 1) /* Transmit/Receive Mode Select */ | ||
| 45 | #define EN (1 << 0) /* SSI Module Enable */ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * SSISR | ||
| 49 | */ | ||
| 50 | #define UIRQ (1 << 27) /* Underflow Error Interrupt Status */ | ||
| 51 | #define OIRQ (1 << 26) /* Overflow Error Interrupt Status */ | ||
| 52 | #define IIRQ (1 << 25) /* Idle Mode Interrupt Status */ | ||
| 53 | #define DIRQ (1 << 24) /* Data Interrupt Status Flag */ | ||
| 54 | |||
| 55 | /* | ||
| 56 | * SSIWSR | ||
| 57 | */ | ||
| 58 | #define CONT (1 << 8) /* WS Continue Function */ | ||
| 59 | |||
| 60 | struct rsnd_ssi { | ||
| 61 | struct clk *clk; | ||
| 62 | struct rsnd_ssi_platform_info *info; /* rcar_snd.h */ | ||
| 63 | struct rsnd_ssi *parent; | ||
| 64 | struct rsnd_mod mod; | ||
| 65 | |||
| 66 | struct rsnd_dai *rdai; | ||
| 67 | struct rsnd_dai_stream *io; | ||
| 68 | u32 cr_own; | ||
| 69 | u32 cr_clk; | ||
| 70 | u32 cr_etc; | ||
| 71 | int err; | ||
| 72 | int dma_offset; | ||
| 73 | unsigned int usrcnt; | ||
| 74 | unsigned int rate; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct rsnd_ssiu { | ||
| 78 | u32 ssi_mode0; | ||
| 79 | u32 ssi_mode1; | ||
| 80 | |||
| 81 | int ssi_nr; | ||
| 82 | struct rsnd_ssi *ssi; | ||
| 83 | }; | ||
| 84 | |||
| 85 | #define for_each_rsnd_ssi(pos, priv, i) \ | ||
| 86 | for (i = 0; \ | ||
| 87 | (i < rsnd_ssi_nr(priv)) && \ | ||
| 88 | ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ | ||
| 89 | i++) | ||
| 90 | |||
| 91 | #define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) | ||
| 92 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | ||
| 93 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) | ||
| 94 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) | ||
| 95 | #define rsnd_ssi_dma_available(ssi) \ | ||
| 96 | rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) | ||
| 97 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) | ||
| 98 | #define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) | ||
| 99 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | ||
| 100 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | ||
| 101 | #define rsnd_ssi_to_ssiu(ssi)\ | ||
| 102 | (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) | ||
| 103 | |||
| 104 | static void rsnd_ssi_mode_init(struct rsnd_priv *priv, | ||
| 105 | struct rsnd_ssiu *ssiu) | ||
| 106 | { | ||
| 107 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 108 | struct rsnd_ssi *ssi; | ||
| 109 | u32 flags; | ||
| 110 | u32 val; | ||
| 111 | int i; | ||
| 112 | |||
| 113 | /* | ||
| 114 | * SSI_MODE0 | ||
| 115 | */ | ||
| 116 | ssiu->ssi_mode0 = 0; | ||
| 117 | for_each_rsnd_ssi(ssi, priv, i) { | ||
| 118 | flags = rsnd_ssi_mode_flags(ssi); | ||
| 119 | |||
| 120 | /* see also BUSIF_MODE */ | ||
| 121 | if (!(flags & RSND_SSI_DEPENDENT)) { | ||
| 122 | ssiu->ssi_mode0 |= (1 << i); | ||
| 123 | dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i); | ||
| 124 | } else { | ||
| 125 | dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * SSI_MODE1 | ||
| 131 | */ | ||
| 132 | #define ssi_parent_set(p, sync, adg, ext) \ | ||
| 133 | do { \ | ||
| 134 | ssi->parent = ssiu->ssi + p; \ | ||
| 135 | if (flags & RSND_SSI_CLK_FROM_ADG) \ | ||
| 136 | val = adg; \ | ||
| 137 | else \ | ||
| 138 | val = ext; \ | ||
| 139 | if (flags & RSND_SSI_SYNC) \ | ||
| 140 | val |= sync; \ | ||
| 141 | } while (0) | ||
| 142 | |||
| 143 | ssiu->ssi_mode1 = 0; | ||
| 144 | for_each_rsnd_ssi(ssi, priv, i) { | ||
| 145 | flags = rsnd_ssi_mode_flags(ssi); | ||
| 146 | |||
| 147 | if (!(flags & RSND_SSI_CLK_PIN_SHARE)) | ||
| 148 | continue; | ||
| 149 | |||
| 150 | val = 0; | ||
| 151 | switch (i) { | ||
| 152 | case 1: | ||
| 153 | ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); | ||
| 154 | break; | ||
| 155 | case 2: | ||
| 156 | ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); | ||
| 157 | break; | ||
| 158 | case 4: | ||
| 159 | ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); | ||
| 160 | break; | ||
| 161 | case 8: | ||
| 162 | ssi_parent_set(7, 0, 0, 0); | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | |||
| 166 | ssiu->ssi_mode1 |= val; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | static void rsnd_ssi_mode_set(struct rsnd_ssi *ssi) | ||
| 171 | { | ||
| 172 | struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); | ||
| 173 | |||
| 174 | rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); | ||
| 175 | rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, | ||
| 179 | u32 bit) | ||
| 180 | { | ||
| 181 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 182 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 183 | u32 status; | ||
| 184 | int i; | ||
| 185 | |||
| 186 | for (i = 0; i < 1024; i++) { | ||
| 187 | status = rsnd_mod_read(mod, SSISR); | ||
| 188 | if (status & bit) | ||
| 189 | return; | ||
| 190 | |||
| 191 | udelay(50); | ||
| 192 | } | ||
| 193 | |||
| 194 | dev_warn(dev, "status check failed\n"); | ||
| 195 | } | ||
| 196 | |||
| 197 | static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | ||
| 198 | unsigned int rate) | ||
| 199 | { | ||
| 200 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | ||
| 201 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 202 | int i, j, ret; | ||
| 203 | int adg_clk_div_table[] = { | ||
| 204 | 1, 6, /* see adg.c */ | ||
| 205 | }; | ||
| 206 | int ssi_clk_mul_table[] = { | ||
| 207 | 1, 2, 4, 8, 16, 6, 12, | ||
| 208 | }; | ||
| 209 | unsigned int main_rate; | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Find best clock, and try to start ADG | ||
| 213 | */ | ||
| 214 | for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) { | ||
| 215 | for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { | ||
| 216 | |||
| 217 | /* | ||
| 218 | * this driver is assuming that | ||
| 219 | * system word is 64fs (= 2 x 32bit) | ||
| 220 | * see rsnd_ssi_start() | ||
| 221 | */ | ||
| 222 | main_rate = rate / adg_clk_div_table[i] | ||
| 223 | * 32 * 2 * ssi_clk_mul_table[j]; | ||
| 224 | |||
| 225 | ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate); | ||
| 226 | if (0 == ret) { | ||
| 227 | ssi->rate = rate; | ||
| 228 | ssi->cr_clk = FORCE | SWL_32 | | ||
| 229 | SCKD | SWSD | CKDV(j); | ||
| 230 | |||
| 231 | dev_dbg(dev, "ssi%d outputs %u Hz\n", | ||
| 232 | rsnd_mod_id(&ssi->mod), rate); | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | dev_err(dev, "unsupported clock rate\n"); | ||
| 240 | return -EIO; | ||
| 241 | } | ||
| 242 | |||
| 243 | static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi) | ||
| 244 | { | ||
| 245 | ssi->rate = 0; | ||
| 246 | ssi->cr_clk = 0; | ||
| 247 | rsnd_adg_ssi_clk_stop(&ssi->mod); | ||
| 248 | } | ||
| 249 | |||
| 250 | static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | ||
| 251 | struct rsnd_dai *rdai, | ||
| 252 | struct rsnd_dai_stream *io) | ||
| 253 | { | ||
| 254 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | ||
| 255 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 256 | u32 cr; | ||
| 257 | |||
| 258 | if (0 == ssi->usrcnt) { | ||
| 259 | clk_enable(ssi->clk); | ||
| 260 | |||
| 261 | if (rsnd_rdai_is_clk_master(rdai)) { | ||
| 262 | struct snd_pcm_runtime *runtime; | ||
| 263 | |||
| 264 | runtime = rsnd_io_to_runtime(io); | ||
| 265 | |||
| 266 | if (rsnd_ssi_clk_from_parent(ssi)) | ||
| 267 | rsnd_ssi_hw_start(ssi->parent, rdai, io); | ||
| 268 | else | ||
| 269 | rsnd_ssi_master_clk_start(ssi, runtime->rate); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | cr = ssi->cr_own | | ||
| 274 | ssi->cr_clk | | ||
| 275 | ssi->cr_etc | | ||
| 276 | EN; | ||
| 277 | |||
| 278 | rsnd_mod_write(&ssi->mod, SSICR, cr); | ||
| 279 | |||
| 280 | ssi->usrcnt++; | ||
| 281 | |||
| 282 | dev_dbg(dev, "ssi%d hw started\n", rsnd_mod_id(&ssi->mod)); | ||
| 283 | } | ||
| 284 | |||
| 285 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | ||
| 286 | struct rsnd_dai *rdai) | ||
| 287 | { | ||
| 288 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | ||
| 289 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 290 | u32 cr; | ||
| 291 | |||
| 292 | if (0 == ssi->usrcnt) /* stop might be called without start */ | ||
| 293 | return; | ||
| 294 | |||
| 295 | ssi->usrcnt--; | ||
| 296 | |||
| 297 | if (0 == ssi->usrcnt) { | ||
| 298 | /* | ||
| 299 | * disable all IRQ, | ||
| 300 | * and, wait all data was sent | ||
| 301 | */ | ||
| 302 | cr = ssi->cr_own | | ||
| 303 | ssi->cr_clk; | ||
| 304 | |||
| 305 | rsnd_mod_write(&ssi->mod, SSICR, cr | EN); | ||
| 306 | rsnd_ssi_status_check(&ssi->mod, DIRQ); | ||
| 307 | |||
| 308 | /* | ||
| 309 | * disable SSI, | ||
| 310 | * and, wait idle state | ||
| 311 | */ | ||
| 312 | rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ | ||
| 313 | rsnd_ssi_status_check(&ssi->mod, IIRQ); | ||
| 314 | |||
| 315 | if (rsnd_rdai_is_clk_master(rdai)) { | ||
| 316 | if (rsnd_ssi_clk_from_parent(ssi)) | ||
| 317 | rsnd_ssi_hw_stop(ssi->parent, rdai); | ||
| 318 | else | ||
| 319 | rsnd_ssi_master_clk_stop(ssi); | ||
| 320 | } | ||
| 321 | |||
| 322 | clk_disable(ssi->clk); | ||
| 323 | } | ||
| 324 | |||
| 325 | dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod)); | ||
| 326 | } | ||
| 327 | |||
| 328 | /* | ||
| 329 | * SSI mod common functions | ||
| 330 | */ | ||
| 331 | static int rsnd_ssi_init(struct rsnd_mod *mod, | ||
| 332 | struct rsnd_dai *rdai, | ||
| 333 | struct rsnd_dai_stream *io) | ||
| 334 | { | ||
| 335 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 336 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 337 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 338 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
| 339 | u32 cr; | ||
| 340 | |||
| 341 | cr = FORCE; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * always use 32bit system word for easy clock calculation. | ||
| 345 | * see also rsnd_ssi_master_clk_enable() | ||
| 346 | */ | ||
| 347 | cr |= SWL_32; | ||
| 348 | |||
| 349 | /* | ||
| 350 | * init clock settings for SSICR | ||
| 351 | */ | ||
| 352 | switch (runtime->sample_bits) { | ||
| 353 | case 16: | ||
| 354 | cr |= DWL_16; | ||
| 355 | break; | ||
| 356 | case 32: | ||
| 357 | cr |= DWL_24; | ||
| 358 | break; | ||
| 359 | default: | ||
| 360 | return -EIO; | ||
| 361 | } | ||
| 362 | |||
| 363 | if (rdai->bit_clk_inv) | ||
| 364 | cr |= SCKP; | ||
| 365 | if (rdai->frm_clk_inv) | ||
| 366 | cr |= SWSP; | ||
| 367 | if (rdai->data_alignment) | ||
| 368 | cr |= SDTA; | ||
| 369 | if (rdai->sys_delay) | ||
| 370 | cr |= DEL; | ||
| 371 | if (rsnd_dai_is_play(rdai, io)) | ||
| 372 | cr |= TRMD; | ||
| 373 | |||
| 374 | /* | ||
| 375 | * set ssi parameter | ||
| 376 | */ | ||
| 377 | ssi->rdai = rdai; | ||
| 378 | ssi->io = io; | ||
| 379 | ssi->cr_own = cr; | ||
| 380 | ssi->err = -1; /* ignore 1st error */ | ||
| 381 | |||
| 382 | rsnd_ssi_mode_set(ssi); | ||
| 383 | |||
| 384 | dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 385 | |||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int rsnd_ssi_quit(struct rsnd_mod *mod, | ||
| 390 | struct rsnd_dai *rdai, | ||
| 391 | struct rsnd_dai_stream *io) | ||
| 392 | { | ||
| 393 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 394 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 395 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 396 | |||
| 397 | dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 398 | |||
| 399 | if (ssi->err > 0) | ||
| 400 | dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); | ||
| 401 | |||
| 402 | ssi->rdai = NULL; | ||
| 403 | ssi->io = NULL; | ||
| 404 | ssi->cr_own = 0; | ||
| 405 | ssi->err = 0; | ||
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | ||
| 411 | { | ||
| 412 | /* under/over flow error */ | ||
| 413 | if (status & (UIRQ | OIRQ)) { | ||
| 414 | ssi->err++; | ||
| 415 | |||
| 416 | /* clear error status */ | ||
| 417 | rsnd_mod_write(&ssi->mod, SSISR, 0); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | /* | ||
| 422 | * SSI PIO | ||
| 423 | */ | ||
| 424 | static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | ||
| 425 | { | ||
| 426 | struct rsnd_ssi *ssi = data; | ||
| 427 | struct rsnd_dai_stream *io = ssi->io; | ||
| 428 | u32 status = rsnd_mod_read(&ssi->mod, SSISR); | ||
| 429 | irqreturn_t ret = IRQ_NONE; | ||
| 430 | |||
| 431 | if (io && (status & DIRQ)) { | ||
| 432 | struct rsnd_dai *rdai = ssi->rdai; | ||
| 433 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
| 434 | u32 *buf = (u32 *)(runtime->dma_area + | ||
| 435 | rsnd_dai_pointer_offset(io, 0)); | ||
| 436 | |||
| 437 | rsnd_ssi_record_error(ssi, status); | ||
| 438 | |||
| 439 | /* | ||
| 440 | * 8/16/32 data can be assesse to TDR/RDR register | ||
| 441 | * directly as 32bit data | ||
| 442 | * see rsnd_ssi_init() | ||
| 443 | */ | ||
| 444 | if (rsnd_dai_is_play(rdai, io)) | ||
| 445 | rsnd_mod_write(&ssi->mod, SSITDR, *buf); | ||
| 446 | else | ||
| 447 | *buf = rsnd_mod_read(&ssi->mod, SSIRDR); | ||
| 448 | |||
| 449 | rsnd_dai_pointer_update(io, sizeof(*buf)); | ||
| 450 | |||
| 451 | ret = IRQ_HANDLED; | ||
| 452 | } | ||
| 453 | |||
| 454 | return ret; | ||
| 455 | } | ||
| 456 | |||
| 457 | static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | ||
| 458 | struct rsnd_dai *rdai, | ||
| 459 | struct rsnd_dai_stream *io) | ||
| 460 | { | ||
| 461 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 462 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 463 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 464 | |||
| 465 | /* enable PIO IRQ */ | ||
| 466 | ssi->cr_etc = UIEN | OIEN | DIEN; | ||
| 467 | |||
| 468 | rsnd_ssi_hw_start(ssi, rdai, io); | ||
| 469 | |||
| 470 | dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | ||
| 476 | struct rsnd_dai *rdai, | ||
| 477 | struct rsnd_dai_stream *io) | ||
| 478 | { | ||
| 479 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 480 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 481 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 482 | |||
| 483 | dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
| 484 | |||
| 485 | ssi->cr_etc = 0; | ||
| 486 | |||
| 487 | rsnd_ssi_hw_stop(ssi, rdai); | ||
| 488 | |||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | ||
| 493 | .name = "ssi (pio)", | ||
| 494 | .init = rsnd_ssi_init, | ||
| 495 | .quit = rsnd_ssi_quit, | ||
| 496 | .start = rsnd_ssi_pio_start, | ||
| 497 | .stop = rsnd_ssi_pio_stop, | ||
| 498 | }; | ||
| 499 | |||
| 500 | static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) | ||
| 501 | { | ||
| 502 | struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); | ||
| 503 | struct rsnd_dai_stream *io = ssi->io; | ||
| 504 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
| 505 | |||
| 506 | *len = io->byte_per_period; | ||
| 507 | *buf = runtime->dma_addr + | ||
| 508 | rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); | ||
| 509 | ssi->dma_offset = *len; /* it cares A/B plane */ | ||
| 510 | |||
| 511 | return 0; | ||
| 512 | } | ||
| 513 | |||
| 514 | static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) | ||
| 515 | { | ||
| 516 | struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); | ||
| 517 | struct rsnd_dai_stream *io = ssi->io; | ||
| 518 | u32 status = rsnd_mod_read(&ssi->mod, SSISR); | ||
| 519 | |||
| 520 | rsnd_ssi_record_error(ssi, status); | ||
| 521 | |||
| 522 | rsnd_dai_pointer_update(ssi->io, io->byte_per_period); | ||
| 523 | |||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | ||
| 528 | struct rsnd_dai *rdai, | ||
| 529 | struct rsnd_dai_stream *io) | ||
| 530 | { | ||
| 531 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 532 | struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); | ||
| 533 | |||
| 534 | /* enable DMA transfer */ | ||
| 535 | ssi->cr_etc = DMEN; | ||
| 536 | ssi->dma_offset = 0; | ||
| 537 | |||
| 538 | rsnd_dma_start(dma); | ||
| 539 | |||
| 540 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | ||
| 541 | |||
| 542 | /* enable WS continue */ | ||
| 543 | if (rsnd_rdai_is_clk_master(rdai)) | ||
| 544 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); | ||
| 545 | |||
| 546 | return 0; | ||
| 547 | } | ||
| 548 | |||
| 549 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | ||
| 550 | struct rsnd_dai *rdai, | ||
| 551 | struct rsnd_dai_stream *io) | ||
| 552 | { | ||
| 553 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
| 554 | struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); | ||
| 555 | |||
| 556 | ssi->cr_etc = 0; | ||
| 557 | |||
| 558 | rsnd_ssi_hw_stop(ssi, rdai); | ||
| 559 | |||
| 560 | rsnd_dma_stop(dma); | ||
| 561 | |||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | ||
| 566 | .name = "ssi (dma)", | ||
| 567 | .init = rsnd_ssi_init, | ||
| 568 | .quit = rsnd_ssi_quit, | ||
| 569 | .start = rsnd_ssi_dma_start, | ||
| 570 | .stop = rsnd_ssi_dma_stop, | ||
| 571 | }; | ||
| 572 | |||
| 573 | /* | ||
| 574 | * Non SSI | ||
| 575 | */ | ||
| 576 | static int rsnd_ssi_non(struct rsnd_mod *mod, | ||
| 577 | struct rsnd_dai *rdai, | ||
| 578 | struct rsnd_dai_stream *io) | ||
| 579 | { | ||
| 580 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
| 581 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 582 | |||
| 583 | dev_dbg(dev, "%s\n", __func__); | ||
| 584 | |||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | static struct rsnd_mod_ops rsnd_ssi_non_ops = { | ||
| 589 | .name = "ssi (non)", | ||
| 590 | .init = rsnd_ssi_non, | ||
| 591 | .quit = rsnd_ssi_non, | ||
| 592 | .start = rsnd_ssi_non, | ||
| 593 | .stop = rsnd_ssi_non, | ||
| 594 | }; | ||
| 595 | |||
| 596 | /* | ||
| 597 | * ssi mod function | ||
| 598 | */ | ||
| 599 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, | ||
| 600 | int dai_id, int is_play) | ||
| 601 | { | ||
| 602 | struct rsnd_ssi *ssi; | ||
| 603 | int i, has_play; | ||
| 604 | |||
| 605 | is_play = !!is_play; | ||
| 606 | |||
| 607 | for_each_rsnd_ssi(ssi, priv, i) { | ||
| 608 | if (rsnd_ssi_dai_id(ssi) != dai_id) | ||
| 609 | continue; | ||
| 610 | |||
| 611 | has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); | ||
| 612 | |||
| 613 | if (is_play == has_play) | ||
| 614 | return &ssi->mod; | ||
| 615 | } | ||
| 616 | |||
| 617 | return NULL; | ||
| 618 | } | ||
| 619 | |||
| 620 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) | ||
| 621 | { | ||
| 622 | BUG_ON(id < 0 || id >= rsnd_ssi_nr(priv)); | ||
| 623 | |||
| 624 | return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; | ||
| 625 | } | ||
| 626 | |||
| 627 | int rsnd_ssi_probe(struct platform_device *pdev, | ||
| 628 | struct rcar_snd_info *info, | ||
| 629 | struct rsnd_priv *priv) | ||
| 630 | { | ||
| 631 | struct rsnd_ssi_platform_info *pinfo; | ||
| 632 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 633 | struct rsnd_mod_ops *ops; | ||
| 634 | struct clk *clk; | ||
| 635 | struct rsnd_ssiu *ssiu; | ||
| 636 | struct rsnd_ssi *ssi; | ||
| 637 | char name[RSND_SSI_NAME_SIZE]; | ||
| 638 | int i, nr, ret; | ||
| 639 | |||
| 640 | /* | ||
| 641 | * init SSI | ||
| 642 | */ | ||
| 643 | nr = info->ssi_info_nr; | ||
| 644 | ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), | ||
| 645 | GFP_KERNEL); | ||
| 646 | if (!ssiu) { | ||
| 647 | dev_err(dev, "SSI allocate failed\n"); | ||
| 648 | return -ENOMEM; | ||
| 649 | } | ||
| 650 | |||
| 651 | priv->ssiu = ssiu; | ||
| 652 | ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); | ||
| 653 | ssiu->ssi_nr = nr; | ||
| 654 | |||
| 655 | for_each_rsnd_ssi(ssi, priv, i) { | ||
| 656 | pinfo = &info->ssi_info[i]; | ||
| 657 | |||
| 658 | snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i); | ||
| 659 | |||
| 660 | clk = clk_get(dev, name); | ||
| 661 | if (IS_ERR(clk)) | ||
| 662 | return PTR_ERR(clk); | ||
| 663 | |||
| 664 | ssi->info = pinfo; | ||
| 665 | ssi->clk = clk; | ||
| 666 | |||
| 667 | ops = &rsnd_ssi_non_ops; | ||
| 668 | |||
| 669 | /* | ||
| 670 | * SSI DMA case | ||
| 671 | */ | ||
| 672 | if (pinfo->dma_id > 0) { | ||
| 673 | ret = rsnd_dma_init( | ||
| 674 | priv, rsnd_mod_to_dma(&ssi->mod), | ||
| 675 | (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), | ||
| 676 | pinfo->dma_id, | ||
| 677 | rsnd_ssi_dma_inquiry, | ||
| 678 | rsnd_ssi_dma_complete); | ||
| 679 | if (ret < 0) | ||
| 680 | dev_info(dev, "SSI DMA failed. try PIO transter\n"); | ||
| 681 | else | ||
| 682 | ops = &rsnd_ssi_dma_ops; | ||
| 683 | |||
| 684 | dev_dbg(dev, "SSI%d use DMA transfer\n", i); | ||
| 685 | } | ||
| 686 | |||
| 687 | /* | ||
| 688 | * SSI PIO case | ||
| 689 | */ | ||
| 690 | if (!rsnd_ssi_dma_available(ssi) && | ||
| 691 | rsnd_ssi_pio_available(ssi)) { | ||
| 692 | ret = devm_request_irq(dev, pinfo->pio_irq, | ||
| 693 | &rsnd_ssi_pio_interrupt, | ||
| 694 | IRQF_SHARED, | ||
| 695 | dev_name(dev), ssi); | ||
| 696 | if (ret) { | ||
| 697 | dev_err(dev, "SSI request interrupt failed\n"); | ||
| 698 | return ret; | ||
| 699 | } | ||
| 700 | |||
| 701 | ops = &rsnd_ssi_pio_ops; | ||
| 702 | |||
| 703 | dev_dbg(dev, "SSI%d use PIO transfer\n", i); | ||
| 704 | } | ||
| 705 | |||
| 706 | rsnd_mod_init(priv, &ssi->mod, ops, i); | ||
| 707 | } | ||
| 708 | |||
| 709 | rsnd_ssi_mode_init(priv, ssiu); | ||
| 710 | |||
| 711 | dev_dbg(dev, "ssi probed\n"); | ||
| 712 | |||
| 713 | return 0; | ||
| 714 | } | ||
| 715 | |||
| 716 | void rsnd_ssi_remove(struct platform_device *pdev, | ||
| 717 | struct rsnd_priv *priv) | ||
| 718 | { | ||
| 719 | struct rsnd_ssi *ssi; | ||
| 720 | int i; | ||
| 721 | |||
| 722 | for_each_rsnd_ssi(ssi, priv, i) { | ||
| 723 | clk_put(ssi->clk); | ||
| 724 | if (rsnd_ssi_dma_available(ssi)) | ||
| 725 | rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); | ||
| 726 | } | ||
| 727 | |||
| 728 | } | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 06a8000aa07b..53c9ecdd119f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
| @@ -149,8 +149,9 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
| 149 | SND_SOC_DAPM_STREAM_STOP); | 149 | SND_SOC_DAPM_STREAM_STOP); |
| 150 | } else { | 150 | } else { |
| 151 | rtd->pop_wait = 1; | 151 | rtd->pop_wait = 1; |
| 152 | schedule_delayed_work(&rtd->delayed_work, | 152 | queue_delayed_work(system_power_efficient_wq, |
| 153 | msecs_to_jiffies(rtd->pmdown_time)); | 153 | &rtd->delayed_work, |
| 154 | msecs_to_jiffies(rtd->pmdown_time)); | ||
| 154 | } | 155 | } |
| 155 | } else { | 156 | } else { |
| 156 | /* capture streams can be powered down now */ | 157 | /* capture streams can be powered down now */ |
| @@ -334,7 +335,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, | |||
| 334 | return ret; | 335 | return ret; |
| 335 | } | 336 | } |
| 336 | 337 | ||
| 337 | static int sst_compr_set_metadata(struct snd_compr_stream *cstream, | 338 | static int soc_compr_set_metadata(struct snd_compr_stream *cstream, |
| 338 | struct snd_compr_metadata *metadata) | 339 | struct snd_compr_metadata *metadata) |
| 339 | { | 340 | { |
| 340 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | 341 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; |
| @@ -347,7 +348,7 @@ static int sst_compr_set_metadata(struct snd_compr_stream *cstream, | |||
| 347 | return ret; | 348 | return ret; |
| 348 | } | 349 | } |
| 349 | 350 | ||
| 350 | static int sst_compr_get_metadata(struct snd_compr_stream *cstream, | 351 | static int soc_compr_get_metadata(struct snd_compr_stream *cstream, |
| 351 | struct snd_compr_metadata *metadata) | 352 | struct snd_compr_metadata *metadata) |
| 352 | { | 353 | { |
| 353 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | 354 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; |
| @@ -364,8 +365,8 @@ static struct snd_compr_ops soc_compr_ops = { | |||
| 364 | .open = soc_compr_open, | 365 | .open = soc_compr_open, |
| 365 | .free = soc_compr_free, | 366 | .free = soc_compr_free, |
| 366 | .set_params = soc_compr_set_params, | 367 | .set_params = soc_compr_set_params, |
| 367 | .set_metadata = sst_compr_set_metadata, | 368 | .set_metadata = soc_compr_set_metadata, |
| 368 | .get_metadata = sst_compr_get_metadata, | 369 | .get_metadata = soc_compr_get_metadata, |
| 369 | .get_params = soc_compr_get_params, | 370 | .get_params = soc_compr_get_params, |
| 370 | .trigger = soc_compr_trigger, | 371 | .trigger = soc_compr_trigger, |
| 371 | .pointer = soc_compr_pointer, | 372 | .pointer = soc_compr_pointer, |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d82ee386eab5..528f8708221d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -30,9 +30,12 @@ | |||
| 30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
| 31 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
| 32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 33 | #include <linux/pinctrl/consumer.h> | ||
| 33 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
| 34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 35 | #include <linux/of.h> | 36 | #include <linux/of.h> |
| 37 | #include <linux/gpio.h> | ||
| 38 | #include <linux/of_gpio.h> | ||
| 36 | #include <sound/ac97_codec.h> | 39 | #include <sound/ac97_codec.h> |
| 37 | #include <sound/core.h> | 40 | #include <sound/core.h> |
| 38 | #include <sound/jack.h> | 41 | #include <sound/jack.h> |
| @@ -47,8 +50,6 @@ | |||
| 47 | 50 | ||
| 48 | #define NAME_SIZE 32 | 51 | #define NAME_SIZE 32 |
| 49 | 52 | ||
| 50 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | ||
| 51 | |||
| 52 | #ifdef CONFIG_DEBUG_FS | 53 | #ifdef CONFIG_DEBUG_FS |
| 53 | struct dentry *snd_soc_debugfs_root; | 54 | struct dentry *snd_soc_debugfs_root; |
| 54 | EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); | 55 | EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); |
| @@ -69,6 +70,16 @@ static int pmdown_time = 5000; | |||
| 69 | module_param(pmdown_time, int, 0); | 70 | module_param(pmdown_time, int, 0); |
| 70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 71 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
| 71 | 72 | ||
| 73 | struct snd_ac97_reset_cfg { | ||
| 74 | struct pinctrl *pctl; | ||
| 75 | struct pinctrl_state *pstate_reset; | ||
| 76 | struct pinctrl_state *pstate_warm_reset; | ||
| 77 | struct pinctrl_state *pstate_run; | ||
| 78 | int gpio_sdata; | ||
| 79 | int gpio_sync; | ||
| 80 | int gpio_reset; | ||
| 81 | }; | ||
| 82 | |||
| 72 | /* returns the minimum number of bytes needed to represent | 83 | /* returns the minimum number of bytes needed to represent |
| 73 | * a particular given value */ | 84 | * a particular given value */ |
| 74 | static int min_bytes_needed(unsigned long val) | 85 | static int min_bytes_needed(unsigned long val) |
| @@ -530,6 +541,15 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
| 530 | } | 541 | } |
| 531 | #endif | 542 | #endif |
| 532 | 543 | ||
| 544 | static void codec2codec_close_delayed_work(struct work_struct *work) | ||
| 545 | { | ||
| 546 | /* Currently nothing to do for c2c links | ||
| 547 | * Since c2c links are internal nodes in the DAPM graph and | ||
| 548 | * don't interface with the outside world or application layer | ||
| 549 | * we don't have to do any special handling on close. | ||
| 550 | */ | ||
| 551 | } | ||
| 552 | |||
| 533 | #ifdef CONFIG_PM_SLEEP | 553 | #ifdef CONFIG_PM_SLEEP |
| 534 | /* powers down audio subsystem for suspend */ | 554 | /* powers down audio subsystem for suspend */ |
| 535 | int snd_soc_suspend(struct device *dev) | 555 | int snd_soc_suspend(struct device *dev) |
| @@ -1428,6 +1448,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
| 1428 | return ret; | 1448 | return ret; |
| 1429 | } | 1449 | } |
| 1430 | } else { | 1450 | } else { |
| 1451 | INIT_DELAYED_WORK(&rtd->delayed_work, | ||
| 1452 | codec2codec_close_delayed_work); | ||
| 1453 | |||
| 1431 | /* link the DAI widgets */ | 1454 | /* link the DAI widgets */ |
| 1432 | play_w = codec_dai->playback_widget; | 1455 | play_w = codec_dai->playback_widget; |
| 1433 | capture_w = cpu_dai->capture_widget; | 1456 | capture_w = cpu_dai->capture_widget; |
| @@ -2080,6 +2103,117 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
| 2080 | } | 2103 | } |
| 2081 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 2104 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
| 2082 | 2105 | ||
| 2106 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
| 2107 | |||
| 2108 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
| 2109 | { | ||
| 2110 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
| 2111 | |||
| 2112 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
| 2113 | |||
| 2114 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
| 2115 | |||
| 2116 | udelay(10); | ||
| 2117 | |||
| 2118 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
| 2119 | |||
| 2120 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
| 2121 | msleep(2); | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
| 2125 | { | ||
| 2126 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
| 2127 | |||
| 2128 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
| 2129 | |||
| 2130 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
| 2131 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
| 2132 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
| 2133 | |||
| 2134 | udelay(10); | ||
| 2135 | |||
| 2136 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
| 2137 | |||
| 2138 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
| 2139 | msleep(2); | ||
| 2140 | } | ||
| 2141 | |||
| 2142 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
| 2143 | struct snd_ac97_reset_cfg *cfg) | ||
| 2144 | { | ||
| 2145 | struct pinctrl *p; | ||
| 2146 | struct pinctrl_state *state; | ||
| 2147 | int gpio; | ||
| 2148 | int ret; | ||
| 2149 | |||
| 2150 | p = devm_pinctrl_get(dev); | ||
| 2151 | if (IS_ERR(p)) { | ||
| 2152 | dev_err(dev, "Failed to get pinctrl\n"); | ||
| 2153 | return PTR_RET(p); | ||
| 2154 | } | ||
| 2155 | cfg->pctl = p; | ||
| 2156 | |||
| 2157 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
| 2158 | if (IS_ERR(state)) { | ||
| 2159 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
| 2160 | return PTR_RET(state); | ||
| 2161 | } | ||
| 2162 | cfg->pstate_reset = state; | ||
| 2163 | |||
| 2164 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
| 2165 | if (IS_ERR(state)) { | ||
| 2166 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
| 2167 | return PTR_RET(state); | ||
| 2168 | } | ||
| 2169 | cfg->pstate_warm_reset = state; | ||
| 2170 | |||
| 2171 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
| 2172 | if (IS_ERR(state)) { | ||
| 2173 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
| 2174 | return PTR_RET(state); | ||
| 2175 | } | ||
| 2176 | cfg->pstate_run = state; | ||
| 2177 | |||
| 2178 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
| 2179 | if (gpio < 0) { | ||
| 2180 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
| 2181 | return gpio; | ||
| 2182 | } | ||
| 2183 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
| 2184 | if (ret) { | ||
| 2185 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
| 2186 | return ret; | ||
| 2187 | } | ||
| 2188 | cfg->gpio_sync = gpio; | ||
| 2189 | |||
| 2190 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
| 2191 | if (gpio < 0) { | ||
| 2192 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
| 2193 | return gpio; | ||
| 2194 | } | ||
| 2195 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
| 2196 | if (ret) { | ||
| 2197 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
| 2198 | return ret; | ||
| 2199 | } | ||
| 2200 | cfg->gpio_sdata = gpio; | ||
| 2201 | |||
| 2202 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
| 2203 | if (gpio < 0) { | ||
| 2204 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
| 2205 | return gpio; | ||
| 2206 | } | ||
| 2207 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
| 2208 | if (ret) { | ||
| 2209 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
| 2210 | return ret; | ||
| 2211 | } | ||
| 2212 | cfg->gpio_reset = gpio; | ||
| 2213 | |||
| 2214 | return 0; | ||
| 2215 | } | ||
| 2216 | |||
| 2083 | struct snd_ac97_bus_ops *soc_ac97_ops; | 2217 | struct snd_ac97_bus_ops *soc_ac97_ops; |
| 2084 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 2218 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
| 2085 | 2219 | ||
| @@ -2098,6 +2232,35 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | |||
| 2098 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | 2232 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); |
| 2099 | 2233 | ||
| 2100 | /** | 2234 | /** |
| 2235 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
| 2236 | * | ||
| 2237 | * This function sets the reset and warm_reset properties of ops and parses | ||
| 2238 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
| 2239 | */ | ||
| 2240 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
| 2241 | struct platform_device *pdev) | ||
| 2242 | { | ||
| 2243 | struct device *dev = &pdev->dev; | ||
| 2244 | struct snd_ac97_reset_cfg cfg; | ||
| 2245 | int ret; | ||
| 2246 | |||
| 2247 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
| 2248 | if (ret) | ||
| 2249 | return ret; | ||
| 2250 | |||
| 2251 | ret = snd_soc_set_ac97_ops(ops); | ||
| 2252 | if (ret) | ||
| 2253 | return ret; | ||
| 2254 | |||
| 2255 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
| 2256 | ops->reset = snd_soc_ac97_reset; | ||
| 2257 | |||
| 2258 | snd_ac97_rst_cfg = cfg; | ||
| 2259 | return 0; | ||
| 2260 | } | ||
| 2261 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
| 2262 | |||
| 2263 | /** | ||
| 2101 | * snd_soc_free_ac97_codec - free AC97 codec device | 2264 | * snd_soc_free_ac97_codec - free AC97 codec device |
| 2102 | * @codec: audio codec | 2265 | * @codec: audio codec |
| 2103 | * | 2266 | * |
| @@ -2299,6 +2462,22 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev, | |||
| 2299 | return 0; | 2462 | return 0; |
| 2300 | } | 2463 | } |
| 2301 | 2464 | ||
| 2465 | struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, | ||
| 2466 | const char *name) | ||
| 2467 | { | ||
| 2468 | struct snd_card *card = soc_card->snd_card; | ||
| 2469 | struct snd_kcontrol *kctl; | ||
| 2470 | |||
| 2471 | if (unlikely(!name)) | ||
| 2472 | return NULL; | ||
| 2473 | |||
| 2474 | list_for_each_entry(kctl, &card->controls, list) | ||
| 2475 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) | ||
| 2476 | return kctl; | ||
| 2477 | return NULL; | ||
| 2478 | } | ||
| 2479 | EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); | ||
| 2480 | |||
| 2302 | /** | 2481 | /** |
| 2303 | * snd_soc_add_codec_controls - add an array of controls to a codec. | 2482 | * snd_soc_add_codec_controls - add an array of controls to a codec. |
| 2304 | * Convenience function to add a list of controls. Many codecs were | 2483 | * Convenience function to add a list of controls. Many codecs were |
| @@ -2541,59 +2720,6 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2541 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); | 2720 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); |
| 2542 | 2721 | ||
| 2543 | /** | 2722 | /** |
| 2544 | * snd_soc_info_enum_ext - external enumerated single mixer info callback | ||
| 2545 | * @kcontrol: mixer control | ||
| 2546 | * @uinfo: control element information | ||
| 2547 | * | ||
| 2548 | * Callback to provide information about an external enumerated | ||
| 2549 | * single mixer. | ||
| 2550 | * | ||
| 2551 | * Returns 0 for success. | ||
| 2552 | */ | ||
| 2553 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, | ||
| 2554 | struct snd_ctl_elem_info *uinfo) | ||
| 2555 | { | ||
| 2556 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
| 2557 | |||
| 2558 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 2559 | uinfo->count = 1; | ||
| 2560 | uinfo->value.enumerated.items = e->max; | ||
| 2561 | |||
| 2562 | if (uinfo->value.enumerated.item > e->max - 1) | ||
| 2563 | uinfo->value.enumerated.item = e->max - 1; | ||
| 2564 | strcpy(uinfo->value.enumerated.name, | ||
| 2565 | e->texts[uinfo->value.enumerated.item]); | ||
| 2566 | return 0; | ||
| 2567 | } | ||
| 2568 | EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext); | ||
| 2569 | |||
| 2570 | /** | ||
| 2571 | * snd_soc_info_volsw_ext - external single mixer info callback | ||
| 2572 | * @kcontrol: mixer control | ||
| 2573 | * @uinfo: control element information | ||
| 2574 | * | ||
| 2575 | * Callback to provide information about a single external mixer control. | ||
| 2576 | * | ||
| 2577 | * Returns 0 for success. | ||
| 2578 | */ | ||
| 2579 | int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, | ||
| 2580 | struct snd_ctl_elem_info *uinfo) | ||
| 2581 | { | ||
| 2582 | int max = kcontrol->private_value; | ||
| 2583 | |||
| 2584 | if (max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
| 2585 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
| 2586 | else | ||
| 2587 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 2588 | |||
| 2589 | uinfo->count = 1; | ||
| 2590 | uinfo->value.integer.min = 0; | ||
| 2591 | uinfo->value.integer.max = max; | ||
| 2592 | return 0; | ||
| 2593 | } | ||
| 2594 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); | ||
| 2595 | |||
| 2596 | /** | ||
| 2597 | * snd_soc_info_volsw - single mixer info callback | 2723 | * snd_soc_info_volsw - single mixer info callback |
| 2598 | * @kcontrol: mixer control | 2724 | * @kcontrol: mixer control |
| 2599 | * @uinfo: control element information | 2725 | * @uinfo: control element information |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bd16010441cc..d84bd0f167b6 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -47,6 +47,15 @@ | |||
| 47 | 47 | ||
| 48 | #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; | 48 | #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; |
| 49 | 49 | ||
| 50 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | ||
| 51 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, | ||
| 52 | const char *control, | ||
| 53 | int (*connected)(struct snd_soc_dapm_widget *source, | ||
| 54 | struct snd_soc_dapm_widget *sink)); | ||
| 55 | static struct snd_soc_dapm_widget * | ||
| 56 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | ||
| 57 | const struct snd_soc_dapm_widget *widget); | ||
| 58 | |||
| 50 | /* dapm power sequences - make this per codec in the future */ | 59 | /* dapm power sequences - make this per codec in the future */ |
| 51 | static int dapm_up_seq[] = { | 60 | static int dapm_up_seq[] = { |
| 52 | [snd_soc_dapm_pre] = 0, | 61 | [snd_soc_dapm_pre] = 0, |
| @@ -73,16 +82,18 @@ static int dapm_up_seq[] = { | |||
| 73 | [snd_soc_dapm_hp] = 10, | 82 | [snd_soc_dapm_hp] = 10, |
| 74 | [snd_soc_dapm_spk] = 10, | 83 | [snd_soc_dapm_spk] = 10, |
| 75 | [snd_soc_dapm_line] = 10, | 84 | [snd_soc_dapm_line] = 10, |
| 76 | [snd_soc_dapm_post] = 11, | 85 | [snd_soc_dapm_kcontrol] = 11, |
| 86 | [snd_soc_dapm_post] = 12, | ||
| 77 | }; | 87 | }; |
| 78 | 88 | ||
| 79 | static int dapm_down_seq[] = { | 89 | static int dapm_down_seq[] = { |
| 80 | [snd_soc_dapm_pre] = 0, | 90 | [snd_soc_dapm_pre] = 0, |
| 81 | [snd_soc_dapm_adc] = 1, | 91 | [snd_soc_dapm_kcontrol] = 1, |
| 82 | [snd_soc_dapm_hp] = 2, | 92 | [snd_soc_dapm_adc] = 2, |
| 83 | [snd_soc_dapm_spk] = 2, | 93 | [snd_soc_dapm_hp] = 3, |
| 84 | [snd_soc_dapm_line] = 2, | 94 | [snd_soc_dapm_spk] = 3, |
| 85 | [snd_soc_dapm_out_drv] = 2, | 95 | [snd_soc_dapm_line] = 3, |
| 96 | [snd_soc_dapm_out_drv] = 3, | ||
| 86 | [snd_soc_dapm_pga] = 4, | 97 | [snd_soc_dapm_pga] = 4, |
| 87 | [snd_soc_dapm_switch] = 5, | 98 | [snd_soc_dapm_switch] = 5, |
| 88 | [snd_soc_dapm_mixer_named_ctl] = 5, | 99 | [snd_soc_dapm_mixer_named_ctl] = 5, |
| @@ -174,35 +185,175 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
| 174 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); | 185 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); |
| 175 | } | 186 | } |
| 176 | 187 | ||
| 177 | /* get snd_card from DAPM context */ | 188 | struct dapm_kcontrol_data { |
| 178 | static inline struct snd_card *dapm_get_snd_card( | 189 | unsigned int value; |
| 179 | struct snd_soc_dapm_context *dapm) | 190 | struct snd_soc_dapm_widget *widget; |
| 191 | struct list_head paths; | ||
| 192 | struct snd_soc_dapm_widget_list *wlist; | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | ||
| 196 | struct snd_kcontrol *kcontrol) | ||
| 180 | { | 197 | { |
| 181 | if (dapm->codec) | 198 | struct dapm_kcontrol_data *data; |
| 182 | return dapm->codec->card->snd_card; | 199 | struct soc_mixer_control *mc; |
| 183 | else if (dapm->platform) | ||
| 184 | return dapm->platform->card->snd_card; | ||
| 185 | else | ||
| 186 | BUG(); | ||
| 187 | 200 | ||
| 188 | /* unreachable */ | 201 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 189 | return NULL; | 202 | if (!data) { |
| 203 | dev_err(widget->dapm->dev, | ||
| 204 | "ASoC: can't allocate kcontrol data for %s\n", | ||
| 205 | widget->name); | ||
| 206 | return -ENOMEM; | ||
| 207 | } | ||
| 208 | |||
| 209 | INIT_LIST_HEAD(&data->paths); | ||
| 210 | |||
| 211 | switch (widget->id) { | ||
| 212 | case snd_soc_dapm_switch: | ||
| 213 | case snd_soc_dapm_mixer: | ||
| 214 | case snd_soc_dapm_mixer_named_ctl: | ||
| 215 | mc = (struct soc_mixer_control *)kcontrol->private_value; | ||
| 216 | |||
| 217 | if (mc->autodisable) { | ||
| 218 | struct snd_soc_dapm_widget template; | ||
| 219 | |||
| 220 | memset(&template, 0, sizeof(template)); | ||
| 221 | template.reg = mc->reg; | ||
| 222 | template.mask = (1 << fls(mc->max)) - 1; | ||
| 223 | template.shift = mc->shift; | ||
| 224 | if (mc->invert) | ||
| 225 | template.off_val = mc->max; | ||
| 226 | else | ||
| 227 | template.off_val = 0; | ||
| 228 | template.on_val = template.off_val; | ||
| 229 | template.id = snd_soc_dapm_kcontrol; | ||
| 230 | template.name = kcontrol->id.name; | ||
| 231 | |||
| 232 | data->widget = snd_soc_dapm_new_control(widget->dapm, | ||
| 233 | &template); | ||
| 234 | if (!data->widget) { | ||
| 235 | kfree(data); | ||
| 236 | return -ENOMEM; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | break; | ||
| 240 | default: | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | |||
| 244 | kcontrol->private_data = data; | ||
| 245 | |||
| 246 | return 0; | ||
| 190 | } | 247 | } |
| 191 | 248 | ||
| 192 | /* get soc_card from DAPM context */ | 249 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) |
| 193 | static inline struct snd_soc_card *dapm_get_soc_card( | ||
| 194 | struct snd_soc_dapm_context *dapm) | ||
| 195 | { | 250 | { |
| 196 | if (dapm->codec) | 251 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl); |
| 197 | return dapm->codec->card; | 252 | kfree(data->widget); |
| 198 | else if (dapm->platform) | 253 | kfree(data->wlist); |
| 199 | return dapm->platform->card; | 254 | kfree(data); |
| 255 | } | ||
| 256 | |||
| 257 | static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist( | ||
| 258 | const struct snd_kcontrol *kcontrol) | ||
| 259 | { | ||
| 260 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 261 | |||
| 262 | return data->wlist; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol, | ||
| 266 | struct snd_soc_dapm_widget *widget) | ||
| 267 | { | ||
| 268 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 269 | struct snd_soc_dapm_widget_list *new_wlist; | ||
| 270 | unsigned int n; | ||
| 271 | |||
| 272 | if (data->wlist) | ||
| 273 | n = data->wlist->num_widgets + 1; | ||
| 200 | else | 274 | else |
| 201 | BUG(); | 275 | n = 1; |
| 202 | 276 | ||
| 203 | /* unreachable */ | 277 | new_wlist = krealloc(data->wlist, |
| 204 | return NULL; | 278 | sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL); |
| 279 | if (!new_wlist) | ||
| 280 | return -ENOMEM; | ||
| 281 | |||
| 282 | new_wlist->widgets[n - 1] = widget; | ||
| 283 | new_wlist->num_widgets = n; | ||
| 284 | |||
| 285 | data->wlist = new_wlist; | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol, | ||
| 291 | struct snd_soc_dapm_path *path) | ||
| 292 | { | ||
| 293 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 294 | |||
| 295 | list_add_tail(&path->list_kcontrol, &data->paths); | ||
| 296 | |||
| 297 | if (data->widget) { | ||
| 298 | snd_soc_dapm_add_path(data->widget->dapm, data->widget, | ||
| 299 | path->source, NULL, NULL); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol) | ||
| 304 | { | ||
| 305 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 306 | |||
| 307 | if (!data->widget) | ||
| 308 | return true; | ||
| 309 | |||
| 310 | return data->widget->power; | ||
| 311 | } | ||
| 312 | |||
| 313 | static struct list_head *dapm_kcontrol_get_path_list( | ||
| 314 | const struct snd_kcontrol *kcontrol) | ||
| 315 | { | ||
| 316 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 317 | |||
| 318 | return &data->paths; | ||
| 319 | } | ||
| 320 | |||
| 321 | #define dapm_kcontrol_for_each_path(path, kcontrol) \ | ||
| 322 | list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \ | ||
| 323 | list_kcontrol) | ||
| 324 | |||
| 325 | static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) | ||
| 326 | { | ||
| 327 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 328 | |||
| 329 | return data->value; | ||
| 330 | } | ||
| 331 | |||
| 332 | static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, | ||
| 333 | unsigned int value) | ||
| 334 | { | ||
| 335 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | ||
| 336 | |||
| 337 | if (data->value == value) | ||
| 338 | return false; | ||
| 339 | |||
| 340 | if (data->widget) | ||
| 341 | data->widget->on_val = value; | ||
| 342 | |||
| 343 | data->value = value; | ||
| 344 | |||
| 345 | return true; | ||
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol | ||
| 350 | * @kcontrol: The kcontrol | ||
| 351 | */ | ||
| 352 | struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) | ||
| 353 | { | ||
| 354 | return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec; | ||
| 205 | } | 355 | } |
| 356 | EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); | ||
| 206 | 357 | ||
| 207 | static void dapm_reset(struct snd_soc_card *card) | 358 | static void dapm_reset(struct snd_soc_card *card) |
| 208 | { | 359 | { |
| @@ -211,6 +362,7 @@ static void dapm_reset(struct snd_soc_card *card) | |||
| 211 | memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); | 362 | memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); |
| 212 | 363 | ||
| 213 | list_for_each_entry(w, &card->widgets, list) { | 364 | list_for_each_entry(w, &card->widgets, list) { |
| 365 | w->new_power = w->power; | ||
| 214 | w->power_checked = false; | 366 | w->power_checked = false; |
| 215 | w->inputs = -1; | 367 | w->inputs = -1; |
| 216 | w->outputs = -1; | 368 | w->outputs = -1; |
| @@ -428,6 +580,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
| 428 | case snd_soc_dapm_spk: | 580 | case snd_soc_dapm_spk: |
| 429 | case snd_soc_dapm_line: | 581 | case snd_soc_dapm_line: |
| 430 | case snd_soc_dapm_dai_link: | 582 | case snd_soc_dapm_dai_link: |
| 583 | case snd_soc_dapm_kcontrol: | ||
| 431 | p->connect = 1; | 584 | p->connect = 1; |
| 432 | break; | 585 | break; |
| 433 | /* does affect routing - dynamically connected */ | 586 | /* does affect routing - dynamically connected */ |
| @@ -507,17 +660,12 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, | |||
| 507 | return 0; | 660 | return 0; |
| 508 | } | 661 | } |
| 509 | 662 | ||
| 510 | static void dapm_kcontrol_free(struct snd_kcontrol *kctl) | ||
| 511 | { | ||
| 512 | kfree(kctl->private_data); | ||
| 513 | } | ||
| 514 | |||
| 515 | /* | 663 | /* |
| 516 | * Determine if a kcontrol is shared. If it is, look it up. If it isn't, | 664 | * Determine if a kcontrol is shared. If it is, look it up. If it isn't, |
| 517 | * create it. Either way, add the widget into the control's widget list | 665 | * create it. Either way, add the widget into the control's widget list |
| 518 | */ | 666 | */ |
| 519 | static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | 667 | static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, |
| 520 | int kci, struct snd_soc_dapm_path *path) | 668 | int kci) |
| 521 | { | 669 | { |
| 522 | struct snd_soc_dapm_context *dapm = w->dapm; | 670 | struct snd_soc_dapm_context *dapm = w->dapm; |
| 523 | struct snd_card *card = dapm->card->snd_card; | 671 | struct snd_card *card = dapm->card->snd_card; |
| @@ -525,9 +673,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 525 | size_t prefix_len; | 673 | size_t prefix_len; |
| 526 | int shared; | 674 | int shared; |
| 527 | struct snd_kcontrol *kcontrol; | 675 | struct snd_kcontrol *kcontrol; |
| 528 | struct snd_soc_dapm_widget_list *wlist; | ||
| 529 | int wlistentries; | ||
| 530 | size_t wlistsize; | ||
| 531 | bool wname_in_long_name, kcname_in_long_name; | 676 | bool wname_in_long_name, kcname_in_long_name; |
| 532 | char *long_name; | 677 | char *long_name; |
| 533 | const char *name; | 678 | const char *name; |
| @@ -546,25 +691,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 546 | shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci], | 691 | shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci], |
| 547 | &kcontrol); | 692 | &kcontrol); |
| 548 | 693 | ||
| 549 | if (kcontrol) { | ||
| 550 | wlist = kcontrol->private_data; | ||
| 551 | wlistentries = wlist->num_widgets + 1; | ||
| 552 | } else { | ||
| 553 | wlist = NULL; | ||
| 554 | wlistentries = 1; | ||
| 555 | } | ||
| 556 | |||
| 557 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
| 558 | wlistentries * sizeof(struct snd_soc_dapm_widget *); | ||
| 559 | wlist = krealloc(wlist, wlistsize, GFP_KERNEL); | ||
| 560 | if (wlist == NULL) { | ||
| 561 | dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n", | ||
| 562 | w->name); | ||
| 563 | return -ENOMEM; | ||
| 564 | } | ||
| 565 | wlist->num_widgets = wlistentries; | ||
| 566 | wlist->widgets[wlistentries - 1] = w; | ||
| 567 | |||
| 568 | if (!kcontrol) { | 694 | if (!kcontrol) { |
| 569 | if (shared) { | 695 | if (shared) { |
| 570 | wname_in_long_name = false; | 696 | wname_in_long_name = false; |
| @@ -587,7 +713,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 587 | kcname_in_long_name = false; | 713 | kcname_in_long_name = false; |
| 588 | break; | 714 | break; |
| 589 | default: | 715 | default: |
| 590 | kfree(wlist); | ||
| 591 | return -EINVAL; | 716 | return -EINVAL; |
| 592 | } | 717 | } |
| 593 | } | 718 | } |
| @@ -602,10 +727,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 602 | long_name = kasprintf(GFP_KERNEL, "%s %s", | 727 | long_name = kasprintf(GFP_KERNEL, "%s %s", |
| 603 | w->name + prefix_len, | 728 | w->name + prefix_len, |
| 604 | w->kcontrol_news[kci].name); | 729 | w->kcontrol_news[kci].name); |
| 605 | if (long_name == NULL) { | 730 | if (long_name == NULL) |
| 606 | kfree(wlist); | ||
| 607 | return -ENOMEM; | 731 | return -ENOMEM; |
| 608 | } | ||
| 609 | 732 | ||
| 610 | name = long_name; | 733 | name = long_name; |
| 611 | } else if (wname_in_long_name) { | 734 | } else if (wname_in_long_name) { |
| @@ -616,23 +739,33 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
| 616 | name = w->kcontrol_news[kci].name; | 739 | name = w->kcontrol_news[kci].name; |
| 617 | } | 740 | } |
| 618 | 741 | ||
| 619 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, | 742 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, |
| 620 | prefix); | 743 | prefix); |
| 621 | kcontrol->private_free = dapm_kcontrol_free; | ||
| 622 | kfree(long_name); | 744 | kfree(long_name); |
| 745 | if (!kcontrol) | ||
| 746 | return -ENOMEM; | ||
| 747 | kcontrol->private_free = dapm_kcontrol_free; | ||
| 748 | |||
| 749 | ret = dapm_kcontrol_data_alloc(w, kcontrol); | ||
| 750 | if (ret) { | ||
| 751 | snd_ctl_free_one(kcontrol); | ||
| 752 | return ret; | ||
| 753 | } | ||
| 754 | |||
| 623 | ret = snd_ctl_add(card, kcontrol); | 755 | ret = snd_ctl_add(card, kcontrol); |
| 624 | if (ret < 0) { | 756 | if (ret < 0) { |
| 625 | dev_err(dapm->dev, | 757 | dev_err(dapm->dev, |
| 626 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", | 758 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", |
| 627 | w->name, name, ret); | 759 | w->name, name, ret); |
| 628 | kfree(wlist); | ||
| 629 | return ret; | 760 | return ret; |
| 630 | } | 761 | } |
| 631 | } | 762 | } |
| 632 | 763 | ||
| 633 | kcontrol->private_data = wlist; | 764 | ret = dapm_kcontrol_add_widget(kcontrol, w); |
| 765 | if (ret) | ||
| 766 | return ret; | ||
| 767 | |||
| 634 | w->kcontrols[kci] = kcontrol; | 768 | w->kcontrols[kci] = kcontrol; |
| 635 | path->kcontrol = kcontrol; | ||
| 636 | 769 | ||
| 637 | return 0; | 770 | return 0; |
| 638 | } | 771 | } |
| @@ -652,13 +785,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
| 652 | continue; | 785 | continue; |
| 653 | 786 | ||
| 654 | if (w->kcontrols[i]) { | 787 | if (w->kcontrols[i]) { |
| 655 | path->kcontrol = w->kcontrols[i]; | 788 | dapm_kcontrol_add_path(w->kcontrols[i], path); |
| 656 | continue; | 789 | continue; |
| 657 | } | 790 | } |
| 658 | 791 | ||
| 659 | ret = dapm_create_or_share_mixmux_kcontrol(w, i, path); | 792 | ret = dapm_create_or_share_mixmux_kcontrol(w, i); |
| 660 | if (ret < 0) | 793 | if (ret < 0) |
| 661 | return ret; | 794 | return ret; |
| 795 | |||
| 796 | dapm_kcontrol_add_path(w->kcontrols[i], path); | ||
| 662 | } | 797 | } |
| 663 | } | 798 | } |
| 664 | 799 | ||
| @@ -679,19 +814,17 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
| 679 | return -EINVAL; | 814 | return -EINVAL; |
| 680 | } | 815 | } |
| 681 | 816 | ||
| 682 | path = list_first_entry(&w->sources, struct snd_soc_dapm_path, | 817 | if (list_empty(&w->sources)) { |
| 683 | list_sink); | ||
| 684 | if (!path) { | ||
| 685 | dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name); | 818 | dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name); |
| 686 | return -EINVAL; | 819 | return -EINVAL; |
| 687 | } | 820 | } |
| 688 | 821 | ||
| 689 | ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path); | 822 | ret = dapm_create_or_share_mixmux_kcontrol(w, 0); |
| 690 | if (ret < 0) | 823 | if (ret < 0) |
| 691 | return ret; | 824 | return ret; |
| 692 | 825 | ||
| 693 | list_for_each_entry(path, &w->sources, list_sink) | 826 | list_for_each_entry(path, &w->sources, list_sink) |
| 694 | path->kcontrol = w->kcontrols[0]; | 827 | dapm_kcontrol_add_path(w->kcontrols[0], path); |
| 695 | 828 | ||
| 696 | return 0; | 829 | return 0; |
| 697 | } | 830 | } |
| @@ -812,6 +945,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | |||
| 812 | case snd_soc_dapm_supply: | 945 | case snd_soc_dapm_supply: |
| 813 | case snd_soc_dapm_regulator_supply: | 946 | case snd_soc_dapm_regulator_supply: |
| 814 | case snd_soc_dapm_clock_supply: | 947 | case snd_soc_dapm_clock_supply: |
| 948 | case snd_soc_dapm_kcontrol: | ||
| 815 | return 0; | 949 | return 0; |
| 816 | default: | 950 | default: |
| 817 | break; | 951 | break; |
| @@ -907,6 +1041,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
| 907 | case snd_soc_dapm_supply: | 1041 | case snd_soc_dapm_supply: |
| 908 | case snd_soc_dapm_regulator_supply: | 1042 | case snd_soc_dapm_regulator_supply: |
| 909 | case snd_soc_dapm_clock_supply: | 1043 | case snd_soc_dapm_clock_supply: |
| 1044 | case snd_soc_dapm_kcontrol: | ||
| 910 | return 0; | 1045 | return 0; |
| 911 | default: | 1046 | default: |
| 912 | break; | 1047 | break; |
| @@ -1061,7 +1196,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
| 1061 | int ret; | 1196 | int ret; |
| 1062 | 1197 | ||
| 1063 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 1198 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
| 1064 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | 1199 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { |
| 1065 | ret = regulator_allow_bypass(w->regulator, false); | 1200 | ret = regulator_allow_bypass(w->regulator, false); |
| 1066 | if (ret != 0) | 1201 | if (ret != 0) |
| 1067 | dev_warn(w->dapm->dev, | 1202 | dev_warn(w->dapm->dev, |
| @@ -1071,7 +1206,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
| 1071 | 1206 | ||
| 1072 | return regulator_enable(w->regulator); | 1207 | return regulator_enable(w->regulator); |
| 1073 | } else { | 1208 | } else { |
| 1074 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | 1209 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { |
| 1075 | ret = regulator_allow_bypass(w->regulator, true); | 1210 | ret = regulator_allow_bypass(w->regulator, true); |
| 1076 | if (ret != 0) | 1211 | if (ret != 0) |
| 1077 | dev_warn(w->dapm->dev, | 1212 | dev_warn(w->dapm->dev, |
| @@ -1243,10 +1378,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | |||
| 1243 | list_add_tail(&new_widget->power_list, list); | 1378 | list_add_tail(&new_widget->power_list, list); |
| 1244 | } | 1379 | } |
| 1245 | 1380 | ||
| 1246 | static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, | 1381 | static void dapm_seq_check_event(struct snd_soc_card *card, |
| 1247 | struct snd_soc_dapm_widget *w, int event) | 1382 | struct snd_soc_dapm_widget *w, int event) |
| 1248 | { | 1383 | { |
| 1249 | struct snd_soc_card *card = dapm->card; | ||
| 1250 | const char *ev_name; | 1384 | const char *ev_name; |
| 1251 | int power, ret; | 1385 | int power, ret; |
| 1252 | 1386 | ||
| @@ -1280,55 +1414,50 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, | |||
| 1280 | return; | 1414 | return; |
| 1281 | } | 1415 | } |
| 1282 | 1416 | ||
| 1283 | if (w->power != power) | 1417 | if (w->new_power != power) |
| 1284 | return; | 1418 | return; |
| 1285 | 1419 | ||
| 1286 | if (w->event && (w->event_flags & event)) { | 1420 | if (w->event && (w->event_flags & event)) { |
| 1287 | pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", | 1421 | pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", |
| 1288 | w->name, ev_name); | 1422 | w->name, ev_name); |
| 1289 | trace_snd_soc_dapm_widget_event_start(w, event); | 1423 | trace_snd_soc_dapm_widget_event_start(w, event); |
| 1290 | ret = w->event(w, NULL, event); | 1424 | ret = w->event(w, NULL, event); |
| 1291 | trace_snd_soc_dapm_widget_event_done(w, event); | 1425 | trace_snd_soc_dapm_widget_event_done(w, event); |
| 1292 | if (ret < 0) | 1426 | if (ret < 0) |
| 1293 | dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n", | 1427 | dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n", |
| 1294 | ev_name, w->name, ret); | 1428 | ev_name, w->name, ret); |
| 1295 | } | 1429 | } |
| 1296 | } | 1430 | } |
| 1297 | 1431 | ||
| 1298 | /* Apply the coalesced changes from a DAPM sequence */ | 1432 | /* Apply the coalesced changes from a DAPM sequence */ |
| 1299 | static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | 1433 | static void dapm_seq_run_coalesced(struct snd_soc_card *card, |
| 1300 | struct list_head *pending) | 1434 | struct list_head *pending) |
| 1301 | { | 1435 | { |
| 1302 | struct snd_soc_card *card = dapm->card; | ||
| 1303 | struct snd_soc_dapm_widget *w; | 1436 | struct snd_soc_dapm_widget *w; |
| 1304 | int reg, power; | 1437 | int reg; |
| 1305 | unsigned int value = 0; | 1438 | unsigned int value = 0; |
| 1306 | unsigned int mask = 0; | 1439 | unsigned int mask = 0; |
| 1307 | unsigned int cur_mask; | ||
| 1308 | 1440 | ||
| 1309 | reg = list_first_entry(pending, struct snd_soc_dapm_widget, | 1441 | reg = list_first_entry(pending, struct snd_soc_dapm_widget, |
| 1310 | power_list)->reg; | 1442 | power_list)->reg; |
| 1311 | 1443 | ||
| 1312 | list_for_each_entry(w, pending, power_list) { | 1444 | list_for_each_entry(w, pending, power_list) { |
| 1313 | cur_mask = 1 << w->shift; | ||
| 1314 | BUG_ON(reg != w->reg); | 1445 | BUG_ON(reg != w->reg); |
| 1446 | w->power = w->new_power; | ||
| 1315 | 1447 | ||
| 1316 | if (w->invert) | 1448 | mask |= w->mask << w->shift; |
| 1317 | power = !w->power; | 1449 | if (w->power) |
| 1450 | value |= w->on_val << w->shift; | ||
| 1318 | else | 1451 | else |
| 1319 | power = w->power; | 1452 | value |= w->off_val << w->shift; |
| 1320 | 1453 | ||
| 1321 | mask |= cur_mask; | 1454 | pop_dbg(w->dapm->dev, card->pop_time, |
| 1322 | if (power) | ||
| 1323 | value |= cur_mask; | ||
| 1324 | |||
| 1325 | pop_dbg(dapm->dev, card->pop_time, | ||
| 1326 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", | 1455 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", |
| 1327 | w->name, reg, value, mask); | 1456 | w->name, reg, value, mask); |
| 1328 | 1457 | ||
| 1329 | /* Check for events */ | 1458 | /* Check for events */ |
| 1330 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); | 1459 | dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU); |
| 1331 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); | 1460 | dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD); |
| 1332 | } | 1461 | } |
| 1333 | 1462 | ||
| 1334 | if (reg >= 0) { | 1463 | if (reg >= 0) { |
| @@ -1338,7 +1467,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
| 1338 | w = list_first_entry(pending, struct snd_soc_dapm_widget, | 1467 | w = list_first_entry(pending, struct snd_soc_dapm_widget, |
| 1339 | power_list); | 1468 | power_list); |
| 1340 | 1469 | ||
| 1341 | pop_dbg(dapm->dev, card->pop_time, | 1470 | pop_dbg(w->dapm->dev, card->pop_time, |
| 1342 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 1471 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
| 1343 | value, mask, reg, card->pop_time); | 1472 | value, mask, reg, card->pop_time); |
| 1344 | pop_wait(card->pop_time); | 1473 | pop_wait(card->pop_time); |
| @@ -1346,8 +1475,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
| 1346 | } | 1475 | } |
| 1347 | 1476 | ||
| 1348 | list_for_each_entry(w, pending, power_list) { | 1477 | list_for_each_entry(w, pending, power_list) { |
| 1349 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); | 1478 | dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU); |
| 1350 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); | 1479 | dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD); |
| 1351 | } | 1480 | } |
| 1352 | } | 1481 | } |
| 1353 | 1482 | ||
| @@ -1359,8 +1488,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
| 1359 | * Currently anything that requires more than a single write is not | 1488 | * Currently anything that requires more than a single write is not |
| 1360 | * handled. | 1489 | * handled. |
| 1361 | */ | 1490 | */ |
| 1362 | static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | 1491 | static void dapm_seq_run(struct snd_soc_card *card, |
| 1363 | struct list_head *list, int event, bool power_up) | 1492 | struct list_head *list, int event, bool power_up) |
| 1364 | { | 1493 | { |
| 1365 | struct snd_soc_dapm_widget *w, *n; | 1494 | struct snd_soc_dapm_widget *w, *n; |
| 1366 | LIST_HEAD(pending); | 1495 | LIST_HEAD(pending); |
| @@ -1383,7 +1512,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
| 1383 | if (sort[w->id] != cur_sort || w->reg != cur_reg || | 1512 | if (sort[w->id] != cur_sort || w->reg != cur_reg || |
| 1384 | w->dapm != cur_dapm || w->subseq != cur_subseq) { | 1513 | w->dapm != cur_dapm || w->subseq != cur_subseq) { |
| 1385 | if (!list_empty(&pending)) | 1514 | if (!list_empty(&pending)) |
| 1386 | dapm_seq_run_coalesced(cur_dapm, &pending); | 1515 | dapm_seq_run_coalesced(card, &pending); |
| 1387 | 1516 | ||
| 1388 | if (cur_dapm && cur_dapm->seq_notifier) { | 1517 | if (cur_dapm && cur_dapm->seq_notifier) { |
| 1389 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | 1518 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
| @@ -1443,7 +1572,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
| 1443 | } | 1572 | } |
| 1444 | 1573 | ||
| 1445 | if (!list_empty(&pending)) | 1574 | if (!list_empty(&pending)) |
| 1446 | dapm_seq_run_coalesced(cur_dapm, &pending); | 1575 | dapm_seq_run_coalesced(card, &pending); |
| 1447 | 1576 | ||
| 1448 | if (cur_dapm && cur_dapm->seq_notifier) { | 1577 | if (cur_dapm && cur_dapm->seq_notifier) { |
| 1449 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | 1578 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
| @@ -1453,37 +1582,48 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
| 1453 | } | 1582 | } |
| 1454 | } | 1583 | } |
| 1455 | 1584 | ||
| 1456 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | 1585 | static void dapm_widget_update(struct snd_soc_card *card) |
| 1457 | { | 1586 | { |
| 1458 | struct snd_soc_dapm_update *update = dapm->update; | 1587 | struct snd_soc_dapm_update *update = card->update; |
| 1459 | struct snd_soc_dapm_widget *w; | 1588 | struct snd_soc_dapm_widget_list *wlist; |
| 1589 | struct snd_soc_dapm_widget *w = NULL; | ||
| 1590 | unsigned int wi; | ||
| 1460 | int ret; | 1591 | int ret; |
| 1461 | 1592 | ||
| 1462 | if (!update) | 1593 | if (!update || !dapm_kcontrol_is_powered(update->kcontrol)) |
| 1463 | return; | 1594 | return; |
| 1464 | 1595 | ||
| 1465 | w = update->widget; | 1596 | wlist = dapm_kcontrol_get_wlist(update->kcontrol); |
| 1466 | 1597 | ||
| 1467 | if (w->event && | 1598 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
| 1468 | (w->event_flags & SND_SOC_DAPM_PRE_REG)) { | 1599 | w = wlist->widgets[wi]; |
| 1469 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); | 1600 | |
| 1470 | if (ret != 0) | 1601 | if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) { |
| 1471 | dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", | 1602 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); |
| 1472 | w->name, ret); | 1603 | if (ret != 0) |
| 1604 | dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", | ||
| 1605 | w->name, ret); | ||
| 1606 | } | ||
| 1473 | } | 1607 | } |
| 1474 | 1608 | ||
| 1609 | if (!w) | ||
| 1610 | return; | ||
| 1611 | |||
| 1475 | ret = soc_widget_update_bits_locked(w, update->reg, update->mask, | 1612 | ret = soc_widget_update_bits_locked(w, update->reg, update->mask, |
| 1476 | update->val); | 1613 | update->val); |
| 1477 | if (ret < 0) | 1614 | if (ret < 0) |
| 1478 | dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n", | 1615 | dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", |
| 1479 | w->name, ret); | 1616 | w->name, ret); |
| 1480 | 1617 | ||
| 1481 | if (w->event && | 1618 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
| 1482 | (w->event_flags & SND_SOC_DAPM_POST_REG)) { | 1619 | w = wlist->widgets[wi]; |
| 1483 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); | 1620 | |
| 1484 | if (ret != 0) | 1621 | if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) { |
| 1485 | dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", | 1622 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); |
| 1486 | w->name, ret); | 1623 | if (ret != 0) |
| 1624 | dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", | ||
| 1625 | w->name, ret); | ||
| 1626 | } | ||
| 1487 | } | 1627 | } |
| 1488 | } | 1628 | } |
| 1489 | 1629 | ||
| @@ -1595,6 +1735,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
| 1595 | case snd_soc_dapm_supply: | 1735 | case snd_soc_dapm_supply: |
| 1596 | case snd_soc_dapm_regulator_supply: | 1736 | case snd_soc_dapm_regulator_supply: |
| 1597 | case snd_soc_dapm_clock_supply: | 1737 | case snd_soc_dapm_clock_supply: |
| 1738 | case snd_soc_dapm_kcontrol: | ||
| 1598 | /* Supplies can't affect their outputs, only their inputs */ | 1739 | /* Supplies can't affect their outputs, only their inputs */ |
| 1599 | break; | 1740 | break; |
| 1600 | default: | 1741 | default: |
| @@ -1611,8 +1752,6 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
| 1611 | dapm_seq_insert(w, up_list, true); | 1752 | dapm_seq_insert(w, up_list, true); |
| 1612 | else | 1753 | else |
| 1613 | dapm_seq_insert(w, down_list, false); | 1754 | dapm_seq_insert(w, down_list, false); |
| 1614 | |||
| 1615 | w->power = power; | ||
| 1616 | } | 1755 | } |
| 1617 | 1756 | ||
| 1618 | static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, | 1757 | static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, |
| @@ -1646,9 +1785,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, | |||
| 1646 | * o Input pin to Output pin (bypass, sidetone) | 1785 | * o Input pin to Output pin (bypass, sidetone) |
| 1647 | * o DAC to ADC (loopback). | 1786 | * o DAC to ADC (loopback). |
| 1648 | */ | 1787 | */ |
| 1649 | static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | 1788 | static int dapm_power_widgets(struct snd_soc_card *card, int event) |
| 1650 | { | 1789 | { |
| 1651 | struct snd_soc_card *card = dapm->card; | ||
| 1652 | struct snd_soc_dapm_widget *w; | 1790 | struct snd_soc_dapm_widget *w; |
| 1653 | struct snd_soc_dapm_context *d; | 1791 | struct snd_soc_dapm_context *d; |
| 1654 | LIST_HEAD(up_list); | 1792 | LIST_HEAD(up_list); |
| @@ -1688,7 +1826,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
| 1688 | break; | 1826 | break; |
| 1689 | } | 1827 | } |
| 1690 | 1828 | ||
| 1691 | if (w->power) { | 1829 | if (w->new_power) { |
| 1692 | d = w->dapm; | 1830 | d = w->dapm; |
| 1693 | 1831 | ||
| 1694 | /* Supplies and micbiases only bring the | 1832 | /* Supplies and micbiases only bring the |
| @@ -1730,29 +1868,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
| 1730 | trace_snd_soc_dapm_walk_done(card); | 1868 | trace_snd_soc_dapm_walk_done(card); |
| 1731 | 1869 | ||
| 1732 | /* Run all the bias changes in parallel */ | 1870 | /* Run all the bias changes in parallel */ |
| 1733 | list_for_each_entry(d, &dapm->card->dapm_list, list) | 1871 | list_for_each_entry(d, &card->dapm_list, list) |
| 1734 | async_schedule_domain(dapm_pre_sequence_async, d, | 1872 | async_schedule_domain(dapm_pre_sequence_async, d, |
| 1735 | &async_domain); | 1873 | &async_domain); |
| 1736 | async_synchronize_full_domain(&async_domain); | 1874 | async_synchronize_full_domain(&async_domain); |
| 1737 | 1875 | ||
| 1738 | list_for_each_entry(w, &down_list, power_list) { | 1876 | list_for_each_entry(w, &down_list, power_list) { |
| 1739 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD); | 1877 | dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD); |
| 1740 | } | 1878 | } |
| 1741 | 1879 | ||
| 1742 | list_for_each_entry(w, &up_list, power_list) { | 1880 | list_for_each_entry(w, &up_list, power_list) { |
| 1743 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU); | 1881 | dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU); |
| 1744 | } | 1882 | } |
| 1745 | 1883 | ||
| 1746 | /* Power down widgets first; try to avoid amplifying pops. */ | 1884 | /* Power down widgets first; try to avoid amplifying pops. */ |
| 1747 | dapm_seq_run(dapm, &down_list, event, false); | 1885 | dapm_seq_run(card, &down_list, event, false); |
| 1748 | 1886 | ||
| 1749 | dapm_widget_update(dapm); | 1887 | dapm_widget_update(card); |
| 1750 | 1888 | ||
| 1751 | /* Now power up. */ | 1889 | /* Now power up. */ |
| 1752 | dapm_seq_run(dapm, &up_list, event, true); | 1890 | dapm_seq_run(card, &up_list, event, true); |
| 1753 | 1891 | ||
| 1754 | /* Run all the bias changes in parallel */ | 1892 | /* Run all the bias changes in parallel */ |
| 1755 | list_for_each_entry(d, &dapm->card->dapm_list, list) | 1893 | list_for_each_entry(d, &card->dapm_list, list) |
| 1756 | async_schedule_domain(dapm_post_sequence_async, d, | 1894 | async_schedule_domain(dapm_post_sequence_async, d, |
| 1757 | &async_domain); | 1895 | &async_domain); |
| 1758 | async_synchronize_full_domain(&async_domain); | 1896 | async_synchronize_full_domain(&async_domain); |
| @@ -1763,7 +1901,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
| 1763 | d->stream_event(d, event); | 1901 | d->stream_event(d, event); |
| 1764 | } | 1902 | } |
| 1765 | 1903 | ||
| 1766 | pop_dbg(dapm->dev, card->pop_time, | 1904 | pop_dbg(card->dev, card->pop_time, |
| 1767 | "DAPM sequencing finished, waiting %dms\n", card->pop_time); | 1905 | "DAPM sequencing finished, waiting %dms\n", card->pop_time); |
| 1768 | pop_wait(card->pop_time); | 1906 | pop_wait(card->pop_time); |
| 1769 | 1907 | ||
| @@ -1798,8 +1936,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
| 1798 | 1936 | ||
| 1799 | if (w->reg >= 0) | 1937 | if (w->reg >= 0) |
| 1800 | ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1938 | ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| 1801 | " - R%d(0x%x) bit %d", | 1939 | " - R%d(0x%x) mask 0x%x", |
| 1802 | w->reg, w->reg, w->shift); | 1940 | w->reg, w->reg, w->mask << w->shift); |
| 1803 | 1941 | ||
| 1804 | ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); | 1942 | ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
| 1805 | 1943 | ||
| @@ -1936,22 +2074,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | |||
| 1936 | #endif | 2074 | #endif |
| 1937 | 2075 | ||
| 1938 | /* test and update the power status of a mux widget */ | 2076 | /* test and update the power status of a mux widget */ |
| 1939 | static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | 2077 | static int soc_dapm_mux_update_power(struct snd_soc_card *card, |
| 1940 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) | 2078 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) |
| 1941 | { | 2079 | { |
| 1942 | struct snd_soc_dapm_path *path; | 2080 | struct snd_soc_dapm_path *path; |
| 1943 | int found = 0; | 2081 | int found = 0; |
| 1944 | 2082 | ||
| 1945 | if (widget->id != snd_soc_dapm_mux && | ||
| 1946 | widget->id != snd_soc_dapm_virt_mux && | ||
| 1947 | widget->id != snd_soc_dapm_value_mux) | ||
| 1948 | return -ENODEV; | ||
| 1949 | |||
| 1950 | /* find dapm widget path assoc with kcontrol */ | 2083 | /* find dapm widget path assoc with kcontrol */ |
| 1951 | list_for_each_entry(path, &widget->dapm->card->paths, list) { | 2084 | dapm_kcontrol_for_each_path(path, kcontrol) { |
| 1952 | if (path->kcontrol != kcontrol) | ||
| 1953 | continue; | ||
| 1954 | |||
| 1955 | if (!path->name || !e->texts[mux]) | 2085 | if (!path->name || !e->texts[mux]) |
| 1956 | continue; | 2086 | continue; |
| 1957 | 2087 | ||
| @@ -1966,73 +2096,68 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
| 1966 | "mux disconnection"); | 2096 | "mux disconnection"); |
| 1967 | path->connect = 0; /* old connection must be powered down */ | 2097 | path->connect = 0; /* old connection must be powered down */ |
| 1968 | } | 2098 | } |
| 2099 | dapm_mark_dirty(path->sink, "mux change"); | ||
| 1969 | } | 2100 | } |
| 1970 | 2101 | ||
| 1971 | if (found) { | 2102 | if (found) |
| 1972 | dapm_mark_dirty(widget, "mux change"); | 2103 | dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); |
| 1973 | dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); | ||
| 1974 | } | ||
| 1975 | 2104 | ||
| 1976 | return found; | 2105 | return found; |
| 1977 | } | 2106 | } |
| 1978 | 2107 | ||
| 1979 | int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | 2108 | int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, |
| 1980 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) | 2109 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e, |
| 2110 | struct snd_soc_dapm_update *update) | ||
| 1981 | { | 2111 | { |
| 1982 | struct snd_soc_card *card = widget->dapm->card; | 2112 | struct snd_soc_card *card = dapm->card; |
| 1983 | int ret; | 2113 | int ret; |
| 1984 | 2114 | ||
| 1985 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2115 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 1986 | ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e); | 2116 | card->update = update; |
| 2117 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); | ||
| 2118 | card->update = NULL; | ||
| 1987 | mutex_unlock(&card->dapm_mutex); | 2119 | mutex_unlock(&card->dapm_mutex); |
| 1988 | if (ret > 0) | 2120 | if (ret > 0) |
| 1989 | soc_dpcm_runtime_update(widget); | 2121 | soc_dpcm_runtime_update(card); |
| 1990 | return ret; | 2122 | return ret; |
| 1991 | } | 2123 | } |
| 1992 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); | 2124 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); |
| 1993 | 2125 | ||
| 1994 | /* test and update the power status of a mixer or switch widget */ | 2126 | /* test and update the power status of a mixer or switch widget */ |
| 1995 | static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | 2127 | static int soc_dapm_mixer_update_power(struct snd_soc_card *card, |
| 1996 | struct snd_kcontrol *kcontrol, int connect) | 2128 | struct snd_kcontrol *kcontrol, int connect) |
| 1997 | { | 2129 | { |
| 1998 | struct snd_soc_dapm_path *path; | 2130 | struct snd_soc_dapm_path *path; |
| 1999 | int found = 0; | 2131 | int found = 0; |
| 2000 | 2132 | ||
| 2001 | if (widget->id != snd_soc_dapm_mixer && | ||
| 2002 | widget->id != snd_soc_dapm_mixer_named_ctl && | ||
| 2003 | widget->id != snd_soc_dapm_switch) | ||
| 2004 | return -ENODEV; | ||
| 2005 | |||
| 2006 | /* find dapm widget path assoc with kcontrol */ | 2133 | /* find dapm widget path assoc with kcontrol */ |
| 2007 | list_for_each_entry(path, &widget->dapm->card->paths, list) { | 2134 | dapm_kcontrol_for_each_path(path, kcontrol) { |
| 2008 | if (path->kcontrol != kcontrol) | ||
| 2009 | continue; | ||
| 2010 | |||
| 2011 | /* found, now check type */ | ||
| 2012 | found = 1; | 2135 | found = 1; |
| 2013 | path->connect = connect; | 2136 | path->connect = connect; |
| 2014 | dapm_mark_dirty(path->source, "mixer connection"); | 2137 | dapm_mark_dirty(path->source, "mixer connection"); |
| 2138 | dapm_mark_dirty(path->sink, "mixer update"); | ||
| 2015 | } | 2139 | } |
| 2016 | 2140 | ||
| 2017 | if (found) { | 2141 | if (found) |
| 2018 | dapm_mark_dirty(widget, "mixer update"); | 2142 | dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); |
| 2019 | dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); | ||
| 2020 | } | ||
| 2021 | 2143 | ||
| 2022 | return found; | 2144 | return found; |
| 2023 | } | 2145 | } |
| 2024 | 2146 | ||
| 2025 | int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | 2147 | int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, |
| 2026 | struct snd_kcontrol *kcontrol, int connect) | 2148 | struct snd_kcontrol *kcontrol, int connect, |
| 2149 | struct snd_soc_dapm_update *update) | ||
| 2027 | { | 2150 | { |
| 2028 | struct snd_soc_card *card = widget->dapm->card; | 2151 | struct snd_soc_card *card = dapm->card; |
| 2029 | int ret; | 2152 | int ret; |
| 2030 | 2153 | ||
| 2031 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2154 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2032 | ret = soc_dapm_mixer_update_power(widget, kcontrol, connect); | 2155 | card->update = update; |
| 2156 | ret = soc_dapm_mixer_update_power(card, kcontrol, connect); | ||
| 2157 | card->update = NULL; | ||
| 2033 | mutex_unlock(&card->dapm_mutex); | 2158 | mutex_unlock(&card->dapm_mutex); |
| 2034 | if (ret > 0) | 2159 | if (ret > 0) |
| 2035 | soc_dpcm_runtime_update(widget); | 2160 | soc_dpcm_runtime_update(card); |
| 2036 | return ret; | 2161 | return ret; |
| 2037 | } | 2162 | } |
| 2038 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); | 2163 | EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); |
| @@ -2111,6 +2236,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path) | |||
| 2111 | { | 2236 | { |
| 2112 | list_del(&path->list_sink); | 2237 | list_del(&path->list_sink); |
| 2113 | list_del(&path->list_source); | 2238 | list_del(&path->list_source); |
| 2239 | list_del(&path->list_kcontrol); | ||
| 2114 | list_del(&path->list); | 2240 | list_del(&path->list); |
| 2115 | kfree(path); | 2241 | kfree(path); |
| 2116 | } | 2242 | } |
| @@ -2205,70 +2331,20 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | |||
| 2205 | return 0; | 2331 | return 0; |
| 2206 | 2332 | ||
| 2207 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2333 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2208 | ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); | 2334 | ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); |
| 2209 | mutex_unlock(&dapm->card->dapm_mutex); | 2335 | mutex_unlock(&dapm->card->dapm_mutex); |
| 2210 | return ret; | 2336 | return ret; |
| 2211 | } | 2337 | } |
| 2212 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 2338 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); |
| 2213 | 2339 | ||
| 2214 | static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | 2340 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, |
| 2215 | const struct snd_soc_dapm_route *route) | 2341 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, |
| 2342 | const char *control, | ||
| 2343 | int (*connected)(struct snd_soc_dapm_widget *source, | ||
| 2344 | struct snd_soc_dapm_widget *sink)) | ||
| 2216 | { | 2345 | { |
| 2217 | struct snd_soc_dapm_path *path; | 2346 | struct snd_soc_dapm_path *path; |
| 2218 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; | 2347 | int ret; |
| 2219 | struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; | ||
| 2220 | const char *sink; | ||
| 2221 | const char *control = route->control; | ||
| 2222 | const char *source; | ||
| 2223 | char prefixed_sink[80]; | ||
| 2224 | char prefixed_source[80]; | ||
| 2225 | int ret = 0; | ||
| 2226 | |||
| 2227 | if (dapm->codec && dapm->codec->name_prefix) { | ||
| 2228 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | ||
| 2229 | dapm->codec->name_prefix, route->sink); | ||
| 2230 | sink = prefixed_sink; | ||
| 2231 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | ||
| 2232 | dapm->codec->name_prefix, route->source); | ||
| 2233 | source = prefixed_source; | ||
| 2234 | } else { | ||
| 2235 | sink = route->sink; | ||
| 2236 | source = route->source; | ||
| 2237 | } | ||
| 2238 | |||
| 2239 | /* | ||
| 2240 | * find src and dest widgets over all widgets but favor a widget from | ||
| 2241 | * current DAPM context | ||
| 2242 | */ | ||
| 2243 | list_for_each_entry(w, &dapm->card->widgets, list) { | ||
| 2244 | if (!wsink && !(strcmp(w->name, sink))) { | ||
| 2245 | wtsink = w; | ||
| 2246 | if (w->dapm == dapm) | ||
| 2247 | wsink = w; | ||
| 2248 | continue; | ||
| 2249 | } | ||
| 2250 | if (!wsource && !(strcmp(w->name, source))) { | ||
| 2251 | wtsource = w; | ||
| 2252 | if (w->dapm == dapm) | ||
| 2253 | wsource = w; | ||
| 2254 | } | ||
| 2255 | } | ||
| 2256 | /* use widget from another DAPM context if not found from this */ | ||
| 2257 | if (!wsink) | ||
| 2258 | wsink = wtsink; | ||
| 2259 | if (!wsource) | ||
| 2260 | wsource = wtsource; | ||
| 2261 | |||
| 2262 | if (wsource == NULL) { | ||
| 2263 | dev_err(dapm->dev, "ASoC: no source widget found for %s\n", | ||
| 2264 | route->source); | ||
| 2265 | return -ENODEV; | ||
| 2266 | } | ||
| 2267 | if (wsink == NULL) { | ||
| 2268 | dev_err(dapm->dev, "ASoC: no sink widget found for %s\n", | ||
| 2269 | route->sink); | ||
| 2270 | return -ENODEV; | ||
| 2271 | } | ||
| 2272 | 2348 | ||
| 2273 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); | 2349 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); |
| 2274 | if (!path) | 2350 | if (!path) |
| @@ -2276,8 +2352,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
| 2276 | 2352 | ||
| 2277 | path->source = wsource; | 2353 | path->source = wsource; |
| 2278 | path->sink = wsink; | 2354 | path->sink = wsink; |
| 2279 | path->connected = route->connected; | 2355 | path->connected = connected; |
| 2280 | INIT_LIST_HEAD(&path->list); | 2356 | INIT_LIST_HEAD(&path->list); |
| 2357 | INIT_LIST_HEAD(&path->list_kcontrol); | ||
| 2281 | INIT_LIST_HEAD(&path->list_source); | 2358 | INIT_LIST_HEAD(&path->list_source); |
| 2282 | INIT_LIST_HEAD(&path->list_sink); | 2359 | INIT_LIST_HEAD(&path->list_sink); |
| 2283 | 2360 | ||
| @@ -2327,6 +2404,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
| 2327 | case snd_soc_dapm_dai_in: | 2404 | case snd_soc_dapm_dai_in: |
| 2328 | case snd_soc_dapm_dai_out: | 2405 | case snd_soc_dapm_dai_out: |
| 2329 | case snd_soc_dapm_dai_link: | 2406 | case snd_soc_dapm_dai_link: |
| 2407 | case snd_soc_dapm_kcontrol: | ||
| 2330 | list_add(&path->list, &dapm->card->paths); | 2408 | list_add(&path->list, &dapm->card->paths); |
| 2331 | list_add(&path->list_sink, &wsink->sources); | 2409 | list_add(&path->list_sink, &wsink->sources); |
| 2332 | list_add(&path->list_source, &wsource->sinks); | 2410 | list_add(&path->list_source, &wsource->sinks); |
| @@ -2362,11 +2440,77 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
| 2362 | dapm_mark_dirty(wsink, "Route added"); | 2440 | dapm_mark_dirty(wsink, "Route added"); |
| 2363 | 2441 | ||
| 2364 | return 0; | 2442 | return 0; |
| 2443 | err: | ||
| 2444 | kfree(path); | ||
| 2445 | return ret; | ||
| 2446 | } | ||
| 2447 | |||
| 2448 | static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | ||
| 2449 | const struct snd_soc_dapm_route *route) | ||
| 2450 | { | ||
| 2451 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; | ||
| 2452 | struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; | ||
| 2453 | const char *sink; | ||
| 2454 | const char *source; | ||
| 2455 | char prefixed_sink[80]; | ||
| 2456 | char prefixed_source[80]; | ||
| 2457 | int ret; | ||
| 2458 | |||
| 2459 | if (dapm->codec && dapm->codec->name_prefix) { | ||
| 2460 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | ||
| 2461 | dapm->codec->name_prefix, route->sink); | ||
| 2462 | sink = prefixed_sink; | ||
| 2463 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | ||
| 2464 | dapm->codec->name_prefix, route->source); | ||
| 2465 | source = prefixed_source; | ||
| 2466 | } else { | ||
| 2467 | sink = route->sink; | ||
| 2468 | source = route->source; | ||
| 2469 | } | ||
| 2470 | |||
| 2471 | /* | ||
| 2472 | * find src and dest widgets over all widgets but favor a widget from | ||
| 2473 | * current DAPM context | ||
| 2474 | */ | ||
| 2475 | list_for_each_entry(w, &dapm->card->widgets, list) { | ||
| 2476 | if (!wsink && !(strcmp(w->name, sink))) { | ||
| 2477 | wtsink = w; | ||
| 2478 | if (w->dapm == dapm) | ||
| 2479 | wsink = w; | ||
| 2480 | continue; | ||
| 2481 | } | ||
| 2482 | if (!wsource && !(strcmp(w->name, source))) { | ||
| 2483 | wtsource = w; | ||
| 2484 | if (w->dapm == dapm) | ||
| 2485 | wsource = w; | ||
| 2486 | } | ||
| 2487 | } | ||
| 2488 | /* use widget from another DAPM context if not found from this */ | ||
| 2489 | if (!wsink) | ||
| 2490 | wsink = wtsink; | ||
| 2491 | if (!wsource) | ||
| 2492 | wsource = wtsource; | ||
| 2493 | |||
| 2494 | if (wsource == NULL) { | ||
| 2495 | dev_err(dapm->dev, "ASoC: no source widget found for %s\n", | ||
| 2496 | route->source); | ||
| 2497 | return -ENODEV; | ||
| 2498 | } | ||
| 2499 | if (wsink == NULL) { | ||
| 2500 | dev_err(dapm->dev, "ASoC: no sink widget found for %s\n", | ||
| 2501 | route->sink); | ||
| 2502 | return -ENODEV; | ||
| 2503 | } | ||
| 2365 | 2504 | ||
| 2505 | ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control, | ||
| 2506 | route->connected); | ||
| 2507 | if (ret) | ||
| 2508 | goto err; | ||
| 2509 | |||
| 2510 | return 0; | ||
| 2366 | err: | 2511 | err: |
| 2367 | dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n", | 2512 | dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n", |
| 2368 | source, control, sink); | 2513 | source, route->control, sink); |
| 2369 | kfree(path); | ||
| 2370 | return ret; | 2514 | return ret; |
| 2371 | } | 2515 | } |
| 2372 | 2516 | ||
| @@ -2570,12 +2714,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes); | |||
| 2570 | */ | 2714 | */ |
| 2571 | int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | 2715 | int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) |
| 2572 | { | 2716 | { |
| 2717 | struct snd_soc_card *card = dapm->card; | ||
| 2573 | struct snd_soc_dapm_widget *w; | 2718 | struct snd_soc_dapm_widget *w; |
| 2574 | unsigned int val; | 2719 | unsigned int val; |
| 2575 | 2720 | ||
| 2576 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | 2721 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); |
| 2577 | 2722 | ||
| 2578 | list_for_each_entry(w, &dapm->card->widgets, list) | 2723 | list_for_each_entry(w, &card->widgets, list) |
| 2579 | { | 2724 | { |
| 2580 | if (w->new) | 2725 | if (w->new) |
| 2581 | continue; | 2726 | continue; |
| @@ -2585,7 +2730,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
| 2585 | sizeof(struct snd_kcontrol *), | 2730 | sizeof(struct snd_kcontrol *), |
| 2586 | GFP_KERNEL); | 2731 | GFP_KERNEL); |
| 2587 | if (!w->kcontrols) { | 2732 | if (!w->kcontrols) { |
| 2588 | mutex_unlock(&dapm->card->dapm_mutex); | 2733 | mutex_unlock(&card->dapm_mutex); |
| 2589 | return -ENOMEM; | 2734 | return -ENOMEM; |
| 2590 | } | 2735 | } |
| 2591 | } | 2736 | } |
| @@ -2611,12 +2756,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
| 2611 | 2756 | ||
| 2612 | /* Read the initial power state from the device */ | 2757 | /* Read the initial power state from the device */ |
| 2613 | if (w->reg >= 0) { | 2758 | if (w->reg >= 0) { |
| 2614 | val = soc_widget_read(w, w->reg); | 2759 | val = soc_widget_read(w, w->reg) >> w->shift; |
| 2615 | val &= 1 << w->shift; | 2760 | val &= w->mask; |
| 2616 | if (w->invert) | 2761 | if (val == w->on_val) |
| 2617 | val = !val; | ||
| 2618 | |||
| 2619 | if (val) | ||
| 2620 | w->power = 1; | 2762 | w->power = 1; |
| 2621 | } | 2763 | } |
| 2622 | 2764 | ||
| @@ -2626,8 +2768,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
| 2626 | dapm_debugfs_add_widget(w); | 2768 | dapm_debugfs_add_widget(w); |
| 2627 | } | 2769 | } |
| 2628 | 2770 | ||
| 2629 | dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); | 2771 | dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); |
| 2630 | mutex_unlock(&dapm->card->dapm_mutex); | 2772 | mutex_unlock(&card->dapm_mutex); |
| 2631 | return 0; | 2773 | return 0; |
| 2632 | } | 2774 | } |
| 2633 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | 2775 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); |
| @@ -2644,8 +2786,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | |||
| 2644 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | 2786 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
| 2645 | struct snd_ctl_elem_value *ucontrol) | 2787 | struct snd_ctl_elem_value *ucontrol) |
| 2646 | { | 2788 | { |
| 2647 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2789 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2648 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | 2790 | struct snd_soc_card *card = codec->card; |
| 2649 | struct soc_mixer_control *mc = | 2791 | struct soc_mixer_control *mc = |
| 2650 | (struct soc_mixer_control *)kcontrol->private_value; | 2792 | (struct soc_mixer_control *)kcontrol->private_value; |
| 2651 | unsigned int reg = mc->reg; | 2793 | unsigned int reg = mc->reg; |
| @@ -2653,17 +2795,24 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
| 2653 | int max = mc->max; | 2795 | int max = mc->max; |
| 2654 | unsigned int mask = (1 << fls(max)) - 1; | 2796 | unsigned int mask = (1 << fls(max)) - 1; |
| 2655 | unsigned int invert = mc->invert; | 2797 | unsigned int invert = mc->invert; |
| 2798 | unsigned int val; | ||
| 2656 | 2799 | ||
| 2657 | if (snd_soc_volsw_is_stereo(mc)) | 2800 | if (snd_soc_volsw_is_stereo(mc)) |
| 2658 | dev_warn(widget->dapm->dev, | 2801 | dev_warn(codec->dapm.dev, |
| 2659 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2802 | "ASoC: Control '%s' is stereo, which is not supported\n", |
| 2660 | kcontrol->id.name); | 2803 | kcontrol->id.name); |
| 2661 | 2804 | ||
| 2662 | ucontrol->value.integer.value[0] = | 2805 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2663 | (snd_soc_read(widget->codec, reg) >> shift) & mask; | 2806 | if (dapm_kcontrol_is_powered(kcontrol)) |
| 2807 | val = (snd_soc_read(codec, reg) >> shift) & mask; | ||
| 2808 | else | ||
| 2809 | val = dapm_kcontrol_get_value(kcontrol); | ||
| 2810 | mutex_unlock(&card->dapm_mutex); | ||
| 2811 | |||
| 2664 | if (invert) | 2812 | if (invert) |
| 2665 | ucontrol->value.integer.value[0] = | 2813 | ucontrol->value.integer.value[0] = max - val; |
| 2666 | max - ucontrol->value.integer.value[0]; | 2814 | else |
| 2815 | ucontrol->value.integer.value[0] = val; | ||
| 2667 | 2816 | ||
| 2668 | return 0; | 2817 | return 0; |
| 2669 | } | 2818 | } |
| @@ -2681,9 +2830,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | |||
| 2681 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 2830 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
| 2682 | struct snd_ctl_elem_value *ucontrol) | 2831 | struct snd_ctl_elem_value *ucontrol) |
| 2683 | { | 2832 | { |
| 2684 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2833 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2685 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2686 | struct snd_soc_codec *codec = widget->codec; | ||
| 2687 | struct snd_soc_card *card = codec->card; | 2834 | struct snd_soc_card *card = codec->card; |
| 2688 | struct soc_mixer_control *mc = | 2835 | struct soc_mixer_control *mc = |
| 2689 | (struct soc_mixer_control *)kcontrol->private_value; | 2836 | (struct soc_mixer_control *)kcontrol->private_value; |
| @@ -2695,10 +2842,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
| 2695 | unsigned int val; | 2842 | unsigned int val; |
| 2696 | int connect, change; | 2843 | int connect, change; |
| 2697 | struct snd_soc_dapm_update update; | 2844 | struct snd_soc_dapm_update update; |
| 2698 | int wi; | ||
| 2699 | 2845 | ||
| 2700 | if (snd_soc_volsw_is_stereo(mc)) | 2846 | if (snd_soc_volsw_is_stereo(mc)) |
| 2701 | dev_warn(widget->dapm->dev, | 2847 | dev_warn(codec->dapm.dev, |
| 2702 | "ASoC: Control '%s' is stereo, which is not supported\n", | 2848 | "ASoC: Control '%s' is stereo, which is not supported\n", |
| 2703 | kcontrol->id.name); | 2849 | kcontrol->id.name); |
| 2704 | 2850 | ||
| @@ -2707,29 +2853,26 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
| 2707 | 2853 | ||
| 2708 | if (invert) | 2854 | if (invert) |
| 2709 | val = max - val; | 2855 | val = max - val; |
| 2710 | mask = mask << shift; | ||
| 2711 | val = val << shift; | ||
| 2712 | 2856 | ||
| 2713 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2857 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2714 | 2858 | ||
| 2715 | change = snd_soc_test_bits(widget->codec, reg, mask, val); | 2859 | dapm_kcontrol_set_value(kcontrol, val); |
| 2716 | if (change) { | ||
| 2717 | for (wi = 0; wi < wlist->num_widgets; wi++) { | ||
| 2718 | widget = wlist->widgets[wi]; | ||
| 2719 | 2860 | ||
| 2720 | widget->value = val; | 2861 | mask = mask << shift; |
| 2862 | val = val << shift; | ||
| 2721 | 2863 | ||
| 2722 | update.kcontrol = kcontrol; | 2864 | change = snd_soc_test_bits(codec, reg, mask, val); |
| 2723 | update.widget = widget; | 2865 | if (change) { |
| 2724 | update.reg = reg; | 2866 | update.kcontrol = kcontrol; |
| 2725 | update.mask = mask; | 2867 | update.reg = reg; |
| 2726 | update.val = val; | 2868 | update.mask = mask; |
| 2727 | widget->dapm->update = &update; | 2869 | update.val = val; |
| 2728 | 2870 | ||
| 2729 | soc_dapm_mixer_update_power(widget, kcontrol, connect); | 2871 | card->update = &update; |
| 2730 | 2872 | ||
| 2731 | widget->dapm->update = NULL; | 2873 | soc_dapm_mixer_update_power(card, kcontrol, connect); |
| 2732 | } | 2874 | |
| 2875 | card->update = NULL; | ||
| 2733 | } | 2876 | } |
| 2734 | 2877 | ||
| 2735 | mutex_unlock(&card->dapm_mutex); | 2878 | mutex_unlock(&card->dapm_mutex); |
| @@ -2749,12 +2892,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | |||
| 2749 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | 2892 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, |
| 2750 | struct snd_ctl_elem_value *ucontrol) | 2893 | struct snd_ctl_elem_value *ucontrol) |
| 2751 | { | 2894 | { |
| 2752 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2895 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2753 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2754 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2896 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2755 | unsigned int val; | 2897 | unsigned int val; |
| 2756 | 2898 | ||
| 2757 | val = snd_soc_read(widget->codec, e->reg); | 2899 | val = snd_soc_read(codec, e->reg); |
| 2758 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; | 2900 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; |
| 2759 | if (e->shift_l != e->shift_r) | 2901 | if (e->shift_l != e->shift_r) |
| 2760 | ucontrol->value.enumerated.item[1] = | 2902 | ucontrol->value.enumerated.item[1] = |
| @@ -2776,15 +2918,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | |||
| 2776 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 2918 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
| 2777 | struct snd_ctl_elem_value *ucontrol) | 2919 | struct snd_ctl_elem_value *ucontrol) |
| 2778 | { | 2920 | { |
| 2779 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2921 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2780 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2781 | struct snd_soc_codec *codec = widget->codec; | ||
| 2782 | struct snd_soc_card *card = codec->card; | 2922 | struct snd_soc_card *card = codec->card; |
| 2783 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2923 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2784 | unsigned int val, mux, change; | 2924 | unsigned int val, mux, change; |
| 2785 | unsigned int mask; | 2925 | unsigned int mask; |
| 2786 | struct snd_soc_dapm_update update; | 2926 | struct snd_soc_dapm_update update; |
| 2787 | int wi; | ||
| 2788 | 2927 | ||
| 2789 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2928 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 2790 | return -EINVAL; | 2929 | return -EINVAL; |
| @@ -2800,24 +2939,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2800 | 2939 | ||
| 2801 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2940 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2802 | 2941 | ||
| 2803 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2942 | change = snd_soc_test_bits(codec, e->reg, mask, val); |
| 2804 | if (change) { | 2943 | if (change) { |
| 2805 | for (wi = 0; wi < wlist->num_widgets; wi++) { | 2944 | update.kcontrol = kcontrol; |
| 2806 | widget = wlist->widgets[wi]; | 2945 | update.reg = e->reg; |
| 2946 | update.mask = mask; | ||
| 2947 | update.val = val; | ||
| 2948 | card->update = &update; | ||
| 2807 | 2949 | ||
| 2808 | widget->value = val; | 2950 | soc_dapm_mux_update_power(card, kcontrol, mux, e); |
| 2809 | 2951 | ||
| 2810 | update.kcontrol = kcontrol; | 2952 | card->update = NULL; |
| 2811 | update.widget = widget; | ||
| 2812 | update.reg = e->reg; | ||
| 2813 | update.mask = mask; | ||
| 2814 | update.val = val; | ||
| 2815 | widget->dapm->update = &update; | ||
| 2816 | |||
| 2817 | soc_dapm_mux_update_power(widget, kcontrol, mux, e); | ||
| 2818 | |||
| 2819 | widget->dapm->update = NULL; | ||
| 2820 | } | ||
| 2821 | } | 2953 | } |
| 2822 | 2954 | ||
| 2823 | mutex_unlock(&card->dapm_mutex); | 2955 | mutex_unlock(&card->dapm_mutex); |
| @@ -2835,11 +2967,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | |||
| 2835 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, | 2967 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, |
| 2836 | struct snd_ctl_elem_value *ucontrol) | 2968 | struct snd_ctl_elem_value *ucontrol) |
| 2837 | { | 2969 | { |
| 2838 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2970 | ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); |
| 2839 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2840 | |||
| 2841 | ucontrol->value.enumerated.item[0] = widget->value; | ||
| 2842 | |||
| 2843 | return 0; | 2971 | return 0; |
| 2844 | } | 2972 | } |
| 2845 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); | 2973 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); |
| @@ -2854,30 +2982,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); | |||
| 2854 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | 2982 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, |
| 2855 | struct snd_ctl_elem_value *ucontrol) | 2983 | struct snd_ctl_elem_value *ucontrol) |
| 2856 | { | 2984 | { |
| 2857 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2985 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2858 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2859 | struct snd_soc_codec *codec = widget->codec; | ||
| 2860 | struct snd_soc_card *card = codec->card; | 2986 | struct snd_soc_card *card = codec->card; |
| 2987 | unsigned int value; | ||
| 2861 | struct soc_enum *e = | 2988 | struct soc_enum *e = |
| 2862 | (struct soc_enum *)kcontrol->private_value; | 2989 | (struct soc_enum *)kcontrol->private_value; |
| 2863 | int change; | 2990 | int change; |
| 2864 | int wi; | ||
| 2865 | 2991 | ||
| 2866 | if (ucontrol->value.enumerated.item[0] >= e->max) | 2992 | if (ucontrol->value.enumerated.item[0] >= e->max) |
| 2867 | return -EINVAL; | 2993 | return -EINVAL; |
| 2868 | 2994 | ||
| 2869 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2995 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2870 | 2996 | ||
| 2871 | change = widget->value != ucontrol->value.enumerated.item[0]; | 2997 | value = ucontrol->value.enumerated.item[0]; |
| 2872 | if (change) { | 2998 | change = dapm_kcontrol_set_value(kcontrol, value); |
| 2873 | for (wi = 0; wi < wlist->num_widgets; wi++) { | 2999 | if (change) |
| 2874 | widget = wlist->widgets[wi]; | 3000 | soc_dapm_mux_update_power(card, kcontrol, value, e); |
| 2875 | |||
| 2876 | widget->value = ucontrol->value.enumerated.item[0]; | ||
| 2877 | |||
| 2878 | soc_dapm_mux_update_power(widget, kcontrol, widget->value, e); | ||
| 2879 | } | ||
| 2880 | } | ||
| 2881 | 3001 | ||
| 2882 | mutex_unlock(&card->dapm_mutex); | 3002 | mutex_unlock(&card->dapm_mutex); |
| 2883 | return change; | 3003 | return change; |
| @@ -2900,12 +3020,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | |||
| 2900 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, | 3020 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, |
| 2901 | struct snd_ctl_elem_value *ucontrol) | 3021 | struct snd_ctl_elem_value *ucontrol) |
| 2902 | { | 3022 | { |
| 2903 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 3023 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2904 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2905 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 3024 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2906 | unsigned int reg_val, val, mux; | 3025 | unsigned int reg_val, val, mux; |
| 2907 | 3026 | ||
| 2908 | reg_val = snd_soc_read(widget->codec, e->reg); | 3027 | reg_val = snd_soc_read(codec, e->reg); |
| 2909 | val = (reg_val >> e->shift_l) & e->mask; | 3028 | val = (reg_val >> e->shift_l) & e->mask; |
| 2910 | for (mux = 0; mux < e->max; mux++) { | 3029 | for (mux = 0; mux < e->max; mux++) { |
| 2911 | if (val == e->values[mux]) | 3030 | if (val == e->values[mux]) |
| @@ -2941,15 +3060,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); | |||
| 2941 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | 3060 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, |
| 2942 | struct snd_ctl_elem_value *ucontrol) | 3061 | struct snd_ctl_elem_value *ucontrol) |
| 2943 | { | 3062 | { |
| 2944 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 3063 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
| 2945 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
| 2946 | struct snd_soc_codec *codec = widget->codec; | ||
| 2947 | struct snd_soc_card *card = codec->card; | 3064 | struct snd_soc_card *card = codec->card; |
| 2948 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 3065 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2949 | unsigned int val, mux, change; | 3066 | unsigned int val, mux, change; |
| 2950 | unsigned int mask; | 3067 | unsigned int mask; |
| 2951 | struct snd_soc_dapm_update update; | 3068 | struct snd_soc_dapm_update update; |
| 2952 | int wi; | ||
| 2953 | 3069 | ||
| 2954 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 3070 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 2955 | return -EINVAL; | 3071 | return -EINVAL; |
| @@ -2965,24 +3081,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2965 | 3081 | ||
| 2966 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 3082 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
| 2967 | 3083 | ||
| 2968 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 3084 | change = snd_soc_test_bits(codec, e->reg, mask, val); |
| 2969 | if (change) { | 3085 | if (change) { |
| 2970 | for (wi = 0; wi < wlist->num_widgets; wi++) { | 3086 | update.kcontrol = kcontrol; |
| 2971 | widget = wlist->widgets[wi]; | 3087 | update.reg = e->reg; |
| 2972 | 3088 | update.mask = mask; | |
| 2973 | widget->value = val; | 3089 | update.val = val; |
| 3090 | card->update = &update; | ||
| 2974 | 3091 | ||
| 2975 | update.kcontrol = kcontrol; | 3092 | soc_dapm_mux_update_power(card, kcontrol, mux, e); |
| 2976 | update.widget = widget; | ||
| 2977 | update.reg = e->reg; | ||
| 2978 | update.mask = mask; | ||
| 2979 | update.val = val; | ||
| 2980 | widget->dapm->update = &update; | ||
| 2981 | 3093 | ||
| 2982 | soc_dapm_mux_update_power(widget, kcontrol, mux, e); | 3094 | card->update = NULL; |
| 2983 | |||
| 2984 | widget->dapm->update = NULL; | ||
| 2985 | } | ||
| 2986 | } | 3095 | } |
| 2987 | 3096 | ||
| 2988 | mutex_unlock(&card->dapm_mutex); | 3097 | mutex_unlock(&card->dapm_mutex); |
| @@ -3079,7 +3188,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
| 3079 | return NULL; | 3188 | return NULL; |
| 3080 | } | 3189 | } |
| 3081 | 3190 | ||
| 3082 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | 3191 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { |
| 3083 | ret = regulator_allow_bypass(w->regulator, true); | 3192 | ret = regulator_allow_bypass(w->regulator, true); |
| 3084 | if (ret != 0) | 3193 | if (ret != 0) |
| 3085 | dev_warn(w->dapm->dev, | 3194 | dev_warn(w->dapm->dev, |
| @@ -3126,16 +3235,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
| 3126 | case snd_soc_dapm_value_mux: | 3235 | case snd_soc_dapm_value_mux: |
| 3127 | w->power_check = dapm_generic_check_power; | 3236 | w->power_check = dapm_generic_check_power; |
| 3128 | break; | 3237 | break; |
| 3129 | case snd_soc_dapm_adc: | ||
| 3130 | case snd_soc_dapm_aif_out: | ||
| 3131 | case snd_soc_dapm_dai_out: | 3238 | case snd_soc_dapm_dai_out: |
| 3132 | w->power_check = dapm_adc_check_power; | 3239 | w->power_check = dapm_adc_check_power; |
| 3133 | break; | 3240 | break; |
| 3134 | case snd_soc_dapm_dac: | ||
| 3135 | case snd_soc_dapm_aif_in: | ||
| 3136 | case snd_soc_dapm_dai_in: | 3241 | case snd_soc_dapm_dai_in: |
| 3137 | w->power_check = dapm_dac_check_power; | 3242 | w->power_check = dapm_dac_check_power; |
| 3138 | break; | 3243 | break; |
| 3244 | case snd_soc_dapm_adc: | ||
| 3245 | case snd_soc_dapm_aif_out: | ||
| 3246 | case snd_soc_dapm_dac: | ||
| 3247 | case snd_soc_dapm_aif_in: | ||
| 3139 | case snd_soc_dapm_pga: | 3248 | case snd_soc_dapm_pga: |
| 3140 | case snd_soc_dapm_out_drv: | 3249 | case snd_soc_dapm_out_drv: |
| 3141 | case snd_soc_dapm_input: | 3250 | case snd_soc_dapm_input: |
| @@ -3151,6 +3260,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
| 3151 | case snd_soc_dapm_supply: | 3260 | case snd_soc_dapm_supply: |
| 3152 | case snd_soc_dapm_regulator_supply: | 3261 | case snd_soc_dapm_regulator_supply: |
| 3153 | case snd_soc_dapm_clock_supply: | 3262 | case snd_soc_dapm_clock_supply: |
| 3263 | case snd_soc_dapm_kcontrol: | ||
| 3154 | w->power_check = dapm_supply_check_power; | 3264 | w->power_check = dapm_supply_check_power; |
| 3155 | break; | 3265 | break; |
| 3156 | default: | 3266 | default: |
| @@ -3415,9 +3525,6 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
| 3415 | { | 3525 | { |
| 3416 | struct snd_soc_dapm_widget *dai_w, *w; | 3526 | struct snd_soc_dapm_widget *dai_w, *w; |
| 3417 | struct snd_soc_dai *dai; | 3527 | struct snd_soc_dai *dai; |
| 3418 | struct snd_soc_dapm_route r; | ||
| 3419 | |||
| 3420 | memset(&r, 0, sizeof(r)); | ||
| 3421 | 3528 | ||
| 3422 | /* For each DAI widget... */ | 3529 | /* For each DAI widget... */ |
| 3423 | list_for_each_entry(dai_w, &card->widgets, list) { | 3530 | list_for_each_entry(dai_w, &card->widgets, list) { |
| @@ -3444,29 +3551,27 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) | |||
| 3444 | break; | 3551 | break; |
| 3445 | } | 3552 | } |
| 3446 | 3553 | ||
| 3447 | if (!w->sname) | 3554 | if (!w->sname || !strstr(w->sname, dai_w->name)) |
| 3448 | continue; | 3555 | continue; |
| 3449 | 3556 | ||
| 3450 | if (dai->driver->playback.stream_name && | 3557 | if (dai->driver->playback.stream_name && |
| 3451 | strstr(w->sname, | 3558 | strstr(w->sname, |
| 3452 | dai->driver->playback.stream_name)) { | 3559 | dai->driver->playback.stream_name)) { |
| 3453 | r.source = dai->playback_widget->name; | ||
| 3454 | r.sink = w->name; | ||
| 3455 | dev_dbg(dai->dev, "%s -> %s\n", | 3560 | dev_dbg(dai->dev, "%s -> %s\n", |
| 3456 | r.source, r.sink); | 3561 | dai->playback_widget->name, w->name); |
| 3457 | 3562 | ||
| 3458 | snd_soc_dapm_add_route(w->dapm, &r); | 3563 | snd_soc_dapm_add_path(w->dapm, |
| 3564 | dai->playback_widget, w, NULL, NULL); | ||
| 3459 | } | 3565 | } |
| 3460 | 3566 | ||
| 3461 | if (dai->driver->capture.stream_name && | 3567 | if (dai->driver->capture.stream_name && |
| 3462 | strstr(w->sname, | 3568 | strstr(w->sname, |
| 3463 | dai->driver->capture.stream_name)) { | 3569 | dai->driver->capture.stream_name)) { |
| 3464 | r.source = w->name; | ||
| 3465 | r.sink = dai->capture_widget->name; | ||
| 3466 | dev_dbg(dai->dev, "%s -> %s\n", | 3570 | dev_dbg(dai->dev, "%s -> %s\n", |
| 3467 | r.source, r.sink); | 3571 | w->name, dai->capture_widget->name); |
| 3468 | 3572 | ||
| 3469 | snd_soc_dapm_add_route(w->dapm, &r); | 3573 | snd_soc_dapm_add_path(w->dapm, w, |
| 3574 | dai->capture_widget, NULL, NULL); | ||
| 3470 | } | 3575 | } |
| 3471 | } | 3576 | } |
| 3472 | } | 3577 | } |
| @@ -3528,7 +3633,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | |||
| 3528 | } | 3633 | } |
| 3529 | } | 3634 | } |
| 3530 | 3635 | ||
| 3531 | dapm_power_widgets(&rtd->card->dapm, event); | 3636 | dapm_power_widgets(rtd->card, event); |
| 3532 | } | 3637 | } |
| 3533 | 3638 | ||
| 3534 | /** | 3639 | /** |
| @@ -3797,7 +3902,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
| 3797 | if (dapm->bias_level == SND_SOC_BIAS_ON) | 3902 | if (dapm->bias_level == SND_SOC_BIAS_ON) |
| 3798 | snd_soc_dapm_set_bias_level(dapm, | 3903 | snd_soc_dapm_set_bias_level(dapm, |
| 3799 | SND_SOC_BIAS_PREPARE); | 3904 | SND_SOC_BIAS_PREPARE); |
| 3800 | dapm_seq_run(dapm, &down_list, 0, false); | 3905 | dapm_seq_run(card, &down_list, 0, false); |
| 3801 | if (dapm->bias_level == SND_SOC_BIAS_PREPARE) | 3906 | if (dapm->bias_level == SND_SOC_BIAS_PREPARE) |
| 3802 | snd_soc_dapm_set_bias_level(dapm, | 3907 | snd_soc_dapm_set_bias_level(dapm, |
| 3803 | SND_SOC_BIAS_STANDBY); | 3908 | SND_SOC_BIAS_STANDBY); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 0bb5cccd7766..7aa26b5178aa 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
| @@ -263,7 +263,7 @@ static irqreturn_t gpio_handler(int irq, void *data) | |||
| 263 | if (device_may_wakeup(dev)) | 263 | if (device_may_wakeup(dev)) |
| 264 | pm_wakeup_event(dev, gpio->debounce_time + 50); | 264 | pm_wakeup_event(dev, gpio->debounce_time + 50); |
| 265 | 265 | ||
| 266 | schedule_delayed_work(&gpio->work, | 266 | queue_delayed_work(system_power_efficient_wq, &gpio->work, |
| 267 | msecs_to_jiffies(gpio->debounce_time)); | 267 | msecs_to_jiffies(gpio->debounce_time)); |
| 268 | 268 | ||
| 269 | return IRQ_HANDLED; | 269 | return IRQ_HANDLED; |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b6c640332a17..fb70fbe26862 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
| @@ -411,8 +411,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
| 411 | } else { | 411 | } else { |
| 412 | /* start delayed pop wq here for playback streams */ | 412 | /* start delayed pop wq here for playback streams */ |
| 413 | rtd->pop_wait = 1; | 413 | rtd->pop_wait = 1; |
| 414 | schedule_delayed_work(&rtd->delayed_work, | 414 | queue_delayed_work(system_power_efficient_wq, |
| 415 | msecs_to_jiffies(rtd->pmdown_time)); | 415 | &rtd->delayed_work, |
| 416 | msecs_to_jiffies(rtd->pmdown_time)); | ||
| 416 | } | 417 | } |
| 417 | } else { | 418 | } else { |
| 418 | /* capture streams can be powered down now */ | 419 | /* capture streams can be powered down now */ |
| @@ -1832,18 +1833,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) | |||
| 1832 | /* Called by DAPM mixer/mux changes to update audio routing between PCMs and | 1833 | /* Called by DAPM mixer/mux changes to update audio routing between PCMs and |
| 1833 | * any DAI links. | 1834 | * any DAI links. |
| 1834 | */ | 1835 | */ |
| 1835 | int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget) | 1836 | int soc_dpcm_runtime_update(struct snd_soc_card *card) |
| 1836 | { | 1837 | { |
| 1837 | struct snd_soc_card *card; | ||
| 1838 | int i, old, new, paths; | 1838 | int i, old, new, paths; |
| 1839 | 1839 | ||
| 1840 | if (widget->codec) | ||
| 1841 | card = widget->codec->card; | ||
| 1842 | else if (widget->platform) | ||
| 1843 | card = widget->platform->card; | ||
| 1844 | else | ||
| 1845 | return -EINVAL; | ||
| 1846 | |||
| 1847 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | 1840 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); |
| 1848 | for (i = 0; i < card->num_rtd; i++) { | 1841 | for (i = 0; i < card->num_rtd; i++) { |
| 1849 | struct snd_soc_dapm_widget_list *list; | 1842 | struct snd_soc_dapm_widget_list *list; |
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig index 3567d73b218e..0a53053495f3 100644 --- a/sound/soc/spear/Kconfig +++ b/sound/soc/spear/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config SND_SPEAR_SOC | 1 | config SND_SPEAR_SOC |
| 2 | tristate | 2 | tristate |
| 3 | select SND_SOC_DMAENGINE_PCM | 3 | select SND_DMAENGINE_PCM |
| 4 | 4 | ||
| 5 | config SND_SPEAR_SPDIF_OUT | 5 | config SND_SPEAR_SPDIF_OUT |
| 6 | tristate | 6 | tristate |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 995b120c2cd0..8fc653ca3ab4 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | config SND_SOC_TEGRA | 1 | config SND_SOC_TEGRA |
| 2 | tristate "SoC Audio for the Tegra System-on-Chip" | 2 | tristate "SoC Audio for the Tegra System-on-Chip" |
| 3 | depends on ARCH_TEGRA && TEGRA20_APB_DMA | 3 | depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST |
| 4 | select REGMAP_MMIO | 4 | select REGMAP_MMIO |
| 5 | select SND_SOC_GENERIC_DMAENGINE_PCM if TEGRA20_APB_DMA | 5 | select SND_SOC_GENERIC_DMAENGINE_PCM |
| 6 | help | 6 | help |
| 7 | Say Y or M here if you want support for SoC audio on Tegra. | 7 | Say Y or M here if you want support for SoC audio on Tegra. |
| 8 | 8 | ||
| @@ -61,7 +61,7 @@ config SND_SOC_TEGRA30_I2S | |||
| 61 | 61 | ||
| 62 | config SND_SOC_TEGRA_RT5640 | 62 | config SND_SOC_TEGRA_RT5640 |
| 63 | tristate "SoC Audio support for Tegra boards using an RT5640 codec" | 63 | tristate "SoC Audio support for Tegra boards using an RT5640 codec" |
| 64 | depends on SND_SOC_TEGRA && I2C | 64 | depends on SND_SOC_TEGRA && I2C && GPIOLIB |
| 65 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 65 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
| 66 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | 66 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC |
| 67 | select SND_SOC_RT5640 | 67 | select SND_SOC_RT5640 |
| @@ -71,7 +71,7 @@ config SND_SOC_TEGRA_RT5640 | |||
| 71 | 71 | ||
| 72 | config SND_SOC_TEGRA_WM8753 | 72 | config SND_SOC_TEGRA_WM8753 |
| 73 | tristate "SoC Audio support for Tegra boards using a WM8753 codec" | 73 | tristate "SoC Audio support for Tegra boards using a WM8753 codec" |
| 74 | depends on SND_SOC_TEGRA && I2C | 74 | depends on SND_SOC_TEGRA && I2C && GPIOLIB |
| 75 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 75 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
| 76 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | 76 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC |
| 77 | select SND_SOC_WM8753 | 77 | select SND_SOC_WM8753 |
| @@ -81,7 +81,7 @@ config SND_SOC_TEGRA_WM8753 | |||
| 81 | 81 | ||
| 82 | config SND_SOC_TEGRA_WM8903 | 82 | config SND_SOC_TEGRA_WM8903 |
| 83 | tristate "SoC Audio support for Tegra boards using a WM8903 codec" | 83 | tristate "SoC Audio support for Tegra boards using a WM8903 codec" |
| 84 | depends on SND_SOC_TEGRA && I2C | 84 | depends on SND_SOC_TEGRA && I2C && GPIOLIB |
| 85 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 85 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
| 86 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | 86 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC |
| 87 | select SND_SOC_WM8903 | 87 | select SND_SOC_WM8903 |
| @@ -92,7 +92,7 @@ config SND_SOC_TEGRA_WM8903 | |||
| 92 | 92 | ||
| 93 | config SND_SOC_TEGRA_WM9712 | 93 | config SND_SOC_TEGRA_WM9712 |
| 94 | tristate "SoC Audio support for Tegra boards using a WM9712 codec" | 94 | tristate "SoC Audio support for Tegra boards using a WM9712 codec" |
| 95 | depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC | 95 | depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC && GPIOLIB |
| 96 | select SND_SOC_TEGRA20_AC97 | 96 | select SND_SOC_TEGRA20_AC97 |
| 97 | select SND_SOC_WM9712 | 97 | select SND_SOC_WM9712 |
| 98 | help | 98 | help |
| @@ -110,7 +110,7 @@ config SND_SOC_TEGRA_TRIMSLICE | |||
| 110 | 110 | ||
| 111 | config SND_SOC_TEGRA_ALC5632 | 111 | config SND_SOC_TEGRA_ALC5632 |
| 112 | tristate "SoC Audio support for Tegra boards using an ALC5632 codec" | 112 | tristate "SoC Audio support for Tegra boards using an ALC5632 codec" |
| 113 | depends on SND_SOC_TEGRA && I2C | 113 | depends on SND_SOC_TEGRA && I2C && GPIOLIB |
| 114 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 114 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
| 115 | select SND_SOC_ALC5632 | 115 | select SND_SOC_ALC5632 |
| 116 | help | 116 | help |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 6c486625321b..ae27bcd586d2 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
| @@ -334,12 +334,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 336 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 337 | if (!mem) { | ||
| 338 | dev_err(&pdev->dev, "No memory resource\n"); | ||
| 339 | ret = -ENODEV; | ||
| 340 | goto err_clk_put; | ||
| 341 | } | ||
| 342 | |||
| 343 | regs = devm_ioremap_resource(&pdev->dev, mem); | 337 | regs = devm_ioremap_resource(&pdev->dev, mem); |
| 344 | if (IS_ERR(regs)) { | 338 | if (IS_ERR(regs)) { |
| 345 | ret = PTR_ERR(regs); | 339 | ret = PTR_ERR(regs); |
| @@ -432,8 +426,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
| 432 | 426 | ||
| 433 | return 0; | 427 | return 0; |
| 434 | 428 | ||
| 435 | err_unregister_pcm: | ||
| 436 | tegra_pcm_platform_unregister(&pdev->dev); | ||
| 437 | err_unregister_component: | 429 | err_unregister_component: |
| 438 | snd_soc_unregister_component(&pdev->dev); | 430 | snd_soc_unregister_component(&pdev->dev); |
| 439 | err_asoc_utils_fini: | 431 | err_asoc_utils_fini: |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index d04146cad61f..47565fd04505 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
| @@ -228,7 +228,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
| 228 | reg = TEGRA30_I2S_CIF_RX_CTRL; | 228 | reg = TEGRA30_I2S_CIF_RX_CTRL; |
| 229 | } else { | 229 | } else { |
| 230 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; | 230 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; |
| 231 | reg = TEGRA30_I2S_CIF_RX_CTRL; | 231 | reg = TEGRA30_I2S_CIF_TX_CTRL; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | regmap_write(i2s->regmap, reg, val); | 234 | regmap_write(i2s->regmap, reg, val); |
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 48d05d9e1002..c61ea3a1030f 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c | |||
| @@ -13,8 +13,6 @@ | |||
| 13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <asm/mach-types.h> | ||
| 17 | |||
| 18 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 19 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 20 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 08794f915a94..4511c5a875ec 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c | |||
| @@ -99,6 +99,7 @@ static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = { | |||
| 99 | static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = { | 99 | static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = { |
| 100 | SND_SOC_DAPM_HP("Headphones", NULL), | 100 | SND_SOC_DAPM_HP("Headphones", NULL), |
| 101 | SND_SOC_DAPM_SPK("Speakers", NULL), | 101 | SND_SOC_DAPM_SPK("Speakers", NULL), |
| 102 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | static const struct snd_kcontrol_new tegra_rt5640_controls[] = { | 105 | static const struct snd_kcontrol_new tegra_rt5640_controls[] = { |
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index f87fc53e9b8c..8e774d1a243c 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c | |||
| @@ -28,8 +28,6 @@ | |||
| 28 | * | 28 | * |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <asm/mach-types.h> | ||
| 32 | |||
| 33 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 34 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 35 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 05c68aab5cf0..734bfcd21148 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c | |||
| @@ -24,8 +24,6 @@ | |||
| 24 | * | 24 | * |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <asm/mach-types.h> | ||
| 28 | |||
| 29 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 30 | #include <linux/of.h> | 28 | #include <linux/of.h> |
| 31 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c index 9e6e3ffd86bb..23452ee617e1 100644 --- a/sound/usb/6fire/comm.c +++ b/sound/usb/6fire/comm.c | |||
| @@ -110,19 +110,37 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev) | |||
| 110 | static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request, | 110 | static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request, |
| 111 | u8 reg, u8 value) | 111 | u8 reg, u8 value) |
| 112 | { | 112 | { |
| 113 | u8 buffer[13]; /* 13: maximum length of message */ | 113 | u8 *buffer; |
| 114 | int ret; | ||
| 115 | |||
| 116 | /* 13: maximum length of message */ | ||
| 117 | buffer = kmalloc(13, GFP_KERNEL); | ||
| 118 | if (!buffer) | ||
| 119 | return -ENOMEM; | ||
| 114 | 120 | ||
| 115 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00); | 121 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00); |
| 116 | return usb6fire_comm_send_buffer(buffer, rt->chip->dev); | 122 | ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev); |
| 123 | |||
| 124 | kfree(buffer); | ||
| 125 | return ret; | ||
| 117 | } | 126 | } |
| 118 | 127 | ||
| 119 | static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request, | 128 | static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request, |
| 120 | u8 reg, u8 vl, u8 vh) | 129 | u8 reg, u8 vl, u8 vh) |
| 121 | { | 130 | { |
| 122 | u8 buffer[13]; /* 13: maximum length of message */ | 131 | u8 *buffer; |
| 132 | int ret; | ||
| 133 | |||
| 134 | /* 13: maximum length of message */ | ||
| 135 | buffer = kmalloc(13, GFP_KERNEL); | ||
| 136 | if (!buffer) | ||
| 137 | return -ENOMEM; | ||
| 123 | 138 | ||
| 124 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh); | 139 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh); |
| 125 | return usb6fire_comm_send_buffer(buffer, rt->chip->dev); | 140 | ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev); |
| 141 | |||
| 142 | kfree(buffer); | ||
| 143 | return ret; | ||
| 126 | } | 144 | } |
| 127 | 145 | ||
| 128 | int usb6fire_comm_init(struct sfire_chip *chip) | 146 | int usb6fire_comm_init(struct sfire_chip *chip) |
| @@ -135,6 +153,12 @@ int usb6fire_comm_init(struct sfire_chip *chip) | |||
| 135 | if (!rt) | 153 | if (!rt) |
| 136 | return -ENOMEM; | 154 | return -ENOMEM; |
| 137 | 155 | ||
| 156 | rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL); | ||
| 157 | if (!rt->receiver_buffer) { | ||
| 158 | kfree(rt); | ||
| 159 | return -ENOMEM; | ||
| 160 | } | ||
| 161 | |||
| 138 | urb = &rt->receiver; | 162 | urb = &rt->receiver; |
| 139 | rt->serial = 1; | 163 | rt->serial = 1; |
| 140 | rt->chip = chip; | 164 | rt->chip = chip; |
| @@ -153,6 +177,7 @@ int usb6fire_comm_init(struct sfire_chip *chip) | |||
| 153 | urb->interval = 1; | 177 | urb->interval = 1; |
| 154 | ret = usb_submit_urb(urb, GFP_KERNEL); | 178 | ret = usb_submit_urb(urb, GFP_KERNEL); |
| 155 | if (ret < 0) { | 179 | if (ret < 0) { |
| 180 | kfree(rt->receiver_buffer); | ||
| 156 | kfree(rt); | 181 | kfree(rt); |
| 157 | snd_printk(KERN_ERR PREFIX "cannot create comm data receiver."); | 182 | snd_printk(KERN_ERR PREFIX "cannot create comm data receiver."); |
| 158 | return ret; | 183 | return ret; |
| @@ -171,6 +196,9 @@ void usb6fire_comm_abort(struct sfire_chip *chip) | |||
| 171 | 196 | ||
| 172 | void usb6fire_comm_destroy(struct sfire_chip *chip) | 197 | void usb6fire_comm_destroy(struct sfire_chip *chip) |
| 173 | { | 198 | { |
| 174 | kfree(chip->comm); | 199 | struct comm_runtime *rt = chip->comm; |
| 200 | |||
| 201 | kfree(rt->receiver_buffer); | ||
| 202 | kfree(rt); | ||
| 175 | chip->comm = NULL; | 203 | chip->comm = NULL; |
| 176 | } | 204 | } |
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h index 6a0840b0dcff..780d5ed8e5d8 100644 --- a/sound/usb/6fire/comm.h +++ b/sound/usb/6fire/comm.h | |||
| @@ -24,7 +24,7 @@ struct comm_runtime { | |||
| 24 | struct sfire_chip *chip; | 24 | struct sfire_chip *chip; |
| 25 | 25 | ||
| 26 | struct urb receiver; | 26 | struct urb receiver; |
| 27 | u8 receiver_buffer[COMM_RECEIVER_BUFSIZE]; | 27 | u8 *receiver_buffer; |
| 28 | 28 | ||
| 29 | u8 serial; /* urb serial */ | 29 | u8 serial; /* urb serial */ |
| 30 | 30 | ||
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c index 26722423330d..f3dd7266c391 100644 --- a/sound/usb/6fire/midi.c +++ b/sound/usb/6fire/midi.c | |||
| @@ -19,6 +19,10 @@ | |||
| 19 | #include "chip.h" | 19 | #include "chip.h" |
| 20 | #include "comm.h" | 20 | #include "comm.h" |
| 21 | 21 | ||
| 22 | enum { | ||
| 23 | MIDI_BUFSIZE = 64 | ||
| 24 | }; | ||
| 25 | |||
| 22 | static void usb6fire_midi_out_handler(struct urb *urb) | 26 | static void usb6fire_midi_out_handler(struct urb *urb) |
| 23 | { | 27 | { |
| 24 | struct midi_runtime *rt = urb->context; | 28 | struct midi_runtime *rt = urb->context; |
| @@ -156,6 +160,12 @@ int usb6fire_midi_init(struct sfire_chip *chip) | |||
| 156 | if (!rt) | 160 | if (!rt) |
| 157 | return -ENOMEM; | 161 | return -ENOMEM; |
| 158 | 162 | ||
| 163 | rt->out_buffer = kzalloc(MIDI_BUFSIZE, GFP_KERNEL); | ||
| 164 | if (!rt->out_buffer) { | ||
| 165 | kfree(rt); | ||
| 166 | return -ENOMEM; | ||
| 167 | } | ||
| 168 | |||
| 159 | rt->chip = chip; | 169 | rt->chip = chip; |
| 160 | rt->in_received = usb6fire_midi_in_received; | 170 | rt->in_received = usb6fire_midi_in_received; |
| 161 | rt->out_buffer[0] = 0x80; /* 'send midi' command */ | 171 | rt->out_buffer[0] = 0x80; /* 'send midi' command */ |
| @@ -169,6 +179,7 @@ int usb6fire_midi_init(struct sfire_chip *chip) | |||
| 169 | 179 | ||
| 170 | ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance); | 180 | ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance); |
| 171 | if (ret < 0) { | 181 | if (ret < 0) { |
| 182 | kfree(rt->out_buffer); | ||
| 172 | kfree(rt); | 183 | kfree(rt); |
| 173 | snd_printk(KERN_ERR PREFIX "unable to create midi.\n"); | 184 | snd_printk(KERN_ERR PREFIX "unable to create midi.\n"); |
| 174 | return ret; | 185 | return ret; |
| @@ -197,6 +208,9 @@ void usb6fire_midi_abort(struct sfire_chip *chip) | |||
| 197 | 208 | ||
| 198 | void usb6fire_midi_destroy(struct sfire_chip *chip) | 209 | void usb6fire_midi_destroy(struct sfire_chip *chip) |
| 199 | { | 210 | { |
| 200 | kfree(chip->midi); | 211 | struct midi_runtime *rt = chip->midi; |
| 212 | |||
| 213 | kfree(rt->out_buffer); | ||
| 214 | kfree(rt); | ||
| 201 | chip->midi = NULL; | 215 | chip->midi = NULL; |
| 202 | } | 216 | } |
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h index c321006e5430..84851b9f5559 100644 --- a/sound/usb/6fire/midi.h +++ b/sound/usb/6fire/midi.h | |||
| @@ -16,10 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | #include "common.h" | 17 | #include "common.h" |
| 18 | 18 | ||
| 19 | enum { | ||
| 20 | MIDI_BUFSIZE = 64 | ||
| 21 | }; | ||
| 22 | |||
| 23 | struct midi_runtime { | 19 | struct midi_runtime { |
| 24 | struct sfire_chip *chip; | 20 | struct sfire_chip *chip; |
| 25 | struct snd_rawmidi *instance; | 21 | struct snd_rawmidi *instance; |
| @@ -32,7 +28,7 @@ struct midi_runtime { | |||
| 32 | struct snd_rawmidi_substream *out; | 28 | struct snd_rawmidi_substream *out; |
| 33 | struct urb out_urb; | 29 | struct urb out_urb; |
| 34 | u8 out_serial; /* serial number of out packet */ | 30 | u8 out_serial; /* serial number of out packet */ |
| 35 | u8 out_buffer[MIDI_BUFSIZE]; | 31 | u8 *out_buffer; |
| 36 | int buffer_offset; | 32 | int buffer_offset; |
| 37 | 33 | ||
| 38 | void (*in_received)(struct midi_runtime *rt, u8 *data, int length); | 34 | void (*in_received)(struct midi_runtime *rt, u8 *data, int length); |
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index 3d2551cc10f2..b5eb97fdc842 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c | |||
| @@ -582,6 +582,33 @@ static void usb6fire_pcm_init_urb(struct pcm_urb *urb, | |||
| 582 | urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB; | 582 | urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB; |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 585 | static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt) | ||
| 586 | { | ||
| 587 | int i; | ||
| 588 | |||
| 589 | for (i = 0; i < PCM_N_URBS; i++) { | ||
| 590 | rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB | ||
| 591 | * PCM_MAX_PACKET_SIZE, GFP_KERNEL); | ||
| 592 | if (!rt->out_urbs[i].buffer) | ||
| 593 | return -ENOMEM; | ||
| 594 | rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB | ||
| 595 | * PCM_MAX_PACKET_SIZE, GFP_KERNEL); | ||
| 596 | if (!rt->in_urbs[i].buffer) | ||
| 597 | return -ENOMEM; | ||
| 598 | } | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt) | ||
| 603 | { | ||
| 604 | int i; | ||
| 605 | |||
| 606 | for (i = 0; i < PCM_N_URBS; i++) { | ||
| 607 | kfree(rt->out_urbs[i].buffer); | ||
| 608 | kfree(rt->in_urbs[i].buffer); | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 585 | int usb6fire_pcm_init(struct sfire_chip *chip) | 612 | int usb6fire_pcm_init(struct sfire_chip *chip) |
| 586 | { | 613 | { |
| 587 | int i; | 614 | int i; |
| @@ -593,6 +620,13 @@ int usb6fire_pcm_init(struct sfire_chip *chip) | |||
| 593 | if (!rt) | 620 | if (!rt) |
| 594 | return -ENOMEM; | 621 | return -ENOMEM; |
| 595 | 622 | ||
| 623 | ret = usb6fire_pcm_buffers_init(rt); | ||
| 624 | if (ret) { | ||
| 625 | usb6fire_pcm_buffers_destroy(rt); | ||
| 626 | kfree(rt); | ||
| 627 | return ret; | ||
| 628 | } | ||
| 629 | |||
| 596 | rt->chip = chip; | 630 | rt->chip = chip; |
| 597 | rt->stream_state = STREAM_DISABLED; | 631 | rt->stream_state = STREAM_DISABLED; |
| 598 | rt->rate = ARRAY_SIZE(rates); | 632 | rt->rate = ARRAY_SIZE(rates); |
| @@ -614,6 +648,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip) | |||
| 614 | 648 | ||
| 615 | ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm); | 649 | ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm); |
| 616 | if (ret < 0) { | 650 | if (ret < 0) { |
| 651 | usb6fire_pcm_buffers_destroy(rt); | ||
| 617 | kfree(rt); | 652 | kfree(rt); |
| 618 | snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n"); | 653 | snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n"); |
| 619 | return ret; | 654 | return ret; |
| @@ -625,6 +660,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip) | |||
| 625 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); | 660 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); |
| 626 | 661 | ||
| 627 | if (ret) { | 662 | if (ret) { |
| 663 | usb6fire_pcm_buffers_destroy(rt); | ||
| 628 | kfree(rt); | 664 | kfree(rt); |
| 629 | snd_printk(KERN_ERR PREFIX | 665 | snd_printk(KERN_ERR PREFIX |
| 630 | "error preallocating pcm buffers.\n"); | 666 | "error preallocating pcm buffers.\n"); |
| @@ -669,6 +705,9 @@ void usb6fire_pcm_abort(struct sfire_chip *chip) | |||
| 669 | 705 | ||
| 670 | void usb6fire_pcm_destroy(struct sfire_chip *chip) | 706 | void usb6fire_pcm_destroy(struct sfire_chip *chip) |
| 671 | { | 707 | { |
| 672 | kfree(chip->pcm); | 708 | struct pcm_runtime *rt = chip->pcm; |
| 709 | |||
| 710 | usb6fire_pcm_buffers_destroy(rt); | ||
| 711 | kfree(rt); | ||
| 673 | chip->pcm = NULL; | 712 | chip->pcm = NULL; |
| 674 | } | 713 | } |
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h index 9b01133ee3fe..f5779d6182c6 100644 --- a/sound/usb/6fire/pcm.h +++ b/sound/usb/6fire/pcm.h | |||
| @@ -32,7 +32,7 @@ struct pcm_urb { | |||
| 32 | struct urb instance; | 32 | struct urb instance; |
| 33 | struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB]; | 33 | struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB]; |
| 34 | /* END DO NOT SEPARATE */ | 34 | /* END DO NOT SEPARATE */ |
| 35 | u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE]; | 35 | u8 *buffer; |
| 36 | 36 | ||
| 37 | struct pcm_urb *peer; | 37 | struct pcm_urb *peer; |
| 38 | }; | 38 | }; |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7a444b5501d9..659950e5b94f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -591,17 +591,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, | |||
| 591 | ep->stride = frame_bits >> 3; | 591 | ep->stride = frame_bits >> 3; |
| 592 | ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; | 592 | ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; |
| 593 | 593 | ||
| 594 | /* calculate max. frequency */ | 594 | /* assume max. frequency is 25% higher than nominal */ |
| 595 | if (ep->maxpacksize) { | 595 | ep->freqmax = ep->freqn + (ep->freqn >> 2); |
| 596 | maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3)) | ||
| 597 | >> (16 - ep->datainterval); | ||
| 598 | /* but wMaxPacketSize might reduce this */ | ||
| 599 | if (ep->maxpacksize && ep->maxpacksize < maxsize) { | ||
| 596 | /* whatever fits into a max. size packet */ | 600 | /* whatever fits into a max. size packet */ |
| 597 | maxsize = ep->maxpacksize; | 601 | maxsize = ep->maxpacksize; |
| 598 | ep->freqmax = (maxsize / (frame_bits >> 3)) | 602 | ep->freqmax = (maxsize / (frame_bits >> 3)) |
| 599 | << (16 - ep->datainterval); | 603 | << (16 - ep->datainterval); |
| 600 | } else { | ||
| 601 | /* no max. packet size: just take 25% higher than nominal */ | ||
| 602 | ep->freqmax = ep->freqn + (ep->freqn >> 2); | ||
| 603 | maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3)) | ||
| 604 | >> (16 - ep->datainterval); | ||
| 605 | } | 604 | } |
| 606 | 605 | ||
| 607 | if (ep->fill_max) | 606 | if (ep->fill_max) |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index d5438083fd6a..95558ef4a7a0 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
| @@ -888,6 +888,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
| 888 | case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ | 888 | case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ |
| 889 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ | 889 | case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ |
| 890 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ | 890 | case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ |
| 891 | case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ | ||
| 891 | case USB_ID(0x046d, 0x0991): | 892 | case USB_ID(0x046d, 0x0991): |
| 892 | /* Most audio usb devices lie about volume resolution. | 893 | /* Most audio usb devices lie about volume resolution. |
| 893 | * Most Logitech webcams have res = 384. | 894 | * Most Logitech webcams have res = 384. |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 1bc45e71f1fe..0df9ede99dfd 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
| @@ -319,19 +319,19 @@ static int create_auto_midi_quirk(struct snd_usb_audio *chip, | |||
| 319 | if (altsd->bNumEndpoints < 1) | 319 | if (altsd->bNumEndpoints < 1) |
| 320 | return -ENODEV; | 320 | return -ENODEV; |
| 321 | epd = get_endpoint(alts, 0); | 321 | epd = get_endpoint(alts, 0); |
| 322 | if (!usb_endpoint_xfer_bulk(epd) || | 322 | if (!usb_endpoint_xfer_bulk(epd) && |
| 323 | !usb_endpoint_xfer_int(epd)) | 323 | !usb_endpoint_xfer_int(epd)) |
| 324 | return -ENODEV; | 324 | return -ENODEV; |
| 325 | 325 | ||
| 326 | switch (USB_ID_VENDOR(chip->usb_id)) { | 326 | switch (USB_ID_VENDOR(chip->usb_id)) { |
| 327 | case 0x0499: /* Yamaha */ | 327 | case 0x0499: /* Yamaha */ |
| 328 | err = create_yamaha_midi_quirk(chip, iface, driver, alts); | 328 | err = create_yamaha_midi_quirk(chip, iface, driver, alts); |
| 329 | if (err < 0 && err != -ENODEV) | 329 | if (err != -ENODEV) |
| 330 | return err; | 330 | return err; |
| 331 | break; | 331 | break; |
| 332 | case 0x0582: /* Roland */ | 332 | case 0x0582: /* Roland */ |
| 333 | err = create_roland_midi_quirk(chip, iface, driver, alts); | 333 | err = create_roland_midi_quirk(chip, iface, driver, alts); |
| 334 | if (err < 0 && err != -ENODEV) | 334 | if (err != -ENODEV) |
| 335 | return err; | 335 | return err; |
| 336 | break; | 336 | break; |
| 337 | } | 337 | } |
