diff options
195 files changed, 8018 insertions, 3263 deletions
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 6f639d9530b5..784793df81ed 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl | |||
@@ -2742,7 +2742,9 @@ struct _snd_pcm_runtime { | |||
2742 | 2742 | ||
2743 | <para> | 2743 | <para> |
2744 | Another note is that this callback is non-atomic | 2744 | Another note is that this callback is non-atomic |
2745 | (schedulable). This is important, because the | 2745 | (schedulable) as default, i.e. when no |
2746 | <structfield>nonatomic</structfield> flag set. | ||
2747 | This is important, because the | ||
2746 | <structfield>trigger</structfield> callback | 2748 | <structfield>trigger</structfield> callback |
2747 | is atomic (non-schedulable). That is, mutexes or any | 2749 | is atomic (non-schedulable). That is, mutexes or any |
2748 | schedule-related functions are not available in | 2750 | schedule-related functions are not available in |
@@ -2900,8 +2902,9 @@ struct _snd_pcm_runtime { | |||
2900 | </para> | 2902 | </para> |
2901 | 2903 | ||
2902 | <para> | 2904 | <para> |
2903 | As mentioned, this callback is atomic. You cannot call | 2905 | As mentioned, this callback is atomic as default unless |
2904 | functions which may sleep. | 2906 | <structfield>nonatomic</structfield> flag set, and |
2907 | you cannot call functions which may sleep. | ||
2905 | The trigger callback should be as minimal as possible, | 2908 | The trigger callback should be as minimal as possible, |
2906 | just really triggering the DMA. The other stuff should be | 2909 | just really triggering the DMA. The other stuff should be |
2907 | initialized hw_params and prepare callbacks properly | 2910 | initialized hw_params and prepare callbacks properly |
@@ -2936,7 +2939,7 @@ struct _snd_pcm_runtime { | |||
2936 | </para> | 2939 | </para> |
2937 | 2940 | ||
2938 | <para> | 2941 | <para> |
2939 | This callback is also atomic. | 2942 | This callback is also atomic as default. |
2940 | </para> | 2943 | </para> |
2941 | </section> | 2944 | </section> |
2942 | 2945 | ||
@@ -2972,7 +2975,7 @@ struct _snd_pcm_runtime { | |||
2972 | is useful only for such a purpose. | 2975 | is useful only for such a purpose. |
2973 | </para> | 2976 | </para> |
2974 | <para> | 2977 | <para> |
2975 | This callback is atomic. | 2978 | This callback is atomic as default. |
2976 | </para> | 2979 | </para> |
2977 | </section> | 2980 | </section> |
2978 | 2981 | ||
@@ -3175,6 +3178,21 @@ struct _snd_pcm_runtime { | |||
3175 | called with local interrupts disabled. | 3178 | called with local interrupts disabled. |
3176 | </para> | 3179 | </para> |
3177 | 3180 | ||
3181 | <para> | ||
3182 | The recent changes in PCM core code, however, allow all PCM | ||
3183 | operations to be non-atomic. This assumes that the all caller | ||
3184 | sides are in non-atomic contexts. For example, the function | ||
3185 | <function>snd_pcm_period_elapsed()</function> is called | ||
3186 | typically from the interrupt handler. But, if you set up the | ||
3187 | driver to use a threaded interrupt handler, this call can be in | ||
3188 | non-atomic context, too. In such a case, you can set | ||
3189 | <structfield>nonatomic</structfield> filed of | ||
3190 | <structname>snd_pcm</structname> object after creating it. | ||
3191 | When this flag is set, mutex and rwsem are used internally in | ||
3192 | the PCM core instead of spin and rwlocks, so that you can call | ||
3193 | all PCM functions safely in a non-atomic context. | ||
3194 | </para> | ||
3195 | |||
3178 | </section> | 3196 | </section> |
3179 | <section id="pcm-interface-constraints"> | 3197 | <section id="pcm-interface-constraints"> |
3180 | <title>Constraints</title> | 3198 | <title>Constraints</title> |
diff --git a/Documentation/devicetree/bindings/sound/adi,ssm2602.txt b/Documentation/devicetree/bindings/sound/adi,ssm2602.txt new file mode 100644 index 000000000000..3b3302fe399b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,ssm2602.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | Analog Devices SSM2602, SSM2603 and SSM2604 I2S audio CODEC devices | ||
2 | |||
3 | SSM2602 support both I2C and SPI as the configuration interface, | ||
4 | the selection is made by the MODE strap-in pin. | ||
5 | SSM2603 and SSM2604 only support I2C as the configuration interface. | ||
6 | |||
7 | Required properties: | ||
8 | |||
9 | - compatible : One of "adi,ssm2602", "adi,ssm2603" or "adi,ssm2604" | ||
10 | |||
11 | - reg : the I2C address of the device for I2C, the chip select | ||
12 | number for SPI. | ||
13 | |||
14 | Example: | ||
15 | |||
16 | ssm2602: ssm2602@1a { | ||
17 | compatible = "adi,ssm2602"; | ||
18 | reg = <0x1a>; | ||
19 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/cs35l32.txt b/Documentation/devicetree/bindings/sound/cs35l32.txt new file mode 100644 index 000000000000..1417d3f5cc22 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs35l32.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | CS35L32 audio CODEC | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : "cirrus,cs35l32" | ||
6 | |||
7 | - reg : the I2C address of the device for I2C. Address is determined by the level | ||
8 | of the AD0 pin. Level 0 is 0x40 while Level 1 is 0x41. | ||
9 | |||
10 | - VA-supply, VP-supply : power supplies for the device, | ||
11 | as covered in Documentation/devicetree/bindings/regulator/regulator.txt. | ||
12 | |||
13 | Optional properties: | ||
14 | |||
15 | - reset-gpios : a GPIO spec for the reset pin. If specified, it will be | ||
16 | deasserted before communication to the codec starts. | ||
17 | |||
18 | - cirrus,boost-manager : Boost voltage control. | ||
19 | 0 = Automatically managed. Boost-converter output voltage is the higher | ||
20 | of the two: Class G or adaptive LED voltage. | ||
21 | 1 = Automatically managed irrespective of audio, adapting for low-power | ||
22 | dissipation when LEDs are ON, and operating in Fixed-Boost Bypass Mode | ||
23 | if LEDs are OFF (VBST = VP). | ||
24 | 2 = (Default) Boost voltage fixed in Bypass Mode (VBST = VP). | ||
25 | 3 = Boost voltage fixed at 5 V. | ||
26 | |||
27 | - cirrus,sdout-datacfg : Data configuration for dual CS35L32 applications only. | ||
28 | Determines the data packed in a two-CS35L32 configuration. | ||
29 | 0 = Left/right channels VMON[11:0], IMON[11:0], VPMON[7:0]. | ||
30 | 1 = Left/right channels VMON[11:0], IMON[11:0], STATUS. | ||
31 | 2 = (Default) left/right channels VMON[15:0], IMON [15:0]. | ||
32 | 3 = Left/right channels VPMON[7:0], STATUS. | ||
33 | |||
34 | - cirrus,sdout-share : SDOUT sharing. Determines whether one or two CS35L32 | ||
35 | devices are on board sharing SDOUT. | ||
36 | 0 = (Default) One IC. | ||
37 | 1 = Two IC's. | ||
38 | |||
39 | - cirrus,battery-recovery : Low battery nominal recovery threshold, rising VP. | ||
40 | 0 = 3.1V | ||
41 | 1 = 3.2V | ||
42 | 2 = 3.3V (Default) | ||
43 | 3 = 3.4V | ||
44 | |||
45 | - cirrus,battery-threshold : Low battery nominal threshold, falling VP. | ||
46 | 0 = 3.1V | ||
47 | 1 = 3.2V | ||
48 | 2 = 3.3V | ||
49 | 3 = 3.4V (Default) | ||
50 | 4 = 3.5V | ||
51 | 5 = 3.6V | ||
52 | |||
53 | Example: | ||
54 | |||
55 | codec: codec@40 { | ||
56 | compatible = "cirrus,cs35l32"; | ||
57 | reg = <0x40>; | ||
58 | reset-gpios = <&gpio 10 0>; | ||
59 | cirrus,boost-manager = <0x03>; | ||
60 | cirrus,sdout-datacfg = <0x02>; | ||
61 | VA-supply = <®_audio>; | ||
62 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/es8328.txt b/Documentation/devicetree/bindings/sound/es8328.txt new file mode 100644 index 000000000000..30ea8a318ae9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/es8328.txt | |||
@@ -0,0 +1,38 @@ | |||
1 | Everest ES8328 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "everest,es8328" | ||
8 | - DVDD-supply : Regulator providing digital core supply voltage 1.8 - 3.6V | ||
9 | - AVDD-supply : Regulator providing analog supply voltage 3.3V | ||
10 | - PVDD-supply : Regulator providing digital IO supply voltage 1.8 - 3.6V | ||
11 | - IPVDD-supply : Regulator providing analog output voltage 3.3V | ||
12 | - clocks : A 22.5792 or 11.2896 MHz clock | ||
13 | - reg : the I2C address of the device for I2C, the chip select number for SPI | ||
14 | |||
15 | Pins on the device (for linking into audio routes): | ||
16 | |||
17 | * LOUT1 | ||
18 | * LOUT2 | ||
19 | * ROUT1 | ||
20 | * ROUT2 | ||
21 | * LINPUT1 | ||
22 | * RINPUT1 | ||
23 | * LINPUT2 | ||
24 | * RINPUT2 | ||
25 | * Mic Bias | ||
26 | |||
27 | |||
28 | Example: | ||
29 | |||
30 | codec: es8328@11 { | ||
31 | compatible = "everest,es8328"; | ||
32 | DVDD-supply = <®_3p3v>; | ||
33 | AVDD-supply = <®_3p3v>; | ||
34 | PVDD-supply = <®_3p3v>; | ||
35 | HPVDD-supply = <®_3p3v>; | ||
36 | clocks = <&clks 169>; | ||
37 | reg = <0x11>; | ||
38 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index aeb8c4a0b88d..52f5b6bf3e8e 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt | |||
@@ -7,7 +7,8 @@ other DSPs. It has up to six transmitters and four receivers. | |||
7 | 7 | ||
8 | Required properties: | 8 | Required properties: |
9 | 9 | ||
10 | - compatible : Compatible list, must contain "fsl,imx35-esai". | 10 | - compatible : Compatible list, must contain "fsl,imx35-esai" or |
11 | "fsl,vf610-esai" | ||
11 | 12 | ||
12 | - reg : Offset and length of the register set for the device. | 13 | - reg : Offset and length of the register set for the device. |
13 | 14 | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt index 3aa4a8f528f4..5b76be45d18b 100644 --- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt +++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt | |||
@@ -58,13 +58,7 @@ Optional properties: | |||
58 | Documentation/devicetree/bindings/dma/dma.txt. | 58 | Documentation/devicetree/bindings/dma/dma.txt. |
59 | - dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq | 59 | - dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq |
60 | is not defined. | 60 | is not defined. |
61 | - fsl,mode: The operating mode for the SSI interface. | 61 | - fsl,mode: The operating mode for the AC97 interface only. |
62 | "i2s-slave" - I2S mode, SSI is clock slave | ||
63 | "i2s-master" - I2S mode, SSI is clock master | ||
64 | "lj-slave" - left-justified mode, SSI is clock slave | ||
65 | "lj-master" - l.j. mode, SSI is clock master | ||
66 | "rj-slave" - right-justified mode, SSI is clock slave | ||
67 | "rj-master" - r.j., SSI is clock master | ||
68 | "ac97-slave" - AC97 mode, SSI is clock slave | 62 | "ac97-slave" - AC97 mode, SSI is clock slave |
69 | "ac97-master" - AC97 mode, SSI is clock master | 63 | "ac97-master" - AC97 mode, SSI is clock master |
70 | 64 | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt new file mode 100644 index 000000000000..a96774c194c8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt | |||
@@ -0,0 +1,82 @@ | |||
1 | Freescale Generic ASoC Sound Card with ASRC support | ||
2 | |||
3 | The Freescale Generic ASoC Sound Card can be used, ideally, for all Freescale | ||
4 | SoCs connecting with external CODECs. | ||
5 | |||
6 | The idea of this generic sound card is a bit like ASoC Simple Card. However, | ||
7 | for Freescale SoCs (especially those released in recent years), most of them | ||
8 | have ASRC (Documentation/devicetree/bindings/sound/fsl,asrc.txt) inside. And | ||
9 | this is a specific feature that might be painstakingly controlled and merged | ||
10 | into the Simple Card. | ||
11 | |||
12 | So having this generic sound card allows all Freescale SoC users to benefit | ||
13 | from the simplification of a new card support and the capability of the wide | ||
14 | sample rates support through ASRC. | ||
15 | |||
16 | Note: The card is initially designed for those sound cards who use I2S and | ||
17 | PCM DAI formats. However, it'll be also possible to support those non | ||
18 | I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as long | ||
19 | as the driver has been properly upgraded. | ||
20 | |||
21 | |||
22 | The compatible list for this generic sound card currently: | ||
23 | "fsl,imx-audio-cs42888" | ||
24 | |||
25 | "fsl,imx-audio-wm8962" | ||
26 | (compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt) | ||
27 | |||
28 | "fsl,imx-audio-sgtl5000" | ||
29 | (compatible with Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt) | ||
30 | |||
31 | Required properties: | ||
32 | |||
33 | - compatible : Contains one of entries in the compatible list. | ||
34 | |||
35 | - model : The user-visible name of this sound complex | ||
36 | |||
37 | - audio-cpu : The phandle of an CPU DAI controller | ||
38 | |||
39 | - audio-codec : The phandle of an audio codec | ||
40 | |||
41 | - audio-routing : A list of the connections between audio components. | ||
42 | Each entry is a pair of strings, the first being the | ||
43 | connection's sink, the second being the connection's | ||
44 | source. There're a few pre-designed board connectors: | ||
45 | * Line Out Jack | ||
46 | * Line In Jack | ||
47 | * Headphone Jack | ||
48 | * Mic Jack | ||
49 | * Ext Spk | ||
50 | * AMIC (stands for Analog Microphone Jack) | ||
51 | * DMIC (stands for Digital Microphone Jack) | ||
52 | |||
53 | Note: The "Mic Jack" and "AMIC" are redundant while | ||
54 | coexsiting in order to support the old bindings | ||
55 | of wm8962 and sgtl5000. | ||
56 | |||
57 | Optional properties: | ||
58 | |||
59 | - audio-asrc : The phandle of ASRC. It can be absent if there's no | ||
60 | need to add ASRC support via DPCM. | ||
61 | |||
62 | Example: | ||
63 | sound-cs42888 { | ||
64 | compatible = "fsl,imx-audio-cs42888"; | ||
65 | model = "cs42888-audio"; | ||
66 | audio-cpu = <&esai>; | ||
67 | audio-asrc = <&asrc>; | ||
68 | audio-codec = <&cs42888>; | ||
69 | audio-routing = | ||
70 | "Line Out Jack", "AOUT1L", | ||
71 | "Line Out Jack", "AOUT1R", | ||
72 | "Line Out Jack", "AOUT2L", | ||
73 | "Line Out Jack", "AOUT2R", | ||
74 | "Line Out Jack", "AOUT3L", | ||
75 | "Line Out Jack", "AOUT3R", | ||
76 | "Line Out Jack", "AOUT4L", | ||
77 | "Line Out Jack", "AOUT4R", | ||
78 | "AIN1L", "Line In Jack", | ||
79 | "AIN1R", "Line In Jack", | ||
80 | "AIN2L", "Line In Jack", | ||
81 | "AIN2R", "Line In Jack"; | ||
82 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index 0f4e23828190..4956b14d4b06 100644 --- a/Documentation/devicetree/bindings/sound/fsl-sai.txt +++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt | |||
@@ -18,12 +18,26 @@ Required properties: | |||
18 | - pinctrl-names: Must contain a "default" entry. | 18 | - pinctrl-names: Must contain a "default" entry. |
19 | - pinctrl-NNN: One property must exist for each entry in pinctrl-names. | 19 | - pinctrl-NNN: One property must exist for each entry in pinctrl-names. |
20 | See ../pinctrl/pinctrl-bindings.txt for details of the property values. | 20 | See ../pinctrl/pinctrl-bindings.txt for details of the property values. |
21 | - big-endian-regs: If this property is absent, the little endian mode will | 21 | - big-endian: Boolean property, required if all the FTM_PWM registers |
22 | be in use as default, or the big endian mode will be in use for all the | 22 | are big-endian rather than little-endian. |
23 | device registers. | 23 | - lsb-first: Configures whether the LSB or the MSB is transmitted first for |
24 | - big-endian-data: If this property is absent, the little endian mode will | 24 | the fifo data. If this property is absent, the MSB is transmitted first as |
25 | be in use as default, or the big endian mode will be in use for all the | 25 | default, or the LSB is transmitted first. |
26 | fifo data. | 26 | - fsl,sai-synchronous-rx: This is a boolean property. If present, indicating |
27 | that SAI will work in the synchronous mode (sync Tx with Rx) which means | ||
28 | both the transimitter and receiver will send and receive data by following | ||
29 | receiver's bit clocks and frame sync clocks. | ||
30 | - fsl,sai-asynchronous: This is a boolean property. If present, indicating | ||
31 | that SAI will work in the asynchronous mode, which means both transimitter | ||
32 | and receiver will send and receive data by following their own bit clocks | ||
33 | and frame sync clocks separately. | ||
34 | |||
35 | Note: | ||
36 | - If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the | ||
37 | default synchronous mode (sync Rx with Tx) will be used, which means both | ||
38 | transimitter and receiver will send and receive data by following clocks | ||
39 | of transimitter. | ||
40 | - fsl,sai-asynchronous and fsl,sai-synchronous-rx are exclusive. | ||
27 | 41 | ||
28 | Example: | 42 | Example: |
29 | sai2: sai@40031000 { | 43 | sai2: sai@40031000 { |
@@ -38,6 +52,6 @@ sai2: sai@40031000 { | |||
38 | dma-names = "tx", "rx"; | 52 | dma-names = "tx", "rx"; |
39 | dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>, | 53 | dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>, |
40 | <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>; | 54 | <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>; |
41 | big-endian-regs; | 55 | big-endian; |
42 | big-endian-data; | 56 | lsb-first; |
43 | }; | 57 | }; |
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt b/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt new file mode 100644 index 000000000000..07b68ab206fb --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt | |||
@@ -0,0 +1,60 @@ | |||
1 | Freescale i.MX audio complex with ES8328 codec | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "fsl,imx-audio-es8328" | ||
5 | - model : The user-visible name of this sound complex | ||
6 | - ssi-controller : The phandle of the i.MX SSI controller | ||
7 | - jack-gpio : Optional GPIO for headphone jack | ||
8 | - audio-amp-supply : Power regulator for speaker amps | ||
9 | - audio-codec : The phandle of the ES8328 audio codec | ||
10 | - audio-routing : A list of the connections between audio components. | ||
11 | Each entry is a pair of strings, the first being the | ||
12 | connection's sink, the second being the connection's | ||
13 | source. Valid names could be power supplies, ES8328 | ||
14 | pins, and the jacks on the board: | ||
15 | |||
16 | Power supplies: | ||
17 | * audio-amp | ||
18 | |||
19 | ES8328 pins: | ||
20 | * LOUT1 | ||
21 | * LOUT2 | ||
22 | * ROUT1 | ||
23 | * ROUT2 | ||
24 | * LINPUT1 | ||
25 | * LINPUT2 | ||
26 | * RINPUT1 | ||
27 | * RINPUT2 | ||
28 | * Mic PGA | ||
29 | |||
30 | Board connectors: | ||
31 | * Headphone | ||
32 | * Speaker | ||
33 | * Mic Jack | ||
34 | - mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) | ||
35 | - mux-ext-port : The external port of the i.MX audio muxer (AUDMIX) | ||
36 | |||
37 | Note: The AUDMUX port numbering should start at 1, which is consistent with | ||
38 | hardware manual. | ||
39 | |||
40 | Example: | ||
41 | |||
42 | sound { | ||
43 | compatible = "fsl,imx-audio-es8328"; | ||
44 | model = "imx-audio-es8328"; | ||
45 | ssi-controller = <&ssi1>; | ||
46 | audio-codec = <&codec>; | ||
47 | jack-gpio = <&gpio5 15 0>; | ||
48 | audio-amp-supply = <®_audio_amp>; | ||
49 | audio-routing = | ||
50 | "Speaker", "LOUT2", | ||
51 | "Speaker", "ROUT2", | ||
52 | "Speaker", "audio-amp", | ||
53 | "Headphone", "ROUT1", | ||
54 | "Headphone", "LOUT1", | ||
55 | "LINPUT1", "Mic Jack", | ||
56 | "RINPUT1", "Mic Jack", | ||
57 | "Mic Jack", "Mic Bias"; | ||
58 | mux-int-port = <1>; | ||
59 | mux-ext-port = <3>; | ||
60 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt index 9c7c55c71370..c949abc2992f 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt | |||
@@ -25,6 +25,7 @@ Required properties: | |||
25 | 25 | ||
26 | Optional properties: | 26 | Optional properties: |
27 | - nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in | 27 | - nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in |
28 | - nvidia,mic-det-gpios : The GPIO that detect microphones are plugged in | ||
28 | 29 | ||
29 | Example: | 30 | Example: |
30 | 31 | ||
diff --git a/Documentation/devicetree/bindings/sound/rt5677.txt b/Documentation/devicetree/bindings/sound/rt5677.txt new file mode 100644 index 000000000000..0701b834fc73 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5677.txt | |||
@@ -0,0 +1,59 @@ | |||
1 | RT5677 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "realtek,rt5677". | ||
8 | |||
9 | - reg : The I2C address of the device. | ||
10 | |||
11 | - interrupts : The CODEC's interrupt output. | ||
12 | |||
13 | - gpio-controller : Indicates this device is a GPIO controller. | ||
14 | |||
15 | - #gpio-cells : Should be two. The first cell is the pin number and the | ||
16 | second cell is used to specify optional parameters (currently unused). | ||
17 | |||
18 | Optional properties: | ||
19 | |||
20 | - realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin. | ||
21 | |||
22 | - realtek,in1-differential | ||
23 | - realtek,in2-differential | ||
24 | - realtek,lout1-differential | ||
25 | - realtek,lout2-differential | ||
26 | - realtek,lout3-differential | ||
27 | Boolean. Indicate MIC1/2 input and LOUT1/2/3 outputs are differential, | ||
28 | rather than single-ended. | ||
29 | |||
30 | Pins on the device (for linking into audio routes): | ||
31 | |||
32 | * IN1P | ||
33 | * IN1N | ||
34 | * IN2P | ||
35 | * IN2N | ||
36 | * MICBIAS1 | ||
37 | * DMIC1 | ||
38 | * DMIC2 | ||
39 | * DMIC3 | ||
40 | * DMIC4 | ||
41 | * LOUT1 | ||
42 | * LOUT2 | ||
43 | * LOUT3 | ||
44 | |||
45 | Example: | ||
46 | |||
47 | rt5677 { | ||
48 | compatible = "realtek,rt5677"; | ||
49 | reg = <0x2c>; | ||
50 | interrupt-parent = <&gpio>; | ||
51 | interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>; | ||
52 | |||
53 | gpio-controller; | ||
54 | #gpio-cells = <2>; | ||
55 | |||
56 | realtek,pow-ldo2-gpio = | ||
57 | <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; | ||
58 | realtek,in1-differential = "true"; | ||
59 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index c2e9841dfce4..c3cba600bf11 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt | |||
@@ -17,6 +17,10 @@ Optional properties: | |||
17 | source. | 17 | source. |
18 | - simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec | 18 | - simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec |
19 | mclk. | 19 | mclk. |
20 | - simple-audio-card,hp-det-gpio : Reference to GPIO that signals when | ||
21 | headphones are attached. | ||
22 | - simple-audio-card,mic-det-gpio : Reference to GPIO that signals when | ||
23 | a microphone is attached. | ||
20 | 24 | ||
21 | Optional subnodes: | 25 | Optional subnodes: |
22 | 26 | ||
diff --git a/Documentation/devicetree/bindings/sound/ssm4567.txt b/Documentation/devicetree/bindings/sound/ssm4567.txt new file mode 100644 index 000000000000..ec3d9e7004b5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ssm4567.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | Analog Devices SSM4567 audio amplifier | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible : Must be "adi,ssm4567" | ||
7 | - reg : the I2C address of the device. This will either be 0x34 (LR_SEL/ADDR connected to AGND), | ||
8 | 0x35 (LR_SEL/ADDR connected to IOVDD) or 0x36 (LR_SEL/ADDR open). | ||
9 | |||
10 | Example: | ||
11 | |||
12 | ssm4567: ssm4567@34 { | ||
13 | compatible = "adi,ssm4567"; | ||
14 | reg = <0x34>; | ||
15 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 653beaa392dc..71259df60e96 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -51,6 +51,7 @@ epfl Ecole Polytechnique Fédérale de Lausanne | |||
51 | epson Seiko Epson Corp. | 51 | epson Seiko Epson Corp. |
52 | est ESTeem Wireless Modems | 52 | est ESTeem Wireless Modems |
53 | eukrea Eukréa Electromatique | 53 | eukrea Eukréa Electromatique |
54 | everest Everest Semiconductor Co. Ltd. | ||
54 | excito Excito | 55 | excito Excito |
55 | fcs Fairchild Semiconductor | 56 | fcs Fairchild Semiconductor |
56 | fsl Freescale Semiconductor | 57 | fsl Freescale Semiconductor |
diff --git a/include/dt-bindings/sound/cs35l32.h b/include/dt-bindings/sound/cs35l32.h new file mode 100644 index 000000000000..0c6d6a3c15a2 --- /dev/null +++ b/include/dt-bindings/sound/cs35l32.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef __DT_CS35L32_H | ||
2 | #define __DT_CS35L32_H | ||
3 | |||
4 | #define CS35L32_BOOST_MGR_AUTO 0 | ||
5 | #define CS35L32_BOOST_MGR_AUTO_AUDIO 1 | ||
6 | #define CS35L32_BOOST_MGR_BYPASS 2 | ||
7 | #define CS35L32_BOOST_MGR_FIXED 3 | ||
8 | |||
9 | #define CS35L32_DATA_CFG_LR_VP 0 | ||
10 | #define CS35L32_DATA_CFG_LR_STAT 1 | ||
11 | #define CS35L32_DATA_CFG_LR 2 | ||
12 | #define CS35L32_DATA_CFG_LR_VPSTAT 3 | ||
13 | |||
14 | #define CS35L32_BATT_THRESH_3_1V 0 | ||
15 | #define CS35L32_BATT_THRESH_3_2V 1 | ||
16 | #define CS35L32_BATT_THRESH_3_3V 2 | ||
17 | #define CS35L32_BATT_THRESH_3_4V 3 | ||
18 | |||
19 | #define CS35L32_BATT_RECOV_3_1V 0 | ||
20 | #define CS35L32_BATT_RECOV_3_2V 1 | ||
21 | #define CS35L32_BATT_RECOV_3_3V 2 | ||
22 | #define CS35L32_BATT_RECOV_3_4V 3 | ||
23 | #define CS35L32_BATT_RECOV_3_5V 4 | ||
24 | #define CS35L32_BATT_RECOV_3_6V 5 | ||
25 | |||
26 | #endif /* __DT_CS35L32_H */ | ||
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 6f3e10ca0e32..e862497f7556 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -183,6 +183,7 @@ struct snd_pcm_ops { | |||
183 | #define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B) | 183 | #define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B) |
184 | #define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8) | 184 | #define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8) |
185 | #define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE) | 185 | #define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE) |
186 | #define SNDRV_PCM_FMTBIT_DSD_U32_LE _SNDRV_PCM_FMTBIT(DSD_U32_LE) | ||
186 | 187 | ||
187 | #ifdef SNDRV_LITTLE_ENDIAN | 188 | #ifdef SNDRV_LITTLE_ENDIAN |
188 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE | 189 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE |
@@ -365,6 +366,7 @@ struct snd_pcm_runtime { | |||
365 | 366 | ||
366 | struct snd_pcm_group { /* keep linked substreams */ | 367 | struct snd_pcm_group { /* keep linked substreams */ |
367 | spinlock_t lock; | 368 | spinlock_t lock; |
369 | struct mutex mutex; | ||
368 | struct list_head substreams; | 370 | struct list_head substreams; |
369 | int count; | 371 | int count; |
370 | }; | 372 | }; |
@@ -460,6 +462,7 @@ struct snd_pcm { | |||
460 | void (*private_free) (struct snd_pcm *pcm); | 462 | void (*private_free) (struct snd_pcm *pcm); |
461 | struct device *dev; /* actual hw device this belongs to */ | 463 | struct device *dev; /* actual hw device this belongs to */ |
462 | bool internal; /* pcm is for internal use only */ | 464 | bool internal; /* pcm is for internal use only */ |
465 | bool nonatomic; /* whole PCM operations are in non-atomic context */ | ||
463 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 466 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
464 | struct snd_pcm_oss oss; | 467 | struct snd_pcm_oss oss; |
465 | #endif | 468 | #endif |
@@ -492,8 +495,6 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); | |||
492 | * Native I/O | 495 | * Native I/O |
493 | */ | 496 | */ |
494 | 497 | ||
495 | extern rwlock_t snd_pcm_link_rwlock; | ||
496 | |||
497 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); | 498 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); |
498 | int snd_pcm_info_user(struct snd_pcm_substream *substream, | 499 | int snd_pcm_info_user(struct snd_pcm_substream *substream, |
499 | struct snd_pcm_info __user *info); | 500 | struct snd_pcm_info __user *info); |
@@ -537,41 +538,18 @@ static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream) | |||
537 | return substream->group != &substream->self_group; | 538 | return substream->group != &substream->self_group; |
538 | } | 539 | } |
539 | 540 | ||
540 | static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream) | 541 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream); |
541 | { | 542 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream); |
542 | read_lock(&snd_pcm_link_rwlock); | 543 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream); |
543 | spin_lock(&substream->self_group.lock); | 544 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream); |
544 | } | 545 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream); |
545 | 546 | #define snd_pcm_stream_lock_irqsave(substream, flags) \ | |
546 | static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) | 547 | do { \ |
547 | { | 548 | typecheck(unsigned long, flags); \ |
548 | spin_unlock(&substream->self_group.lock); | 549 | flags = _snd_pcm_stream_lock_irqsave(substream); \ |
549 | read_unlock(&snd_pcm_link_rwlock); | 550 | } while (0) |
550 | } | 551 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, |
551 | 552 | unsigned long flags); | |
552 | static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) | ||
553 | { | ||
554 | read_lock_irq(&snd_pcm_link_rwlock); | ||
555 | spin_lock(&substream->self_group.lock); | ||
556 | } | ||
557 | |||
558 | static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) | ||
559 | { | ||
560 | spin_unlock(&substream->self_group.lock); | ||
561 | read_unlock_irq(&snd_pcm_link_rwlock); | ||
562 | } | ||
563 | |||
564 | #define snd_pcm_stream_lock_irqsave(substream, flags) \ | ||
565 | do { \ | ||
566 | read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \ | ||
567 | spin_lock(&substream->self_group.lock); \ | ||
568 | } while (0) | ||
569 | |||
570 | #define snd_pcm_stream_unlock_irqrestore(substream, flags) \ | ||
571 | do { \ | ||
572 | spin_unlock(&substream->self_group.lock); \ | ||
573 | read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ | ||
574 | } while (0) | ||
575 | 553 | ||
576 | #define snd_pcm_group_for_each_entry(s, substream) \ | 554 | #define snd_pcm_group_for_each_entry(s, substream) \ |
577 | list_for_each_entry(s, &substream->group->substreams, link_list) | 555 | list_for_each_entry(s, &substream->group->substreams, link_list) |
diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 1de744c242f6..a5352712194b 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h | |||
@@ -20,6 +20,9 @@ struct rt5645_platform_data { | |||
20 | /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ | 20 | /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ |
21 | unsigned int dmic2_data_pin; | 21 | unsigned int dmic2_data_pin; |
22 | /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ | 22 | /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ |
23 | |||
24 | unsigned int hp_det_gpio; | ||
25 | bool gpio_hp_det_active_high; | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | #endif | 28 | #endif |
diff --git a/include/sound/rt5677.h b/include/sound/rt5677.h index 3da14313bcfc..082670e3a353 100644 --- a/include/sound/rt5677.h +++ b/include/sound/rt5677.h | |||
@@ -12,10 +12,21 @@ | |||
12 | #ifndef __LINUX_SND_RT5677_H | 12 | #ifndef __LINUX_SND_RT5677_H |
13 | #define __LINUX_SND_RT5677_H | 13 | #define __LINUX_SND_RT5677_H |
14 | 14 | ||
15 | enum rt5677_dmic2_clk { | ||
16 | RT5677_DMIC_CLK1 = 0, | ||
17 | RT5677_DMIC_CLK2 = 1, | ||
18 | }; | ||
19 | |||
20 | |||
15 | struct rt5677_platform_data { | 21 | struct rt5677_platform_data { |
16 | /* IN1 IN2 can optionally be differential */ | 22 | /* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */ |
17 | bool in1_diff; | 23 | bool in1_diff; |
18 | bool in2_diff; | 24 | bool in2_diff; |
25 | bool lout1_diff; | ||
26 | bool lout2_diff; | ||
27 | bool lout3_diff; | ||
28 | /* DMIC2 clock source selection */ | ||
29 | enum rt5677_dmic2_clk dmic2_clk_pin; | ||
19 | }; | 30 | }; |
20 | 31 | ||
21 | #endif | 32 | #endif |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index aac04ff84eea..3a4d7da67b8d 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -432,6 +432,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, | |||
432 | int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, | 432 | int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, |
433 | const char *pin); | 433 | const char *pin); |
434 | void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card); | 434 | void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card); |
435 | unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); | ||
435 | 436 | ||
436 | /* Mostly internal - should not normally be used */ | 437 | /* Mostly internal - should not normally be used */ |
437 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); | 438 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); |
@@ -587,13 +588,13 @@ struct snd_soc_dapm_context { | |||
587 | enum snd_soc_bias_level suspend_bias_level; | 588 | enum snd_soc_bias_level suspend_bias_level; |
588 | struct delayed_work delayed_work; | 589 | struct delayed_work delayed_work; |
589 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 590 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
590 | 591 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ | |
592 | unsigned int suspend_bias_off:1; | ||
591 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 593 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
592 | enum snd_soc_dapm_type, int); | 594 | enum snd_soc_dapm_type, int); |
593 | 595 | ||
594 | struct device *dev; /* from parent - for debug */ | 596 | struct device *dev; /* from parent - for debug */ |
595 | struct snd_soc_component *component; /* parent component */ | 597 | struct snd_soc_component *component; /* parent component */ |
596 | struct snd_soc_codec *codec; /* parent codec */ | ||
597 | struct snd_soc_card *card; /* parent card */ | 598 | struct snd_soc_card *card; /* parent card */ |
598 | 599 | ||
599 | /* used during DAPM updates */ | 600 | /* used during DAPM updates */ |
diff --git a/include/sound/soc.h b/include/sound/soc.h index c83a334dd00f..7ba7130037a0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -690,6 +690,17 @@ struct snd_soc_compr_ops { | |||
690 | struct snd_soc_component_driver { | 690 | struct snd_soc_component_driver { |
691 | const char *name; | 691 | const char *name; |
692 | 692 | ||
693 | /* Default control and setup, added after probe() is run */ | ||
694 | const struct snd_kcontrol_new *controls; | ||
695 | unsigned int num_controls; | ||
696 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
697 | unsigned int num_dapm_widgets; | ||
698 | const struct snd_soc_dapm_route *dapm_routes; | ||
699 | unsigned int num_dapm_routes; | ||
700 | |||
701 | int (*probe)(struct snd_soc_component *); | ||
702 | void (*remove)(struct snd_soc_component *); | ||
703 | |||
693 | /* DT */ | 704 | /* DT */ |
694 | int (*of_xlate_dai_name)(struct snd_soc_component *component, | 705 | int (*of_xlate_dai_name)(struct snd_soc_component *component, |
695 | struct of_phandle_args *args, | 706 | struct of_phandle_args *args, |
@@ -697,6 +708,10 @@ struct snd_soc_component_driver { | |||
697 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, | 708 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, |
698 | int subseq); | 709 | int subseq); |
699 | int (*stream_event)(struct snd_soc_component *, int event); | 710 | int (*stream_event)(struct snd_soc_component *, int event); |
711 | |||
712 | /* probe ordering - for components with runtime dependencies */ | ||
713 | int probe_order; | ||
714 | int remove_order; | ||
700 | }; | 715 | }; |
701 | 716 | ||
702 | struct snd_soc_component { | 717 | struct snd_soc_component { |
@@ -710,6 +725,7 @@ struct snd_soc_component { | |||
710 | 725 | ||
711 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ | 726 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ |
712 | unsigned int registered_as_component:1; | 727 | unsigned int registered_as_component:1; |
728 | unsigned int probed:1; | ||
713 | 729 | ||
714 | struct list_head list; | 730 | struct list_head list; |
715 | 731 | ||
@@ -728,9 +744,35 @@ struct snd_soc_component { | |||
728 | 744 | ||
729 | struct mutex io_mutex; | 745 | struct mutex io_mutex; |
730 | 746 | ||
747 | #ifdef CONFIG_DEBUG_FS | ||
748 | struct dentry *debugfs_root; | ||
749 | #endif | ||
750 | |||
751 | /* | ||
752 | * DO NOT use any of the fields below in drivers, they are temporary and | ||
753 | * are going to be removed again soon. If you use them in driver code the | ||
754 | * driver will be marked as BROKEN when these fields are removed. | ||
755 | */ | ||
756 | |||
731 | /* Don't use these, use snd_soc_component_get_dapm() */ | 757 | /* Don't use these, use snd_soc_component_get_dapm() */ |
732 | struct snd_soc_dapm_context dapm; | 758 | struct snd_soc_dapm_context dapm; |
733 | struct snd_soc_dapm_context *dapm_ptr; | 759 | struct snd_soc_dapm_context *dapm_ptr; |
760 | |||
761 | const struct snd_kcontrol_new *controls; | ||
762 | unsigned int num_controls; | ||
763 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
764 | unsigned int num_dapm_widgets; | ||
765 | const struct snd_soc_dapm_route *dapm_routes; | ||
766 | unsigned int num_dapm_routes; | ||
767 | struct snd_soc_codec *codec; | ||
768 | |||
769 | int (*probe)(struct snd_soc_component *); | ||
770 | void (*remove)(struct snd_soc_component *); | ||
771 | |||
772 | #ifdef CONFIG_DEBUG_FS | ||
773 | void (*init_debugfs)(struct snd_soc_component *component); | ||
774 | const char *debugfs_prefix; | ||
775 | #endif | ||
734 | }; | 776 | }; |
735 | 777 | ||
736 | /* SoC Audio Codec device */ | 778 | /* SoC Audio Codec device */ |
@@ -746,11 +788,9 @@ struct snd_soc_codec { | |||
746 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ | 788 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ |
747 | unsigned int cache_bypass:1; /* Suppress access to the cache */ | 789 | unsigned int cache_bypass:1; /* Suppress access to the cache */ |
748 | unsigned int suspended:1; /* Codec is in suspend PM state */ | 790 | unsigned int suspended:1; /* Codec is in suspend PM state */ |
749 | unsigned int probed:1; /* Codec has been probed */ | ||
750 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | 791 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ |
751 | unsigned int ac97_created:1; /* Codec has been created by SoC */ | 792 | unsigned int ac97_created:1; /* Codec has been created by SoC */ |
752 | unsigned int cache_init:1; /* codec cache has been initialized */ | 793 | unsigned int cache_init:1; /* codec cache has been initialized */ |
753 | u32 cache_only; /* Suppress writes to hardware */ | ||
754 | u32 cache_sync; /* Cache needs to be synced to hardware */ | 794 | u32 cache_sync; /* Cache needs to be synced to hardware */ |
755 | 795 | ||
756 | /* codec IO */ | 796 | /* codec IO */ |
@@ -766,7 +806,6 @@ struct snd_soc_codec { | |||
766 | struct snd_soc_dapm_context dapm; | 806 | struct snd_soc_dapm_context dapm; |
767 | 807 | ||
768 | #ifdef CONFIG_DEBUG_FS | 808 | #ifdef CONFIG_DEBUG_FS |
769 | struct dentry *debugfs_codec_root; | ||
770 | struct dentry *debugfs_reg; | 809 | struct dentry *debugfs_reg; |
771 | #endif | 810 | #endif |
772 | }; | 811 | }; |
@@ -808,15 +847,12 @@ struct snd_soc_codec_driver { | |||
808 | int (*set_bias_level)(struct snd_soc_codec *, | 847 | int (*set_bias_level)(struct snd_soc_codec *, |
809 | enum snd_soc_bias_level level); | 848 | enum snd_soc_bias_level level); |
810 | bool idle_bias_off; | 849 | bool idle_bias_off; |
850 | bool suspend_bias_off; | ||
811 | 851 | ||
812 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 852 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
813 | enum snd_soc_dapm_type, int); | 853 | enum snd_soc_dapm_type, int); |
814 | 854 | ||
815 | bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */ | 855 | bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */ |
816 | |||
817 | /* probe ordering - for components with runtime dependencies */ | ||
818 | int probe_order; | ||
819 | int remove_order; | ||
820 | }; | 856 | }; |
821 | 857 | ||
822 | /* SoC platform interface */ | 858 | /* SoC platform interface */ |
@@ -832,14 +868,6 @@ struct snd_soc_platform_driver { | |||
832 | int (*pcm_new)(struct snd_soc_pcm_runtime *); | 868 | int (*pcm_new)(struct snd_soc_pcm_runtime *); |
833 | void (*pcm_free)(struct snd_pcm *); | 869 | void (*pcm_free)(struct snd_pcm *); |
834 | 870 | ||
835 | /* Default control and setup, added after probe() is run */ | ||
836 | const struct snd_kcontrol_new *controls; | ||
837 | int num_controls; | ||
838 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
839 | int num_dapm_widgets; | ||
840 | const struct snd_soc_dapm_route *dapm_routes; | ||
841 | int num_dapm_routes; | ||
842 | |||
843 | /* | 871 | /* |
844 | * For platform caused delay reporting. | 872 | * For platform caused delay reporting. |
845 | * Optional. | 873 | * Optional. |
@@ -853,13 +881,6 @@ struct snd_soc_platform_driver { | |||
853 | /* platform stream compress ops */ | 881 | /* platform stream compress ops */ |
854 | const struct snd_compr_ops *compr_ops; | 882 | const struct snd_compr_ops *compr_ops; |
855 | 883 | ||
856 | /* probe ordering - for components with runtime dependencies */ | ||
857 | int probe_order; | ||
858 | int remove_order; | ||
859 | |||
860 | /* platform IO - used for platform DAPM */ | ||
861 | unsigned int (*read)(struct snd_soc_platform *, unsigned int); | ||
862 | int (*write)(struct snd_soc_platform *, unsigned int, unsigned int); | ||
863 | int (*bespoke_trigger)(struct snd_pcm_substream *, int); | 884 | int (*bespoke_trigger)(struct snd_pcm_substream *, int); |
864 | }; | 885 | }; |
865 | 886 | ||
@@ -874,15 +895,10 @@ struct snd_soc_platform { | |||
874 | const struct snd_soc_platform_driver *driver; | 895 | const struct snd_soc_platform_driver *driver; |
875 | 896 | ||
876 | unsigned int suspended:1; /* platform is suspended */ | 897 | unsigned int suspended:1; /* platform is suspended */ |
877 | unsigned int probed:1; | ||
878 | 898 | ||
879 | struct list_head list; | 899 | struct list_head list; |
880 | 900 | ||
881 | struct snd_soc_component component; | 901 | struct snd_soc_component component; |
882 | |||
883 | #ifdef CONFIG_DEBUG_FS | ||
884 | struct dentry *debugfs_platform_root; | ||
885 | #endif | ||
886 | }; | 902 | }; |
887 | 903 | ||
888 | struct snd_soc_dai_link { | 904 | struct snd_soc_dai_link { |
@@ -897,7 +913,7 @@ struct snd_soc_dai_link { | |||
897 | * only for codec to codec links, or systems using device tree. | 913 | * only for codec to codec links, or systems using device tree. |
898 | */ | 914 | */ |
899 | const char *cpu_name; | 915 | const char *cpu_name; |
900 | const struct device_node *cpu_of_node; | 916 | struct device_node *cpu_of_node; |
901 | /* | 917 | /* |
902 | * You MAY specify the DAI name of the CPU DAI. If this information is | 918 | * You MAY specify the DAI name of the CPU DAI. If this information is |
903 | * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node | 919 | * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node |
@@ -909,7 +925,7 @@ struct snd_soc_dai_link { | |||
909 | * DT/OF node, but not both. | 925 | * DT/OF node, but not both. |
910 | */ | 926 | */ |
911 | const char *codec_name; | 927 | const char *codec_name; |
912 | const struct device_node *codec_of_node; | 928 | struct device_node *codec_of_node; |
913 | /* You MUST specify the DAI name within the codec */ | 929 | /* You MUST specify the DAI name within the codec */ |
914 | const char *codec_dai_name; | 930 | const char *codec_dai_name; |
915 | 931 | ||
@@ -922,7 +938,7 @@ struct snd_soc_dai_link { | |||
922 | * do not need a platform. | 938 | * do not need a platform. |
923 | */ | 939 | */ |
924 | const char *platform_name; | 940 | const char *platform_name; |
925 | const struct device_node *platform_of_node; | 941 | struct device_node *platform_of_node; |
926 | int be_id; /* optional ID for machine driver BE identification */ | 942 | int be_id; /* optional ID for machine driver BE identification */ |
927 | 943 | ||
928 | const struct snd_soc_pcm_stream *params; | 944 | const struct snd_soc_pcm_stream *params; |
@@ -994,7 +1010,7 @@ struct snd_soc_aux_dev { | |||
994 | const struct device_node *codec_of_node; | 1010 | const struct device_node *codec_of_node; |
995 | 1011 | ||
996 | /* codec/machine specific init - e.g. add machine controls */ | 1012 | /* codec/machine specific init - e.g. add machine controls */ |
997 | int (*init)(struct snd_soc_dapm_context *dapm); | 1013 | int (*init)(struct snd_soc_component *component); |
998 | }; | 1014 | }; |
999 | 1015 | ||
1000 | /* SoC card */ | 1016 | /* SoC card */ |
@@ -1112,6 +1128,7 @@ struct snd_soc_pcm_runtime { | |||
1112 | struct snd_soc_platform *platform; | 1128 | struct snd_soc_platform *platform; |
1113 | struct snd_soc_dai *codec_dai; | 1129 | struct snd_soc_dai *codec_dai; |
1114 | struct snd_soc_dai *cpu_dai; | 1130 | struct snd_soc_dai *cpu_dai; |
1131 | struct snd_soc_component *component; /* Only valid for AUX dev rtds */ | ||
1115 | 1132 | ||
1116 | struct snd_soc_dai **codec_dais; | 1133 | struct snd_soc_dai **codec_dais; |
1117 | unsigned int num_codecs; | 1134 | unsigned int num_codecs; |
@@ -1260,9 +1277,6 @@ void snd_soc_component_async_complete(struct snd_soc_component *component); | |||
1260 | int snd_soc_component_test_bits(struct snd_soc_component *component, | 1277 | int snd_soc_component_test_bits(struct snd_soc_component *component, |
1261 | unsigned int reg, unsigned int mask, unsigned int value); | 1278 | unsigned int reg, unsigned int mask, unsigned int value); |
1262 | 1279 | ||
1263 | int snd_soc_component_init_io(struct snd_soc_component *component, | ||
1264 | struct regmap *regmap); | ||
1265 | |||
1266 | /* device driver data */ | 1280 | /* device driver data */ |
1267 | 1281 | ||
1268 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, | 1282 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, |
@@ -1276,26 +1290,37 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) | |||
1276 | return card->drvdata; | 1290 | return card->drvdata; |
1277 | } | 1291 | } |
1278 | 1292 | ||
1293 | static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, | ||
1294 | void *data) | ||
1295 | { | ||
1296 | dev_set_drvdata(c->dev, data); | ||
1297 | } | ||
1298 | |||
1299 | static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) | ||
1300 | { | ||
1301 | return dev_get_drvdata(c->dev); | ||
1302 | } | ||
1303 | |||
1279 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, | 1304 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, |
1280 | void *data) | 1305 | void *data) |
1281 | { | 1306 | { |
1282 | dev_set_drvdata(codec->dev, data); | 1307 | snd_soc_component_set_drvdata(&codec->component, data); |
1283 | } | 1308 | } |
1284 | 1309 | ||
1285 | static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) | 1310 | static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) |
1286 | { | 1311 | { |
1287 | return dev_get_drvdata(codec->dev); | 1312 | return snd_soc_component_get_drvdata(&codec->component); |
1288 | } | 1313 | } |
1289 | 1314 | ||
1290 | static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform, | 1315 | static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform, |
1291 | void *data) | 1316 | void *data) |
1292 | { | 1317 | { |
1293 | dev_set_drvdata(platform->dev, data); | 1318 | snd_soc_component_set_drvdata(&platform->component, data); |
1294 | } | 1319 | } |
1295 | 1320 | ||
1296 | static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform) | 1321 | static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform) |
1297 | { | 1322 | { |
1298 | return dev_get_drvdata(platform->dev); | 1323 | return snd_soc_component_get_drvdata(&platform->component); |
1299 | } | 1324 | } |
1300 | 1325 | ||
1301 | static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, | 1326 | static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, |
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index f634f8f85db5..cae9c9d4ef22 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h | |||
@@ -80,8 +80,6 @@ struct vx_pipe { | |||
80 | 80 | ||
81 | unsigned int references; /* an output pipe may be used for monitoring and/or playback */ | 81 | unsigned int references; /* an output pipe may be used for monitoring and/or playback */ |
82 | struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/ | 82 | struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/ |
83 | |||
84 | struct tasklet_struct start_tq; | ||
85 | }; | 83 | }; |
86 | 84 | ||
87 | struct vx_core; | 85 | struct vx_core; |
@@ -165,9 +163,7 @@ struct vx_core { | |||
165 | struct snd_vx_hardware *hw; | 163 | struct snd_vx_hardware *hw; |
166 | struct snd_vx_ops *ops; | 164 | struct snd_vx_ops *ops; |
167 | 165 | ||
168 | spinlock_t lock; | 166 | struct mutex lock; |
169 | spinlock_t irq_lock; | ||
170 | struct tasklet_struct tq; | ||
171 | 167 | ||
172 | unsigned int chip_status; | 168 | unsigned int chip_status; |
173 | unsigned int pcm_running; | 169 | unsigned int pcm_running; |
@@ -223,6 +219,7 @@ void snd_vx_free_firmware(struct vx_core *chip); | |||
223 | * interrupt handler; exported for pcmcia | 219 | * interrupt handler; exported for pcmcia |
224 | */ | 220 | */ |
225 | irqreturn_t snd_vx_irq_handler(int irq, void *dev); | 221 | irqreturn_t snd_vx_irq_handler(int irq, void *dev); |
222 | irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev); | ||
226 | 223 | ||
227 | /* | 224 | /* |
228 | * lowlevel functions | 225 | * lowlevel functions |
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h index 0194a641e4e2..b04ee7e5a466 100644 --- a/include/trace/events/asoc.h +++ b/include/trace/events/asoc.h | |||
@@ -175,7 +175,7 @@ TRACE_EVENT(snd_soc_dapm_output_path, | |||
175 | __entry->path_sink = (long)path->sink; | 175 | __entry->path_sink = (long)path->sink; |
176 | ), | 176 | ), |
177 | 177 | ||
178 | TP_printk("%c%s -> %s -> %s\n", | 178 | TP_printk("%c%s -> %s -> %s", |
179 | (int) __entry->path_sink && | 179 | (int) __entry->path_sink && |
180 | (int) __entry->path_connect ? '*' : ' ', | 180 | (int) __entry->path_connect ? '*' : ' ', |
181 | __get_str(wname), __get_str(pname), __get_str(psname)) | 181 | __get_str(wname), __get_str(pname), __get_str(psname)) |
@@ -204,7 +204,7 @@ TRACE_EVENT(snd_soc_dapm_input_path, | |||
204 | __entry->path_source = (long)path->source; | 204 | __entry->path_source = (long)path->source; |
205 | ), | 205 | ), |
206 | 206 | ||
207 | TP_printk("%c%s <- %s <- %s\n", | 207 | TP_printk("%c%s <- %s <- %s", |
208 | (int) __entry->path_source && | 208 | (int) __entry->path_source && |
209 | (int) __entry->path_connect ? '*' : ' ', | 209 | (int) __entry->path_connect ? '*' : ' ', |
210 | __get_str(wname), __get_str(pname), __get_str(psname)) | 210 | __get_str(wname), __get_str(pname), __get_str(psname)) |
@@ -226,7 +226,7 @@ TRACE_EVENT(snd_soc_dapm_connected, | |||
226 | __entry->stream = stream; | 226 | __entry->stream = stream; |
227 | ), | 227 | ), |
228 | 228 | ||
229 | TP_printk("%s: found %d paths\n", | 229 | TP_printk("%s: found %d paths", |
230 | __entry->stream ? "capture" : "playback", __entry->paths) | 230 | __entry->stream ? "capture" : "playback", __entry->paths) |
231 | ); | 231 | ); |
232 | 232 | ||
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 32168f7ffce3..6ee586728df9 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h | |||
@@ -219,7 +219,8 @@ typedef int __bitwise snd_pcm_format_t; | |||
219 | #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ | 219 | #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ |
220 | #define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ | 220 | #define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */ |
221 | #define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ | 221 | #define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */ |
222 | #define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE | 222 | #define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */ |
223 | #define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_LE | ||
223 | 224 | ||
224 | #ifdef SNDRV_LITTLE_ENDIAN | 225 | #ifdef SNDRV_LITTLE_ENDIAN |
225 | #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE | 226 | #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE |
diff --git a/sound/core/misc.c b/sound/core/misc.c index 30e027ecf4da..f2e8226c88fb 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c | |||
@@ -145,6 +145,8 @@ EXPORT_SYMBOL(snd_pci_quirk_lookup_id); | |||
145 | const struct snd_pci_quirk * | 145 | const struct snd_pci_quirk * |
146 | snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) | 146 | snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) |
147 | { | 147 | { |
148 | if (!pci) | ||
149 | return NULL; | ||
148 | return snd_pci_quirk_lookup_id(pci->subsystem_vendor, | 150 | return snd_pci_quirk_lookup_id(pci->subsystem_vendor, |
149 | pci->subsystem_device, | 151 | pci->subsystem_device, |
150 | list); | 152 | list); |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 43932e8dce66..42ded997b223 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -215,6 +215,7 @@ static char *snd_pcm_format_names[] = { | |||
215 | FORMAT(G723_40_1B), | 215 | FORMAT(G723_40_1B), |
216 | FORMAT(DSD_U8), | 216 | FORMAT(DSD_U8), |
217 | FORMAT(DSD_U16_LE), | 217 | FORMAT(DSD_U16_LE), |
218 | FORMAT(DSD_U32_LE), | ||
218 | }; | 219 | }; |
219 | 220 | ||
220 | const char *snd_pcm_format_name(snd_pcm_format_t format) | 221 | const char *snd_pcm_format_name(snd_pcm_format_t format) |
@@ -698,6 +699,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
698 | } | 699 | } |
699 | substream->group = &substream->self_group; | 700 | substream->group = &substream->self_group; |
700 | spin_lock_init(&substream->self_group.lock); | 701 | spin_lock_init(&substream->self_group.lock); |
702 | mutex_init(&substream->self_group.mutex); | ||
701 | INIT_LIST_HEAD(&substream->self_group.substreams); | 703 | INIT_LIST_HEAD(&substream->self_group.substreams); |
702 | list_add_tail(&substream->link_list, &substream->self_group.substreams); | 704 | list_add_tail(&substream->link_list, &substream->self_group.substreams); |
703 | atomic_set(&substream->mmap_count, 0); | 705 | atomic_set(&substream->mmap_count, 0); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 0032278567ad..dfc28542a007 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1113,18 +1113,20 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, | |||
1113 | 1113 | ||
1114 | EXPORT_SYMBOL(snd_interval_list); | 1114 | EXPORT_SYMBOL(snd_interval_list); |
1115 | 1115 | ||
1116 | static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) | 1116 | static int snd_interval_step(struct snd_interval *i, unsigned int step) |
1117 | { | 1117 | { |
1118 | unsigned int n; | 1118 | unsigned int n; |
1119 | int changed = 0; | 1119 | int changed = 0; |
1120 | n = (i->min - min) % step; | 1120 | n = i->min % step; |
1121 | if (n != 0 || i->openmin) { | 1121 | if (n != 0 || i->openmin) { |
1122 | i->min += step - n; | 1122 | i->min += step - n; |
1123 | i->openmin = 0; | ||
1123 | changed = 1; | 1124 | changed = 1; |
1124 | } | 1125 | } |
1125 | n = (i->max - min) % step; | 1126 | n = i->max % step; |
1126 | if (n != 0 || i->openmax) { | 1127 | if (n != 0 || i->openmax) { |
1127 | i->max -= n; | 1128 | i->max -= n; |
1129 | i->openmax = 0; | ||
1128 | changed = 1; | 1130 | changed = 1; |
1129 | } | 1131 | } |
1130 | if (snd_interval_checkempty(i)) { | 1132 | if (snd_interval_checkempty(i)) { |
@@ -1427,7 +1429,7 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, | |||
1427 | struct snd_pcm_hw_rule *rule) | 1429 | struct snd_pcm_hw_rule *rule) |
1428 | { | 1430 | { |
1429 | unsigned long step = (unsigned long) rule->private; | 1431 | unsigned long step = (unsigned long) rule->private; |
1430 | return snd_interval_step(hw_param_interval(params, rule->var), 0, step); | 1432 | return snd_interval_step(hw_param_interval(params, rule->var), step); |
1431 | } | 1433 | } |
1432 | 1434 | ||
1433 | /** | 1435 | /** |
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 2c6fd80e0bd1..ae7a0feb3b76 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -148,6 +148,10 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = { | |||
148 | .width = 16, .phys = 16, .le = 1, .signd = 0, | 148 | .width = 16, .phys = 16, .le = 1, .signd = 0, |
149 | .silence = { 0x69, 0x69 }, | 149 | .silence = { 0x69, 0x69 }, |
150 | }, | 150 | }, |
151 | [SNDRV_PCM_FORMAT_DSD_U32_LE] = { | ||
152 | .width = 32, .phys = 32, .le = 1, .signd = 0, | ||
153 | .silence = { 0x69, 0x69, 0x69, 0x69 }, | ||
154 | }, | ||
151 | /* FIXME: the following three formats are not defined properly yet */ | 155 | /* FIXME: the following three formats are not defined properly yet */ |
152 | [SNDRV_PCM_FORMAT_MPEG] = { | 156 | [SNDRV_PCM_FORMAT_MPEG] = { |
153 | .le = -1, .signd = -1, | 157 | .le = -1, .signd = -1, |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8cd2f930ad0b..85fe1a216225 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -74,11 +74,68 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); | |||
74 | * | 74 | * |
75 | */ | 75 | */ |
76 | 76 | ||
77 | DEFINE_RWLOCK(snd_pcm_link_rwlock); | 77 | static DEFINE_RWLOCK(snd_pcm_link_rwlock); |
78 | EXPORT_SYMBOL(snd_pcm_link_rwlock); | ||
79 | |||
80 | static DECLARE_RWSEM(snd_pcm_link_rwsem); | 78 | static DECLARE_RWSEM(snd_pcm_link_rwsem); |
81 | 79 | ||
80 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream) | ||
81 | { | ||
82 | if (substream->pcm->nonatomic) { | ||
83 | down_read(&snd_pcm_link_rwsem); | ||
84 | mutex_lock(&substream->self_group.mutex); | ||
85 | } else { | ||
86 | read_lock(&snd_pcm_link_rwlock); | ||
87 | spin_lock(&substream->self_group.lock); | ||
88 | } | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); | ||
91 | |||
92 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) | ||
93 | { | ||
94 | if (substream->pcm->nonatomic) { | ||
95 | mutex_unlock(&substream->self_group.mutex); | ||
96 | up_read(&snd_pcm_link_rwsem); | ||
97 | } else { | ||
98 | spin_unlock(&substream->self_group.lock); | ||
99 | read_unlock(&snd_pcm_link_rwlock); | ||
100 | } | ||
101 | } | ||
102 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); | ||
103 | |||
104 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) | ||
105 | { | ||
106 | if (!substream->pcm->nonatomic) | ||
107 | local_irq_disable(); | ||
108 | snd_pcm_stream_lock(substream); | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); | ||
111 | |||
112 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) | ||
113 | { | ||
114 | snd_pcm_stream_unlock(substream); | ||
115 | if (!substream->pcm->nonatomic) | ||
116 | local_irq_enable(); | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); | ||
119 | |||
120 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) | ||
121 | { | ||
122 | unsigned long flags = 0; | ||
123 | if (!substream->pcm->nonatomic) | ||
124 | local_irq_save(flags); | ||
125 | snd_pcm_stream_lock(substream); | ||
126 | return flags; | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | ||
129 | |||
130 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, | ||
131 | unsigned long flags) | ||
132 | { | ||
133 | snd_pcm_stream_unlock(substream); | ||
134 | if (!substream->pcm->nonatomic) | ||
135 | local_irq_restore(flags); | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); | ||
138 | |||
82 | static inline mm_segment_t snd_enter_user(void) | 139 | static inline mm_segment_t snd_enter_user(void) |
83 | { | 140 | { |
84 | mm_segment_t fs = get_fs(); | 141 | mm_segment_t fs = get_fs(); |
@@ -727,9 +784,14 @@ static int snd_pcm_action_group(struct action_ops *ops, | |||
727 | int res = 0; | 784 | int res = 0; |
728 | 785 | ||
729 | snd_pcm_group_for_each_entry(s, substream) { | 786 | snd_pcm_group_for_each_entry(s, substream) { |
730 | if (do_lock && s != substream) | 787 | if (do_lock && s != substream) { |
731 | spin_lock_nested(&s->self_group.lock, | 788 | if (s->pcm->nonatomic) |
732 | SINGLE_DEPTH_NESTING); | 789 | mutex_lock_nested(&s->self_group.mutex, |
790 | SINGLE_DEPTH_NESTING); | ||
791 | else | ||
792 | spin_lock_nested(&s->self_group.lock, | ||
793 | SINGLE_DEPTH_NESTING); | ||
794 | } | ||
733 | res = ops->pre_action(s, state); | 795 | res = ops->pre_action(s, state); |
734 | if (res < 0) | 796 | if (res < 0) |
735 | goto _unlock; | 797 | goto _unlock; |
@@ -755,8 +817,12 @@ static int snd_pcm_action_group(struct action_ops *ops, | |||
755 | if (do_lock) { | 817 | if (do_lock) { |
756 | /* unlock streams */ | 818 | /* unlock streams */ |
757 | snd_pcm_group_for_each_entry(s1, substream) { | 819 | snd_pcm_group_for_each_entry(s1, substream) { |
758 | if (s1 != substream) | 820 | if (s1 != substream) { |
759 | spin_unlock(&s1->self_group.lock); | 821 | if (s->pcm->nonatomic) |
822 | mutex_unlock(&s1->self_group.mutex); | ||
823 | else | ||
824 | spin_unlock(&s1->self_group.lock); | ||
825 | } | ||
760 | if (s1 == s) /* end */ | 826 | if (s1 == s) /* end */ |
761 | break; | 827 | break; |
762 | } | 828 | } |
@@ -784,6 +850,27 @@ static int snd_pcm_action_single(struct action_ops *ops, | |||
784 | return res; | 850 | return res; |
785 | } | 851 | } |
786 | 852 | ||
853 | /* call in mutex-protected context */ | ||
854 | static int snd_pcm_action_mutex(struct action_ops *ops, | ||
855 | struct snd_pcm_substream *substream, | ||
856 | int state) | ||
857 | { | ||
858 | int res; | ||
859 | |||
860 | if (snd_pcm_stream_linked(substream)) { | ||
861 | if (!mutex_trylock(&substream->group->mutex)) { | ||
862 | mutex_unlock(&substream->self_group.mutex); | ||
863 | mutex_lock(&substream->group->mutex); | ||
864 | mutex_lock(&substream->self_group.mutex); | ||
865 | } | ||
866 | res = snd_pcm_action_group(ops, substream, state, 1); | ||
867 | mutex_unlock(&substream->group->mutex); | ||
868 | } else { | ||
869 | res = snd_pcm_action_single(ops, substream, state); | ||
870 | } | ||
871 | return res; | ||
872 | } | ||
873 | |||
787 | /* | 874 | /* |
788 | * Note: call with stream lock | 875 | * Note: call with stream lock |
789 | */ | 876 | */ |
@@ -793,6 +880,9 @@ static int snd_pcm_action(struct action_ops *ops, | |||
793 | { | 880 | { |
794 | int res; | 881 | int res; |
795 | 882 | ||
883 | if (substream->pcm->nonatomic) | ||
884 | return snd_pcm_action_mutex(ops, substream, state); | ||
885 | |||
796 | if (snd_pcm_stream_linked(substream)) { | 886 | if (snd_pcm_stream_linked(substream)) { |
797 | if (!spin_trylock(&substream->group->lock)) { | 887 | if (!spin_trylock(&substream->group->lock)) { |
798 | spin_unlock(&substream->self_group.lock); | 888 | spin_unlock(&substream->self_group.lock); |
@@ -807,6 +897,29 @@ static int snd_pcm_action(struct action_ops *ops, | |||
807 | return res; | 897 | return res; |
808 | } | 898 | } |
809 | 899 | ||
900 | static int snd_pcm_action_lock_mutex(struct action_ops *ops, | ||
901 | struct snd_pcm_substream *substream, | ||
902 | int state) | ||
903 | { | ||
904 | int res; | ||
905 | |||
906 | down_read(&snd_pcm_link_rwsem); | ||
907 | if (snd_pcm_stream_linked(substream)) { | ||
908 | mutex_lock(&substream->group->mutex); | ||
909 | mutex_lock_nested(&substream->self_group.mutex, | ||
910 | SINGLE_DEPTH_NESTING); | ||
911 | res = snd_pcm_action_group(ops, substream, state, 1); | ||
912 | mutex_unlock(&substream->self_group.mutex); | ||
913 | mutex_unlock(&substream->group->mutex); | ||
914 | } else { | ||
915 | mutex_lock(&substream->self_group.mutex); | ||
916 | res = snd_pcm_action_single(ops, substream, state); | ||
917 | mutex_unlock(&substream->self_group.mutex); | ||
918 | } | ||
919 | up_read(&snd_pcm_link_rwsem); | ||
920 | return res; | ||
921 | } | ||
922 | |||
810 | /* | 923 | /* |
811 | * Note: don't use any locks before | 924 | * Note: don't use any locks before |
812 | */ | 925 | */ |
@@ -816,6 +929,9 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops, | |||
816 | { | 929 | { |
817 | int res; | 930 | int res; |
818 | 931 | ||
932 | if (substream->pcm->nonatomic) | ||
933 | return snd_pcm_action_lock_mutex(ops, substream, state); | ||
934 | |||
819 | read_lock_irq(&snd_pcm_link_rwlock); | 935 | read_lock_irq(&snd_pcm_link_rwlock); |
820 | if (snd_pcm_stream_linked(substream)) { | 936 | if (snd_pcm_stream_linked(substream)) { |
821 | spin_lock(&substream->group->lock); | 937 | spin_lock(&substream->group->lock); |
@@ -1634,7 +1750,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) | |||
1634 | down_write(&snd_pcm_link_rwsem); | 1750 | down_write(&snd_pcm_link_rwsem); |
1635 | write_lock_irq(&snd_pcm_link_rwlock); | 1751 | write_lock_irq(&snd_pcm_link_rwlock); |
1636 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || | 1752 | if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || |
1637 | substream->runtime->status->state != substream1->runtime->status->state) { | 1753 | substream->runtime->status->state != substream1->runtime->status->state || |
1754 | substream->pcm->nonatomic != substream1->pcm->nonatomic) { | ||
1638 | res = -EBADFD; | 1755 | res = -EBADFD; |
1639 | goto _end; | 1756 | goto _end; |
1640 | } | 1757 | } |
@@ -1646,6 +1763,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) | |||
1646 | substream->group = group; | 1763 | substream->group = group; |
1647 | group = NULL; | 1764 | group = NULL; |
1648 | spin_lock_init(&substream->group->lock); | 1765 | spin_lock_init(&substream->group->lock); |
1766 | mutex_init(&substream->group->mutex); | ||
1649 | INIT_LIST_HEAD(&substream->group->substreams); | 1767 | INIT_LIST_HEAD(&substream->group->substreams); |
1650 | list_add_tail(&substream->link_list, &substream->group->substreams); | 1768 | list_add_tail(&substream->link_list, &substream->group->substreams); |
1651 | substream->group->count = 1; | 1769 | substream->group->count = 1; |
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 83596891cde4..e8cc16993903 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -117,7 +117,7 @@ static int vx_reset_chk(struct vx_core *chip) | |||
117 | * | 117 | * |
118 | * returns 0 if successful, or a negative error code. | 118 | * returns 0 if successful, or a negative error code. |
119 | * the error code can be VX-specific, retrieved via vx_get_error(). | 119 | * the error code can be VX-specific, retrieved via vx_get_error(). |
120 | * NB: call with spinlock held! | 120 | * NB: call with mutex held! |
121 | */ | 121 | */ |
122 | static int vx_transfer_end(struct vx_core *chip, int cmd) | 122 | static int vx_transfer_end(struct vx_core *chip, int cmd) |
123 | { | 123 | { |
@@ -155,7 +155,7 @@ static int vx_transfer_end(struct vx_core *chip, int cmd) | |||
155 | * | 155 | * |
156 | * returns 0 if successful, or a negative error code. | 156 | * returns 0 if successful, or a negative error code. |
157 | * the error code can be VX-specific, retrieved via vx_get_error(). | 157 | * the error code can be VX-specific, retrieved via vx_get_error(). |
158 | * NB: call with spinlock held! | 158 | * NB: call with mutex held! |
159 | */ | 159 | */ |
160 | static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) | 160 | static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) |
161 | { | 161 | { |
@@ -236,7 +236,7 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) | |||
236 | * returns 0 if successful, or a negative error code. | 236 | * returns 0 if successful, or a negative error code. |
237 | * the error code can be VX-specific, retrieved via vx_get_error(). | 237 | * the error code can be VX-specific, retrieved via vx_get_error(). |
238 | * | 238 | * |
239 | * this function doesn't call spinlock at all. | 239 | * this function doesn't call mutex lock at all. |
240 | */ | 240 | */ |
241 | int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) | 241 | int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) |
242 | { | 242 | { |
@@ -337,7 +337,7 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) | |||
337 | 337 | ||
338 | 338 | ||
339 | /* | 339 | /* |
340 | * vx_send_msg - send a DSP message with spinlock | 340 | * vx_send_msg - send a DSP message with mutex |
341 | * @rmh: the rmh record to send and receive | 341 | * @rmh: the rmh record to send and receive |
342 | * | 342 | * |
343 | * returns 0 if successful, or a negative error code. | 343 | * returns 0 if successful, or a negative error code. |
@@ -345,12 +345,11 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) | |||
345 | */ | 345 | */ |
346 | int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) | 346 | int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) |
347 | { | 347 | { |
348 | unsigned long flags; | ||
349 | int err; | 348 | int err; |
350 | 349 | ||
351 | spin_lock_irqsave(&chip->lock, flags); | 350 | mutex_lock(&chip->lock); |
352 | err = vx_send_msg_nolock(chip, rmh); | 351 | err = vx_send_msg_nolock(chip, rmh); |
353 | spin_unlock_irqrestore(&chip->lock, flags); | 352 | mutex_unlock(&chip->lock); |
354 | return err; | 353 | return err; |
355 | } | 354 | } |
356 | 355 | ||
@@ -362,7 +361,7 @@ int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) | |||
362 | * returns 0 if successful, or a negative error code. | 361 | * returns 0 if successful, or a negative error code. |
363 | * the error code can be VX-specific, retrieved via vx_get_error(). | 362 | * the error code can be VX-specific, retrieved via vx_get_error(). |
364 | * | 363 | * |
365 | * this function doesn't call spinlock at all. | 364 | * this function doesn't call mutex at all. |
366 | * | 365 | * |
367 | * unlike RMH, no command is sent to DSP. | 366 | * unlike RMH, no command is sent to DSP. |
368 | */ | 367 | */ |
@@ -398,19 +397,18 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd) | |||
398 | 397 | ||
399 | 398 | ||
400 | /* | 399 | /* |
401 | * vx_send_rih - send an RIH with spinlock | 400 | * vx_send_rih - send an RIH with mutex |
402 | * @cmd: the command to send | 401 | * @cmd: the command to send |
403 | * | 402 | * |
404 | * see vx_send_rih_nolock(). | 403 | * see vx_send_rih_nolock(). |
405 | */ | 404 | */ |
406 | int vx_send_rih(struct vx_core *chip, int cmd) | 405 | int vx_send_rih(struct vx_core *chip, int cmd) |
407 | { | 406 | { |
408 | unsigned long flags; | ||
409 | int err; | 407 | int err; |
410 | 408 | ||
411 | spin_lock_irqsave(&chip->lock, flags); | 409 | mutex_lock(&chip->lock); |
412 | err = vx_send_rih_nolock(chip, cmd); | 410 | err = vx_send_rih_nolock(chip, cmd); |
413 | spin_unlock_irqrestore(&chip->lock, flags); | 411 | mutex_unlock(&chip->lock); |
414 | return err; | 412 | return err; |
415 | } | 413 | } |
416 | 414 | ||
@@ -482,30 +480,30 @@ static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret) | |||
482 | int err; | 480 | int err; |
483 | 481 | ||
484 | vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT); | 482 | vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT); |
485 | spin_lock(&chip->lock); | 483 | mutex_lock(&chip->lock); |
486 | err = vx_send_msg_nolock(chip, &chip->irq_rmh); | 484 | err = vx_send_msg_nolock(chip, &chip->irq_rmh); |
487 | if (err < 0) | 485 | if (err < 0) |
488 | *ret = 0; | 486 | *ret = 0; |
489 | else | 487 | else |
490 | *ret = chip->irq_rmh.Stat[0]; | 488 | *ret = chip->irq_rmh.Stat[0]; |
491 | spin_unlock(&chip->lock); | 489 | mutex_unlock(&chip->lock); |
492 | return err; | 490 | return err; |
493 | } | 491 | } |
494 | 492 | ||
495 | 493 | ||
496 | /* | 494 | /* |
497 | * vx_interrupt - soft irq handler | 495 | * snd_vx_threaded_irq_handler - threaded irq handler |
498 | */ | 496 | */ |
499 | static void vx_interrupt(unsigned long private_data) | 497 | irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev) |
500 | { | 498 | { |
501 | struct vx_core *chip = (struct vx_core *) private_data; | 499 | struct vx_core *chip = dev; |
502 | unsigned int events; | 500 | unsigned int events; |
503 | 501 | ||
504 | if (chip->chip_status & VX_STAT_IS_STALE) | 502 | if (chip->chip_status & VX_STAT_IS_STALE) |
505 | return; | 503 | return IRQ_HANDLED; |
506 | 504 | ||
507 | if (vx_test_irq_src(chip, &events) < 0) | 505 | if (vx_test_irq_src(chip, &events) < 0) |
508 | return; | 506 | return IRQ_HANDLED; |
509 | 507 | ||
510 | #if 0 | 508 | #if 0 |
511 | if (events & 0x000800) | 509 | if (events & 0x000800) |
@@ -519,7 +517,7 @@ static void vx_interrupt(unsigned long private_data) | |||
519 | */ | 517 | */ |
520 | if (events & FATAL_DSP_ERROR) { | 518 | if (events & FATAL_DSP_ERROR) { |
521 | snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n"); | 519 | snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n"); |
522 | return; | 520 | return IRQ_HANDLED; |
523 | } | 521 | } |
524 | 522 | ||
525 | /* The start on time code conditions are filled (ie the time code | 523 | /* The start on time code conditions are filled (ie the time code |
@@ -534,8 +532,9 @@ static void vx_interrupt(unsigned long private_data) | |||
534 | 532 | ||
535 | /* update the pcm streams */ | 533 | /* update the pcm streams */ |
536 | vx_pcm_update_intr(chip, events); | 534 | vx_pcm_update_intr(chip, events); |
535 | return IRQ_HANDLED; | ||
537 | } | 536 | } |
538 | 537 | EXPORT_SYMBOL(snd_vx_threaded_irq_handler); | |
539 | 538 | ||
540 | /** | 539 | /** |
541 | * snd_vx_irq_handler - interrupt handler | 540 | * snd_vx_irq_handler - interrupt handler |
@@ -548,8 +547,8 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev) | |||
548 | (chip->chip_status & VX_STAT_IS_STALE)) | 547 | (chip->chip_status & VX_STAT_IS_STALE)) |
549 | return IRQ_NONE; | 548 | return IRQ_NONE; |
550 | if (! vx_test_and_ack(chip)) | 549 | if (! vx_test_and_ack(chip)) |
551 | tasklet_schedule(&chip->tq); | 550 | return IRQ_WAKE_THREAD; |
552 | return IRQ_HANDLED; | 551 | return IRQ_NONE; |
553 | } | 552 | } |
554 | 553 | ||
555 | EXPORT_SYMBOL(snd_vx_irq_handler); | 554 | EXPORT_SYMBOL(snd_vx_irq_handler); |
@@ -790,13 +789,11 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, | |||
790 | snd_printk(KERN_ERR "vx_core: no memory\n"); | 789 | snd_printk(KERN_ERR "vx_core: no memory\n"); |
791 | return NULL; | 790 | return NULL; |
792 | } | 791 | } |
793 | spin_lock_init(&chip->lock); | 792 | mutex_init(&chip->lock); |
794 | spin_lock_init(&chip->irq_lock); | ||
795 | chip->irq = -1; | 793 | chip->irq = -1; |
796 | chip->hw = hw; | 794 | chip->hw = hw; |
797 | chip->type = hw->type; | 795 | chip->type = hw->type; |
798 | chip->ops = ops; | 796 | chip->ops = ops; |
799 | tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip); | ||
800 | mutex_init(&chip->mixer_mutex); | 797 | mutex_init(&chip->mixer_mutex); |
801 | 798 | ||
802 | chip->card = card; | 799 | chip->card = card; |
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index c71b8d148d7f..3b6823fc0606 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c | |||
@@ -32,17 +32,15 @@ | |||
32 | */ | 32 | */ |
33 | static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data) | 33 | static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data) |
34 | { | 34 | { |
35 | unsigned long flags; | ||
36 | |||
37 | if (snd_BUG_ON(!chip->ops->write_codec)) | 35 | if (snd_BUG_ON(!chip->ops->write_codec)) |
38 | return; | 36 | return; |
39 | 37 | ||
40 | if (chip->chip_status & VX_STAT_IS_STALE) | 38 | if (chip->chip_status & VX_STAT_IS_STALE) |
41 | return; | 39 | return; |
42 | 40 | ||
43 | spin_lock_irqsave(&chip->lock, flags); | 41 | mutex_lock(&chip->lock); |
44 | chip->ops->write_codec(chip, codec, data); | 42 | chip->ops->write_codec(chip, codec, data); |
45 | spin_unlock_irqrestore(&chip->lock, flags); | 43 | mutex_unlock(&chip->lock); |
46 | } | 44 | } |
47 | 45 | ||
48 | /* | 46 | /* |
@@ -178,14 +176,12 @@ void vx_reset_codec(struct vx_core *chip, int cold_reset) | |||
178 | */ | 176 | */ |
179 | static void vx_change_audio_source(struct vx_core *chip, int src) | 177 | static void vx_change_audio_source(struct vx_core *chip, int src) |
180 | { | 178 | { |
181 | unsigned long flags; | ||
182 | |||
183 | if (chip->chip_status & VX_STAT_IS_STALE) | 179 | if (chip->chip_status & VX_STAT_IS_STALE) |
184 | return; | 180 | return; |
185 | 181 | ||
186 | spin_lock_irqsave(&chip->lock, flags); | 182 | mutex_lock(&chip->lock); |
187 | chip->ops->change_audio_source(chip, src); | 183 | chip->ops->change_audio_source(chip, src); |
188 | spin_unlock_irqrestore(&chip->lock, flags); | 184 | mutex_unlock(&chip->lock); |
189 | } | 185 | } |
190 | 186 | ||
191 | 187 | ||
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index deed5efff33c..11467272089e 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c | |||
@@ -229,7 +229,7 @@ static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *st | |||
229 | 229 | ||
230 | vx_init_rmh(&rmh, CMD_PIPE_STATE); | 230 | vx_init_rmh(&rmh, CMD_PIPE_STATE); |
231 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); | 231 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); |
232 | err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 232 | err = vx_send_msg(chip, &rmh); |
233 | if (! err) | 233 | if (! err) |
234 | *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; | 234 | *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; |
235 | return err; | 235 | return err; |
@@ -280,7 +280,7 @@ static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe) | |||
280 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); | 280 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); |
281 | rmh.Cmd[0] |= 1; | 281 | rmh.Cmd[0] |= 1; |
282 | 282 | ||
283 | err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 283 | err = vx_send_msg(chip, &rmh); |
284 | if (! err) { | 284 | if (! err) { |
285 | if (rmh.Stat[0]) | 285 | if (rmh.Stat[0]) |
286 | err = 1; | 286 | err = 1; |
@@ -300,7 +300,7 @@ static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe) | |||
300 | if (pipe->is_capture) | 300 | if (pipe->is_capture) |
301 | rmh.Cmd[0] |= COMMAND_RECORD_MASK; | 301 | rmh.Cmd[0] |= COMMAND_RECORD_MASK; |
302 | rmh.Cmd[1] = 1 << pipe->number; | 302 | rmh.Cmd[1] = 1 << pipe->number; |
303 | return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 303 | return vx_send_msg(chip, &rmh); |
304 | } | 304 | } |
305 | 305 | ||
306 | /* | 306 | /* |
@@ -311,7 +311,7 @@ static int vx_send_irqa(struct vx_core *chip) | |||
311 | struct vx_rmh rmh; | 311 | struct vx_rmh rmh; |
312 | 312 | ||
313 | vx_init_rmh(&rmh, CMD_SEND_IRQA); | 313 | vx_init_rmh(&rmh, CMD_SEND_IRQA); |
314 | return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 314 | return vx_send_msg(chip, &rmh); |
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
@@ -389,7 +389,7 @@ static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe) | |||
389 | struct vx_rmh rmh; | 389 | struct vx_rmh rmh; |
390 | vx_init_rmh(&rmh, CMD_STOP_PIPE); | 390 | vx_init_rmh(&rmh, CMD_STOP_PIPE); |
391 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); | 391 | vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); |
392 | return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 392 | return vx_send_msg(chip, &rmh); |
393 | } | 393 | } |
394 | 394 | ||
395 | 395 | ||
@@ -477,7 +477,7 @@ static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe) | |||
477 | vx_init_rmh(&rmh, CMD_START_ONE_STREAM); | 477 | vx_init_rmh(&rmh, CMD_START_ONE_STREAM); |
478 | vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); | 478 | vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); |
479 | vx_set_differed_time(chip, &rmh, pipe); | 479 | vx_set_differed_time(chip, &rmh, pipe); |
480 | return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 480 | return vx_send_msg(chip, &rmh); |
481 | } | 481 | } |
482 | 482 | ||
483 | 483 | ||
@@ -492,7 +492,7 @@ static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe) | |||
492 | 492 | ||
493 | vx_init_rmh(&rmh, CMD_STOP_STREAM); | 493 | vx_init_rmh(&rmh, CMD_STOP_STREAM); |
494 | vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); | 494 | vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); |
495 | return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ | 495 | return vx_send_msg(chip, &rmh); |
496 | } | 496 | } |
497 | 497 | ||
498 | 498 | ||
@@ -520,8 +520,6 @@ static struct snd_pcm_hardware vx_pcm_playback_hw = { | |||
520 | }; | 520 | }; |
521 | 521 | ||
522 | 522 | ||
523 | static void vx_pcm_delayed_start(unsigned long arg); | ||
524 | |||
525 | /* | 523 | /* |
526 | * vx_pcm_playback_open - open callback for playback | 524 | * vx_pcm_playback_open - open callback for playback |
527 | */ | 525 | */ |
@@ -553,7 +551,6 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs) | |||
553 | pipe->references++; | 551 | pipe->references++; |
554 | 552 | ||
555 | pipe->substream = subs; | 553 | pipe->substream = subs; |
556 | tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); | ||
557 | chip->playback_pipes[audio] = pipe; | 554 | chip->playback_pipes[audio] = pipe; |
558 | 555 | ||
559 | runtime->hw = vx_pcm_playback_hw; | 556 | runtime->hw = vx_pcm_playback_hw; |
@@ -646,12 +643,12 @@ static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, | |||
646 | /* we don't need irqsave here, because this function | 643 | /* we don't need irqsave here, because this function |
647 | * is called from either trigger callback or irq handler | 644 | * is called from either trigger callback or irq handler |
648 | */ | 645 | */ |
649 | spin_lock(&chip->lock); | 646 | mutex_lock(&chip->lock); |
650 | vx_pseudo_dma_write(chip, runtime, pipe, size); | 647 | vx_pseudo_dma_write(chip, runtime, pipe, size); |
651 | err = vx_notify_end_of_buffer(chip, pipe); | 648 | err = vx_notify_end_of_buffer(chip, pipe); |
652 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ | 649 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ |
653 | vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); | 650 | vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); |
654 | spin_unlock(&chip->lock); | 651 | mutex_unlock(&chip->lock); |
655 | return err; | 652 | return err; |
656 | } | 653 | } |
657 | 654 | ||
@@ -728,31 +725,6 @@ static void vx_pcm_playback_update(struct vx_core *chip, | |||
728 | } | 725 | } |
729 | 726 | ||
730 | /* | 727 | /* |
731 | * start the stream and pipe. | ||
732 | * this function is called from tasklet, which is invoked by the trigger | ||
733 | * START callback. | ||
734 | */ | ||
735 | static void vx_pcm_delayed_start(unsigned long arg) | ||
736 | { | ||
737 | struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg; | ||
738 | struct vx_core *chip = subs->pcm->private_data; | ||
739 | struct vx_pipe *pipe = subs->runtime->private_data; | ||
740 | int err; | ||
741 | |||
742 | /* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/ | ||
743 | |||
744 | if ((err = vx_start_stream(chip, pipe)) < 0) { | ||
745 | snd_printk(KERN_ERR "vx: cannot start stream\n"); | ||
746 | return; | ||
747 | } | ||
748 | if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) { | ||
749 | snd_printk(KERN_ERR "vx: cannot start pipe\n"); | ||
750 | return; | ||
751 | } | ||
752 | /* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/ | ||
753 | } | ||
754 | |||
755 | /* | ||
756 | * vx_pcm_playback_trigger - trigger callback for playback | 728 | * vx_pcm_playback_trigger - trigger callback for playback |
757 | */ | 729 | */ |
758 | static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) | 730 | static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) |
@@ -769,11 +741,17 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) | |||
769 | case SNDRV_PCM_TRIGGER_RESUME: | 741 | case SNDRV_PCM_TRIGGER_RESUME: |
770 | if (! pipe->is_capture) | 742 | if (! pipe->is_capture) |
771 | vx_pcm_playback_transfer(chip, subs, pipe, 2); | 743 | vx_pcm_playback_transfer(chip, subs, pipe, 2); |
772 | /* FIXME: | 744 | err = vx_start_stream(chip, pipe); |
773 | * we trigger the pipe using tasklet, so that the interrupts are | 745 | if (err < 0) { |
774 | * issued surely after the trigger is completed. | 746 | pr_debug("vx: cannot start stream\n"); |
775 | */ | 747 | return err; |
776 | tasklet_schedule(&pipe->start_tq); | 748 | } |
749 | err = vx_toggle_pipe(chip, pipe, 1); | ||
750 | if (err < 0) { | ||
751 | pr_debug("vx: cannot start pipe\n"); | ||
752 | vx_stop_stream(chip, pipe); | ||
753 | return err; | ||
754 | } | ||
777 | chip->pcm_running++; | 755 | chip->pcm_running++; |
778 | pipe->running = 1; | 756 | pipe->running = 1; |
779 | break; | 757 | break; |
@@ -955,7 +933,6 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs) | |||
955 | if (err < 0) | 933 | if (err < 0) |
956 | return err; | 934 | return err; |
957 | pipe->substream = subs; | 935 | pipe->substream = subs; |
958 | tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); | ||
959 | chip->capture_pipes[audio] = pipe; | 936 | chip->capture_pipes[audio] = pipe; |
960 | 937 | ||
961 | /* check if monitoring is needed */ | 938 | /* check if monitoring is needed */ |
@@ -1082,7 +1059,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream | |||
1082 | count -= 3; | 1059 | count -= 3; |
1083 | } | 1060 | } |
1084 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ | 1061 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ |
1085 | vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); | 1062 | vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); |
1086 | /* read the last pending 6 bytes */ | 1063 | /* read the last pending 6 bytes */ |
1087 | count = DMA_READ_ALIGN; | 1064 | count = DMA_READ_ALIGN; |
1088 | while (count > 0) { | 1065 | while (count > 0) { |
@@ -1099,7 +1076,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream | |||
1099 | 1076 | ||
1100 | _error: | 1077 | _error: |
1101 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ | 1078 | /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ |
1102 | vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); | 1079 | vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); |
1103 | return; | 1080 | return; |
1104 | } | 1081 | } |
1105 | 1082 | ||
@@ -1275,6 +1252,7 @@ int snd_vx_pcm_new(struct vx_core *chip) | |||
1275 | pcm->private_data = chip; | 1252 | pcm->private_data = chip; |
1276 | pcm->private_free = snd_vx_pcm_free; | 1253 | pcm->private_free = snd_vx_pcm_free; |
1277 | pcm->info_flags = 0; | 1254 | pcm->info_flags = 0; |
1255 | pcm->nonatomic = true; | ||
1278 | strcpy(pcm->name, chip->card->shortname); | 1256 | strcpy(pcm->name, chip->card->shortname); |
1279 | chip->pcm[i] = pcm; | 1257 | chip->pcm[i] = pcm; |
1280 | } | 1258 | } |
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index b0560fec6bba..ef0b40c0a594 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c | |||
@@ -60,9 +60,9 @@ static int vx_modify_board_inputs(struct vx_core *chip) | |||
60 | */ | 60 | */ |
61 | static int vx_read_one_cbit(struct vx_core *chip, int index) | 61 | static int vx_read_one_cbit(struct vx_core *chip, int index) |
62 | { | 62 | { |
63 | unsigned long flags; | ||
64 | int val; | 63 | int val; |
65 | spin_lock_irqsave(&chip->lock, flags); | 64 | |
65 | mutex_lock(&chip->lock); | ||
66 | if (chip->type >= VX_TYPE_VXPOCKET) { | 66 | if (chip->type >= VX_TYPE_VXPOCKET) { |
67 | vx_outb(chip, CSUER, 1); /* read */ | 67 | vx_outb(chip, CSUER, 1); /* read */ |
68 | vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); | 68 | vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); |
@@ -72,7 +72,7 @@ static int vx_read_one_cbit(struct vx_core *chip, int index) | |||
72 | vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); | 72 | vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); |
73 | val = (vx_inl(chip, RUER) >> 7) & 0x01; | 73 | val = (vx_inl(chip, RUER) >> 7) & 0x01; |
74 | } | 74 | } |
75 | spin_unlock_irqrestore(&chip->lock, flags); | 75 | mutex_unlock(&chip->lock); |
76 | return val; | 76 | return val; |
77 | } | 77 | } |
78 | 78 | ||
@@ -83,9 +83,8 @@ static int vx_read_one_cbit(struct vx_core *chip, int index) | |||
83 | */ | 83 | */ |
84 | static void vx_write_one_cbit(struct vx_core *chip, int index, int val) | 84 | static void vx_write_one_cbit(struct vx_core *chip, int index, int val) |
85 | { | 85 | { |
86 | unsigned long flags; | ||
87 | val = !!val; /* 0 or 1 */ | 86 | val = !!val; /* 0 or 1 */ |
88 | spin_lock_irqsave(&chip->lock, flags); | 87 | mutex_lock(&chip->lock); |
89 | if (vx_is_pcmcia(chip)) { | 88 | if (vx_is_pcmcia(chip)) { |
90 | vx_outb(chip, CSUER, 0); /* write */ | 89 | vx_outb(chip, CSUER, 0); /* write */ |
91 | vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); | 90 | vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); |
@@ -93,7 +92,7 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val) | |||
93 | vx_outl(chip, CSUER, 0); /* write */ | 92 | vx_outl(chip, CSUER, 0); /* write */ |
94 | vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); | 93 | vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); |
95 | } | 94 | } |
96 | spin_unlock_irqrestore(&chip->lock, flags); | 95 | mutex_unlock(&chip->lock); |
97 | } | 96 | } |
98 | 97 | ||
99 | /* | 98 | /* |
@@ -190,14 +189,12 @@ static int vx_calc_clock_from_freq(struct vx_core *chip, int freq) | |||
190 | */ | 189 | */ |
191 | static void vx_change_clock_source(struct vx_core *chip, int source) | 190 | static void vx_change_clock_source(struct vx_core *chip, int source) |
192 | { | 191 | { |
193 | unsigned long flags; | ||
194 | |||
195 | /* we mute DAC to prevent clicks */ | 192 | /* we mute DAC to prevent clicks */ |
196 | vx_toggle_dac_mute(chip, 1); | 193 | vx_toggle_dac_mute(chip, 1); |
197 | spin_lock_irqsave(&chip->lock, flags); | 194 | mutex_lock(&chip->lock); |
198 | chip->ops->set_clock_source(chip, source); | 195 | chip->ops->set_clock_source(chip, source); |
199 | chip->clock_source = source; | 196 | chip->clock_source = source; |
200 | spin_unlock_irqrestore(&chip->lock, flags); | 197 | mutex_unlock(&chip->lock); |
201 | /* unmute */ | 198 | /* unmute */ |
202 | vx_toggle_dac_mute(chip, 0); | 199 | vx_toggle_dac_mute(chip, 0); |
203 | } | 200 | } |
@@ -209,11 +206,11 @@ static void vx_change_clock_source(struct vx_core *chip, int source) | |||
209 | void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) | 206 | void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) |
210 | { | 207 | { |
211 | int clock; | 208 | int clock; |
212 | unsigned long flags; | 209 | |
213 | /* Get real clock value */ | 210 | /* Get real clock value */ |
214 | clock = vx_calc_clock_from_freq(chip, freq); | 211 | clock = vx_calc_clock_from_freq(chip, freq); |
215 | snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); | 212 | snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); |
216 | spin_lock_irqsave(&chip->lock, flags); | 213 | mutex_lock(&chip->lock); |
217 | if (vx_is_pcmcia(chip)) { | 214 | if (vx_is_pcmcia(chip)) { |
218 | vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); | 215 | vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); |
219 | vx_outb(chip, LOFREQ, clock & 0xff); | 216 | vx_outb(chip, LOFREQ, clock & 0xff); |
@@ -221,7 +218,7 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) | |||
221 | vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); | 218 | vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); |
222 | vx_outl(chip, LOFREQ, clock & 0xff); | 219 | vx_outl(chip, LOFREQ, clock & 0xff); |
223 | } | 220 | } |
224 | spin_unlock_irqrestore(&chip->lock, flags); | 221 | mutex_unlock(&chip->lock); |
225 | } | 222 | } |
226 | 223 | ||
227 | 224 | ||
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index afb1b44b741e..21ce31f636bc 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -48,10 +48,10 @@ static void vortex_fix_latency(struct pci_dev *vortex) | |||
48 | { | 48 | { |
49 | int rc; | 49 | int rc; |
50 | if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) { | 50 | if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) { |
51 | printk(KERN_INFO CARD_NAME | 51 | pr_info( CARD_NAME |
52 | ": vortex latency is 0xff\n"); | 52 | ": vortex latency is 0xff\n"); |
53 | } else { | 53 | } else { |
54 | printk(KERN_WARNING CARD_NAME | 54 | pr_warn( CARD_NAME |
55 | ": could not set vortex latency: pci error 0x%x\n", rc); | 55 | ": could not set vortex latency: pci error 0x%x\n", rc); |
56 | } | 56 | } |
57 | } | 57 | } |
@@ -70,10 +70,10 @@ static void vortex_fix_agp_bridge(struct pci_dev *via) | |||
70 | if (!(rc = pci_read_config_byte(via, 0x42, &value)) | 70 | if (!(rc = pci_read_config_byte(via, 0x42, &value)) |
71 | && ((value & 0x10) | 71 | && ((value & 0x10) |
72 | || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) { | 72 | || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) { |
73 | printk(KERN_INFO CARD_NAME | 73 | pr_info( CARD_NAME |
74 | ": bridge config is 0x%x\n", value | 0x10); | 74 | ": bridge config is 0x%x\n", value | 0x10); |
75 | } else { | 75 | } else { |
76 | printk(KERN_WARNING CARD_NAME | 76 | pr_warn( CARD_NAME |
77 | ": could not set vortex latency: pci error 0x%x\n", rc); | 77 | ": could not set vortex latency: pci error 0x%x\n", rc); |
78 | } | 78 | } |
79 | } | 79 | } |
@@ -97,7 +97,7 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix) | |||
97 | PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL); | 97 | PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL); |
98 | } | 98 | } |
99 | if (via) { | 99 | if (via) { |
100 | printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n"); | 100 | pr_info( CARD_NAME ": Activating latency workaround...\n"); |
101 | vortex_fix_latency(vortex); | 101 | vortex_fix_latency(vortex); |
102 | vortex_fix_agp_bridge(via); | 102 | vortex_fix_agp_bridge(via); |
103 | } | 103 | } |
@@ -153,7 +153,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
153 | return err; | 153 | return err; |
154 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || | 154 | if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || |
155 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { | 155 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { |
156 | printk(KERN_ERR "error to set DMA mask\n"); | 156 | pr_err( "error to set DMA mask\n"); |
157 | pci_disable_device(pci); | 157 | pci_disable_device(pci); |
158 | return -ENXIO; | 158 | return -ENXIO; |
159 | } | 159 | } |
@@ -182,7 +182,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
182 | 182 | ||
183 | chip->mmio = pci_ioremap_bar(pci, 0); | 183 | chip->mmio = pci_ioremap_bar(pci, 0); |
184 | if (!chip->mmio) { | 184 | if (!chip->mmio) { |
185 | printk(KERN_ERR "MMIO area remap failed.\n"); | 185 | pr_err( "MMIO area remap failed.\n"); |
186 | err = -ENOMEM; | 186 | err = -ENOMEM; |
187 | goto ioremap_out; | 187 | goto ioremap_out; |
188 | } | 188 | } |
@@ -191,14 +191,14 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
191 | * This must be done before we do request_irq otherwise we can get spurious | 191 | * This must be done before we do request_irq otherwise we can get spurious |
192 | * interrupts that we do not handle properly and make a mess of things */ | 192 | * interrupts that we do not handle properly and make a mess of things */ |
193 | if ((err = vortex_core_init(chip)) != 0) { | 193 | if ((err = vortex_core_init(chip)) != 0) { |
194 | printk(KERN_ERR "hw core init failed\n"); | 194 | pr_err( "hw core init failed\n"); |
195 | goto core_out; | 195 | goto core_out; |
196 | } | 196 | } |
197 | 197 | ||
198 | if ((err = request_irq(pci->irq, vortex_interrupt, | 198 | if ((err = request_irq(pci->irq, vortex_interrupt, |
199 | IRQF_SHARED, KBUILD_MODNAME, | 199 | IRQF_SHARED, KBUILD_MODNAME, |
200 | chip)) != 0) { | 200 | chip)) != 0) { |
201 | printk(KERN_ERR "cannot grab irq\n"); | 201 | pr_err( "cannot grab irq\n"); |
202 | goto irq_out; | 202 | goto irq_out; |
203 | } | 203 | } |
204 | chip->irq = pci->irq; | 204 | chip->irq = pci->irq; |
@@ -342,10 +342,10 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
342 | chip->rev = pci->revision; | 342 | chip->rev = pci->revision; |
343 | #ifdef CHIP_AU8830 | 343 | #ifdef CHIP_AU8830 |
344 | if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) { | 344 | if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) { |
345 | printk(KERN_ALERT | 345 | pr_alert( |
346 | "vortex: The revision (%x) of your card has not been seen before.\n", | 346 | "vortex: The revision (%x) of your card has not been seen before.\n", |
347 | chip->rev); | 347 | chip->rev); |
348 | printk(KERN_ALERT | 348 | pr_alert( |
349 | "vortex: Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n"); | 349 | "vortex: Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n"); |
350 | snd_card_free(card); | 350 | snd_card_free(card); |
351 | err = -ENODEV; | 351 | err = -ENODEV; |
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index aad831acbb17..30f760e3d2c0 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c | |||
@@ -463,7 +463,7 @@ static void a3dsrc_ZeroSliceIO(a3dsrc_t * a) | |||
463 | static void a3dsrc_ZeroState(a3dsrc_t * a) | 463 | static void a3dsrc_ZeroState(a3dsrc_t * a) |
464 | { | 464 | { |
465 | /* | 465 | /* |
466 | printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n", | 466 | pr_debug( "vortex: ZeroState slice: %d, source %d\n", |
467 | a->slice, a->source); | 467 | a->slice, a->source); |
468 | */ | 468 | */ |
469 | a3dsrc_SetAtmosState(a, 0, 0, 0, 0); | 469 | a3dsrc_SetAtmosState(a, 0, 0, 0, 0); |
@@ -489,7 +489,7 @@ static void a3dsrc_ZeroStateA3D(a3dsrc_t * a) | |||
489 | int i, var, var2; | 489 | int i, var, var2; |
490 | 490 | ||
491 | if ((a->vortex) == NULL) { | 491 | if ((a->vortex) == NULL) { |
492 | printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); | 492 | pr_err( "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); |
493 | return; | 493 | return; |
494 | } | 494 | } |
495 | 495 | ||
@@ -628,14 +628,14 @@ static void vortex_Vort3D_connect(vortex_t * v, int en) | |||
628 | v->mixxtlk[0] = | 628 | v->mixxtlk[0] = |
629 | vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); | 629 | vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); |
630 | if (v->mixxtlk[0] < 0) { | 630 | if (v->mixxtlk[0] < 0) { |
631 | printk | 631 | pr_warn |
632 | ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); | 632 | ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); |
633 | return; | 633 | return; |
634 | } | 634 | } |
635 | v->mixxtlk[1] = | 635 | v->mixxtlk[1] = |
636 | vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); | 636 | vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); |
637 | if (v->mixxtlk[1] < 0) { | 637 | if (v->mixxtlk[1] < 0) { |
638 | printk | 638 | pr_warn |
639 | ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); | 639 | ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); |
640 | return; | 640 | return; |
641 | } | 641 | } |
@@ -679,7 +679,7 @@ static void vortex_Vort3D_connect(vortex_t * v, int en) | |||
679 | static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en) | 679 | static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en) |
680 | { | 680 | { |
681 | if (a->vortex == NULL) { | 681 | if (a->vortex == NULL) { |
682 | printk | 682 | pr_warn |
683 | ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); | 683 | ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); |
684 | return; | 684 | return; |
685 | } | 685 | } |
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index ae59dbaa53d9..72e81286b70e 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -285,7 +285,7 @@ vortex_mixer_addWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | |||
285 | temp = hwread(vortex->mmio, prev); | 285 | temp = hwread(vortex->mmio, prev); |
286 | //printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp); | 286 | //printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp); |
287 | if ((++lifeboat) > 0xf) { | 287 | if ((++lifeboat) > 0xf) { |
288 | printk(KERN_ERR | 288 | pr_err( |
289 | "vortex_mixer_addWTD: lifeboat overflow\n"); | 289 | "vortex_mixer_addWTD: lifeboat overflow\n"); |
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
@@ -303,7 +303,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | |||
303 | 303 | ||
304 | eax = hwread(vortex->mmio, VORTEX_MIXER_SR); | 304 | eax = hwread(vortex->mmio, VORTEX_MIXER_SR); |
305 | if (((1 << ch) & eax) == 0) { | 305 | if (((1 << ch) & eax) == 0) { |
306 | printk(KERN_ERR "mix ALARM %x\n", eax); | 306 | pr_err( "mix ALARM %x\n", eax); |
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | ebp = VORTEX_MIXER_CHNBASE + (ch << 2); | 309 | ebp = VORTEX_MIXER_CHNBASE + (ch << 2); |
@@ -324,7 +324,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | |||
324 | //printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); | 324 | //printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); |
325 | while ((edx & 0xf) != mix) { | 325 | while ((edx & 0xf) != mix) { |
326 | if ((esi) > 0xf) { | 326 | if ((esi) > 0xf) { |
327 | printk(KERN_ERR | 327 | pr_err( |
328 | "vortex: mixdelWTD: error lifeboat overflow\n"); | 328 | "vortex: mixdelWTD: error lifeboat overflow\n"); |
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
@@ -492,7 +492,7 @@ vortex_src_persist_convratio(vortex_t * vortex, unsigned char src, int ratio) | |||
492 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), ratio); | 492 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), ratio); |
493 | temp = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); | 493 | temp = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); |
494 | if ((++lifeboat) > 0x9) { | 494 | if ((++lifeboat) > 0x9) { |
495 | printk(KERN_ERR "Vortex: Src cvr fail\n"); | 495 | pr_err( "Vortex: Src cvr fail\n"); |
496 | break; | 496 | break; |
497 | } | 497 | } |
498 | } | 498 | } |
@@ -545,7 +545,7 @@ vortex_src_checkratio(vortex_t * vortex, unsigned char src, | |||
545 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), desired_ratio); | 545 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), desired_ratio); |
546 | 546 | ||
547 | if ((lifeboat++) > 15) { | 547 | if ((lifeboat++) > 15) { |
548 | printk(KERN_ERR "Vortex: could not set src-%d from %d to %d\n", | 548 | pr_err( "Vortex: could not set src-%d from %d to %d\n", |
549 | src, hw_ratio, desired_ratio); | 549 | src, hw_ratio, desired_ratio); |
550 | break; | 550 | break; |
551 | } | 551 | } |
@@ -684,7 +684,7 @@ vortex_src_addWTD(vortex_t * vortex, unsigned char src, unsigned char ch) | |||
684 | temp = hwread(vortex->mmio, prev); | 684 | temp = hwread(vortex->mmio, prev); |
685 | //printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp); | 685 | //printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp); |
686 | if ((++lifeboat) > 0xf) { | 686 | if ((++lifeboat) > 0xf) { |
687 | printk(KERN_ERR | 687 | pr_err( |
688 | "vortex_src_addWTD: lifeboat overflow\n"); | 688 | "vortex_src_addWTD: lifeboat overflow\n"); |
689 | return 0; | 689 | return 0; |
690 | } | 690 | } |
@@ -703,7 +703,7 @@ vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch) | |||
703 | 703 | ||
704 | eax = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); | 704 | eax = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); |
705 | if (((1 << ch) & eax) == 0) { | 705 | if (((1 << ch) & eax) == 0) { |
706 | printk(KERN_ERR "src alarm\n"); | 706 | pr_err( "src alarm\n"); |
707 | return 0; | 707 | return 0; |
708 | } | 708 | } |
709 | ebp = VORTEX_SRC_CHNBASE + (ch << 2); | 709 | ebp = VORTEX_SRC_CHNBASE + (ch << 2); |
@@ -724,7 +724,7 @@ vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch) | |||
724 | //printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); | 724 | //printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); |
725 | while ((edx & 0xf) != src) { | 725 | while ((edx & 0xf) != src) { |
726 | if ((esi) > 0xf) { | 726 | if ((esi) > 0xf) { |
727 | printk | 727 | pr_warn |
728 | ("vortex: srcdelWTD: error, lifeboat overflow\n"); | 728 | ("vortex: srcdelWTD: error, lifeboat overflow\n"); |
729 | return 0; | 729 | return 0; |
730 | } | 730 | } |
@@ -819,7 +819,7 @@ vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int stereo, int priority, | |||
819 | do { | 819 | do { |
820 | temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); | 820 | temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); |
821 | if (lifeboat++ > 0xbb8) { | 821 | if (lifeboat++ > 0xbb8) { |
822 | printk(KERN_ERR | 822 | pr_err( |
823 | "Vortex: vortex_fifo_setadbctrl fail\n"); | 823 | "Vortex: vortex_fifo_setadbctrl fail\n"); |
824 | break; | 824 | break; |
825 | } | 825 | } |
@@ -915,7 +915,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority, | |||
915 | do { | 915 | do { |
916 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | 916 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); |
917 | if (lifeboat++ > 0xbb8) { | 917 | if (lifeboat++ > 0xbb8) { |
918 | printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail\n"); | 918 | pr_err( "Vortex: vortex_fifo_setwtctrl fail\n"); |
919 | break; | 919 | break; |
920 | } | 920 | } |
921 | } | 921 | } |
@@ -970,7 +970,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority, | |||
970 | do { | 970 | do { |
971 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | 971 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); |
972 | if (lifeboat++ > 0xbb8) { | 972 | if (lifeboat++ > 0xbb8) { |
973 | printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail (hanging)\n"); | 973 | pr_err( "Vortex: vortex_fifo_setwtctrl fail (hanging)\n"); |
974 | break; | 974 | break; |
975 | } | 975 | } |
976 | } while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF)); | 976 | } while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF)); |
@@ -1042,7 +1042,7 @@ static void vortex_fifo_init(vortex_t * vortex) | |||
1042 | for (x = NR_ADB - 1; x >= 0; x--) { | 1042 | for (x = NR_ADB - 1; x >= 0; x--) { |
1043 | hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); | 1043 | hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); |
1044 | if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) | 1044 | if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) |
1045 | printk(KERN_ERR "bad adb fifo reset!"); | 1045 | pr_err( "bad adb fifo reset!"); |
1046 | vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); | 1046 | vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); |
1047 | addr -= 4; | 1047 | addr -= 4; |
1048 | } | 1048 | } |
@@ -1053,7 +1053,7 @@ static void vortex_fifo_init(vortex_t * vortex) | |||
1053 | for (x = NR_WT - 1; x >= 0; x--) { | 1053 | for (x = NR_WT - 1; x >= 0; x--) { |
1054 | hwwrite(vortex->mmio, addr, FIFO_U0); | 1054 | hwwrite(vortex->mmio, addr, FIFO_U0); |
1055 | if (hwread(vortex->mmio, addr) != FIFO_U0) | 1055 | if (hwread(vortex->mmio, addr) != FIFO_U0) |
1056 | printk(KERN_ERR | 1056 | pr_err( |
1057 | "bad wt fifo reset (0x%08x, 0x%08x)!\n", | 1057 | "bad wt fifo reset (0x%08x, 0x%08x)!\n", |
1058 | addr, hwread(vortex->mmio, addr)); | 1058 | addr, hwread(vortex->mmio, addr)); |
1059 | vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); | 1059 | vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); |
@@ -1136,7 +1136,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
1136 | break; | 1136 | break; |
1137 | } | 1137 | } |
1138 | /* | 1138 | /* |
1139 | printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", | 1139 | pr_debug( "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", |
1140 | dma->cfg0, dma->cfg1); | 1140 | dma->cfg0, dma->cfg1); |
1141 | */ | 1141 | */ |
1142 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); | 1142 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); |
@@ -1213,7 +1213,7 @@ static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma) | |||
1213 | if (dma->period_virt >= dma->nr_periods) | 1213 | if (dma->period_virt >= dma->nr_periods) |
1214 | dma->period_virt -= dma->nr_periods; | 1214 | dma->period_virt -= dma->nr_periods; |
1215 | if (delta != 1) | 1215 | if (delta != 1) |
1216 | printk(KERN_INFO "vortex: %d virt=%d, real=%d, delta=%d\n", | 1216 | pr_info( "vortex: %d virt=%d, real=%d, delta=%d\n", |
1217 | adbdma, dma->period_virt, dma->period_real, delta); | 1217 | adbdma, dma->period_virt, dma->period_real, delta); |
1218 | 1218 | ||
1219 | return delta; | 1219 | return delta; |
@@ -1482,7 +1482,7 @@ static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma) | |||
1482 | dma->period_real = page; | 1482 | dma->period_real = page; |
1483 | 1483 | ||
1484 | if (delta != 1) | 1484 | if (delta != 1) |
1485 | printk(KERN_WARNING "vortex: wt virt = %d, delta = %d\n", | 1485 | pr_warn( "vortex: wt virt = %d, delta = %d\n", |
1486 | dma->period_virt, delta); | 1486 | dma->period_virt, delta); |
1487 | 1487 | ||
1488 | return delta; | 1488 | return delta; |
@@ -1667,7 +1667,7 @@ vortex_adb_addroutes(vortex_t * vortex, unsigned char channel, | |||
1667 | hwread(vortex->mmio, | 1667 | hwread(vortex->mmio, |
1668 | VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK; | 1668 | VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK; |
1669 | if ((lifeboat++) > ADB_MASK) { | 1669 | if ((lifeboat++) > ADB_MASK) { |
1670 | printk(KERN_ERR | 1670 | pr_err( |
1671 | "vortex_adb_addroutes: unending route! 0x%x\n", | 1671 | "vortex_adb_addroutes: unending route! 0x%x\n", |
1672 | *route); | 1672 | *route); |
1673 | return; | 1673 | return; |
@@ -1703,7 +1703,7 @@ vortex_adb_delroutes(vortex_t * vortex, unsigned char channel, | |||
1703 | hwread(vortex->mmio, | 1703 | hwread(vortex->mmio, |
1704 | VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK; | 1704 | VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK; |
1705 | if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) { | 1705 | if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) { |
1706 | printk(KERN_ERR | 1706 | pr_err( |
1707 | "vortex_adb_delroutes: route not found! 0x%x\n", | 1707 | "vortex_adb_delroutes: route not found! 0x%x\n", |
1708 | route0); | 1708 | route0); |
1709 | return; | 1709 | return; |
@@ -1967,7 +1967,7 @@ vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]) | |||
1967 | ADB_CODECOUT(0 + 4)); | 1967 | ADB_CODECOUT(0 + 4)); |
1968 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], | 1968 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], |
1969 | ADB_CODECOUT(1 + 4)); | 1969 | ADB_CODECOUT(1 + 4)); |
1970 | /* printk(KERN_DEBUG "SDAC detected "); */ | 1970 | /* pr_debug( "SDAC detected "); */ |
1971 | } | 1971 | } |
1972 | #else | 1972 | #else |
1973 | // Use plain direct output to codec. | 1973 | // Use plain direct output to codec. |
@@ -2022,7 +2022,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2022 | else | 2022 | else |
2023 | vortex->dma_adb[i].resources[restype] |= (1 << i); | 2023 | vortex->dma_adb[i].resources[restype] |= (1 << i); |
2024 | /* | 2024 | /* |
2025 | printk(KERN_DEBUG | 2025 | pr_debug( |
2026 | "vortex: ResManager: type %d out %d\n", | 2026 | "vortex: ResManager: type %d out %d\n", |
2027 | restype, i); | 2027 | restype, i); |
2028 | */ | 2028 | */ |
@@ -2037,7 +2037,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2037 | if (resmap[restype] & (1 << i)) { | 2037 | if (resmap[restype] & (1 << i)) { |
2038 | resmap[restype] &= ~(1 << i); | 2038 | resmap[restype] &= ~(1 << i); |
2039 | /* | 2039 | /* |
2040 | printk(KERN_DEBUG | 2040 | pr_debug( |
2041 | "vortex: ResManager: type %d in %d\n", | 2041 | "vortex: ResManager: type %d in %d\n", |
2042 | restype, i); | 2042 | restype, i); |
2043 | */ | 2043 | */ |
@@ -2045,7 +2045,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2045 | } | 2045 | } |
2046 | } | 2046 | } |
2047 | } | 2047 | } |
2048 | printk(KERN_ERR "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); | 2048 | pr_err( "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); |
2049 | return -ENOMEM; | 2049 | return -ENOMEM; |
2050 | } | 2050 | } |
2051 | 2051 | ||
@@ -2173,7 +2173,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, | |||
2173 | memset(stream->resources, 0, | 2173 | memset(stream->resources, 0, |
2174 | sizeof(unsigned char) * | 2174 | sizeof(unsigned char) * |
2175 | VORTEX_RESOURCE_LAST); | 2175 | VORTEX_RESOURCE_LAST); |
2176 | printk(KERN_ERR "vortex: out of A3D sources. Sorry\n"); | 2176 | pr_err( "vortex: out of A3D sources. Sorry\n"); |
2177 | return -EBUSY; | 2177 | return -EBUSY; |
2178 | } | 2178 | } |
2179 | /* (De)Initialize A3D hardware source. */ | 2179 | /* (De)Initialize A3D hardware source. */ |
@@ -2421,7 +2421,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) | |||
2421 | hwread(vortex->mmio, VORTEX_IRQ_SOURCE); | 2421 | hwread(vortex->mmio, VORTEX_IRQ_SOURCE); |
2422 | // Is at least one IRQ flag set? | 2422 | // Is at least one IRQ flag set? |
2423 | if (source == 0) { | 2423 | if (source == 0) { |
2424 | printk(KERN_ERR "vortex: missing irq source\n"); | 2424 | pr_err( "vortex: missing irq source\n"); |
2425 | return IRQ_NONE; | 2425 | return IRQ_NONE; |
2426 | } | 2426 | } |
2427 | 2427 | ||
@@ -2429,19 +2429,19 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) | |||
2429 | // Attend every interrupt source. | 2429 | // Attend every interrupt source. |
2430 | if (unlikely(source & IRQ_ERR_MASK)) { | 2430 | if (unlikely(source & IRQ_ERR_MASK)) { |
2431 | if (source & IRQ_FATAL) { | 2431 | if (source & IRQ_FATAL) { |
2432 | printk(KERN_ERR "vortex: IRQ fatal error\n"); | 2432 | pr_err( "vortex: IRQ fatal error\n"); |
2433 | } | 2433 | } |
2434 | if (source & IRQ_PARITY) { | 2434 | if (source & IRQ_PARITY) { |
2435 | printk(KERN_ERR "vortex: IRQ parity error\n"); | 2435 | pr_err( "vortex: IRQ parity error\n"); |
2436 | } | 2436 | } |
2437 | if (source & IRQ_REG) { | 2437 | if (source & IRQ_REG) { |
2438 | printk(KERN_ERR "vortex: IRQ reg error\n"); | 2438 | pr_err( "vortex: IRQ reg error\n"); |
2439 | } | 2439 | } |
2440 | if (source & IRQ_FIFO) { | 2440 | if (source & IRQ_FIFO) { |
2441 | printk(KERN_ERR "vortex: IRQ fifo error\n"); | 2441 | pr_err( "vortex: IRQ fifo error\n"); |
2442 | } | 2442 | } |
2443 | if (source & IRQ_DMA) { | 2443 | if (source & IRQ_DMA) { |
2444 | printk(KERN_ERR "vortex: IRQ dma error\n"); | 2444 | pr_err( "vortex: IRQ dma error\n"); |
2445 | } | 2445 | } |
2446 | handled = 1; | 2446 | handled = 1; |
2447 | } | 2447 | } |
@@ -2489,7 +2489,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) | |||
2489 | } | 2489 | } |
2490 | 2490 | ||
2491 | if (!handled) { | 2491 | if (!handled) { |
2492 | printk(KERN_ERR "vortex: unknown irq source %x\n", source); | 2492 | pr_err( "vortex: unknown irq source %x\n", source); |
2493 | } | 2493 | } |
2494 | return IRQ_RETVAL(handled); | 2494 | return IRQ_RETVAL(handled); |
2495 | } | 2495 | } |
@@ -2546,7 +2546,7 @@ vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, unsigned short | |||
2546 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { | 2546 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { |
2547 | udelay(100); | 2547 | udelay(100); |
2548 | if (lifeboat++ > POLL_COUNT) { | 2548 | if (lifeboat++ > POLL_COUNT) { |
2549 | printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); | 2549 | pr_err( "vortex: ac97 codec stuck busy\n"); |
2550 | return; | 2550 | return; |
2551 | } | 2551 | } |
2552 | } | 2552 | } |
@@ -2572,7 +2572,7 @@ static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short | |||
2572 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { | 2572 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { |
2573 | udelay(100); | 2573 | udelay(100); |
2574 | if (lifeboat++ > POLL_COUNT) { | 2574 | if (lifeboat++ > POLL_COUNT) { |
2575 | printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); | 2575 | pr_err( "vortex: ac97 codec stuck busy\n"); |
2576 | return 0xffff; | 2576 | return 0xffff; |
2577 | } | 2577 | } |
2578 | } | 2578 | } |
@@ -2586,7 +2586,7 @@ static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short | |||
2586 | udelay(100); | 2586 | udelay(100); |
2587 | data = hwread(card->mmio, VORTEX_CODEC_IO); | 2587 | data = hwread(card->mmio, VORTEX_CODEC_IO); |
2588 | if (lifeboat++ > POLL_COUNT) { | 2588 | if (lifeboat++ > POLL_COUNT) { |
2589 | printk(KERN_ERR "vortex: ac97 address never arrived\n"); | 2589 | pr_err( "vortex: ac97 address never arrived\n"); |
2590 | return 0xffff; | 2590 | return 0xffff; |
2591 | } | 2591 | } |
2592 | } while ((data & VORTEX_CODEC_ADDMASK) != | 2592 | } while ((data & VORTEX_CODEC_ADDMASK) != |
@@ -2683,7 +2683,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode) | |||
2683 | static int vortex_core_init(vortex_t *vortex) | 2683 | static int vortex_core_init(vortex_t *vortex) |
2684 | { | 2684 | { |
2685 | 2685 | ||
2686 | printk(KERN_INFO "Vortex: init.... "); | 2686 | pr_info( "Vortex: init.... "); |
2687 | /* Hardware Init. */ | 2687 | /* Hardware Init. */ |
2688 | hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff); | 2688 | hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff); |
2689 | msleep(5); | 2689 | msleep(5); |
@@ -2728,7 +2728,7 @@ static int vortex_core_init(vortex_t *vortex) | |||
2728 | //vortex_enable_timer_int(vortex); | 2728 | //vortex_enable_timer_int(vortex); |
2729 | //vortex_disable_timer_int(vortex); | 2729 | //vortex_disable_timer_int(vortex); |
2730 | 2730 | ||
2731 | printk(KERN_INFO "done.\n"); | 2731 | pr_info( "done.\n"); |
2732 | spin_lock_init(&vortex->lock); | 2732 | spin_lock_init(&vortex->lock); |
2733 | 2733 | ||
2734 | return 0; | 2734 | return 0; |
@@ -2737,7 +2737,7 @@ static int vortex_core_init(vortex_t *vortex) | |||
2737 | static int vortex_core_shutdown(vortex_t * vortex) | 2737 | static int vortex_core_shutdown(vortex_t * vortex) |
2738 | { | 2738 | { |
2739 | 2739 | ||
2740 | printk(KERN_INFO "Vortex: shutdown..."); | 2740 | pr_info( "Vortex: shutdown..."); |
2741 | #ifndef CHIP_AU8820 | 2741 | #ifndef CHIP_AU8820 |
2742 | vortex_eq_free(vortex); | 2742 | vortex_eq_free(vortex); |
2743 | vortex_Vort3D_disable(vortex); | 2743 | vortex_Vort3D_disable(vortex); |
@@ -2759,7 +2759,7 @@ static int vortex_core_shutdown(vortex_t * vortex) | |||
2759 | msleep(5); | 2759 | msleep(5); |
2760 | hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff); | 2760 | hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff); |
2761 | 2761 | ||
2762 | printk(KERN_INFO "done.\n"); | 2762 | pr_info( "done.\n"); |
2763 | return 0; | 2763 | return 0; |
2764 | } | 2764 | } |
2765 | 2765 | ||
@@ -2793,7 +2793,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt) | |||
2793 | break; | 2793 | break; |
2794 | default: | 2794 | default: |
2795 | fmt = 0x8; | 2795 | fmt = 0x8; |
2796 | printk(KERN_ERR "vortex: format unsupported %d\n", alsafmt); | 2796 | pr_err( "vortex: format unsupported %d\n", alsafmt); |
2797 | break; | 2797 | break; |
2798 | } | 2798 | } |
2799 | return fmt; | 2799 | return fmt; |
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index e7220533ecfc..9404ba73eaf6 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c | |||
@@ -845,7 +845,7 @@ snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u | |||
845 | 845 | ||
846 | vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); | 846 | vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); |
847 | if (count != 20) { | 847 | if (count != 20) { |
848 | printk(KERN_ERR "vortex: peak count error 20 != %d \n", count); | 848 | pr_err( "vortex: peak count error 20 != %d \n", count); |
849 | return -1; | 849 | return -1; |
850 | } | 850 | } |
851 | for (i = 0; i < 20; i++) | 851 | for (i = 0; i < 20; i++) |
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c index 280f86de2230..72daf6cf8169 100644 --- a/sound/pci/au88x0/au88x0_game.c +++ b/sound/pci/au88x0/au88x0_game.c | |||
@@ -98,7 +98,7 @@ static int vortex_gameport_register(vortex_t *vortex) | |||
98 | 98 | ||
99 | vortex->gameport = gp = gameport_allocate_port(); | 99 | vortex->gameport = gp = gameport_allocate_port(); |
100 | if (!gp) { | 100 | if (!gp) { |
101 | printk(KERN_ERR "vortex: cannot allocate memory for gameport\n"); | 101 | pr_err( "vortex: cannot allocate memory for gameport\n"); |
102 | return -ENOMEM; | 102 | return -ENOMEM; |
103 | } | 103 | } |
104 | 104 | ||
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 29e5945eef60..328c1943c0c3 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c | |||
@@ -73,7 +73,7 @@ static int snd_vortex_midi(vortex_t *vortex) | |||
73 | /* Check if anything is OK. */ | 73 | /* Check if anything is OK. */ |
74 | temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); | 74 | temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); |
75 | if (temp != MPU401_ACK /*0xfe */ ) { | 75 | if (temp != MPU401_ACK /*0xfe */ ) { |
76 | printk(KERN_ERR "midi port doesn't acknowledge!\n"); | 76 | pr_err( "midi port doesn't acknowledge!\n"); |
77 | return -ENODEV; | 77 | return -ENODEV; |
78 | } | 78 | } |
79 | /* Enable MPU401 interrupts. */ | 79 | /* Enable MPU401 interrupts. */ |
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 9fb03b4ea925..5adc6b92ffab 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c | |||
@@ -227,11 +227,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, | |||
227 | err = | 227 | err = |
228 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 228 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
229 | if (err < 0) { | 229 | if (err < 0) { |
230 | printk(KERN_ERR "Vortex: pcm page alloc failed!\n"); | 230 | pr_err( "Vortex: pcm page alloc failed!\n"); |
231 | return err; | 231 | return err; |
232 | } | 232 | } |
233 | /* | 233 | /* |
234 | printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params), | 234 | pr_info( "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params), |
235 | params_period_bytes(hw_params), params_channels(hw_params)); | 235 | params_period_bytes(hw_params), params_channels(hw_params)); |
236 | */ | 236 | */ |
237 | spin_lock_irq(&chip->lock); | 237 | spin_lock_irq(&chip->lock); |
@@ -371,7 +371,7 @@ static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
371 | } | 371 | } |
372 | #ifndef CHIP_AU8810 | 372 | #ifndef CHIP_AU8810 |
373 | else { | 373 | else { |
374 | printk(KERN_INFO "vortex: wt start %d\n", dma); | 374 | pr_info( "vortex: wt start %d\n", dma); |
375 | vortex_wtdma_startfifo(chip, dma); | 375 | vortex_wtdma_startfifo(chip, dma); |
376 | } | 376 | } |
377 | #endif | 377 | #endif |
@@ -384,7 +384,7 @@ static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
384 | vortex_adbdma_stopfifo(chip, dma); | 384 | vortex_adbdma_stopfifo(chip, dma); |
385 | #ifndef CHIP_AU8810 | 385 | #ifndef CHIP_AU8810 |
386 | else { | 386 | else { |
387 | printk(KERN_INFO "vortex: wt stop %d\n", dma); | 387 | pr_info( "vortex: wt stop %d\n", dma); |
388 | vortex_wtdma_stopfifo(chip, dma); | 388 | vortex_wtdma_stopfifo(chip, dma); |
389 | } | 389 | } |
390 | #endif | 390 | #endif |
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 922a84bba2ef..f094bac24291 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c | |||
@@ -90,7 +90,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) | |||
90 | hwwrite(vortex->mmio, WT_PARM(wt, 2), 0); | 90 | hwwrite(vortex->mmio, WT_PARM(wt, 2), 0); |
91 | 91 | ||
92 | temp = hwread(vortex->mmio, WT_PARM(wt, 3)); | 92 | temp = hwread(vortex->mmio, WT_PARM(wt, 3)); |
93 | printk(KERN_DEBUG "vortex: WT PARM3: %x\n", temp); | 93 | pr_debug( "vortex: WT PARM3: %x\n", temp); |
94 | //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp); | 94 | //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp); |
95 | 95 | ||
96 | hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0); | 96 | hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0); |
@@ -98,7 +98,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) | |||
98 | hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0); | 98 | hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0); |
99 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0); | 99 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0); |
100 | 100 | ||
101 | printk(KERN_DEBUG "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt))); | 101 | pr_debug( "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt))); |
102 | 102 | ||
103 | hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff); | 103 | hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff); |
104 | hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810); | 104 | hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810); |
@@ -106,7 +106,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) | |||
106 | voice->parm0 = voice->parm1 = 0xcfb23e2f; | 106 | voice->parm0 = voice->parm1 = 0xcfb23e2f; |
107 | hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0); | 107 | hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0); |
108 | hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1); | 108 | hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1); |
109 | printk(KERN_DEBUG "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt))); | 109 | pr_debug( "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt))); |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
@@ -196,14 +196,14 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
196 | 196 | ||
197 | if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) { | 197 | if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) { |
198 | if (wt >= (NR_WT / NR_WT_PB)) { | 198 | if (wt >= (NR_WT / NR_WT_PB)) { |
199 | printk | 199 | pr_warn |
200 | ("vortex: WT SetReg: bank out of range. reg=0x%x, wt=%d\n", | 200 | ("vortex: WT SetReg: bank out of range. reg=0x%x, wt=%d\n", |
201 | reg, wt); | 201 | reg, wt); |
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | } else { | 204 | } else { |
205 | if (wt >= NR_WT) { | 205 | if (wt >= NR_WT) { |
206 | printk(KERN_ERR "vortex: WT SetReg: voice out of range\n"); | 206 | pr_err( "vortex: WT SetReg: voice out of range\n"); |
207 | return 0; | 207 | return 0; |
208 | } | 208 | } |
209 | } | 209 | } |
@@ -214,42 +214,42 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
214 | /* Voice specific parameters */ | 214 | /* Voice specific parameters */ |
215 | case 0: /* running */ | 215 | case 0: /* running */ |
216 | /* | 216 | /* |
217 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 217 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
218 | WT_RUN(wt), (int)val); | 218 | WT_RUN(wt), (int)val); |
219 | */ | 219 | */ |
220 | hwwrite(vortex->mmio, WT_RUN(wt), val); | 220 | hwwrite(vortex->mmio, WT_RUN(wt), val); |
221 | return 0xc; | 221 | return 0xc; |
222 | case 1: /* param 0 */ | 222 | case 1: /* param 0 */ |
223 | /* | 223 | /* |
224 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 224 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
225 | WT_PARM(wt,0), (int)val); | 225 | WT_PARM(wt,0), (int)val); |
226 | */ | 226 | */ |
227 | hwwrite(vortex->mmio, WT_PARM(wt, 0), val); | 227 | hwwrite(vortex->mmio, WT_PARM(wt, 0), val); |
228 | return 0xc; | 228 | return 0xc; |
229 | case 2: /* param 1 */ | 229 | case 2: /* param 1 */ |
230 | /* | 230 | /* |
231 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 231 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
232 | WT_PARM(wt,1), (int)val); | 232 | WT_PARM(wt,1), (int)val); |
233 | */ | 233 | */ |
234 | hwwrite(vortex->mmio, WT_PARM(wt, 1), val); | 234 | hwwrite(vortex->mmio, WT_PARM(wt, 1), val); |
235 | return 0xc; | 235 | return 0xc; |
236 | case 3: /* param 2 */ | 236 | case 3: /* param 2 */ |
237 | /* | 237 | /* |
238 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 238 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
239 | WT_PARM(wt,2), (int)val); | 239 | WT_PARM(wt,2), (int)val); |
240 | */ | 240 | */ |
241 | hwwrite(vortex->mmio, WT_PARM(wt, 2), val); | 241 | hwwrite(vortex->mmio, WT_PARM(wt, 2), val); |
242 | return 0xc; | 242 | return 0xc; |
243 | case 4: /* param 3 */ | 243 | case 4: /* param 3 */ |
244 | /* | 244 | /* |
245 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 245 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
246 | WT_PARM(wt,3), (int)val); | 246 | WT_PARM(wt,3), (int)val); |
247 | */ | 247 | */ |
248 | hwwrite(vortex->mmio, WT_PARM(wt, 3), val); | 248 | hwwrite(vortex->mmio, WT_PARM(wt, 3), val); |
249 | return 0xc; | 249 | return 0xc; |
250 | case 6: /* mute */ | 250 | case 6: /* mute */ |
251 | /* | 251 | /* |
252 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 252 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
253 | WT_MUTE(wt), (int)val); | 253 | WT_MUTE(wt), (int)val); |
254 | */ | 254 | */ |
255 | hwwrite(vortex->mmio, WT_MUTE(wt), val); | 255 | hwwrite(vortex->mmio, WT_MUTE(wt), val); |
@@ -257,7 +257,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
257 | case 0xb: | 257 | case 0xb: |
258 | /* delay */ | 258 | /* delay */ |
259 | /* | 259 | /* |
260 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", | 260 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", |
261 | WT_DELAY(wt,0), (int)val); | 261 | WT_DELAY(wt,0), (int)val); |
262 | */ | 262 | */ |
263 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); | 263 | hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); |
@@ -285,7 +285,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
285 | return 0; | 285 | return 0; |
286 | } | 286 | } |
287 | /* | 287 | /* |
288 | printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); | 288 | pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); |
289 | */ | 289 | */ |
290 | hwwrite(vortex->mmio, ecx, val); | 290 | hwwrite(vortex->mmio, ecx, val); |
291 | return 1; | 291 | return 1; |
diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c index fee35cfc0c7f..c7dc38d41b7f 100644 --- a/sound/pci/ctxfi/ctamixer.c +++ b/sound/pci/ctxfi/ctamixer.c | |||
@@ -258,7 +258,8 @@ static int get_amixer_rsc(struct amixer_mgr *mgr, | |||
258 | } | 258 | } |
259 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); | 259 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); |
260 | if (err) { | 260 | if (err) { |
261 | printk(KERN_ERR "ctxfi: Can't meet AMIXER resource request!\n"); | 261 | dev_err(mgr->card->dev, |
262 | "Can't meet AMIXER resource request!\n"); | ||
262 | goto error; | 263 | goto error; |
263 | } | 264 | } |
264 | 265 | ||
@@ -296,7 +297,7 @@ static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer) | |||
296 | return 0; | 297 | return 0; |
297 | } | 298 | } |
298 | 299 | ||
299 | int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr) | 300 | int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr) |
300 | { | 301 | { |
301 | int err; | 302 | int err; |
302 | struct amixer_mgr *amixer_mgr; | 303 | struct amixer_mgr *amixer_mgr; |
@@ -314,6 +315,7 @@ int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr) | |||
314 | 315 | ||
315 | amixer_mgr->get_amixer = get_amixer_rsc; | 316 | amixer_mgr->get_amixer = get_amixer_rsc; |
316 | amixer_mgr->put_amixer = put_amixer_rsc; | 317 | amixer_mgr->put_amixer = put_amixer_rsc; |
318 | amixer_mgr->card = hw->card; | ||
317 | 319 | ||
318 | *ramixer_mgr = amixer_mgr; | 320 | *ramixer_mgr = amixer_mgr; |
319 | 321 | ||
@@ -411,7 +413,8 @@ static int get_sum_rsc(struct sum_mgr *mgr, | |||
411 | } | 413 | } |
412 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); | 414 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); |
413 | if (err) { | 415 | if (err) { |
414 | printk(KERN_ERR "ctxfi: Can't meet SUM resource request!\n"); | 416 | dev_err(mgr->card->dev, |
417 | "Can't meet SUM resource request!\n"); | ||
415 | goto error; | 418 | goto error; |
416 | } | 419 | } |
417 | 420 | ||
@@ -449,7 +452,7 @@ static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum) | |||
449 | return 0; | 452 | return 0; |
450 | } | 453 | } |
451 | 454 | ||
452 | int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr) | 455 | int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr) |
453 | { | 456 | { |
454 | int err; | 457 | int err; |
455 | struct sum_mgr *sum_mgr; | 458 | struct sum_mgr *sum_mgr; |
@@ -467,6 +470,7 @@ int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr) | |||
467 | 470 | ||
468 | sum_mgr->get_sum = get_sum_rsc; | 471 | sum_mgr->get_sum = get_sum_rsc; |
469 | sum_mgr->put_sum = put_sum_rsc; | 472 | sum_mgr->put_sum = put_sum_rsc; |
473 | sum_mgr->card = hw->card; | ||
470 | 474 | ||
471 | *rsum_mgr = sum_mgr; | 475 | *rsum_mgr = sum_mgr; |
472 | 476 | ||
diff --git a/sound/pci/ctxfi/ctamixer.h b/sound/pci/ctxfi/ctamixer.h index cc49e5ab4750..72f42f27434e 100644 --- a/sound/pci/ctxfi/ctamixer.h +++ b/sound/pci/ctxfi/ctamixer.h | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include "ctresource.h" | 22 | #include "ctresource.h" |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <sound/core.h> | ||
24 | 25 | ||
25 | /* Define the descriptor of a summation node resource */ | 26 | /* Define the descriptor of a summation node resource */ |
26 | struct sum { | 27 | struct sum { |
@@ -35,6 +36,7 @@ struct sum_desc { | |||
35 | 36 | ||
36 | struct sum_mgr { | 37 | struct sum_mgr { |
37 | struct rsc_mgr mgr; /* Basic resource manager info */ | 38 | struct rsc_mgr mgr; /* Basic resource manager info */ |
39 | struct snd_card *card; /* pointer to this card */ | ||
38 | spinlock_t mgr_lock; | 40 | spinlock_t mgr_lock; |
39 | 41 | ||
40 | /* request one sum resource */ | 42 | /* request one sum resource */ |
@@ -45,7 +47,7 @@ struct sum_mgr { | |||
45 | }; | 47 | }; |
46 | 48 | ||
47 | /* Constructor and destructor of daio resource manager */ | 49 | /* Constructor and destructor of daio resource manager */ |
48 | int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr); | 50 | int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr); |
49 | int sum_mgr_destroy(struct sum_mgr *sum_mgr); | 51 | int sum_mgr_destroy(struct sum_mgr *sum_mgr); |
50 | 52 | ||
51 | /* Define the descriptor of a amixer resource */ | 53 | /* Define the descriptor of a amixer resource */ |
@@ -79,6 +81,7 @@ struct amixer_desc { | |||
79 | 81 | ||
80 | struct amixer_mgr { | 82 | struct amixer_mgr { |
81 | struct rsc_mgr mgr; /* Basic resource manager info */ | 83 | struct rsc_mgr mgr; /* Basic resource manager info */ |
84 | struct snd_card *card; /* pointer to this card */ | ||
82 | spinlock_t mgr_lock; | 85 | spinlock_t mgr_lock; |
83 | 86 | ||
84 | /* request one amixer resource */ | 87 | /* request one amixer resource */ |
@@ -90,7 +93,7 @@ struct amixer_mgr { | |||
90 | }; | 93 | }; |
91 | 94 | ||
92 | /* Constructor and destructor of amixer resource manager */ | 95 | /* Constructor and destructor of amixer resource manager */ |
93 | int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr); | 96 | int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr); |
94 | int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr); | 97 | int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr); |
95 | 98 | ||
96 | #endif /* CTAMIXER_H */ | 99 | #endif /* CTAMIXER_H */ |
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index af632bd08323..454659074390 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -106,11 +106,11 @@ static struct { | |||
106 | .public_name = "Mixer"} | 106 | .public_name = "Mixer"} |
107 | }; | 107 | }; |
108 | 108 | ||
109 | typedef int (*create_t)(void *, void **); | 109 | typedef int (*create_t)(struct hw *, void **); |
110 | typedef int (*destroy_t)(void *); | 110 | typedef int (*destroy_t)(void *); |
111 | 111 | ||
112 | static struct { | 112 | static struct { |
113 | int (*create)(void *hw, void **rmgr); | 113 | int (*create)(struct hw *hw, void **rmgr); |
114 | int (*destroy)(void *mgr); | 114 | int (*destroy)(void *mgr); |
115 | } rsc_mgr_funcs[NUM_RSCTYP] = { | 115 | } rsc_mgr_funcs[NUM_RSCTYP] = { |
116 | [SRC] = { .create = (create_t)src_mgr_create, | 116 | [SRC] = { .create = (create_t)src_mgr_create, |
@@ -171,7 +171,8 @@ static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index) | |||
171 | return atc->vm->get_ptp_phys(atc->vm, index); | 171 | return atc->vm->get_ptp_phys(atc->vm, index); |
172 | } | 172 | } |
173 | 173 | ||
174 | static unsigned int convert_format(snd_pcm_format_t snd_format) | 174 | static unsigned int convert_format(snd_pcm_format_t snd_format, |
175 | struct snd_card *card) | ||
175 | { | 176 | { |
176 | switch (snd_format) { | 177 | switch (snd_format) { |
177 | case SNDRV_PCM_FORMAT_U8: | 178 | case SNDRV_PCM_FORMAT_U8: |
@@ -185,7 +186,7 @@ static unsigned int convert_format(snd_pcm_format_t snd_format) | |||
185 | case SNDRV_PCM_FORMAT_FLOAT_LE: | 186 | case SNDRV_PCM_FORMAT_FLOAT_LE: |
186 | return SRC_SF_F32; | 187 | return SRC_SF_F32; |
187 | default: | 188 | default: |
188 | printk(KERN_ERR "ctxfi: not recognized snd format is %d \n", | 189 | dev_err(card->dev, "not recognized snd format is %d\n", |
189 | snd_format); | 190 | snd_format); |
190 | return SRC_SF_S16; | 191 | return SRC_SF_S16; |
191 | } | 192 | } |
@@ -268,7 +269,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
268 | src = apcm->src; | 269 | src = apcm->src; |
269 | src->ops->set_pitch(src, pitch); | 270 | src->ops->set_pitch(src, pitch); |
270 | src->ops->set_rom(src, select_rom(pitch)); | 271 | src->ops->set_rom(src, select_rom(pitch)); |
271 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); | 272 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format, |
273 | atc->card)); | ||
272 | src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); | 274 | src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); |
273 | 275 | ||
274 | /* Get AMIXER resource */ | 276 | /* Get AMIXER resource */ |
@@ -738,7 +740,8 @@ static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
738 | 740 | ||
739 | /* Set up recording SRC */ | 741 | /* Set up recording SRC */ |
740 | src = apcm->src; | 742 | src = apcm->src; |
741 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); | 743 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format, |
744 | atc->card)); | ||
742 | src->ops->set_sa(src, apcm->vm_block->addr); | 745 | src->ops->set_sa(src, apcm->vm_block->addr); |
743 | src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size); | 746 | src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size); |
744 | src->ops->set_ca(src, apcm->vm_block->addr); | 747 | src->ops->set_ca(src, apcm->vm_block->addr); |
@@ -807,7 +810,8 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc, | |||
807 | src = apcm->src; | 810 | src = apcm->src; |
808 | src->ops->set_pitch(src, pitch); | 811 | src->ops->set_pitch(src, pitch); |
809 | src->ops->set_rom(src, select_rom(pitch)); | 812 | src->ops->set_rom(src, select_rom(pitch)); |
810 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); | 813 | src->ops->set_sf(src, convert_format(apcm->substream->runtime->format, |
814 | atc->card)); | ||
811 | src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); | 815 | src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); |
812 | src->ops->set_bp(src, 1); | 816 | src->ops->set_bp(src, 1); |
813 | 817 | ||
@@ -1235,7 +1239,7 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
1235 | } | 1239 | } |
1236 | 1240 | ||
1237 | if (atc->hw) | 1241 | if (atc->hw) |
1238 | destroy_hw_obj((struct hw *)atc->hw); | 1242 | destroy_hw_obj(atc->hw); |
1239 | 1243 | ||
1240 | /* Destroy device virtual memory manager object */ | 1244 | /* Destroy device virtual memory manager object */ |
1241 | if (atc->vm) { | 1245 | if (atc->vm) { |
@@ -1282,9 +1286,9 @@ static int atc_identify_card(struct ct_atc *atc, unsigned int ssid) | |||
1282 | p = snd_pci_quirk_lookup_id(vendor_id, device_id, list); | 1286 | p = snd_pci_quirk_lookup_id(vendor_id, device_id, list); |
1283 | if (p) { | 1287 | if (p) { |
1284 | if (p->value < 0) { | 1288 | if (p->value < 0) { |
1285 | printk(KERN_ERR "ctxfi: " | 1289 | dev_err(atc->card->dev, |
1286 | "Device %04x:%04x is black-listed\n", | 1290 | "Device %04x:%04x is black-listed\n", |
1287 | vendor_id, device_id); | 1291 | vendor_id, device_id); |
1288 | return -ENOENT; | 1292 | return -ENOENT; |
1289 | } | 1293 | } |
1290 | atc->model = p->value; | 1294 | atc->model = p->value; |
@@ -1315,8 +1319,8 @@ int ct_atc_create_alsa_devs(struct ct_atc *atc) | |||
1315 | err = alsa_dev_funcs[i].create(atc, i, | 1319 | err = alsa_dev_funcs[i].create(atc, i, |
1316 | alsa_dev_funcs[i].public_name); | 1320 | alsa_dev_funcs[i].public_name); |
1317 | if (err) { | 1321 | if (err) { |
1318 | printk(KERN_ERR "ctxfi: " | 1322 | dev_err(atc->card->dev, |
1319 | "Creating alsa device %d failed!\n", i); | 1323 | "Creating alsa device %d failed!\n", i); |
1320 | return err; | 1324 | return err; |
1321 | } | 1325 | } |
1322 | } | 1326 | } |
@@ -1332,9 +1336,10 @@ static int atc_create_hw_devs(struct ct_atc *atc) | |||
1332 | 1336 | ||
1333 | err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw); | 1337 | err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw); |
1334 | if (err) { | 1338 | if (err) { |
1335 | printk(KERN_ERR "Failed to create hw obj!!!\n"); | 1339 | dev_err(atc->card->dev, "Failed to create hw obj!!!\n"); |
1336 | return err; | 1340 | return err; |
1337 | } | 1341 | } |
1342 | hw->card = atc->card; | ||
1338 | atc->hw = hw; | 1343 | atc->hw = hw; |
1339 | 1344 | ||
1340 | /* Initialize card hardware. */ | 1345 | /* Initialize card hardware. */ |
@@ -1351,8 +1356,8 @@ static int atc_create_hw_devs(struct ct_atc *atc) | |||
1351 | 1356 | ||
1352 | err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]); | 1357 | err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]); |
1353 | if (err) { | 1358 | if (err) { |
1354 | printk(KERN_ERR "ctxfi: " | 1359 | dev_err(atc->card->dev, |
1355 | "Failed to create rsc_mgr %d!!!\n", i); | 1360 | "Failed to create rsc_mgr %d!!!\n", i); |
1356 | return err; | 1361 | return err; |
1357 | } | 1362 | } |
1358 | } | 1363 | } |
@@ -1399,8 +1404,9 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1399 | err = daio_mgr->get_daio(daio_mgr, &da_desc, | 1404 | err = daio_mgr->get_daio(daio_mgr, &da_desc, |
1400 | (struct daio **)&atc->daios[i]); | 1405 | (struct daio **)&atc->daios[i]); |
1401 | if (err) { | 1406 | if (err) { |
1402 | printk(KERN_ERR "ctxfi: Failed to get DAIO " | 1407 | dev_err(atc->card->dev, |
1403 | "resource %d!!!\n", i); | 1408 | "Failed to get DAIO resource %d!!!\n", |
1409 | i); | ||
1404 | return err; | 1410 | return err; |
1405 | } | 1411 | } |
1406 | atc->n_daio++; | 1412 | atc->n_daio++; |
@@ -1603,8 +1609,8 @@ static int atc_resume(struct ct_atc *atc) | |||
1603 | /* Do hardware resume. */ | 1609 | /* Do hardware resume. */ |
1604 | err = atc_hw_resume(atc); | 1610 | err = atc_hw_resume(atc); |
1605 | if (err < 0) { | 1611 | if (err < 0) { |
1606 | printk(KERN_ERR "ctxfi: pci_enable_device failed, " | 1612 | dev_err(atc->card->dev, |
1607 | "disabling device\n"); | 1613 | "pci_enable_device failed, disabling device\n"); |
1608 | snd_card_disconnect(atc->card); | 1614 | snd_card_disconnect(atc->card); |
1609 | return err; | 1615 | return err; |
1610 | } | 1616 | } |
@@ -1701,7 +1707,7 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
1701 | /* Find card model */ | 1707 | /* Find card model */ |
1702 | err = atc_identify_card(atc, ssid); | 1708 | err = atc_identify_card(atc, ssid); |
1703 | if (err < 0) { | 1709 | if (err < 0) { |
1704 | printk(KERN_ERR "ctatc: Card not recognised\n"); | 1710 | dev_err(card->dev, "ctatc: Card not recognised\n"); |
1705 | goto error1; | 1711 | goto error1; |
1706 | } | 1712 | } |
1707 | 1713 | ||
@@ -1717,7 +1723,7 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
1717 | 1723 | ||
1718 | err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); | 1724 | err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); |
1719 | if (err) { | 1725 | if (err) { |
1720 | printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); | 1726 | dev_err(card->dev, "Failed to create mixer obj!!!\n"); |
1721 | goto error1; | 1727 | goto error1; |
1722 | } | 1728 | } |
1723 | 1729 | ||
@@ -1744,6 +1750,6 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
1744 | 1750 | ||
1745 | error1: | 1751 | error1: |
1746 | ct_atc_destroy(atc); | 1752 | ct_atc_destroy(atc); |
1747 | printk(KERN_ERR "ctxfi: Something wrong!!!\n"); | 1753 | dev_err(card->dev, "Something wrong!!!\n"); |
1748 | return err; | 1754 | return err; |
1749 | } | 1755 | } |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 5f11ca22fcde..56413343a9e8 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
@@ -131,7 +131,7 @@ struct ct_atc { | |||
131 | /* Don't touch! Used for internal object. */ | 131 | /* Don't touch! Used for internal object. */ |
132 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ | 132 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ |
133 | void *mixer; /* internal mixer object */ | 133 | void *mixer; /* internal mixer object */ |
134 | void *hw; /* chip specific hardware access object */ | 134 | struct hw *hw; /* chip specific hardware access object */ |
135 | void **daios; /* digital audio io resources */ | 135 | void **daios; /* digital audio io resources */ |
136 | void **pcm; /* SUMs for collecting all pcm stream */ | 136 | void **pcm; /* SUMs for collecting all pcm stream */ |
137 | void **srcs; /* Sample Rate Converters for input signal */ | 137 | void **srcs; /* Sample Rate Converters for input signal */ |
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 84f86bf63b8f..c1c3f8816fff 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c | |||
@@ -140,19 +140,19 @@ static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); | |||
140 | 140 | ||
141 | static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) | 141 | static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) |
142 | { | 142 | { |
143 | ((struct hw *)dao->hw)->dao_get_spos(dao->ctrl_blk, spos); | 143 | dao->hw->dao_get_spos(dao->ctrl_blk, spos); |
144 | return 0; | 144 | return 0; |
145 | } | 145 | } |
146 | 146 | ||
147 | static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) | 147 | static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) |
148 | { | 148 | { |
149 | ((struct hw *)dao->hw)->dao_set_spos(dao->ctrl_blk, spos); | 149 | dao->hw->dao_set_spos(dao->ctrl_blk, spos); |
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int dao_commit_write(struct dao *dao) | 153 | static int dao_commit_write(struct dao *dao) |
154 | { | 154 | { |
155 | ((struct hw *)dao->hw)->dao_commit_write(dao->hw, | 155 | dao->hw->dao_commit_write(dao->hw, |
156 | daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); | 156 | daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); |
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
@@ -277,16 +277,14 @@ static struct dao_rsc_ops dao_ops = { | |||
277 | static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) | 277 | static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) |
278 | { | 278 | { |
279 | src->ops->master(src); | 279 | src->ops->master(src); |
280 | ((struct hw *)dai->hw)->dai_srt_set_srcm(dai->ctrl_blk, | 280 | dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src)); |
281 | src->ops->index(src)); | ||
282 | return 0; | 281 | return 0; |
283 | } | 282 | } |
284 | 283 | ||
285 | static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) | 284 | static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) |
286 | { | 285 | { |
287 | src->ops->master(src); | 286 | src->ops->master(src); |
288 | ((struct hw *)dai->hw)->dai_srt_set_srco(dai->ctrl_blk, | 287 | dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src)); |
289 | src->ops->index(src)); | ||
290 | return 0; | 288 | return 0; |
291 | } | 289 | } |
292 | 290 | ||
@@ -297,25 +295,25 @@ static int dai_set_srt_msr(struct dai *dai, unsigned int msr) | |||
297 | for (rsr = 0; msr > 1; msr >>= 1) | 295 | for (rsr = 0; msr > 1; msr >>= 1) |
298 | rsr++; | 296 | rsr++; |
299 | 297 | ||
300 | ((struct hw *)dai->hw)->dai_srt_set_rsr(dai->ctrl_blk, rsr); | 298 | dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); |
301 | return 0; | 299 | return 0; |
302 | } | 300 | } |
303 | 301 | ||
304 | static int dai_set_enb_src(struct dai *dai, unsigned int enb) | 302 | static int dai_set_enb_src(struct dai *dai, unsigned int enb) |
305 | { | 303 | { |
306 | ((struct hw *)dai->hw)->dai_srt_set_ec(dai->ctrl_blk, enb); | 304 | dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb); |
307 | return 0; | 305 | return 0; |
308 | } | 306 | } |
309 | 307 | ||
310 | static int dai_set_enb_srt(struct dai *dai, unsigned int enb) | 308 | static int dai_set_enb_srt(struct dai *dai, unsigned int enb) |
311 | { | 309 | { |
312 | ((struct hw *)dai->hw)->dai_srt_set_et(dai->ctrl_blk, enb); | 310 | dai->hw->dai_srt_set_et(dai->ctrl_blk, enb); |
313 | return 0; | 311 | return 0; |
314 | } | 312 | } |
315 | 313 | ||
316 | static int dai_commit_write(struct dai *dai) | 314 | static int dai_commit_write(struct dai *dai) |
317 | { | 315 | { |
318 | ((struct hw *)dai->hw)->dai_commit_write(dai->hw, | 316 | dai->hw->dai_commit_write(dai->hw, |
319 | daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); | 317 | daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); |
320 | return 0; | 318 | return 0; |
321 | } | 319 | } |
@@ -331,12 +329,12 @@ static struct dai_rsc_ops dai_ops = { | |||
331 | 329 | ||
332 | static int daio_rsc_init(struct daio *daio, | 330 | static int daio_rsc_init(struct daio *daio, |
333 | const struct daio_desc *desc, | 331 | const struct daio_desc *desc, |
334 | void *hw) | 332 | struct hw *hw) |
335 | { | 333 | { |
336 | int err; | 334 | int err; |
337 | unsigned int idx_l, idx_r; | 335 | unsigned int idx_l, idx_r; |
338 | 336 | ||
339 | switch (((struct hw *)hw)->chip_type) { | 337 | switch (hw->chip_type) { |
340 | case ATC20K1: | 338 | case ATC20K1: |
341 | idx_l = idx_20k1[desc->type].left; | 339 | idx_l = idx_20k1[desc->type].left; |
342 | idx_r = idx_20k1[desc->type].right; | 340 | idx_r = idx_20k1[desc->type].right; |
@@ -360,7 +358,7 @@ static int daio_rsc_init(struct daio *daio, | |||
360 | if (desc->type <= DAIO_OUT_MAX) { | 358 | if (desc->type <= DAIO_OUT_MAX) { |
361 | daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; | 359 | daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; |
362 | } else { | 360 | } else { |
363 | switch (((struct hw *)hw)->chip_type) { | 361 | switch (hw->chip_type) { |
364 | case ATC20K1: | 362 | case ATC20K1: |
365 | daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; | 363 | daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; |
366 | break; | 364 | break; |
@@ -445,7 +443,7 @@ static int dao_rsc_uninit(struct dao *dao) | |||
445 | kfree(dao->imappers); | 443 | kfree(dao->imappers); |
446 | dao->imappers = NULL; | 444 | dao->imappers = NULL; |
447 | } | 445 | } |
448 | ((struct hw *)dao->hw)->dao_put_ctrl_blk(dao->ctrl_blk); | 446 | dao->hw->dao_put_ctrl_blk(dao->ctrl_blk); |
449 | dao->hw = dao->ctrl_blk = NULL; | 447 | dao->hw = dao->ctrl_blk = NULL; |
450 | daio_rsc_uninit(&dao->daio); | 448 | daio_rsc_uninit(&dao->daio); |
451 | 449 | ||
@@ -502,7 +500,7 @@ error1: | |||
502 | 500 | ||
503 | static int dai_rsc_uninit(struct dai *dai) | 501 | static int dai_rsc_uninit(struct dai *dai) |
504 | { | 502 | { |
505 | ((struct hw *)dai->hw)->dai_put_ctrl_blk(dai->ctrl_blk); | 503 | dai->hw->dai_put_ctrl_blk(dai->ctrl_blk); |
506 | dai->hw = dai->ctrl_blk = NULL; | 504 | dai->hw = dai->ctrl_blk = NULL; |
507 | daio_rsc_uninit(&dai->daio); | 505 | daio_rsc_uninit(&dai->daio); |
508 | return 0; | 506 | return 0; |
@@ -541,7 +539,8 @@ static int get_daio_rsc(struct daio_mgr *mgr, | |||
541 | err = daio_mgr_get_rsc(&mgr->mgr, desc->type); | 539 | err = daio_mgr_get_rsc(&mgr->mgr, desc->type); |
542 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); | 540 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); |
543 | if (err) { | 541 | if (err) { |
544 | printk(KERN_ERR "Can't meet DAIO resource request!\n"); | 542 | dev_err(mgr->card->dev, |
543 | "Can't meet DAIO resource request!\n"); | ||
545 | return err; | 544 | return err; |
546 | } | 545 | } |
547 | 546 | ||
@@ -692,7 +691,7 @@ static int daio_mgr_commit_write(struct daio_mgr *mgr) | |||
692 | return 0; | 691 | return 0; |
693 | } | 692 | } |
694 | 693 | ||
695 | int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) | 694 | int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr) |
696 | { | 695 | { |
697 | int err, i; | 696 | int err, i; |
698 | struct daio_mgr *daio_mgr; | 697 | struct daio_mgr *daio_mgr; |
@@ -727,12 +726,13 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) | |||
727 | daio_mgr->imap_add = daio_imap_add; | 726 | daio_mgr->imap_add = daio_imap_add; |
728 | daio_mgr->imap_delete = daio_imap_delete; | 727 | daio_mgr->imap_delete = daio_imap_delete; |
729 | daio_mgr->commit_write = daio_mgr_commit_write; | 728 | daio_mgr->commit_write = daio_mgr_commit_write; |
729 | daio_mgr->card = hw->card; | ||
730 | 730 | ||
731 | for (i = 0; i < 8; i++) { | 731 | for (i = 0; i < 8; i++) { |
732 | ((struct hw *)hw)->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); | 732 | hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); |
733 | ((struct hw *)hw)->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); | 733 | hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); |
734 | } | 734 | } |
735 | ((struct hw *)hw)->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); | 735 | hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); |
736 | 736 | ||
737 | *rdaio_mgr = daio_mgr; | 737 | *rdaio_mgr = daio_mgr; |
738 | 738 | ||
diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h index 85ccb6ee1ab4..0ebbf350f51a 100644 --- a/sound/pci/ctxfi/ctdaio.h +++ b/sound/pci/ctxfi/ctdaio.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "ctimap.h" | 23 | #include "ctimap.h" |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <sound/core.h> | ||
26 | 27 | ||
27 | /* Define the descriptor of a daio resource */ | 28 | /* Define the descriptor of a daio resource */ |
28 | enum DAIOTYP { | 29 | enum DAIOTYP { |
@@ -53,14 +54,14 @@ struct dao { | |||
53 | struct dao_rsc_ops *ops; /* DAO specific operations */ | 54 | struct dao_rsc_ops *ops; /* DAO specific operations */ |
54 | struct imapper **imappers; | 55 | struct imapper **imappers; |
55 | struct daio_mgr *mgr; | 56 | struct daio_mgr *mgr; |
56 | void *hw; | 57 | struct hw *hw; |
57 | void *ctrl_blk; | 58 | void *ctrl_blk; |
58 | }; | 59 | }; |
59 | 60 | ||
60 | struct dai { | 61 | struct dai { |
61 | struct daio daio; | 62 | struct daio daio; |
62 | struct dai_rsc_ops *ops; /* DAI specific operations */ | 63 | struct dai_rsc_ops *ops; /* DAI specific operations */ |
63 | void *hw; | 64 | struct hw *hw; |
64 | void *ctrl_blk; | 65 | void *ctrl_blk; |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -98,6 +99,7 @@ struct daio_desc { | |||
98 | 99 | ||
99 | struct daio_mgr { | 100 | struct daio_mgr { |
100 | struct rsc_mgr mgr; /* Basic resource manager info */ | 101 | struct rsc_mgr mgr; /* Basic resource manager info */ |
102 | struct snd_card *card; /* pointer to this card */ | ||
101 | spinlock_t mgr_lock; | 103 | spinlock_t mgr_lock; |
102 | spinlock_t imap_lock; | 104 | spinlock_t imap_lock; |
103 | struct list_head imappers; | 105 | struct list_head imappers; |
@@ -117,7 +119,7 @@ struct daio_mgr { | |||
117 | }; | 119 | }; |
118 | 120 | ||
119 | /* Constructor and destructor of daio resource manager */ | 121 | /* Constructor and destructor of daio resource manager */ |
120 | int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr); | 122 | int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr); |
121 | int daio_mgr_destroy(struct daio_mgr *daio_mgr); | 123 | int daio_mgr_destroy(struct daio_mgr *daio_mgr); |
122 | 124 | ||
123 | #endif /* CTDAIO_H */ | 125 | #endif /* CTDAIO_H */ |
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index 5977e9a24b5c..54cc9cb75f00 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <sound/core.h> | ||
23 | 24 | ||
24 | enum CHIPTYP { | 25 | enum CHIPTYP { |
25 | ATC20K1, | 26 | ATC20K1, |
@@ -184,9 +185,10 @@ struct hw { | |||
184 | void *irq_callback_data; | 185 | void *irq_callback_data; |
185 | 186 | ||
186 | struct pci_dev *pci; /* the pci kernel structure of this card */ | 187 | struct pci_dev *pci; /* the pci kernel structure of this card */ |
188 | struct snd_card *card; /* pointer to this card */ | ||
187 | int irq; | 189 | int irq; |
188 | unsigned long io_base; | 190 | unsigned long io_base; |
189 | unsigned long mem_base; | 191 | void __iomem *mem_base; |
190 | 192 | ||
191 | enum CHIPTYP chip_type; | 193 | enum CHIPTYP chip_type; |
192 | enum CTCARDS model; | 194 | enum CTCARDS model; |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 6ac40beb49da..b425aa8ee578 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -1268,7 +1268,8 @@ static int hw_trn_init(struct hw *hw, const struct trn_conf *info) | |||
1268 | 1268 | ||
1269 | /* Set up device page table */ | 1269 | /* Set up device page table */ |
1270 | if ((~0UL) == info->vm_pgt_phys) { | 1270 | if ((~0UL) == info->vm_pgt_phys) { |
1271 | printk(KERN_ERR "Wrong device page table page address!\n"); | 1271 | dev_err(hw->card->dev, |
1272 | "Wrong device page table page address!\n"); | ||
1272 | return -1; | 1273 | return -1; |
1273 | } | 1274 | } |
1274 | 1275 | ||
@@ -1327,7 +1328,7 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1327 | mdelay(40); | 1328 | mdelay(40); |
1328 | } | 1329 | } |
1329 | if (i >= 3) { | 1330 | if (i >= 3) { |
1330 | printk(KERN_ALERT "PLL initialization failed!!!\n"); | 1331 | dev_alert(hw->card->dev, "PLL initialization failed!!!\n"); |
1331 | return -EBUSY; | 1332 | return -EBUSY; |
1332 | } | 1333 | } |
1333 | 1334 | ||
@@ -1351,7 +1352,7 @@ static int hw_auto_init(struct hw *hw) | |||
1351 | break; | 1352 | break; |
1352 | } | 1353 | } |
1353 | if (!get_field(gctl, GCTL_AID)) { | 1354 | if (!get_field(gctl, GCTL_AID)) { |
1354 | printk(KERN_ALERT "Card Auto-init failed!!!\n"); | 1355 | dev_alert(hw->card->dev, "Card Auto-init failed!!!\n"); |
1355 | return -EBUSY; | 1356 | return -EBUSY; |
1356 | } | 1357 | } |
1357 | 1358 | ||
@@ -1802,7 +1803,7 @@ static int uaa_to_xfi(struct pci_dev *pci) | |||
1802 | unsigned int is_uaa; | 1803 | unsigned int is_uaa; |
1803 | unsigned int data[4] = {0}; | 1804 | unsigned int data[4] = {0}; |
1804 | unsigned int io_base; | 1805 | unsigned int io_base; |
1805 | void *mem_base; | 1806 | void __iomem *mem_base; |
1806 | int i; | 1807 | int i; |
1807 | const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); | 1808 | const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); |
1808 | const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); | 1809 | const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); |
@@ -1911,9 +1912,9 @@ static int hw_card_start(struct hw *hw) | |||
1911 | /* Set DMA transfer mask */ | 1912 | /* Set DMA transfer mask */ |
1912 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || | 1913 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || |
1913 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { | 1914 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { |
1914 | printk(KERN_ERR "architecture does not support PCI " | 1915 | dev_err(hw->card->dev, |
1915 | "busmaster DMA with mask 0x%llx\n", | 1916 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
1916 | CT_XFI_DMA_MASK); | 1917 | CT_XFI_DMA_MASK); |
1917 | err = -ENXIO; | 1918 | err = -ENXIO; |
1918 | goto error1; | 1919 | goto error1; |
1919 | } | 1920 | } |
@@ -1942,7 +1943,8 @@ static int hw_card_start(struct hw *hw) | |||
1942 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, | 1943 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, |
1943 | KBUILD_MODNAME, hw); | 1944 | KBUILD_MODNAME, hw); |
1944 | if (err < 0) { | 1945 | if (err < 0) { |
1945 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 1946 | dev_err(hw->card->dev, |
1947 | "XFi: Cannot get irq %d\n", pci->irq); | ||
1946 | goto error2; | 1948 | goto error2; |
1947 | } | 1949 | } |
1948 | hw->irq = pci->irq; | 1950 | hw->irq = pci->irq; |
@@ -1985,9 +1987,9 @@ static int hw_card_shutdown(struct hw *hw) | |||
1985 | hw->irq = -1; | 1987 | hw->irq = -1; |
1986 | 1988 | ||
1987 | if (hw->mem_base) | 1989 | if (hw->mem_base) |
1988 | iounmap((void *)hw->mem_base); | 1990 | iounmap(hw->mem_base); |
1989 | 1991 | ||
1990 | hw->mem_base = (unsigned long)NULL; | 1992 | hw->mem_base = NULL; |
1991 | 1993 | ||
1992 | if (hw->io_base) | 1994 | if (hw->io_base) |
1993 | pci_release_regions(hw->pci); | 1995 | pci_release_regions(hw->pci); |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index b1438861d38a..253899d13790 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -1187,7 +1187,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1187 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); | 1187 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); |
1188 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1188 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1189 | } else { | 1189 | } else { |
1190 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); | 1190 | dev_alert(hw->card->dev, |
1191 | "ERROR!!! Invalid sampling rate!!!\n"); | ||
1191 | return -EINVAL; | 1192 | return -EINVAL; |
1192 | } | 1193 | } |
1193 | 1194 | ||
@@ -1246,8 +1247,8 @@ static int hw_trn_init(struct hw *hw, const struct trn_conf *info) | |||
1246 | 1247 | ||
1247 | /* Set up device page table */ | 1248 | /* Set up device page table */ |
1248 | if ((~0UL) == info->vm_pgt_phys) { | 1249 | if ((~0UL) == info->vm_pgt_phys) { |
1249 | printk(KERN_ALERT "ctxfi: " | 1250 | dev_alert(hw->card->dev, |
1250 | "Wrong device page table page address!!!\n"); | 1251 | "Wrong device page table page address!!!\n"); |
1251 | return -1; | 1252 | return -1; |
1252 | } | 1253 | } |
1253 | 1254 | ||
@@ -1352,7 +1353,8 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1352 | break; | 1353 | break; |
1353 | } | 1354 | } |
1354 | if (i >= 1000) { | 1355 | if (i >= 1000) { |
1355 | printk(KERN_ALERT "ctxfi: PLL initialization failed!!!\n"); | 1356 | dev_alert(hw->card->dev, |
1357 | "PLL initialization failed!!!\n"); | ||
1356 | return -EBUSY; | 1358 | return -EBUSY; |
1357 | } | 1359 | } |
1358 | 1360 | ||
@@ -1376,7 +1378,7 @@ static int hw_auto_init(struct hw *hw) | |||
1376 | break; | 1378 | break; |
1377 | } | 1379 | } |
1378 | if (!get_field(gctl, GCTL_AID)) { | 1380 | if (!get_field(gctl, GCTL_AID)) { |
1379 | printk(KERN_ALERT "ctxfi: Card Auto-init failed!!!\n"); | 1381 | dev_alert(hw->card->dev, "Card Auto-init failed!!!\n"); |
1380 | return -EBUSY; | 1382 | return -EBUSY; |
1381 | } | 1383 | } |
1382 | 1384 | ||
@@ -1847,7 +1849,7 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1847 | /* Initialize I2C */ | 1849 | /* Initialize I2C */ |
1848 | err = hw20k2_i2c_init(hw, 0x1A, 1, 1); | 1850 | err = hw20k2_i2c_init(hw, 0x1A, 1, 1); |
1849 | if (err < 0) { | 1851 | if (err < 0) { |
1850 | printk(KERN_ALERT "ctxfi: Failure to acquire I2C!!!\n"); | 1852 | dev_alert(hw->card->dev, "Failure to acquire I2C!!!\n"); |
1851 | goto error; | 1853 | goto error; |
1852 | } | 1854 | } |
1853 | 1855 | ||
@@ -1890,8 +1892,9 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1890 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), | 1892 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), |
1891 | MAKE_WM8775_DATA(0x0A)); | 1893 | MAKE_WM8775_DATA(0x0A)); |
1892 | } else { | 1894 | } else { |
1893 | printk(KERN_ALERT "ctxfi: Invalid master sampling " | 1895 | dev_alert(hw->card->dev, |
1894 | "rate (msr %d)!!!\n", info->msr); | 1896 | "Invalid master sampling rate (msr %d)!!!\n", |
1897 | info->msr); | ||
1895 | err = -EINVAL; | 1898 | err = -EINVAL; |
1896 | goto error; | 1899 | goto error; |
1897 | } | 1900 | } |
@@ -2034,8 +2037,9 @@ static int hw_card_start(struct hw *hw) | |||
2034 | /* Set DMA transfer mask */ | 2037 | /* Set DMA transfer mask */ |
2035 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || | 2038 | if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || |
2036 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { | 2039 | pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { |
2037 | printk(KERN_ERR "ctxfi: architecture does not support PCI " | 2040 | dev_err(hw->card->dev, |
2038 | "busmaster DMA with mask 0x%llx\n", CT_XFI_DMA_MASK); | 2041 | "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
2042 | CT_XFI_DMA_MASK); | ||
2039 | err = -ENXIO; | 2043 | err = -ENXIO; |
2040 | goto error1; | 2044 | goto error1; |
2041 | } | 2045 | } |
@@ -2046,8 +2050,8 @@ static int hw_card_start(struct hw *hw) | |||
2046 | goto error1; | 2050 | goto error1; |
2047 | 2051 | ||
2048 | hw->io_base = pci_resource_start(hw->pci, 2); | 2052 | hw->io_base = pci_resource_start(hw->pci, 2); |
2049 | hw->mem_base = (unsigned long)ioremap(hw->io_base, | 2053 | hw->mem_base = ioremap(hw->io_base, |
2050 | pci_resource_len(hw->pci, 2)); | 2054 | pci_resource_len(hw->pci, 2)); |
2051 | if (!hw->mem_base) { | 2055 | if (!hw->mem_base) { |
2052 | err = -ENOENT; | 2056 | err = -ENOENT; |
2053 | goto error2; | 2057 | goto error2; |
@@ -2063,7 +2067,8 @@ static int hw_card_start(struct hw *hw) | |||
2063 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, | 2067 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, |
2064 | KBUILD_MODNAME, hw); | 2068 | KBUILD_MODNAME, hw); |
2065 | if (err < 0) { | 2069 | if (err < 0) { |
2066 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 2070 | dev_err(hw->card->dev, |
2071 | "XFi: Cannot get irq %d\n", pci->irq); | ||
2067 | goto error2; | 2072 | goto error2; |
2068 | } | 2073 | } |
2069 | hw->irq = pci->irq; | 2074 | hw->irq = pci->irq; |
@@ -2107,9 +2112,9 @@ static int hw_card_shutdown(struct hw *hw) | |||
2107 | hw->irq = -1; | 2112 | hw->irq = -1; |
2108 | 2113 | ||
2109 | if (hw->mem_base) | 2114 | if (hw->mem_base) |
2110 | iounmap((void *)hw->mem_base); | 2115 | iounmap(hw->mem_base); |
2111 | 2116 | ||
2112 | hw->mem_base = (unsigned long)NULL; | 2117 | hw->mem_base = NULL; |
2113 | 2118 | ||
2114 | if (hw->io_base) | 2119 | if (hw->io_base) |
2115 | pci_release_regions(hw->pci); | 2120 | pci_release_regions(hw->pci); |
@@ -2229,12 +2234,12 @@ static int hw_resume(struct hw *hw, struct card_conf *info) | |||
2229 | 2234 | ||
2230 | static u32 hw_read_20kx(struct hw *hw, u32 reg) | 2235 | static u32 hw_read_20kx(struct hw *hw, u32 reg) |
2231 | { | 2236 | { |
2232 | return readl((void *)(hw->mem_base + reg)); | 2237 | return readl(hw->mem_base + reg); |
2233 | } | 2238 | } |
2234 | 2239 | ||
2235 | static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) | 2240 | static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) |
2236 | { | 2241 | { |
2237 | writel(data, (void *)(hw->mem_base + reg)); | 2242 | writel(data, hw->mem_base + reg); |
2238 | } | 2243 | } |
2239 | 2244 | ||
2240 | static struct hw ct20k2_preset = { | 2245 | static struct hw ct20k2_preset = { |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 48fe0e39c2be..4f4a2a5dedb8 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
@@ -854,8 +854,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer) | |||
854 | for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { | 854 | for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { |
855 | err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum); | 855 | err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum); |
856 | if (err) { | 856 | if (err) { |
857 | printk(KERN_ERR "ctxfi:Failed to get sum resources for " | 857 | dev_err(mixer->atc->card->dev, |
858 | "front output!\n"); | 858 | "Failed to get sum resources for front output!\n"); |
859 | break; | 859 | break; |
860 | } | 860 | } |
861 | mixer->sums[i] = sum; | 861 | mixer->sums[i] = sum; |
@@ -869,8 +869,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer) | |||
869 | for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { | 869 | for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { |
870 | err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer); | 870 | err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer); |
871 | if (err) { | 871 | if (err) { |
872 | printk(KERN_ERR "ctxfi:Failed to get amixer resources " | 872 | dev_err(mixer->atc->card->dev, |
873 | "for mixer obj!\n"); | 873 | "Failed to get amixer resources for mixer obj!\n"); |
874 | break; | 874 | break; |
875 | } | 875 | } |
876 | mixer->amixers[i] = amixer; | 876 | mixer->amixers[i] = amixer; |
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index e8a4feb1ed86..d86c474ca5b6 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c | |||
@@ -217,7 +217,8 @@ static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream) | |||
217 | err = atc->pcm_playback_prepare(atc, apcm); | 217 | err = atc->pcm_playback_prepare(atc, apcm); |
218 | 218 | ||
219 | if (err < 0) { | 219 | if (err < 0) { |
220 | printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n"); | 220 | dev_err(atc->card->dev, |
221 | "Preparing pcm playback failed!!!\n"); | ||
221 | return err; | 222 | return err; |
222 | } | 223 | } |
223 | 224 | ||
@@ -324,7 +325,8 @@ static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream) | |||
324 | 325 | ||
325 | err = atc->pcm_capture_prepare(atc, apcm); | 326 | err = atc->pcm_capture_prepare(atc, apcm); |
326 | if (err < 0) { | 327 | if (err < 0) { |
327 | printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n"); | 328 | dev_err(atc->card->dev, |
329 | "Preparing pcm capture failed!!!\n"); | ||
328 | return err; | 330 | return err; |
329 | } | 331 | } |
330 | 332 | ||
@@ -435,7 +437,8 @@ int ct_alsa_pcm_create(struct ct_atc *atc, | |||
435 | err = snd_pcm_new(atc->card, "ctxfi", device, | 437 | err = snd_pcm_new(atc->card, "ctxfi", device, |
436 | playback_count, capture_count, &pcm); | 438 | playback_count, capture_count, &pcm); |
437 | if (err < 0) { | 439 | if (err < 0) { |
438 | printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err); | 440 | dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n", |
441 | err); | ||
439 | return err; | 442 | return err; |
440 | } | 443 | } |
441 | 444 | ||
diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c index 7dfaf67344d4..1a97e406d8ec 100644 --- a/sound/pci/ctxfi/ctresource.c +++ b/sound/pci/ctxfi/ctresource.c | |||
@@ -134,7 +134,8 @@ static struct rsc_ops rsc_generic_ops = { | |||
134 | .next_conj = rsc_next_conj, | 134 | .next_conj = rsc_next_conj, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw) | 137 | int |
138 | rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw) | ||
138 | { | 139 | { |
139 | int err = 0; | 140 | int err = 0; |
140 | 141 | ||
@@ -151,25 +152,24 @@ int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw) | |||
151 | 152 | ||
152 | switch (type) { | 153 | switch (type) { |
153 | case SRC: | 154 | case SRC: |
154 | err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk); | 155 | err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk); |
155 | break; | 156 | break; |
156 | case AMIXER: | 157 | case AMIXER: |
157 | err = ((struct hw *)hw)-> | 158 | err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk); |
158 | amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk); | ||
159 | break; | 159 | break; |
160 | case SRCIMP: | 160 | case SRCIMP: |
161 | case SUM: | 161 | case SUM: |
162 | case DAIO: | 162 | case DAIO: |
163 | break; | 163 | break; |
164 | default: | 164 | default: |
165 | printk(KERN_ERR | 165 | dev_err(((struct hw *)hw)->card->dev, |
166 | "ctxfi: Invalid resource type value %d!\n", type); | 166 | "Invalid resource type value %d!\n", type); |
167 | return -EINVAL; | 167 | return -EINVAL; |
168 | } | 168 | } |
169 | 169 | ||
170 | if (err) { | 170 | if (err) { |
171 | printk(KERN_ERR | 171 | dev_err(((struct hw *)hw)->card->dev, |
172 | "ctxfi: Failed to get resource control block!\n"); | 172 | "Failed to get resource control block!\n"); |
173 | return err; | 173 | return err; |
174 | } | 174 | } |
175 | 175 | ||
@@ -181,19 +181,18 @@ int rsc_uninit(struct rsc *rsc) | |||
181 | if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) { | 181 | if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) { |
182 | switch (rsc->type) { | 182 | switch (rsc->type) { |
183 | case SRC: | 183 | case SRC: |
184 | ((struct hw *)rsc->hw)-> | 184 | rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk); |
185 | src_rsc_put_ctrl_blk(rsc->ctrl_blk); | ||
186 | break; | 185 | break; |
187 | case AMIXER: | 186 | case AMIXER: |
188 | ((struct hw *)rsc->hw)-> | 187 | rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk); |
189 | amixer_rsc_put_ctrl_blk(rsc->ctrl_blk); | ||
190 | break; | 188 | break; |
191 | case SUM: | 189 | case SUM: |
192 | case DAIO: | 190 | case DAIO: |
193 | break; | 191 | break; |
194 | default: | 192 | default: |
195 | printk(KERN_ERR "ctxfi: " | 193 | dev_err(((struct hw *)rsc->hw)->card->dev, |
196 | "Invalid resource type value %d!\n", rsc->type); | 194 | "Invalid resource type value %d!\n", |
195 | rsc->type); | ||
197 | break; | 196 | break; |
198 | } | 197 | } |
199 | 198 | ||
@@ -208,10 +207,9 @@ int rsc_uninit(struct rsc *rsc) | |||
208 | } | 207 | } |
209 | 208 | ||
210 | int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, | 209 | int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, |
211 | unsigned int amount, void *hw_obj) | 210 | unsigned int amount, struct hw *hw) |
212 | { | 211 | { |
213 | int err = 0; | 212 | int err = 0; |
214 | struct hw *hw = hw_obj; | ||
215 | 213 | ||
216 | mgr->type = NUM_RSCTYP; | 214 | mgr->type = NUM_RSCTYP; |
217 | 215 | ||
@@ -235,15 +233,15 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, | |||
235 | case SUM: | 233 | case SUM: |
236 | break; | 234 | break; |
237 | default: | 235 | default: |
238 | printk(KERN_ERR | 236 | dev_err(hw->card->dev, |
239 | "ctxfi: Invalid resource type value %d!\n", type); | 237 | "Invalid resource type value %d!\n", type); |
240 | err = -EINVAL; | 238 | err = -EINVAL; |
241 | goto error; | 239 | goto error; |
242 | } | 240 | } |
243 | 241 | ||
244 | if (err) { | 242 | if (err) { |
245 | printk(KERN_ERR | 243 | dev_err(hw->card->dev, |
246 | "ctxfi: Failed to get manager control block!\n"); | 244 | "Failed to get manager control block!\n"); |
247 | goto error; | 245 | goto error; |
248 | } | 246 | } |
249 | 247 | ||
@@ -268,26 +266,23 @@ int rsc_mgr_uninit(struct rsc_mgr *mgr) | |||
268 | if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) { | 266 | if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) { |
269 | switch (mgr->type) { | 267 | switch (mgr->type) { |
270 | case SRC: | 268 | case SRC: |
271 | ((struct hw *)mgr->hw)-> | 269 | mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk); |
272 | src_mgr_put_ctrl_blk(mgr->ctrl_blk); | ||
273 | break; | 270 | break; |
274 | case SRCIMP: | 271 | case SRCIMP: |
275 | ((struct hw *)mgr->hw)-> | 272 | mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk); |
276 | srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk); | ||
277 | break; | 273 | break; |
278 | case AMIXER: | 274 | case AMIXER: |
279 | ((struct hw *)mgr->hw)-> | 275 | mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk); |
280 | amixer_mgr_put_ctrl_blk(mgr->ctrl_blk); | ||
281 | break; | 276 | break; |
282 | case DAIO: | 277 | case DAIO: |
283 | ((struct hw *)mgr->hw)-> | 278 | mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk); |
284 | daio_mgr_put_ctrl_blk(mgr->ctrl_blk); | ||
285 | break; | 279 | break; |
286 | case SUM: | 280 | case SUM: |
287 | break; | 281 | break; |
288 | default: | 282 | default: |
289 | printk(KERN_ERR "ctxfi: " | 283 | dev_err(((struct hw *)mgr->hw)->card->dev, |
290 | "Invalid resource type value %d!\n", mgr->type); | 284 | "Invalid resource type value %d!\n", |
285 | mgr->type); | ||
291 | break; | 286 | break; |
292 | } | 287 | } |
293 | 288 | ||
diff --git a/sound/pci/ctxfi/ctresource.h b/sound/pci/ctxfi/ctresource.h index 0838c2e84f8b..9b746c3719e6 100644 --- a/sound/pci/ctxfi/ctresource.h +++ b/sound/pci/ctxfi/ctresource.h | |||
@@ -38,7 +38,7 @@ struct rsc { | |||
38 | u32 conj:12; /* Current conjugate index */ | 38 | u32 conj:12; /* Current conjugate index */ |
39 | u32 msr:4; /* The Master Sample Rate a resource working on */ | 39 | u32 msr:4; /* The Master Sample Rate a resource working on */ |
40 | void *ctrl_blk; /* Chip specific control info block for a resource */ | 40 | void *ctrl_blk; /* Chip specific control info block for a resource */ |
41 | void *hw; /* Chip specific object for hardware access means */ | 41 | struct hw *hw; /* Chip specific object for hardware access means */ |
42 | struct rsc_ops *ops; /* Generic resource operations */ | 42 | struct rsc_ops *ops; /* Generic resource operations */ |
43 | }; | 43 | }; |
44 | 44 | ||
@@ -50,7 +50,8 @@ struct rsc_ops { | |||
50 | int (*output_slot)(const struct rsc *rsc); | 50 | int (*output_slot)(const struct rsc *rsc); |
51 | }; | 51 | }; |
52 | 52 | ||
53 | int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw); | 53 | int |
54 | rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw); | ||
54 | int rsc_uninit(struct rsc *rsc); | 55 | int rsc_uninit(struct rsc *rsc); |
55 | 56 | ||
56 | struct rsc_mgr { | 57 | struct rsc_mgr { |
@@ -59,12 +60,12 @@ struct rsc_mgr { | |||
59 | unsigned int avail; /* The amount of currently available resources */ | 60 | unsigned int avail; /* The amount of currently available resources */ |
60 | unsigned char *rscs; /* The bit-map for resource allocation */ | 61 | unsigned char *rscs; /* The bit-map for resource allocation */ |
61 | void *ctrl_blk; /* Chip specific control info block */ | 62 | void *ctrl_blk; /* Chip specific control info block */ |
62 | void *hw; /* Chip specific object for hardware access */ | 63 | struct hw *hw; /* Chip specific object for hardware access */ |
63 | }; | 64 | }; |
64 | 65 | ||
65 | /* Resource management is based on bit-map mechanism */ | 66 | /* Resource management is based on bit-map mechanism */ |
66 | int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, | 67 | int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, |
67 | unsigned int amount, void *hw); | 68 | unsigned int amount, struct hw *hw); |
68 | int rsc_mgr_uninit(struct rsc_mgr *mgr); | 69 | int rsc_mgr_uninit(struct rsc_mgr *mgr); |
69 | int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx); | 70 | int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx); |
70 | int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx); | 71 | int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx); |
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c index 6e77e86307c2..ec1f08464d93 100644 --- a/sound/pci/ctxfi/ctsrc.c +++ b/sound/pci/ctxfi/ctsrc.c | |||
@@ -431,7 +431,8 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc) | |||
431 | 431 | ||
432 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); | 432 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); |
433 | if (err) { | 433 | if (err) { |
434 | printk(KERN_ERR "ctxfi: Can't meet SRC resource request!\n"); | 434 | dev_err(mgr->card->dev, |
435 | "Can't meet SRC resource request!\n"); | ||
435 | return err; | 436 | return err; |
436 | } | 437 | } |
437 | 438 | ||
@@ -543,7 +544,7 @@ static int src_mgr_commit_write(struct src_mgr *mgr) | |||
543 | return 0; | 544 | return 0; |
544 | } | 545 | } |
545 | 546 | ||
546 | int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr) | 547 | int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr) |
547 | { | 548 | { |
548 | int err, i; | 549 | int err, i; |
549 | struct src_mgr *src_mgr; | 550 | struct src_mgr *src_mgr; |
@@ -558,7 +559,7 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr) | |||
558 | goto error1; | 559 | goto error1; |
559 | 560 | ||
560 | spin_lock_init(&src_mgr->mgr_lock); | 561 | spin_lock_init(&src_mgr->mgr_lock); |
561 | conj_mask = ((struct hw *)hw)->src_dirty_conj_mask(); | 562 | conj_mask = hw->src_dirty_conj_mask(); |
562 | 563 | ||
563 | src_mgr->get_src = get_src_rsc; | 564 | src_mgr->get_src = get_src_rsc; |
564 | src_mgr->put_src = put_src_rsc; | 565 | src_mgr->put_src = put_src_rsc; |
@@ -566,12 +567,13 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr) | |||
566 | src_mgr->src_enable = src_enable; | 567 | src_mgr->src_enable = src_enable; |
567 | src_mgr->src_disable = src_disable; | 568 | src_mgr->src_disable = src_disable; |
568 | src_mgr->commit_write = src_mgr_commit_write; | 569 | src_mgr->commit_write = src_mgr_commit_write; |
570 | src_mgr->card = hw->card; | ||
569 | 571 | ||
570 | /* Disable all SRC resources. */ | 572 | /* Disable all SRC resources. */ |
571 | for (i = 0; i < 256; i++) | 573 | for (i = 0; i < 256; i++) |
572 | ((struct hw *)hw)->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i); | 574 | hw->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i); |
573 | 575 | ||
574 | ((struct hw *)hw)->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk); | 576 | hw->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk); |
575 | 577 | ||
576 | *rsrc_mgr = src_mgr; | 578 | *rsrc_mgr = src_mgr; |
577 | 579 | ||
@@ -739,7 +741,8 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, | |||
739 | } | 741 | } |
740 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); | 742 | spin_unlock_irqrestore(&mgr->mgr_lock, flags); |
741 | if (err) { | 743 | if (err) { |
742 | printk(KERN_ERR "ctxfi: Can't meet SRCIMP resource request!\n"); | 744 | dev_err(mgr->card->dev, |
745 | "Can't meet SRCIMP resource request!\n"); | ||
743 | goto error1; | 746 | goto error1; |
744 | } | 747 | } |
745 | 748 | ||
@@ -825,7 +828,7 @@ static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry) | |||
825 | return err; | 828 | return err; |
826 | } | 829 | } |
827 | 830 | ||
828 | int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr) | 831 | int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr) |
829 | { | 832 | { |
830 | int err; | 833 | int err; |
831 | struct srcimp_mgr *srcimp_mgr; | 834 | struct srcimp_mgr *srcimp_mgr; |
@@ -857,6 +860,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr) | |||
857 | srcimp_mgr->put_srcimp = put_srcimp_rsc; | 860 | srcimp_mgr->put_srcimp = put_srcimp_rsc; |
858 | srcimp_mgr->imap_add = srcimp_imap_add; | 861 | srcimp_mgr->imap_add = srcimp_imap_add; |
859 | srcimp_mgr->imap_delete = srcimp_imap_delete; | 862 | srcimp_mgr->imap_delete = srcimp_imap_delete; |
863 | srcimp_mgr->card = hw->card; | ||
860 | 864 | ||
861 | *rsrcimp_mgr = srcimp_mgr; | 865 | *rsrcimp_mgr = srcimp_mgr; |
862 | 866 | ||
diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h index 259366aabcac..da7573c5db9b 100644 --- a/sound/pci/ctxfi/ctsrc.h +++ b/sound/pci/ctxfi/ctsrc.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "ctimap.h" | 23 | #include "ctimap.h" |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <sound/core.h> | ||
26 | 27 | ||
27 | #define SRC_STATE_OFF 0x0 | 28 | #define SRC_STATE_OFF 0x0 |
28 | #define SRC_STATE_INIT 0x4 | 29 | #define SRC_STATE_INIT 0x4 |
@@ -85,6 +86,7 @@ struct src_desc { | |||
85 | /* Define src manager object */ | 86 | /* Define src manager object */ |
86 | struct src_mgr { | 87 | struct src_mgr { |
87 | struct rsc_mgr mgr; /* Basic resource manager info */ | 88 | struct rsc_mgr mgr; /* Basic resource manager info */ |
89 | struct snd_card *card; /* pointer to this card */ | ||
88 | spinlock_t mgr_lock; | 90 | spinlock_t mgr_lock; |
89 | 91 | ||
90 | /* request src resource */ | 92 | /* request src resource */ |
@@ -123,6 +125,7 @@ struct srcimp_desc { | |||
123 | 125 | ||
124 | struct srcimp_mgr { | 126 | struct srcimp_mgr { |
125 | struct rsc_mgr mgr; /* Basic resource manager info */ | 127 | struct rsc_mgr mgr; /* Basic resource manager info */ |
128 | struct snd_card *card; /* pointer to this card */ | ||
126 | spinlock_t mgr_lock; | 129 | spinlock_t mgr_lock; |
127 | spinlock_t imap_lock; | 130 | spinlock_t imap_lock; |
128 | struct list_head imappers; | 131 | struct list_head imappers; |
@@ -140,10 +143,10 @@ struct srcimp_mgr { | |||
140 | }; | 143 | }; |
141 | 144 | ||
142 | /* Constructor and destructor of SRC resource manager */ | 145 | /* Constructor and destructor of SRC resource manager */ |
143 | int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr); | 146 | int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr); |
144 | int src_mgr_destroy(struct src_mgr *src_mgr); | 147 | int src_mgr_destroy(struct src_mgr *src_mgr); |
145 | /* Constructor and destructor of SRCIMP resource manager */ | 148 | /* Constructor and destructor of SRCIMP resource manager */ |
146 | int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrc_mgr); | 149 | int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrc_mgr); |
147 | int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr); | 150 | int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr); |
148 | 151 | ||
149 | #endif /* CTSRC_H */ | 152 | #endif /* CTSRC_H */ |
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 6109490b83e8..419306ef825f 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "ctvmem.h" | 18 | #include "ctvmem.h" |
19 | #include "ctatc.h" | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
@@ -29,15 +30,15 @@ | |||
29 | * @size must be page aligned. | 30 | * @size must be page aligned. |
30 | * */ | 31 | * */ |
31 | static struct ct_vm_block * | 32 | static struct ct_vm_block * |
32 | get_vm_block(struct ct_vm *vm, unsigned int size) | 33 | get_vm_block(struct ct_vm *vm, unsigned int size, struct ct_atc *atc) |
33 | { | 34 | { |
34 | struct ct_vm_block *block = NULL, *entry; | 35 | struct ct_vm_block *block = NULL, *entry; |
35 | struct list_head *pos; | 36 | struct list_head *pos; |
36 | 37 | ||
37 | size = CT_PAGE_ALIGN(size); | 38 | size = CT_PAGE_ALIGN(size); |
38 | if (size > vm->size) { | 39 | if (size > vm->size) { |
39 | printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual " | 40 | dev_err(atc->card->dev, |
40 | "memory space available!\n"); | 41 | "Fail! No sufficient device virtual memory space available!\n"); |
41 | return NULL; | 42 | return NULL; |
42 | } | 43 | } |
43 | 44 | ||
@@ -129,11 +130,12 @@ ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size) | |||
129 | unsigned int pte_start; | 130 | unsigned int pte_start; |
130 | unsigned i, pages; | 131 | unsigned i, pages; |
131 | unsigned long *ptp; | 132 | unsigned long *ptp; |
133 | struct ct_atc *atc = snd_pcm_substream_chip(substream); | ||
132 | 134 | ||
133 | block = get_vm_block(vm, size); | 135 | block = get_vm_block(vm, size, atc); |
134 | if (block == NULL) { | 136 | if (block == NULL) { |
135 | printk(KERN_ERR "ctxfi: No virtual memory block that is big " | 137 | dev_err(atc->card->dev, |
136 | "enough to allocate!\n"); | 138 | "No virtual memory block that is big enough to allocate!\n"); |
137 | return NULL; | 139 | return NULL; |
138 | } | 140 | } |
139 | 141 | ||
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index 8f8b566a1b35..f2f32779de98 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
@@ -76,17 +76,18 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
76 | if (err) | 76 | if (err) |
77 | return err; | 77 | return err; |
78 | if ((reference_rate != 48000) && (reference_rate != 44100)) { | 78 | if ((reference_rate != 48000) && (reference_rate != 44100)) { |
79 | printk(KERN_ERR "ctxfi: Invalid reference_rate value %u!!!\n", | 79 | dev_err(card->dev, |
80 | reference_rate); | 80 | "Invalid reference_rate value %u!!!\n", |
81 | printk(KERN_ERR "ctxfi: The valid values for reference_rate " | 81 | reference_rate); |
82 | "are 48000 and 44100, Value 48000 is assumed.\n"); | 82 | dev_err(card->dev, |
83 | "The valid values for reference_rate are 48000 and 44100, Value 48000 is assumed.\n"); | ||
83 | reference_rate = 48000; | 84 | reference_rate = 48000; |
84 | } | 85 | } |
85 | if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { | 86 | if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { |
86 | printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", | 87 | dev_err(card->dev, "Invalid multiple value %u!!!\n", |
87 | multiple); | 88 | multiple); |
88 | printk(KERN_ERR "ctxfi: The valid values for multiple are " | 89 | dev_err(card->dev, |
89 | "1, 2 and 4, Value 2 is assumed.\n"); | 90 | "The valid values for multiple are 1, 2 and 4, Value 2 is assumed.\n"); |
90 | multiple = 2; | 91 | multiple = 2; |
91 | } | 92 | } |
92 | err = ct_atc_create(card, pci, reference_rate, multiple, | 93 | err = ct_atc_create(card, pci, reference_rate, multiple, |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 51dea49aadd4..fcc5e478c9a1 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -57,12 +57,14 @@ static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list, | |||
57 | 57 | ||
58 | 58 | ||
59 | /* add the found input-pin to the cfg->inputs[] table */ | 59 | /* add the found input-pin to the cfg->inputs[] table */ |
60 | static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, | 60 | static void add_auto_cfg_input_pin(struct hda_codec *codec, struct auto_pin_cfg *cfg, |
61 | int type) | 61 | hda_nid_t nid, int type) |
62 | { | 62 | { |
63 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { | 63 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { |
64 | cfg->inputs[cfg->num_inputs].pin = nid; | 64 | cfg->inputs[cfg->num_inputs].pin = nid; |
65 | cfg->inputs[cfg->num_inputs].type = type; | 65 | cfg->inputs[cfg->num_inputs].type = type; |
66 | cfg->inputs[cfg->num_inputs].has_boost_on_pin = | ||
67 | nid_has_volume(codec, nid, HDA_INPUT); | ||
66 | cfg->num_inputs++; | 68 | cfg->num_inputs++; |
67 | } | 69 | } |
68 | } | 70 | } |
@@ -71,7 +73,12 @@ static int compare_input_type(const void *ap, const void *bp) | |||
71 | { | 73 | { |
72 | const struct auto_pin_cfg_item *a = ap; | 74 | const struct auto_pin_cfg_item *a = ap; |
73 | const struct auto_pin_cfg_item *b = bp; | 75 | const struct auto_pin_cfg_item *b = bp; |
74 | return (int)(a->type - b->type); | 76 | if (a->type != b->type) |
77 | return (int)(a->type - b->type); | ||
78 | |||
79 | /* In case one has boost and the other one has not, | ||
80 | pick the one with boost first. */ | ||
81 | return (int)(b->has_boost_on_pin - a->has_boost_on_pin); | ||
75 | } | 82 | } |
76 | 83 | ||
77 | /* Reorder the surround channels | 84 | /* Reorder the surround channels |
@@ -268,16 +275,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
268 | cfg->hp_outs++; | 275 | cfg->hp_outs++; |
269 | break; | 276 | break; |
270 | case AC_JACK_MIC_IN: | 277 | case AC_JACK_MIC_IN: |
271 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC); | 278 | add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_MIC); |
272 | break; | 279 | break; |
273 | case AC_JACK_LINE_IN: | 280 | case AC_JACK_LINE_IN: |
274 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN); | 281 | add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_LINE_IN); |
275 | break; | 282 | break; |
276 | case AC_JACK_CD: | 283 | case AC_JACK_CD: |
277 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); | 284 | add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_CD); |
278 | break; | 285 | break; |
279 | case AC_JACK_AUX: | 286 | case AC_JACK_AUX: |
280 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); | 287 | add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_AUX); |
281 | break; | 288 | break; |
282 | case AC_JACK_SPDIF_OUT: | 289 | case AC_JACK_SPDIF_OUT: |
283 | case AC_JACK_DIG_OTHER_OUT: | 290 | case AC_JACK_DIG_OTHER_OUT: |
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h index e941f604f5e5..2b8e29fd73e7 100644 --- a/sound/pci/hda/hda_auto_parser.h +++ b/sound/pci/hda/hda_auto_parser.h | |||
@@ -38,6 +38,7 @@ struct auto_pin_cfg_item { | |||
38 | int type; | 38 | int type; |
39 | unsigned int is_headset_mic:1; | 39 | unsigned int is_headset_mic:1; |
40 | unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */ | 40 | unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */ |
41 | unsigned int has_boost_on_pin:1; | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | struct auto_pin_cfg; | 44 | struct auto_pin_cfg; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ec6a7d0d1886..15e0089492f7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2002,6 +2002,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
2002 | EXPORT_SYMBOL_GPL(query_amp_caps); | 2002 | EXPORT_SYMBOL_GPL(query_amp_caps); |
2003 | 2003 | ||
2004 | /** | 2004 | /** |
2005 | * snd_hda_check_amp_caps - query AMP capabilities | ||
2006 | * @codec: the HD-audio codec | ||
2007 | * @nid: the NID to query | ||
2008 | * @dir: either #HDA_INPUT or #HDA_OUTPUT | ||
2009 | * | ||
2010 | * Check whether the widget has the given amp capability for the direction. | ||
2011 | */ | ||
2012 | bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | ||
2013 | int dir, unsigned int bits) | ||
2014 | { | ||
2015 | if (!nid) | ||
2016 | return false; | ||
2017 | if (get_wcaps(codec, nid) & (1 << (dir + 1))) | ||
2018 | if (query_amp_caps(codec, nid, dir) & bits) | ||
2019 | return true; | ||
2020 | return false; | ||
2021 | } | ||
2022 | EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps); | ||
2023 | |||
2024 | /** | ||
2005 | * snd_hda_override_amp_caps - Override the AMP capabilities | 2025 | * snd_hda_override_amp_caps - Override the AMP capabilities |
2006 | * @codec: the CODEC to clean up | 2026 | * @codec: the CODEC to clean up |
2007 | * @nid: the NID to clean up | 2027 | * @nid: the NID to clean up |
@@ -4817,121 +4837,6 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
4817 | EXPORT_SYMBOL_GPL(snd_hda_build_pcms); | 4837 | EXPORT_SYMBOL_GPL(snd_hda_build_pcms); |
4818 | 4838 | ||
4819 | /** | 4839 | /** |
4820 | * snd_hda_check_board_config - compare the current codec with the config table | ||
4821 | * @codec: the HDA codec | ||
4822 | * @num_configs: number of config enums | ||
4823 | * @models: array of model name strings | ||
4824 | * @tbl: configuration table, terminated by null entries | ||
4825 | * | ||
4826 | * Compares the modelname or PCI subsystem id of the current codec with the | ||
4827 | * given configuration table. If a matching entry is found, returns its | ||
4828 | * config value (supposed to be 0 or positive). | ||
4829 | * | ||
4830 | * If no entries are matching, the function returns a negative value. | ||
4831 | */ | ||
4832 | int snd_hda_check_board_config(struct hda_codec *codec, | ||
4833 | int num_configs, const char * const *models, | ||
4834 | const struct snd_pci_quirk *tbl) | ||
4835 | { | ||
4836 | if (codec->modelname && models) { | ||
4837 | int i; | ||
4838 | for (i = 0; i < num_configs; i++) { | ||
4839 | if (models[i] && | ||
4840 | !strcmp(codec->modelname, models[i])) { | ||
4841 | codec_info(codec, "model '%s' is selected\n", | ||
4842 | models[i]); | ||
4843 | return i; | ||
4844 | } | ||
4845 | } | ||
4846 | } | ||
4847 | |||
4848 | if (!codec->bus->pci || !tbl) | ||
4849 | return -1; | ||
4850 | |||
4851 | tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl); | ||
4852 | if (!tbl) | ||
4853 | return -1; | ||
4854 | if (tbl->value >= 0 && tbl->value < num_configs) { | ||
4855 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
4856 | char tmp[10]; | ||
4857 | const char *model = NULL; | ||
4858 | if (models) | ||
4859 | model = models[tbl->value]; | ||
4860 | if (!model) { | ||
4861 | sprintf(tmp, "#%d", tbl->value); | ||
4862 | model = tmp; | ||
4863 | } | ||
4864 | codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n", | ||
4865 | model, tbl->subvendor, tbl->subdevice, | ||
4866 | (tbl->name ? tbl->name : "Unknown device")); | ||
4867 | #endif | ||
4868 | return tbl->value; | ||
4869 | } | ||
4870 | return -1; | ||
4871 | } | ||
4872 | EXPORT_SYMBOL_GPL(snd_hda_check_board_config); | ||
4873 | |||
4874 | /** | ||
4875 | * snd_hda_check_board_codec_sid_config - compare the current codec | ||
4876 | subsystem ID with the | ||
4877 | config table | ||
4878 | |||
4879 | This is important for Gateway notebooks with SB450 HDA Audio | ||
4880 | where the vendor ID of the PCI device is: | ||
4881 | ATI Technologies Inc SB450 HDA Audio [1002:437b] | ||
4882 | and the vendor/subvendor are found only at the codec. | ||
4883 | |||
4884 | * @codec: the HDA codec | ||
4885 | * @num_configs: number of config enums | ||
4886 | * @models: array of model name strings | ||
4887 | * @tbl: configuration table, terminated by null entries | ||
4888 | * | ||
4889 | * Compares the modelname or PCI subsystem id of the current codec with the | ||
4890 | * given configuration table. If a matching entry is found, returns its | ||
4891 | * config value (supposed to be 0 or positive). | ||
4892 | * | ||
4893 | * If no entries are matching, the function returns a negative value. | ||
4894 | */ | ||
4895 | int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | ||
4896 | int num_configs, const char * const *models, | ||
4897 | const struct snd_pci_quirk *tbl) | ||
4898 | { | ||
4899 | const struct snd_pci_quirk *q; | ||
4900 | |||
4901 | /* Search for codec ID */ | ||
4902 | for (q = tbl; q->subvendor; q++) { | ||
4903 | unsigned int mask = 0xffff0000 | q->subdevice_mask; | ||
4904 | unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; | ||
4905 | if ((codec->subsystem_id & mask) == id) | ||
4906 | break; | ||
4907 | } | ||
4908 | |||
4909 | if (!q->subvendor) | ||
4910 | return -1; | ||
4911 | |||
4912 | tbl = q; | ||
4913 | |||
4914 | if (tbl->value >= 0 && tbl->value < num_configs) { | ||
4915 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
4916 | char tmp[10]; | ||
4917 | const char *model = NULL; | ||
4918 | if (models) | ||
4919 | model = models[tbl->value]; | ||
4920 | if (!model) { | ||
4921 | sprintf(tmp, "#%d", tbl->value); | ||
4922 | model = tmp; | ||
4923 | } | ||
4924 | codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n", | ||
4925 | model, tbl->subvendor, tbl->subdevice, | ||
4926 | (tbl->name ? tbl->name : "Unknown device")); | ||
4927 | #endif | ||
4928 | return tbl->value; | ||
4929 | } | ||
4930 | return -1; | ||
4931 | } | ||
4932 | EXPORT_SYMBOL_GPL(snd_hda_check_board_codec_sid_config); | ||
4933 | |||
4934 | /** | ||
4935 | * snd_hda_add_new_ctls - create controls from the array | 4840 | * snd_hda_add_new_ctls - create controls from the array |
4936 | * @codec: the HDA codec | 4841 | * @codec: the HDA codec |
4937 | * @knew: the array of struct snd_kcontrol_new | 4842 | * @knew: the array of struct snd_kcontrol_new |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index bbc5a1392c75..9c8820f21f94 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -687,6 +687,4 @@ snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, | |||
687 | struct snd_dma_buffer *dmab) {} | 687 | struct snd_dma_buffer *dmab) {} |
688 | #endif | 688 | #endif |
689 | 689 | ||
690 | #define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym) | ||
691 | |||
692 | #endif /* __SOUND_HDA_CODEC_H */ | 690 | #endif /* __SOUND_HDA_CODEC_H */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index b956449ddada..64220c08bd98 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/jack.h> | 33 | #include <sound/jack.h> |
34 | #include <sound/tlv.h> | ||
34 | #include "hda_codec.h" | 35 | #include "hda_codec.h" |
35 | #include "hda_local.h" | 36 | #include "hda_local.h" |
36 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
@@ -518,18 +519,6 @@ static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs) | |||
518 | return val; | 519 | return val; |
519 | } | 520 | } |
520 | 521 | ||
521 | /* check whether the widget has the given amp capability for the direction */ | ||
522 | static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | ||
523 | int dir, unsigned int bits) | ||
524 | { | ||
525 | if (!nid) | ||
526 | return false; | ||
527 | if (get_wcaps(codec, nid) & (1 << (dir + 1))) | ||
528 | if (query_amp_caps(codec, nid, dir) & bits) | ||
529 | return true; | ||
530 | return false; | ||
531 | } | ||
532 | |||
533 | static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1, | 522 | static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1, |
534 | hda_nid_t nid2, int dir) | 523 | hda_nid_t nid2, int dir) |
535 | { | 524 | { |
@@ -539,11 +528,6 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1, | |||
539 | query_amp_caps(codec, nid2, dir)); | 528 | query_amp_caps(codec, nid2, dir)); |
540 | } | 529 | } |
541 | 530 | ||
542 | #define nid_has_mute(codec, nid, dir) \ | ||
543 | check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) | ||
544 | #define nid_has_volume(codec, nid, dir) \ | ||
545 | check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS) | ||
546 | |||
547 | /* look for a widget suitable for assigning a mute switch in the path */ | 531 | /* look for a widget suitable for assigning a mute switch in the path */ |
548 | static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec, | 532 | static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec, |
549 | struct nid_path *path) | 533 | struct nid_path *path) |
@@ -1105,6 +1089,7 @@ enum { | |||
1105 | */ | 1089 | */ |
1106 | static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path) | 1090 | static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path) |
1107 | { | 1091 | { |
1092 | struct hda_gen_spec *spec = codec->spec; | ||
1108 | hda_nid_t nid; | 1093 | hda_nid_t nid; |
1109 | unsigned int val; | 1094 | unsigned int val; |
1110 | int badness = 0; | 1095 | int badness = 0; |
@@ -1119,6 +1104,8 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path) | |||
1119 | nid = look_for_out_vol_nid(codec, path); | 1104 | nid = look_for_out_vol_nid(codec, path); |
1120 | if (nid) { | 1105 | if (nid) { |
1121 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | 1106 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); |
1107 | if (spec->dac_min_mute) | ||
1108 | val |= HDA_AMP_VAL_MIN_MUTE; | ||
1122 | if (is_ctl_used(codec, val, NID_PATH_VOL_CTL)) | 1109 | if (is_ctl_used(codec, val, NID_PATH_VOL_CTL)) |
1123 | badness += BAD_SHARED_VOL; | 1110 | badness += BAD_SHARED_VOL; |
1124 | else | 1111 | else |
@@ -1880,9 +1867,12 @@ static int parse_output_paths(struct hda_codec *codec) | |||
1880 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]); | 1867 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]); |
1881 | if (path) | 1868 | if (path) |
1882 | spec->vmaster_nid = look_for_out_vol_nid(codec, path); | 1869 | spec->vmaster_nid = look_for_out_vol_nid(codec, path); |
1883 | if (spec->vmaster_nid) | 1870 | if (spec->vmaster_nid) { |
1884 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 1871 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
1885 | HDA_OUTPUT, spec->vmaster_tlv); | 1872 | HDA_OUTPUT, spec->vmaster_tlv); |
1873 | if (spec->dac_min_mute) | ||
1874 | spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
1875 | } | ||
1886 | } | 1876 | } |
1887 | 1877 | ||
1888 | /* set initial pinctl targets */ | 1878 | /* set initial pinctl targets */ |
@@ -2025,7 +2015,8 @@ static int create_speaker_out_ctls(struct hda_codec *codec) | |||
2025 | * independent HP controls | 2015 | * independent HP controls |
2026 | */ | 2016 | */ |
2027 | 2017 | ||
2028 | static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack); | 2018 | static void call_hp_automute(struct hda_codec *codec, |
2019 | struct hda_jack_callback *jack); | ||
2029 | static int indep_hp_info(struct snd_kcontrol *kcontrol, | 2020 | static int indep_hp_info(struct snd_kcontrol *kcontrol, |
2030 | struct snd_ctl_elem_info *uinfo) | 2021 | struct snd_ctl_elem_info *uinfo) |
2031 | { | 2022 | { |
@@ -3941,7 +3932,8 @@ static void call_update_outputs(struct hda_codec *codec) | |||
3941 | } | 3932 | } |
3942 | 3933 | ||
3943 | /* standard HP-automute helper */ | 3934 | /* standard HP-automute helper */ |
3944 | void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | 3935 | void snd_hda_gen_hp_automute(struct hda_codec *codec, |
3936 | struct hda_jack_callback *jack) | ||
3945 | { | 3937 | { |
3946 | struct hda_gen_spec *spec = codec->spec; | 3938 | struct hda_gen_spec *spec = codec->spec; |
3947 | hda_nid_t *pins = spec->autocfg.hp_pins; | 3939 | hda_nid_t *pins = spec->autocfg.hp_pins; |
@@ -3961,7 +3953,8 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |||
3961 | EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute); | 3953 | EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute); |
3962 | 3954 | ||
3963 | /* standard line-out-automute helper */ | 3955 | /* standard line-out-automute helper */ |
3964 | void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | 3956 | void snd_hda_gen_line_automute(struct hda_codec *codec, |
3957 | struct hda_jack_callback *jack) | ||
3965 | { | 3958 | { |
3966 | struct hda_gen_spec *spec = codec->spec; | 3959 | struct hda_gen_spec *spec = codec->spec; |
3967 | 3960 | ||
@@ -3981,7 +3974,8 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac | |||
3981 | EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute); | 3974 | EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute); |
3982 | 3975 | ||
3983 | /* standard mic auto-switch helper */ | 3976 | /* standard mic auto-switch helper */ |
3984 | void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack) | 3977 | void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, |
3978 | struct hda_jack_callback *jack) | ||
3985 | { | 3979 | { |
3986 | struct hda_gen_spec *spec = codec->spec; | 3980 | struct hda_gen_spec *spec = codec->spec; |
3987 | int i; | 3981 | int i; |
@@ -4004,7 +3998,8 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja | |||
4004 | EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch); | 3998 | EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch); |
4005 | 3999 | ||
4006 | /* call appropriate hooks */ | 4000 | /* call appropriate hooks */ |
4007 | static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | 4001 | static void call_hp_automute(struct hda_codec *codec, |
4002 | struct hda_jack_callback *jack) | ||
4008 | { | 4003 | { |
4009 | struct hda_gen_spec *spec = codec->spec; | 4004 | struct hda_gen_spec *spec = codec->spec; |
4010 | if (spec->hp_automute_hook) | 4005 | if (spec->hp_automute_hook) |
@@ -4014,7 +4009,7 @@ static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) | |||
4014 | } | 4009 | } |
4015 | 4010 | ||
4016 | static void call_line_automute(struct hda_codec *codec, | 4011 | static void call_line_automute(struct hda_codec *codec, |
4017 | struct hda_jack_tbl *jack) | 4012 | struct hda_jack_callback *jack) |
4018 | { | 4013 | { |
4019 | struct hda_gen_spec *spec = codec->spec; | 4014 | struct hda_gen_spec *spec = codec->spec; |
4020 | if (spec->line_automute_hook) | 4015 | if (spec->line_automute_hook) |
@@ -4024,7 +4019,7 @@ static void call_line_automute(struct hda_codec *codec, | |||
4024 | } | 4019 | } |
4025 | 4020 | ||
4026 | static void call_mic_autoswitch(struct hda_codec *codec, | 4021 | static void call_mic_autoswitch(struct hda_codec *codec, |
4027 | struct hda_jack_tbl *jack) | 4022 | struct hda_jack_callback *jack) |
4028 | { | 4023 | { |
4029 | struct hda_gen_spec *spec = codec->spec; | 4024 | struct hda_gen_spec *spec = codec->spec; |
4030 | if (spec->mic_autoswitch_hook) | 4025 | if (spec->mic_autoswitch_hook) |
@@ -4173,7 +4168,7 @@ static int check_auto_mute_availability(struct hda_codec *codec) | |||
4173 | if (!is_jack_detectable(codec, nid)) | 4168 | if (!is_jack_detectable(codec, nid)) |
4174 | continue; | 4169 | continue; |
4175 | codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid); | 4170 | codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid); |
4176 | snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT, | 4171 | snd_hda_jack_detect_enable_callback(codec, nid, |
4177 | call_hp_automute); | 4172 | call_hp_automute); |
4178 | spec->detect_hp = 1; | 4173 | spec->detect_hp = 1; |
4179 | } | 4174 | } |
@@ -4186,7 +4181,6 @@ static int check_auto_mute_availability(struct hda_codec *codec) | |||
4186 | continue; | 4181 | continue; |
4187 | codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid); | 4182 | codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid); |
4188 | snd_hda_jack_detect_enable_callback(codec, nid, | 4183 | snd_hda_jack_detect_enable_callback(codec, nid, |
4189 | HDA_GEN_FRONT_EVENT, | ||
4190 | call_line_automute); | 4184 | call_line_automute); |
4191 | spec->detect_lo = 1; | 4185 | spec->detect_lo = 1; |
4192 | } | 4186 | } |
@@ -4228,7 +4222,6 @@ static bool auto_mic_check_imux(struct hda_codec *codec) | |||
4228 | for (i = 1; i < spec->am_num_entries; i++) | 4222 | for (i = 1; i < spec->am_num_entries; i++) |
4229 | snd_hda_jack_detect_enable_callback(codec, | 4223 | snd_hda_jack_detect_enable_callback(codec, |
4230 | spec->am_entry[i].pin, | 4224 | spec->am_entry[i].pin, |
4231 | HDA_GEN_MIC_EVENT, | ||
4232 | call_mic_autoswitch); | 4225 | call_mic_autoswitch); |
4233 | return true; | 4226 | return true; |
4234 | } | 4227 | } |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index bb2dea743986..61dd5153f512 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -12,12 +12,6 @@ | |||
12 | #ifndef __SOUND_HDA_GENERIC_H | 12 | #ifndef __SOUND_HDA_GENERIC_H |
13 | #define __SOUND_HDA_GENERIC_H | 13 | #define __SOUND_HDA_GENERIC_H |
14 | 14 | ||
15 | /* unsol event tags */ | ||
16 | enum { | ||
17 | HDA_GEN_HP_EVENT = 1, HDA_GEN_FRONT_EVENT, HDA_GEN_MIC_EVENT, | ||
18 | HDA_GEN_LAST_EVENT = HDA_GEN_MIC_EVENT | ||
19 | }; | ||
20 | |||
21 | /* table entry for multi-io paths */ | 15 | /* table entry for multi-io paths */ |
22 | struct hda_multi_io { | 16 | struct hda_multi_io { |
23 | hda_nid_t pin; /* multi-io widget pin NID */ | 17 | hda_nid_t pin; /* multi-io widget pin NID */ |
@@ -231,6 +225,7 @@ struct hda_gen_spec { | |||
231 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ | 225 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ |
232 | unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */ | 226 | unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */ |
233 | unsigned int power_down_unused:1; /* power down unused widgets */ | 227 | unsigned int power_down_unused:1; /* power down unused widgets */ |
228 | unsigned int dac_min_mute:1; /* minimal = mute for DACs */ | ||
234 | 229 | ||
235 | /* other internal flags */ | 230 | /* other internal flags */ |
236 | unsigned int no_analog:1; /* digital I/O only */ | 231 | unsigned int no_analog:1; /* digital I/O only */ |
@@ -289,11 +284,11 @@ struct hda_gen_spec { | |||
289 | 284 | ||
290 | /* automute / autoswitch hooks */ | 285 | /* automute / autoswitch hooks */ |
291 | void (*hp_automute_hook)(struct hda_codec *codec, | 286 | void (*hp_automute_hook)(struct hda_codec *codec, |
292 | struct hda_jack_tbl *tbl); | 287 | struct hda_jack_callback *cb); |
293 | void (*line_automute_hook)(struct hda_codec *codec, | 288 | void (*line_automute_hook)(struct hda_codec *codec, |
294 | struct hda_jack_tbl *tbl); | 289 | struct hda_jack_callback *cb); |
295 | void (*mic_autoswitch_hook)(struct hda_codec *codec, | 290 | void (*mic_autoswitch_hook)(struct hda_codec *codec, |
296 | struct hda_jack_tbl *tbl); | 291 | struct hda_jack_callback *cb); |
297 | }; | 292 | }; |
298 | 293 | ||
299 | int snd_hda_gen_spec_init(struct hda_gen_spec *spec); | 294 | int snd_hda_gen_spec_init(struct hda_gen_spec *spec); |
@@ -325,11 +320,11 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec); | |||
325 | 320 | ||
326 | /* standard jack event callbacks */ | 321 | /* standard jack event callbacks */ |
327 | void snd_hda_gen_hp_automute(struct hda_codec *codec, | 322 | void snd_hda_gen_hp_automute(struct hda_codec *codec, |
328 | struct hda_jack_tbl *jack); | 323 | struct hda_jack_callback *jack); |
329 | void snd_hda_gen_line_automute(struct hda_codec *codec, | 324 | void snd_hda_gen_line_automute(struct hda_codec *codec, |
330 | struct hda_jack_tbl *jack); | 325 | struct hda_jack_callback *jack); |
331 | void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, | 326 | void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, |
332 | struct hda_jack_tbl *jack); | 327 | struct hda_jack_callback *jack); |
333 | void snd_hda_gen_update_outputs(struct hda_codec *codec); | 328 | void snd_hda_gen_update_outputs(struct hda_codec *codec); |
334 | 329 | ||
335 | #ifdef CONFIG_PM | 330 | #ifdef CONFIG_PM |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9746d73cec52..f56765ae73a7 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -94,7 +94,7 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag); | |||
94 | /** | 94 | /** |
95 | * snd_hda_jack_tbl_new - create a jack-table entry for the given NID | 95 | * snd_hda_jack_tbl_new - create a jack-table entry for the given NID |
96 | */ | 96 | */ |
97 | struct hda_jack_tbl * | 97 | static struct hda_jack_tbl * |
98 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) | 98 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) |
99 | { | 99 | { |
100 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); | 100 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); |
@@ -108,21 +108,24 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) | |||
108 | jack->tag = codec->jacktbl.used; | 108 | jack->tag = codec->jacktbl.used; |
109 | return jack; | 109 | return jack; |
110 | } | 110 | } |
111 | EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new); | ||
112 | 111 | ||
113 | void snd_hda_jack_tbl_clear(struct hda_codec *codec) | 112 | void snd_hda_jack_tbl_clear(struct hda_codec *codec) |
114 | { | 113 | { |
114 | struct hda_jack_tbl *jack = codec->jacktbl.list; | ||
115 | int i; | ||
116 | |||
117 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||
118 | struct hda_jack_callback *cb, *next; | ||
115 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 119 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
116 | /* free jack instances manually when clearing/reconfiguring */ | 120 | /* free jack instances manually when clearing/reconfiguring */ |
117 | if (!codec->bus->shutdown && codec->jacktbl.list) { | 121 | if (!codec->bus->shutdown && jack->jack) |
118 | struct hda_jack_tbl *jack = codec->jacktbl.list; | 122 | snd_device_free(codec->bus->card, jack->jack); |
119 | int i; | 123 | #endif |
120 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | 124 | for (cb = jack->callback; cb; cb = next) { |
121 | if (jack->jack) | 125 | next = cb->next; |
122 | snd_device_free(codec->bus->card, jack->jack); | 126 | kfree(cb); |
123 | } | 127 | } |
124 | } | 128 | } |
125 | #endif | ||
126 | snd_array_free(&codec->jacktbl); | 129 | snd_array_free(&codec->jacktbl); |
127 | } | 130 | } |
128 | 131 | ||
@@ -215,33 +218,49 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state); | |||
215 | 218 | ||
216 | /** | 219 | /** |
217 | * snd_hda_jack_detect_enable - enable the jack-detection | 220 | * snd_hda_jack_detect_enable - enable the jack-detection |
221 | * | ||
222 | * In the case of error, the return value will be a pointer embedded with | ||
223 | * errno. Check and handle the return value appropriately with standard | ||
224 | * macros such as @IS_ERR() and @PTR_ERR(). | ||
218 | */ | 225 | */ |
219 | int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, | 226 | struct hda_jack_callback * |
220 | unsigned char action, | 227 | snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, |
221 | hda_jack_callback cb) | 228 | hda_jack_callback_fn func) |
222 | { | 229 | { |
223 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); | 230 | struct hda_jack_tbl *jack; |
231 | struct hda_jack_callback *callback = NULL; | ||
232 | int err; | ||
233 | |||
234 | jack = snd_hda_jack_tbl_new(codec, nid); | ||
224 | if (!jack) | 235 | if (!jack) |
225 | return -ENOMEM; | 236 | return ERR_PTR(-ENOMEM); |
237 | if (func) { | ||
238 | callback = kzalloc(sizeof(*callback), GFP_KERNEL); | ||
239 | if (!callback) | ||
240 | return ERR_PTR(-ENOMEM); | ||
241 | callback->func = func; | ||
242 | callback->tbl = jack; | ||
243 | callback->next = jack->callback; | ||
244 | jack->callback = callback; | ||
245 | } | ||
246 | |||
226 | if (jack->jack_detect) | 247 | if (jack->jack_detect) |
227 | return 0; /* already registered */ | 248 | return callback; /* already registered */ |
228 | jack->jack_detect = 1; | 249 | jack->jack_detect = 1; |
229 | if (action) | ||
230 | jack->action = action; | ||
231 | if (cb) | ||
232 | jack->callback = cb; | ||
233 | if (codec->jackpoll_interval > 0) | 250 | if (codec->jackpoll_interval > 0) |
234 | return 0; /* No unsol if we're polling instead */ | 251 | return callback; /* No unsol if we're polling instead */ |
235 | return snd_hda_codec_write_cache(codec, nid, 0, | 252 | err = snd_hda_codec_write_cache(codec, nid, 0, |
236 | AC_VERB_SET_UNSOLICITED_ENABLE, | 253 | AC_VERB_SET_UNSOLICITED_ENABLE, |
237 | AC_USRSP_EN | jack->tag); | 254 | AC_USRSP_EN | jack->tag); |
255 | if (err < 0) | ||
256 | return ERR_PTR(err); | ||
257 | return callback; | ||
238 | } | 258 | } |
239 | EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback); | 259 | EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback); |
240 | 260 | ||
241 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 261 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid) |
242 | unsigned char action) | ||
243 | { | 262 | { |
244 | return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL); | 263 | return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback(codec, nid, NULL)); |
245 | } | 264 | } |
246 | EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable); | 265 | EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable); |
247 | 266 | ||
@@ -431,7 +450,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
431 | return err; | 450 | return err; |
432 | 451 | ||
433 | if (!phantom_jack) | 452 | if (!phantom_jack) |
434 | return snd_hda_jack_detect_enable(codec, nid, 0); | 453 | return snd_hda_jack_detect_enable(codec, nid); |
435 | return 0; | 454 | return 0; |
436 | } | 455 | } |
437 | 456 | ||
@@ -498,13 +517,17 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls); | |||
498 | static void call_jack_callback(struct hda_codec *codec, | 517 | static void call_jack_callback(struct hda_codec *codec, |
499 | struct hda_jack_tbl *jack) | 518 | struct hda_jack_tbl *jack) |
500 | { | 519 | { |
501 | if (jack->callback) | 520 | struct hda_jack_callback *cb; |
502 | jack->callback(codec, jack); | 521 | |
522 | for (cb = jack->callback; cb; cb = cb->next) | ||
523 | cb->func(codec, cb); | ||
503 | if (jack->gated_jack) { | 524 | if (jack->gated_jack) { |
504 | struct hda_jack_tbl *gated = | 525 | struct hda_jack_tbl *gated = |
505 | snd_hda_jack_tbl_get(codec, jack->gated_jack); | 526 | snd_hda_jack_tbl_get(codec, jack->gated_jack); |
506 | if (gated && gated->callback) | 527 | if (gated) { |
507 | gated->callback(codec, gated); | 528 | for (cb = gated->callback; cb; cb = cb->next) |
529 | cb->func(codec, cb); | ||
530 | } | ||
508 | } | 531 | } |
509 | } | 532 | } |
510 | 533 | ||
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 46e1ea83ce3c..13cb375454f6 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -12,17 +12,25 @@ | |||
12 | #ifndef __SOUND_HDA_JACK_H | 12 | #ifndef __SOUND_HDA_JACK_H |
13 | #define __SOUND_HDA_JACK_H | 13 | #define __SOUND_HDA_JACK_H |
14 | 14 | ||
15 | #include <linux/err.h> | ||
16 | |||
15 | struct auto_pin_cfg; | 17 | struct auto_pin_cfg; |
16 | struct hda_jack_tbl; | 18 | struct hda_jack_tbl; |
19 | struct hda_jack_callback; | ||
20 | |||
21 | typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *); | ||
17 | 22 | ||
18 | typedef void (*hda_jack_callback) (struct hda_codec *, struct hda_jack_tbl *); | 23 | struct hda_jack_callback { |
24 | struct hda_jack_tbl *tbl; | ||
25 | hda_jack_callback_fn func; | ||
26 | unsigned int private_data; /* arbitrary data */ | ||
27 | struct hda_jack_callback *next; | ||
28 | }; | ||
19 | 29 | ||
20 | struct hda_jack_tbl { | 30 | struct hda_jack_tbl { |
21 | hda_nid_t nid; | 31 | hda_nid_t nid; |
22 | unsigned char action; /* event action (0 = none) */ | ||
23 | unsigned char tag; /* unsol event tag */ | 32 | unsigned char tag; /* unsol event tag */ |
24 | unsigned int private_data; /* arbitrary data */ | 33 | struct hda_jack_callback *callback; |
25 | hda_jack_callback callback; | ||
26 | /* jack-detection stuff */ | 34 | /* jack-detection stuff */ |
27 | unsigned int pin_sense; /* cached pin-sense value */ | 35 | unsigned int pin_sense; /* cached pin-sense value */ |
28 | unsigned int jack_detect:1; /* capable of jack-detection? */ | 36 | unsigned int jack_detect:1; /* capable of jack-detection? */ |
@@ -43,34 +51,14 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); | |||
43 | struct hda_jack_tbl * | 51 | struct hda_jack_tbl * |
44 | snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag); | 52 | snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag); |
45 | 53 | ||
46 | struct hda_jack_tbl * | ||
47 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); | ||
48 | void snd_hda_jack_tbl_clear(struct hda_codec *codec); | 54 | void snd_hda_jack_tbl_clear(struct hda_codec *codec); |
49 | 55 | ||
50 | /** | ||
51 | * snd_hda_jack_get_action - get jack-tbl entry for the tag | ||
52 | * | ||
53 | * Call this from the unsol event handler to get the assigned action for the | ||
54 | * event. This will mark the dirty flag for the later reporting, too. | ||
55 | */ | ||
56 | static inline unsigned char | ||
57 | snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag) | ||
58 | { | ||
59 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag); | ||
60 | if (jack) { | ||
61 | jack->jack_dirty = 1; | ||
62 | return jack->action; | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec); | 56 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec); |
68 | 57 | ||
69 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 58 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid); |
70 | unsigned char action); | 59 | struct hda_jack_callback * |
71 | int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, | 60 | snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, |
72 | unsigned char action, | 61 | hda_jack_callback_fn cb); |
73 | hda_jack_callback cb); | ||
74 | 62 | ||
75 | int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, | 63 | int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, |
76 | hda_nid_t gating_nid); | 64 | hda_nid_t gating_nid); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 364bb413e02a..7eb44e78e141 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -371,12 +371,6 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen); | |||
371 | /* | 371 | /* |
372 | * Misc | 372 | * Misc |
373 | */ | 373 | */ |
374 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, | ||
375 | const char * const *modelnames, | ||
376 | const struct snd_pci_quirk *pci_list); | ||
377 | int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | ||
378 | int num_configs, const char * const *models, | ||
379 | const struct snd_pci_quirk *tbl); | ||
380 | int snd_hda_add_new_ctls(struct hda_codec *codec, | 374 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
381 | const struct snd_kcontrol_new *knew); | 375 | const struct snd_kcontrol_new *knew); |
382 | 376 | ||
@@ -609,6 +603,14 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
609 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | 603 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); |
610 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | 604 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, |
611 | unsigned int caps); | 605 | unsigned int caps); |
606 | bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | ||
607 | int dir, unsigned int bits); | ||
608 | |||
609 | #define nid_has_mute(codec, nid, dir) \ | ||
610 | snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) | ||
611 | #define nid_has_volume(codec, nid, dir) \ | ||
612 | snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS) | ||
613 | |||
612 | 614 | ||
613 | /* flags for hda_nid_item */ | 615 | /* flags for hda_nid_item */ |
614 | #define HDA_NID_ITEM_AMP (1<<0) | 616 | #define HDA_NID_ITEM_AMP (1<<0) |
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index e2079090ca6f..9b49f156a12e 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c | |||
@@ -514,7 +514,7 @@ enum { | |||
514 | 514 | ||
515 | static inline int strmatch(const char *a, const char *b) | 515 | static inline int strmatch(const char *a, const char *b) |
516 | { | 516 | { |
517 | return strnicmp(a, b, strlen(b)) == 0; | 517 | return strncasecmp(a, b, strlen(b)) == 0; |
518 | } | 518 | } |
519 | 519 | ||
520 | /* parse the contents after the line "[codec]" | 520 | /* parse the contents after the line "[codec]" |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 5d8455e2dacd..4f7ffa8c4a0d 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -3224,8 +3224,14 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) | |||
3224 | { | 3224 | { |
3225 | struct ca0132_spec *spec = container_of( | 3225 | struct ca0132_spec *spec = container_of( |
3226 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); | 3226 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); |
3227 | struct hda_jack_tbl *jack; | ||
3228 | |||
3227 | ca0132_select_out(spec->codec); | 3229 | ca0132_select_out(spec->codec); |
3228 | snd_hda_jack_report_sync(spec->codec); | 3230 | jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP); |
3231 | if (jack) { | ||
3232 | jack->block_report = 0; | ||
3233 | snd_hda_jack_report_sync(spec->codec); | ||
3234 | } | ||
3229 | } | 3235 | } |
3230 | 3236 | ||
3231 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 3237 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
@@ -4114,12 +4120,6 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) | |||
4114 | } | 4120 | } |
4115 | } | 4121 | } |
4116 | 4122 | ||
4117 | static void ca0132_init_unsol(struct hda_codec *codec) | ||
4118 | { | ||
4119 | snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP, UNSOL_TAG_HP); | ||
4120 | snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1, UNSOL_TAG_AMIC1); | ||
4121 | } | ||
4122 | |||
4123 | static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) | 4123 | static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir) |
4124 | { | 4124 | { |
4125 | unsigned int caps; | 4125 | unsigned int caps; |
@@ -4390,7 +4390,8 @@ static void ca0132_download_dsp(struct hda_codec *codec) | |||
4390 | ca0132_set_dsp_msr(codec, true); | 4390 | ca0132_set_dsp_msr(codec, true); |
4391 | } | 4391 | } |
4392 | 4392 | ||
4393 | static void ca0132_process_dsp_response(struct hda_codec *codec) | 4393 | static void ca0132_process_dsp_response(struct hda_codec *codec, |
4394 | struct hda_jack_callback *callback) | ||
4394 | { | 4395 | { |
4395 | struct ca0132_spec *spec = codec->spec; | 4396 | struct ca0132_spec *spec = codec->spec; |
4396 | 4397 | ||
@@ -4403,36 +4404,31 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) | |||
4403 | dspio_clear_response_queue(codec); | 4404 | dspio_clear_response_queue(codec); |
4404 | } | 4405 | } |
4405 | 4406 | ||
4406 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | 4407 | static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) |
4407 | { | 4408 | { |
4408 | struct ca0132_spec *spec = codec->spec; | 4409 | struct ca0132_spec *spec = codec->spec; |
4409 | 4410 | ||
4410 | if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { | 4411 | /* Delay enabling the HP amp, to let the mic-detection |
4411 | ca0132_process_dsp_response(codec); | 4412 | * state machine run. |
4412 | } else { | 4413 | */ |
4413 | res = snd_hda_jack_get_action(codec, | 4414 | cancel_delayed_work_sync(&spec->unsol_hp_work); |
4414 | (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f); | 4415 | queue_delayed_work(codec->bus->workq, &spec->unsol_hp_work, |
4415 | 4416 | msecs_to_jiffies(500)); | |
4416 | codec_dbg(codec, "snd_hda_jack_get_action: 0x%x\n", res); | 4417 | cb->tbl->block_report = 1; |
4417 | 4418 | } | |
4418 | switch (res) { | 4419 | |
4419 | case UNSOL_TAG_HP: | 4420 | static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) |
4420 | /* Delay enabling the HP amp, to let the mic-detection | 4421 | { |
4421 | * state machine run. | 4422 | ca0132_select_mic(codec); |
4422 | */ | 4423 | } |
4423 | cancel_delayed_work_sync(&spec->unsol_hp_work); | 4424 | |
4424 | queue_delayed_work(codec->bus->workq, | 4425 | static void ca0132_init_unsol(struct hda_codec *codec) |
4425 | &spec->unsol_hp_work, | 4426 | { |
4426 | msecs_to_jiffies(500)); | 4427 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback); |
4427 | break; | 4428 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1, |
4428 | case UNSOL_TAG_AMIC1: | 4429 | amic_callback); |
4429 | ca0132_select_mic(codec); | 4430 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, |
4430 | snd_hda_jack_report_sync(codec); | 4431 | ca0132_process_dsp_response); |
4431 | break; | ||
4432 | default: | ||
4433 | break; | ||
4434 | } | ||
4435 | } | ||
4436 | } | 4432 | } |
4437 | 4433 | ||
4438 | /* | 4434 | /* |
@@ -4443,8 +4439,6 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4443 | static struct hda_verb ca0132_base_init_verbs[] = { | 4439 | static struct hda_verb ca0132_base_init_verbs[] = { |
4444 | /*enable ct extension*/ | 4440 | /*enable ct extension*/ |
4445 | {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, | 4441 | {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, |
4446 | /*enable DSP node unsol, needed for DSP download*/ | ||
4447 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_DSP}, | ||
4448 | {} | 4442 | {} |
4449 | }; | 4443 | }; |
4450 | 4444 | ||
@@ -4561,6 +4555,8 @@ static int ca0132_init(struct hda_codec *codec) | |||
4561 | 4555 | ||
4562 | snd_hda_power_up(codec); | 4556 | snd_hda_power_up(codec); |
4563 | 4557 | ||
4558 | ca0132_init_unsol(codec); | ||
4559 | |||
4564 | ca0132_init_params(codec); | 4560 | ca0132_init_params(codec); |
4565 | ca0132_init_flags(codec); | 4561 | ca0132_init_flags(codec); |
4566 | snd_hda_sequence_write(codec, spec->base_init_verbs); | 4562 | snd_hda_sequence_write(codec, spec->base_init_verbs); |
@@ -4583,8 +4579,6 @@ static int ca0132_init(struct hda_codec *codec) | |||
4583 | for (i = 0; i < spec->num_init_verbs; i++) | 4579 | for (i = 0; i < spec->num_init_verbs; i++) |
4584 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 4580 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
4585 | 4581 | ||
4586 | ca0132_init_unsol(codec); | ||
4587 | |||
4588 | ca0132_select_out(codec); | 4582 | ca0132_select_out(codec); |
4589 | ca0132_select_mic(codec); | 4583 | ca0132_select_mic(codec); |
4590 | 4584 | ||
@@ -4612,7 +4606,7 @@ static struct hda_codec_ops ca0132_patch_ops = { | |||
4612 | .build_pcms = ca0132_build_pcms, | 4606 | .build_pcms = ca0132_build_pcms, |
4613 | .init = ca0132_init, | 4607 | .init = ca0132_init, |
4614 | .free = ca0132_free, | 4608 | .free = ca0132_free, |
4615 | .unsol_event = ca0132_unsol_event, | 4609 | .unsol_event = snd_hda_jack_unsol_event, |
4616 | }; | 4610 | }; |
4617 | 4611 | ||
4618 | static void ca0132_config(struct hda_codec *codec) | 4612 | static void ca0132_config(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 3db724eaa53c..1589c9bcce3e 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -135,8 +135,6 @@ enum { | |||
135 | #define CS421X_IDX_DAC_CFG 0x03 | 135 | #define CS421X_IDX_DAC_CFG 0x03 |
136 | #define CS421X_IDX_SPK_CTL 0x04 | 136 | #define CS421X_IDX_SPK_CTL 0x04 |
137 | 137 | ||
138 | #define SPDIF_EVENT 0x04 | ||
139 | |||
140 | /* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */ | 138 | /* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */ |
141 | #define CS4213_VENDOR_NID 0x09 | 139 | #define CS4213_VENDOR_NID 0x09 |
142 | 140 | ||
@@ -984,7 +982,7 @@ static void cs4210_pinmux_init(struct hda_codec *codec) | |||
984 | } | 982 | } |
985 | 983 | ||
986 | static void cs4210_spdif_automute(struct hda_codec *codec, | 984 | static void cs4210_spdif_automute(struct hda_codec *codec, |
987 | struct hda_jack_tbl *tbl) | 985 | struct hda_jack_callback *tbl) |
988 | { | 986 | { |
989 | struct cs_spec *spec = codec->spec; | 987 | struct cs_spec *spec = codec->spec; |
990 | bool spdif_present = false; | 988 | bool spdif_present = false; |
@@ -1019,7 +1017,6 @@ static void parse_cs421x_digital(struct hda_codec *codec) | |||
1019 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { | 1017 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
1020 | spec->spdif_detect = 1; | 1018 | spec->spdif_detect = 1; |
1021 | snd_hda_jack_detect_enable_callback(codec, nid, | 1019 | snd_hda_jack_detect_enable_callback(codec, nid, |
1022 | SPDIF_EVENT, | ||
1023 | cs4210_spdif_automute); | 1020 | cs4210_spdif_automute); |
1024 | } | 1021 | } |
1025 | } | 1022 | } |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 47ccb8f44adb..71e4bad06345 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include <sound/jack.h> | 28 | #include <sound/jack.h> |
29 | #include <sound/tlv.h> | ||
30 | 29 | ||
31 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 31 | #include "hda_local.h" |
@@ -394,7 +393,8 @@ static void olpc_xo_update_mic_pins(struct hda_codec *codec) | |||
394 | } | 393 | } |
395 | 394 | ||
396 | /* mic_autoswitch hook */ | 395 | /* mic_autoswitch hook */ |
397 | static void olpc_xo_automic(struct hda_codec *codec, struct hda_jack_tbl *jack) | 396 | static void olpc_xo_automic(struct hda_codec *codec, |
397 | struct hda_jack_callback *jack) | ||
398 | { | 398 | { |
399 | struct conexant_spec *spec = codec->spec; | 399 | struct conexant_spec *spec = codec->spec; |
400 | int saved_cached_write = codec->cached_write; | 400 | int saved_cached_write = codec->cached_write; |
@@ -752,6 +752,7 @@ static const struct hda_model_fixup cxt5051_fixup_models[] = { | |||
752 | static const struct snd_pci_quirk cxt5066_fixups[] = { | 752 | static const struct snd_pci_quirk cxt5066_fixups[] = { |
753 | SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), | 753 | SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), |
754 | SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), | 754 | SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), |
755 | SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC), | ||
755 | SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), | 756 | SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), |
756 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), | 757 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), |
757 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), | 758 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), |
@@ -787,6 +788,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { | |||
787 | */ | 788 | */ |
788 | static void add_cx5051_fake_mutes(struct hda_codec *codec) | 789 | static void add_cx5051_fake_mutes(struct hda_codec *codec) |
789 | { | 790 | { |
791 | struct conexant_spec *spec = codec->spec; | ||
790 | static hda_nid_t out_nids[] = { | 792 | static hda_nid_t out_nids[] = { |
791 | 0x10, 0x11, 0 | 793 | 0x10, 0x11, 0 |
792 | }; | 794 | }; |
@@ -796,6 +798,7 @@ static void add_cx5051_fake_mutes(struct hda_codec *codec) | |||
796 | snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT, | 798 | snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT, |
797 | AC_AMPCAP_MIN_MUTE | | 799 | AC_AMPCAP_MIN_MUTE | |
798 | query_amp_caps(codec, *p, HDA_OUTPUT)); | 800 | query_amp_caps(codec, *p, HDA_OUTPUT)); |
801 | spec->gen.dac_min_mute = true; | ||
799 | } | 802 | } |
800 | 803 | ||
801 | static int patch_conexant_auto(struct hda_codec *codec) | 804 | static int patch_conexant_auto(struct hda_codec *codec) |
@@ -868,11 +871,6 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
868 | if (err < 0) | 871 | if (err < 0) |
869 | goto error; | 872 | goto error; |
870 | 873 | ||
871 | if (codec->vendor_id == 0x14f15051) { | ||
872 | /* minimum value is actually mute */ | ||
873 | spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
874 | } | ||
875 | |||
876 | codec->patch_ops = cx_auto_patch_ops; | 874 | codec->patch_ops = cx_auto_patch_ops; |
877 | 875 | ||
878 | /* Some laptops with Conexant chips show stalls in S3 resume, | 876 | /* Some laptops with Conexant chips show stalls in S3 resume, |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 99d7d7fecaad..39862e98551c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1163,17 +1163,23 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1163 | 1163 | ||
1164 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); | 1164 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); |
1165 | 1165 | ||
1166 | static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack) | 1166 | static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid) |
1167 | { | 1167 | { |
1168 | struct hdmi_spec *spec = codec->spec; | 1168 | struct hdmi_spec *spec = codec->spec; |
1169 | int pin_idx = pin_nid_to_pin_index(codec, jack->nid); | 1169 | int pin_idx = pin_nid_to_pin_index(codec, nid); |
1170 | |||
1170 | if (pin_idx < 0) | 1171 | if (pin_idx < 0) |
1171 | return; | 1172 | return; |
1172 | |||
1173 | if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) | 1173 | if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) |
1174 | snd_hda_jack_report_sync(codec); | 1174 | snd_hda_jack_report_sync(codec); |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | static void jack_callback(struct hda_codec *codec, | ||
1178 | struct hda_jack_callback *jack) | ||
1179 | { | ||
1180 | check_presence_and_report(codec, jack->tbl->nid); | ||
1181 | } | ||
1182 | |||
1177 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1183 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
1178 | { | 1184 | { |
1179 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 1185 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
@@ -1190,7 +1196,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
1190 | codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), | 1196 | codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), |
1191 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); | 1197 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); |
1192 | 1198 | ||
1193 | jack_callback(codec, jack); | 1199 | check_presence_and_report(codec, jack->nid); |
1194 | } | 1200 | } |
1195 | 1201 | ||
1196 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1202 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) |
@@ -2165,7 +2171,7 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
2165 | hda_nid_t pin_nid = per_pin->pin_nid; | 2171 | hda_nid_t pin_nid = per_pin->pin_nid; |
2166 | 2172 | ||
2167 | hdmi_init_pin(codec, pin_nid); | 2173 | hdmi_init_pin(codec, pin_nid); |
2168 | snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid, | 2174 | snd_hda_jack_detect_enable_callback(codec, pin_nid, |
2169 | codec->jackpoll_interval > 0 ? jack_callback : NULL); | 2175 | codec->jackpoll_interval > 0 ? jack_callback : NULL); |
2170 | } | 2176 | } |
2171 | return 0; | 2177 | return 0; |
@@ -2428,7 +2434,7 @@ static int simple_playback_init(struct hda_codec *codec) | |||
2428 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | 2434 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) |
2429 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 2435 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
2430 | AMP_OUT_UNMUTE); | 2436 | AMP_OUT_UNMUTE); |
2431 | snd_hda_jack_detect_enable(codec, pin, pin); | 2437 | snd_hda_jack_detect_enable(codec, pin); |
2432 | return 0; | 2438 | return 0; |
2433 | } | 2439 | } |
2434 | 2440 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1ba22fb527c2..bc86c36b4bfa 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -40,9 +40,6 @@ | |||
40 | /* keep halting ALC5505 DSP, for power saving */ | 40 | /* keep halting ALC5505 DSP, for power saving */ |
41 | #define HALT_REALTEK_ALC5505 | 41 | #define HALT_REALTEK_ALC5505 |
42 | 42 | ||
43 | /* unsol event tags */ | ||
44 | #define ALC_DCVOL_EVENT 0x08 | ||
45 | |||
46 | /* for GPIO Poll */ | 43 | /* for GPIO Poll */ |
47 | #define GPIO_MASK 0x03 | 44 | #define GPIO_MASK 0x03 |
48 | 45 | ||
@@ -93,11 +90,6 @@ struct alc_spec { | |||
93 | struct alc_customize_define cdefine; | 90 | struct alc_customize_define cdefine; |
94 | unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ | 91 | unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ |
95 | 92 | ||
96 | /* inverted dmic fix */ | ||
97 | unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */ | ||
98 | unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ | ||
99 | hda_nid_t inv_dmic_pin; | ||
100 | |||
101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ | 93 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ |
102 | int mute_led_polarity; | 94 | int mute_led_polarity; |
103 | hda_nid_t mute_led_nid; | 95 | hda_nid_t mute_led_nid; |
@@ -129,6 +121,83 @@ struct alc_spec { | |||
129 | }; | 121 | }; |
130 | 122 | ||
131 | /* | 123 | /* |
124 | * COEF access helper functions | ||
125 | */ | ||
126 | |||
127 | static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | ||
128 | unsigned int coef_idx) | ||
129 | { | ||
130 | unsigned int val; | ||
131 | |||
132 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); | ||
133 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0); | ||
134 | return val; | ||
135 | } | ||
136 | |||
137 | #define alc_read_coef_idx(codec, coef_idx) \ | ||
138 | alc_read_coefex_idx(codec, 0x20, coef_idx) | ||
139 | |||
140 | static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | ||
141 | unsigned int coef_idx, unsigned int coef_val) | ||
142 | { | ||
143 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); | ||
144 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val); | ||
145 | } | ||
146 | |||
147 | #define alc_write_coef_idx(codec, coef_idx, coef_val) \ | ||
148 | alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) | ||
149 | |||
150 | static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | ||
151 | unsigned int coef_idx, unsigned int mask, | ||
152 | unsigned int bits_set) | ||
153 | { | ||
154 | unsigned int val = alc_read_coefex_idx(codec, nid, coef_idx); | ||
155 | |||
156 | if (val != -1) | ||
157 | alc_write_coefex_idx(codec, nid, coef_idx, | ||
158 | (val & ~mask) | bits_set); | ||
159 | } | ||
160 | |||
161 | #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ | ||
162 | alc_update_coefex_idx(codec, 0x20, coef_idx, mask, bits_set) | ||
163 | |||
164 | /* a special bypass for COEF 0; read the cached value at the second time */ | ||
165 | static unsigned int alc_get_coef0(struct hda_codec *codec) | ||
166 | { | ||
167 | struct alc_spec *spec = codec->spec; | ||
168 | |||
169 | if (!spec->coef0) | ||
170 | spec->coef0 = alc_read_coef_idx(codec, 0); | ||
171 | return spec->coef0; | ||
172 | } | ||
173 | |||
174 | /* coef writes/updates batch */ | ||
175 | struct coef_fw { | ||
176 | unsigned char nid; | ||
177 | unsigned char idx; | ||
178 | unsigned short mask; | ||
179 | unsigned short val; | ||
180 | }; | ||
181 | |||
182 | #define UPDATE_COEFEX(_nid, _idx, _mask, _val) \ | ||
183 | { .nid = (_nid), .idx = (_idx), .mask = (_mask), .val = (_val) } | ||
184 | #define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val) | ||
185 | #define WRITE_COEF(_idx, _val) WRITE_COEFEX(0x20, _idx, _val) | ||
186 | #define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(0x20, _idx, _mask, _val) | ||
187 | |||
188 | static void alc_process_coef_fw(struct hda_codec *codec, | ||
189 | const struct coef_fw *fw) | ||
190 | { | ||
191 | for (; fw->nid; fw++) { | ||
192 | if (fw->mask == (unsigned short)-1) | ||
193 | alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); | ||
194 | else | ||
195 | alc_update_coefex_idx(codec, fw->nid, fw->idx, | ||
196 | fw->mask, fw->val); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /* | ||
132 | * Append the given mixer and verb elements for the later use | 201 | * Append the given mixer and verb elements for the later use |
133 | * The mixer array is referred in build_controls(), and init_verbs are | 202 | * The mixer array is referred in build_controls(), and init_verbs are |
134 | * called in init(). | 203 | * called in init(). |
@@ -173,20 +242,10 @@ static const struct hda_verb alc_gpio3_init_verbs[] = { | |||
173 | static void alc_fix_pll(struct hda_codec *codec) | 242 | static void alc_fix_pll(struct hda_codec *codec) |
174 | { | 243 | { |
175 | struct alc_spec *spec = codec->spec; | 244 | struct alc_spec *spec = codec->spec; |
176 | unsigned int val; | ||
177 | 245 | ||
178 | if (!spec->pll_nid) | 246 | if (spec->pll_nid) |
179 | return; | 247 | alc_update_coefex_idx(codec, spec->pll_nid, spec->pll_coef_idx, |
180 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, | 248 | 1 << spec->pll_coef_bit, 0); |
181 | spec->pll_coef_idx); | ||
182 | val = snd_hda_codec_read(codec, spec->pll_nid, 0, | ||
183 | AC_VERB_GET_PROC_COEF, 0); | ||
184 | if (val == -1) | ||
185 | return; | ||
186 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, | ||
187 | spec->pll_coef_idx); | ||
188 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, | ||
189 | val & ~(1 << spec->pll_coef_bit)); | ||
190 | } | 249 | } |
191 | 250 | ||
192 | static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | 251 | static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, |
@@ -200,7 +259,8 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
200 | } | 259 | } |
201 | 260 | ||
202 | /* update the master volume per volume-knob's unsol event */ | 261 | /* update the master volume per volume-knob's unsol event */ |
203 | static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack) | 262 | static void alc_update_knob_master(struct hda_codec *codec, |
263 | struct hda_jack_callback *jack) | ||
204 | { | 264 | { |
205 | unsigned int val; | 265 | unsigned int val; |
206 | struct snd_kcontrol *kctl; | 266 | struct snd_kcontrol *kctl; |
@@ -212,7 +272,7 @@ static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl | |||
212 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); | 272 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); |
213 | if (!uctl) | 273 | if (!uctl) |
214 | return; | 274 | return; |
215 | val = snd_hda_codec_read(codec, jack->nid, 0, | 275 | val = snd_hda_codec_read(codec, jack->tbl->nid, 0, |
216 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | 276 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); |
217 | val &= HDA_AMP_VOLMASK; | 277 | val &= HDA_AMP_VOLMASK; |
218 | uctl->value.integer.value[0] = val; | 278 | uctl->value.integer.value[0] = val; |
@@ -231,30 +291,18 @@ static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) | |||
231 | /* additional initialization for ALC888 variants */ | 291 | /* additional initialization for ALC888 variants */ |
232 | static void alc888_coef_init(struct hda_codec *codec) | 292 | static void alc888_coef_init(struct hda_codec *codec) |
233 | { | 293 | { |
234 | unsigned int tmp; | 294 | if (alc_get_coef0(codec) == 0x20) |
235 | |||
236 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); | ||
237 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); | ||
238 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
239 | if ((tmp & 0xf0) == 0x20) | ||
240 | /* alc888S-VC */ | 295 | /* alc888S-VC */ |
241 | snd_hda_codec_read(codec, 0x20, 0, | 296 | alc_write_coef_idx(codec, 7, 0x830); |
242 | AC_VERB_SET_PROC_COEF, 0x830); | ||
243 | else | 297 | else |
244 | /* alc888-VB */ | 298 | /* alc888-VB */ |
245 | snd_hda_codec_read(codec, 0x20, 0, | 299 | alc_write_coef_idx(codec, 7, 0x3030); |
246 | AC_VERB_SET_PROC_COEF, 0x3030); | ||
247 | } | 300 | } |
248 | 301 | ||
249 | /* additional initialization for ALC889 variants */ | 302 | /* additional initialization for ALC889 variants */ |
250 | static void alc889_coef_init(struct hda_codec *codec) | 303 | static void alc889_coef_init(struct hda_codec *codec) |
251 | { | 304 | { |
252 | unsigned int tmp; | 305 | alc_update_coef_idx(codec, 7, 0, 0x2010); |
253 | |||
254 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
255 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); | ||
256 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
257 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010); | ||
258 | } | 306 | } |
259 | 307 | ||
260 | /* turn on/off EAPD control (only if available) */ | 308 | /* turn on/off EAPD control (only if available) */ |
@@ -295,8 +343,6 @@ static void alc_eapd_shutup(struct hda_codec *codec) | |||
295 | /* generic EAPD initialization */ | 343 | /* generic EAPD initialization */ |
296 | static void alc_auto_init_amp(struct hda_codec *codec, int type) | 344 | static void alc_auto_init_amp(struct hda_codec *codec, int type) |
297 | { | 345 | { |
298 | unsigned int tmp; | ||
299 | |||
300 | alc_auto_setup_eapd(codec, true); | 346 | alc_auto_setup_eapd(codec, true); |
301 | switch (type) { | 347 | switch (type) { |
302 | case ALC_INIT_GPIO1: | 348 | case ALC_INIT_GPIO1: |
@@ -311,15 +357,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
311 | case ALC_INIT_DEFAULT: | 357 | case ALC_INIT_DEFAULT: |
312 | switch (codec->vendor_id) { | 358 | switch (codec->vendor_id) { |
313 | case 0x10ec0260: | 359 | case 0x10ec0260: |
314 | snd_hda_codec_write(codec, 0x1a, 0, | 360 | alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010); |
315 | AC_VERB_SET_COEF_INDEX, 7); | ||
316 | tmp = snd_hda_codec_read(codec, 0x1a, 0, | ||
317 | AC_VERB_GET_PROC_COEF, 0); | ||
318 | snd_hda_codec_write(codec, 0x1a, 0, | ||
319 | AC_VERB_SET_COEF_INDEX, 7); | ||
320 | snd_hda_codec_write(codec, 0x1a, 0, | ||
321 | AC_VERB_SET_PROC_COEF, | ||
322 | tmp | 0x2010); | ||
323 | break; | 361 | break; |
324 | case 0x10ec0262: | 362 | case 0x10ec0262: |
325 | case 0x10ec0880: | 363 | case 0x10ec0880: |
@@ -337,15 +375,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
337 | #if 0 /* XXX: This may cause the silent output on speaker on some machines */ | 375 | #if 0 /* XXX: This may cause the silent output on speaker on some machines */ |
338 | case 0x10ec0267: | 376 | case 0x10ec0267: |
339 | case 0x10ec0268: | 377 | case 0x10ec0268: |
340 | snd_hda_codec_write(codec, 0x20, 0, | 378 | alc_update_coef_idx(codec, 7, 0, 0x3000); |
341 | AC_VERB_SET_COEF_INDEX, 7); | ||
342 | tmp = snd_hda_codec_read(codec, 0x20, 0, | ||
343 | AC_VERB_GET_PROC_COEF, 0); | ||
344 | snd_hda_codec_write(codec, 0x20, 0, | ||
345 | AC_VERB_SET_COEF_INDEX, 7); | ||
346 | snd_hda_codec_write(codec, 0x20, 0, | ||
347 | AC_VERB_SET_PROC_COEF, | ||
348 | tmp | 0x3000); | ||
349 | break; | 379 | break; |
350 | #endif /* XXX */ | 380 | #endif /* XXX */ |
351 | } | 381 | } |
@@ -588,190 +618,14 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports) | |||
588 | } | 618 | } |
589 | 619 | ||
590 | /* | 620 | /* |
591 | * COEF access helper functions | ||
592 | */ | ||
593 | |||
594 | static int alc_read_coefex_idx(struct hda_codec *codec, | ||
595 | hda_nid_t nid, | ||
596 | unsigned int coef_idx) | ||
597 | { | ||
598 | unsigned int val; | ||
599 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, | ||
600 | coef_idx); | ||
601 | val = snd_hda_codec_read(codec, nid, 0, | ||
602 | AC_VERB_GET_PROC_COEF, 0); | ||
603 | return val; | ||
604 | } | ||
605 | |||
606 | #define alc_read_coef_idx(codec, coef_idx) \ | ||
607 | alc_read_coefex_idx(codec, 0x20, coef_idx) | ||
608 | |||
609 | static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | ||
610 | unsigned int coef_idx, | ||
611 | unsigned int coef_val) | ||
612 | { | ||
613 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, | ||
614 | coef_idx); | ||
615 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, | ||
616 | coef_val); | ||
617 | } | ||
618 | |||
619 | #define alc_write_coef_idx(codec, coef_idx, coef_val) \ | ||
620 | alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) | ||
621 | |||
622 | /* a special bypass for COEF 0; read the cached value at the second time */ | ||
623 | static unsigned int alc_get_coef0(struct hda_codec *codec) | ||
624 | { | ||
625 | struct alc_spec *spec = codec->spec; | ||
626 | if (!spec->coef0) | ||
627 | spec->coef0 = alc_read_coef_idx(codec, 0); | ||
628 | return spec->coef0; | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | */ | 621 | */ |
633 | 622 | ||
634 | static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx) | 623 | static void alc_fixup_inv_dmic(struct hda_codec *codec, |
635 | { | 624 | const struct hda_fixup *fix, int action) |
636 | struct hda_gen_spec *spec = codec->spec; | ||
637 | if (spec->dyn_adc_switch) | ||
638 | adc_idx = spec->dyn_adc_idx[imux_idx]; | ||
639 | return spec->adc_nids[adc_idx]; | ||
640 | } | ||
641 | |||
642 | static void alc_inv_dmic_sync_adc(struct hda_codec *codec, int adc_idx) | ||
643 | { | ||
644 | struct alc_spec *spec = codec->spec; | ||
645 | struct hda_input_mux *imux = &spec->gen.input_mux; | ||
646 | struct nid_path *path; | ||
647 | hda_nid_t nid; | ||
648 | int i, dir, parm; | ||
649 | unsigned int val; | ||
650 | |||
651 | for (i = 0; i < imux->num_items; i++) { | ||
652 | if (spec->gen.imux_pins[i] == spec->inv_dmic_pin) | ||
653 | break; | ||
654 | } | ||
655 | if (i >= imux->num_items) | ||
656 | return; | ||
657 | |||
658 | path = snd_hda_get_nid_path(codec, spec->inv_dmic_pin, | ||
659 | get_adc_nid(codec, adc_idx, i)); | ||
660 | val = path->ctls[NID_PATH_MUTE_CTL]; | ||
661 | if (!val) | ||
662 | return; | ||
663 | nid = get_amp_nid_(val); | ||
664 | dir = get_amp_direction_(val); | ||
665 | parm = AC_AMP_SET_RIGHT | | ||
666 | (dir == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT); | ||
667 | |||
668 | /* flush all cached amps at first */ | ||
669 | snd_hda_codec_flush_cache(codec); | ||
670 | |||
671 | /* we care only right channel */ | ||
672 | val = snd_hda_codec_amp_read(codec, nid, 1, dir, 0); | ||
673 | if (val & 0x80) /* if already muted, we don't need to touch */ | ||
674 | return; | ||
675 | val |= 0x80; | ||
676 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
677 | parm | val); | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * Inverted digital-mic handling | ||
682 | * | ||
683 | * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch" | ||
684 | * gives the additional mute only to the right channel of the digital mic | ||
685 | * capture stream. This is a workaround for avoiding the almost silence | ||
686 | * by summing the stereo stream from some (known to be ForteMedia) | ||
687 | * digital mic unit. | ||
688 | * | ||
689 | * The logic is to call alc_inv_dmic_sync() after each action (possibly) | ||
690 | * modifying ADC amp. When the mute flag is set, it mutes the R-channel | ||
691 | * without caching so that the cache can still keep the original value. | ||
692 | * The cached value is then restored when the flag is set off or any other | ||
693 | * than d-mic is used as the current input source. | ||
694 | */ | ||
695 | static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) | ||
696 | { | ||
697 | struct alc_spec *spec = codec->spec; | ||
698 | int src, nums; | ||
699 | |||
700 | if (!spec->inv_dmic_fixup) | ||
701 | return; | ||
702 | if (!spec->inv_dmic_muted && !force) | ||
703 | return; | ||
704 | nums = spec->gen.dyn_adc_switch ? 1 : spec->gen.num_adc_nids; | ||
705 | for (src = 0; src < nums; src++) { | ||
706 | bool dmic_fixup = false; | ||
707 | |||
708 | if (spec->inv_dmic_muted && | ||
709 | spec->gen.imux_pins[spec->gen.cur_mux[src]] == spec->inv_dmic_pin) | ||
710 | dmic_fixup = true; | ||
711 | if (!dmic_fixup && !force) | ||
712 | continue; | ||
713 | alc_inv_dmic_sync_adc(codec, src); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | static void alc_inv_dmic_hook(struct hda_codec *codec, | ||
718 | struct snd_kcontrol *kcontrol, | ||
719 | struct snd_ctl_elem_value *ucontrol) | ||
720 | { | ||
721 | alc_inv_dmic_sync(codec, false); | ||
722 | } | ||
723 | |||
724 | static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol, | ||
725 | struct snd_ctl_elem_value *ucontrol) | ||
726 | { | ||
727 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
728 | struct alc_spec *spec = codec->spec; | ||
729 | |||
730 | ucontrol->value.integer.value[0] = !spec->inv_dmic_muted; | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol, | ||
735 | struct snd_ctl_elem_value *ucontrol) | ||
736 | { | ||
737 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
738 | struct alc_spec *spec = codec->spec; | ||
739 | unsigned int val = !ucontrol->value.integer.value[0]; | ||
740 | |||
741 | if (val == spec->inv_dmic_muted) | ||
742 | return 0; | ||
743 | spec->inv_dmic_muted = val; | ||
744 | alc_inv_dmic_sync(codec, true); | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | static const struct snd_kcontrol_new alc_inv_dmic_sw = { | ||
749 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
750 | .name = "Inverted Internal Mic Capture Switch", | ||
751 | .info = snd_ctl_boolean_mono_info, | ||
752 | .get = alc_inv_dmic_sw_get, | ||
753 | .put = alc_inv_dmic_sw_put, | ||
754 | }; | ||
755 | |||
756 | static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) | ||
757 | { | 625 | { |
758 | struct alc_spec *spec = codec->spec; | 626 | struct alc_spec *spec = codec->spec; |
759 | 627 | ||
760 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &alc_inv_dmic_sw)) | 628 | spec->gen.inv_dmic_split = 1; |
761 | return -ENOMEM; | ||
762 | spec->inv_dmic_fixup = 1; | ||
763 | spec->inv_dmic_muted = 0; | ||
764 | spec->inv_dmic_pin = nid; | ||
765 | spec->gen.cap_sync_hook = alc_inv_dmic_hook; | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /* typically the digital mic is put at node 0x12 */ | ||
770 | static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec, | ||
771 | const struct hda_fixup *fix, int action) | ||
772 | { | ||
773 | if (action == HDA_FIXUP_ACT_PROBE) | ||
774 | alc_add_inv_dmic_mixer(codec, 0x12); | ||
775 | } | 629 | } |
776 | 630 | ||
777 | 631 | ||
@@ -880,7 +734,6 @@ static int alc_resume(struct hda_codec *codec) | |||
880 | codec->patch_ops.init(codec); | 734 | codec->patch_ops.init(codec); |
881 | snd_hda_codec_resume_amp(codec); | 735 | snd_hda_codec_resume_amp(codec); |
882 | snd_hda_codec_resume_cache(codec); | 736 | snd_hda_codec_resume_cache(codec); |
883 | alc_inv_dmic_sync(codec, true); | ||
884 | hda_call_check_power_status(codec, 0x01); | 737 | hda_call_check_power_status(codec, 0x01); |
885 | return 0; | 738 | return 0; |
886 | } | 739 | } |
@@ -1134,7 +987,8 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec, | |||
1134 | const struct hda_fixup *fix, int action) | 987 | const struct hda_fixup *fix, int action) |
1135 | { | 988 | { |
1136 | if (action == HDA_FIXUP_ACT_PROBE) | 989 | if (action == HDA_FIXUP_ACT_PROBE) |
1137 | snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master); | 990 | snd_hda_jack_detect_enable_callback(codec, 0x21, |
991 | alc_update_knob_master); | ||
1138 | } | 992 | } |
1139 | 993 | ||
1140 | static const struct hda_fixup alc880_fixups[] = { | 994 | static const struct hda_fixup alc880_fixups[] = { |
@@ -1597,7 +1451,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, | |||
1597 | spec->gen.detect_hp = 1; | 1451 | spec->gen.detect_hp = 1; |
1598 | spec->gen.automute_speaker = 1; | 1452 | spec->gen.automute_speaker = 1; |
1599 | spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ | 1453 | spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ |
1600 | snd_hda_jack_detect_enable_callback(codec, 0x0f, HDA_GEN_HP_EVENT, | 1454 | snd_hda_jack_detect_enable_callback(codec, 0x0f, |
1601 | snd_hda_gen_hp_automute); | 1455 | snd_hda_gen_hp_automute); |
1602 | snd_hda_add_verbs(codec, alc_gpio1_init_verbs); | 1456 | snd_hda_add_verbs(codec, alc_gpio1_init_verbs); |
1603 | } | 1457 | } |
@@ -2222,7 +2076,7 @@ static const struct hda_fixup alc882_fixups[] = { | |||
2222 | }, | 2076 | }, |
2223 | [ALC882_FIXUP_INV_DMIC] = { | 2077 | [ALC882_FIXUP_INV_DMIC] = { |
2224 | .type = HDA_FIXUP_FUNC, | 2078 | .type = HDA_FIXUP_FUNC, |
2225 | .v.func = alc_fixup_inv_dmic_0x12, | 2079 | .v.func = alc_fixup_inv_dmic, |
2226 | }, | 2080 | }, |
2227 | [ALC882_FIXUP_NO_PRIMARY_HP] = { | 2081 | [ALC882_FIXUP_NO_PRIMARY_HP] = { |
2228 | .type = HDA_FIXUP_FUNC, | 2082 | .type = HDA_FIXUP_FUNC, |
@@ -2473,7 +2327,7 @@ static const struct hda_fixup alc262_fixups[] = { | |||
2473 | }, | 2327 | }, |
2474 | [ALC262_FIXUP_INV_DMIC] = { | 2328 | [ALC262_FIXUP_INV_DMIC] = { |
2475 | .type = HDA_FIXUP_FUNC, | 2329 | .type = HDA_FIXUP_FUNC, |
2476 | .v.func = alc_fixup_inv_dmic_0x12, | 2330 | .v.func = alc_fixup_inv_dmic, |
2477 | }, | 2331 | }, |
2478 | [ALC262_FIXUP_INTEL_BAYLEYBAY] = { | 2332 | [ALC262_FIXUP_INTEL_BAYLEYBAY] = { |
2479 | .type = HDA_FIXUP_FUNC, | 2333 | .type = HDA_FIXUP_FUNC, |
@@ -2517,13 +2371,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
2517 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is | 2371 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is |
2518 | * under-run | 2372 | * under-run |
2519 | */ | 2373 | */ |
2520 | { | 2374 | alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80); |
2521 | int tmp; | ||
2522 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
2523 | tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); | ||
2524 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
2525 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); | ||
2526 | } | ||
2527 | #endif | 2375 | #endif |
2528 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 2376 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
2529 | 2377 | ||
@@ -2592,7 +2440,7 @@ enum { | |||
2592 | static const struct hda_fixup alc268_fixups[] = { | 2440 | static const struct hda_fixup alc268_fixups[] = { |
2593 | [ALC268_FIXUP_INV_DMIC] = { | 2441 | [ALC268_FIXUP_INV_DMIC] = { |
2594 | .type = HDA_FIXUP_FUNC, | 2442 | .type = HDA_FIXUP_FUNC, |
2595 | .v.func = alc_fixup_inv_dmic_0x12, | 2443 | .v.func = alc_fixup_inv_dmic, |
2596 | }, | 2444 | }, |
2597 | [ALC268_FIXUP_HP_EAPD] = { | 2445 | [ALC268_FIXUP_HP_EAPD] = { |
2598 | .type = HDA_FIXUP_VERBS, | 2446 | .type = HDA_FIXUP_VERBS, |
@@ -2809,14 +2657,7 @@ static void alc286_shutup(struct hda_codec *codec) | |||
2809 | 2657 | ||
2810 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) | 2658 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) |
2811 | { | 2659 | { |
2812 | int val = alc_read_coef_idx(codec, 0x04); | 2660 | alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0); |
2813 | if (val == -1) | ||
2814 | return; | ||
2815 | if (power_up) | ||
2816 | val |= 1 << 11; | ||
2817 | else | ||
2818 | val &= ~(1 << 11); | ||
2819 | alc_write_coef_idx(codec, 0x04, val); | ||
2820 | } | 2661 | } |
2821 | 2662 | ||
2822 | static void alc269_shutup(struct hda_codec *codec) | 2663 | static void alc269_shutup(struct hda_codec *codec) |
@@ -2832,79 +2673,42 @@ static void alc269_shutup(struct hda_codec *codec) | |||
2832 | snd_hda_shutup_pins(codec); | 2673 | snd_hda_shutup_pins(codec); |
2833 | } | 2674 | } |
2834 | 2675 | ||
2676 | static struct coef_fw alc282_coefs[] = { | ||
2677 | WRITE_COEF(0x03, 0x0002), /* Power Down Control */ | ||
2678 | WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */ | ||
2679 | WRITE_COEF(0x07, 0x0200), /* DMIC control */ | ||
2680 | UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */ | ||
2681 | UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */ | ||
2682 | WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */ | ||
2683 | WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */ | ||
2684 | WRITE_COEF(0x0e, 0x6e00), /* LDO1/2/3, DAC/ADC */ | ||
2685 | UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */ | ||
2686 | UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */ | ||
2687 | WRITE_COEF(0x6f, 0x0), /* Class D test 4 */ | ||
2688 | UPDATE_COEF(0x0c, 0xfe00, 0), /* IO power down directly */ | ||
2689 | WRITE_COEF(0x34, 0xa0c0), /* ANC */ | ||
2690 | UPDATE_COEF(0x16, 0x0008, 0), /* AGC MUX */ | ||
2691 | UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */ | ||
2692 | UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */ | ||
2693 | WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */ | ||
2694 | WRITE_COEF(0x63, 0x2902), /* PLL */ | ||
2695 | WRITE_COEF(0x68, 0xa080), /* capless control 2 */ | ||
2696 | WRITE_COEF(0x69, 0x3400), /* capless control 3 */ | ||
2697 | WRITE_COEF(0x6a, 0x2f3e), /* capless control 4 */ | ||
2698 | WRITE_COEF(0x6b, 0x0), /* capless control 5 */ | ||
2699 | UPDATE_COEF(0x6d, 0x0fff, 0x0900), /* class D test 2 */ | ||
2700 | WRITE_COEF(0x6e, 0x110a), /* class D test 3 */ | ||
2701 | UPDATE_COEF(0x70, 0x00f8, 0x00d8), /* class D test 5 */ | ||
2702 | WRITE_COEF(0x71, 0x0014), /* class D test 6 */ | ||
2703 | WRITE_COEF(0x72, 0xc2ba), /* classD OCP */ | ||
2704 | UPDATE_COEF(0x77, 0x0f80, 0), /* classD pure DC test */ | ||
2705 | WRITE_COEF(0x6c, 0xfc06), /* Class D amp control */ | ||
2706 | {} | ||
2707 | }; | ||
2708 | |||
2835 | static void alc282_restore_default_value(struct hda_codec *codec) | 2709 | static void alc282_restore_default_value(struct hda_codec *codec) |
2836 | { | 2710 | { |
2837 | int val; | 2711 | alc_process_coef_fw(codec, alc282_coefs); |
2838 | |||
2839 | /* Power Down Control */ | ||
2840 | alc_write_coef_idx(codec, 0x03, 0x0002); | ||
2841 | /* FIFO and filter clock */ | ||
2842 | alc_write_coef_idx(codec, 0x05, 0x0700); | ||
2843 | /* DMIC control */ | ||
2844 | alc_write_coef_idx(codec, 0x07, 0x0200); | ||
2845 | /* Analog clock */ | ||
2846 | val = alc_read_coef_idx(codec, 0x06); | ||
2847 | alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0); | ||
2848 | /* JD */ | ||
2849 | val = alc_read_coef_idx(codec, 0x08); | ||
2850 | alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c); | ||
2851 | /* JD offset1 */ | ||
2852 | alc_write_coef_idx(codec, 0x0a, 0xcccc); | ||
2853 | /* JD offset2 */ | ||
2854 | alc_write_coef_idx(codec, 0x0b, 0xcccc); | ||
2855 | /* LDO1/2/3, DAC/ADC */ | ||
2856 | alc_write_coef_idx(codec, 0x0e, 0x6e00); | ||
2857 | /* JD */ | ||
2858 | val = alc_read_coef_idx(codec, 0x0f); | ||
2859 | alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000); | ||
2860 | /* Capless */ | ||
2861 | val = alc_read_coef_idx(codec, 0x10); | ||
2862 | alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00); | ||
2863 | /* Class D test 4 */ | ||
2864 | alc_write_coef_idx(codec, 0x6f, 0x0); | ||
2865 | /* IO power down directly */ | ||
2866 | val = alc_read_coef_idx(codec, 0x0c); | ||
2867 | alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0); | ||
2868 | /* ANC */ | ||
2869 | alc_write_coef_idx(codec, 0x34, 0xa0c0); | ||
2870 | /* AGC MUX */ | ||
2871 | val = alc_read_coef_idx(codec, 0x16); | ||
2872 | alc_write_coef_idx(codec, 0x16, (val & ~0x0008) | 0x0); | ||
2873 | /* DAC simple content protection */ | ||
2874 | val = alc_read_coef_idx(codec, 0x1d); | ||
2875 | alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0); | ||
2876 | /* ADC simple content protection */ | ||
2877 | val = alc_read_coef_idx(codec, 0x1f); | ||
2878 | alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0); | ||
2879 | /* DAC ADC Zero Detection */ | ||
2880 | alc_write_coef_idx(codec, 0x21, 0x8804); | ||
2881 | /* PLL */ | ||
2882 | alc_write_coef_idx(codec, 0x63, 0x2902); | ||
2883 | /* capless control 2 */ | ||
2884 | alc_write_coef_idx(codec, 0x68, 0xa080); | ||
2885 | /* capless control 3 */ | ||
2886 | alc_write_coef_idx(codec, 0x69, 0x3400); | ||
2887 | /* capless control 4 */ | ||
2888 | alc_write_coef_idx(codec, 0x6a, 0x2f3e); | ||
2889 | /* capless control 5 */ | ||
2890 | alc_write_coef_idx(codec, 0x6b, 0x0); | ||
2891 | /* class D test 2 */ | ||
2892 | val = alc_read_coef_idx(codec, 0x6d); | ||
2893 | alc_write_coef_idx(codec, 0x6d, (val & ~0x0fff) | 0x0900); | ||
2894 | /* class D test 3 */ | ||
2895 | alc_write_coef_idx(codec, 0x6e, 0x110a); | ||
2896 | /* class D test 5 */ | ||
2897 | val = alc_read_coef_idx(codec, 0x70); | ||
2898 | alc_write_coef_idx(codec, 0x70, (val & ~0x00f8) | 0x00d8); | ||
2899 | /* class D test 6 */ | ||
2900 | alc_write_coef_idx(codec, 0x71, 0x0014); | ||
2901 | /* classD OCP */ | ||
2902 | alc_write_coef_idx(codec, 0x72, 0xc2ba); | ||
2903 | /* classD pure DC test */ | ||
2904 | val = alc_read_coef_idx(codec, 0x77); | ||
2905 | alc_write_coef_idx(codec, 0x77, (val & ~0x0f80) | 0x0); | ||
2906 | /* Class D amp control */ | ||
2907 | alc_write_coef_idx(codec, 0x6c, 0xfc06); | ||
2908 | } | 2712 | } |
2909 | 2713 | ||
2910 | static void alc282_init(struct hda_codec *codec) | 2714 | static void alc282_init(struct hda_codec *codec) |
@@ -2980,87 +2784,45 @@ static void alc282_shutup(struct hda_codec *codec) | |||
2980 | alc_write_coef_idx(codec, 0x78, coef78); | 2784 | alc_write_coef_idx(codec, 0x78, coef78); |
2981 | } | 2785 | } |
2982 | 2786 | ||
2787 | static struct coef_fw alc283_coefs[] = { | ||
2788 | WRITE_COEF(0x03, 0x0002), /* Power Down Control */ | ||
2789 | WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */ | ||
2790 | WRITE_COEF(0x07, 0x0200), /* DMIC control */ | ||
2791 | UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */ | ||
2792 | UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */ | ||
2793 | WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */ | ||
2794 | WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */ | ||
2795 | WRITE_COEF(0x0e, 0x6fc0), /* LDO1/2/3, DAC/ADC */ | ||
2796 | UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */ | ||
2797 | UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */ | ||
2798 | WRITE_COEF(0x3a, 0x0), /* Class D test 4 */ | ||
2799 | UPDATE_COEF(0x0c, 0xfe00, 0x0), /* IO power down directly */ | ||
2800 | WRITE_COEF(0x22, 0xa0c0), /* ANC */ | ||
2801 | UPDATE_COEFEX(0x53, 0x01, 0x000f, 0x0008), /* AGC MUX */ | ||
2802 | UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */ | ||
2803 | UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */ | ||
2804 | WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */ | ||
2805 | WRITE_COEF(0x2e, 0x2902), /* PLL */ | ||
2806 | WRITE_COEF(0x33, 0xa080), /* capless control 2 */ | ||
2807 | WRITE_COEF(0x34, 0x3400), /* capless control 3 */ | ||
2808 | WRITE_COEF(0x35, 0x2f3e), /* capless control 4 */ | ||
2809 | WRITE_COEF(0x36, 0x0), /* capless control 5 */ | ||
2810 | UPDATE_COEF(0x38, 0x0fff, 0x0900), /* class D test 2 */ | ||
2811 | WRITE_COEF(0x39, 0x110a), /* class D test 3 */ | ||
2812 | UPDATE_COEF(0x3b, 0x00f8, 0x00d8), /* class D test 5 */ | ||
2813 | WRITE_COEF(0x3c, 0x0014), /* class D test 6 */ | ||
2814 | WRITE_COEF(0x3d, 0xc2ba), /* classD OCP */ | ||
2815 | UPDATE_COEF(0x42, 0x0f80, 0x0), /* classD pure DC test */ | ||
2816 | WRITE_COEF(0x49, 0x0), /* test mode */ | ||
2817 | UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */ | ||
2818 | UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */ | ||
2819 | WRITE_COEF(0x37, 0xfc06), /* Class D amp control */ | ||
2820 | {} | ||
2821 | }; | ||
2822 | |||
2983 | static void alc283_restore_default_value(struct hda_codec *codec) | 2823 | static void alc283_restore_default_value(struct hda_codec *codec) |
2984 | { | 2824 | { |
2985 | int val; | 2825 | alc_process_coef_fw(codec, alc283_coefs); |
2986 | |||
2987 | /* Power Down Control */ | ||
2988 | alc_write_coef_idx(codec, 0x03, 0x0002); | ||
2989 | /* FIFO and filter clock */ | ||
2990 | alc_write_coef_idx(codec, 0x05, 0x0700); | ||
2991 | /* DMIC control */ | ||
2992 | alc_write_coef_idx(codec, 0x07, 0x0200); | ||
2993 | /* Analog clock */ | ||
2994 | val = alc_read_coef_idx(codec, 0x06); | ||
2995 | alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0); | ||
2996 | /* JD */ | ||
2997 | val = alc_read_coef_idx(codec, 0x08); | ||
2998 | alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c); | ||
2999 | /* JD offset1 */ | ||
3000 | alc_write_coef_idx(codec, 0x0a, 0xcccc); | ||
3001 | /* JD offset2 */ | ||
3002 | alc_write_coef_idx(codec, 0x0b, 0xcccc); | ||
3003 | /* LDO1/2/3, DAC/ADC */ | ||
3004 | alc_write_coef_idx(codec, 0x0e, 0x6fc0); | ||
3005 | /* JD */ | ||
3006 | val = alc_read_coef_idx(codec, 0x0f); | ||
3007 | alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000); | ||
3008 | /* Capless */ | ||
3009 | val = alc_read_coef_idx(codec, 0x10); | ||
3010 | alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00); | ||
3011 | /* Class D test 4 */ | ||
3012 | alc_write_coef_idx(codec, 0x3a, 0x0); | ||
3013 | /* IO power down directly */ | ||
3014 | val = alc_read_coef_idx(codec, 0x0c); | ||
3015 | alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0); | ||
3016 | /* ANC */ | ||
3017 | alc_write_coef_idx(codec, 0x22, 0xa0c0); | ||
3018 | /* AGC MUX */ | ||
3019 | val = alc_read_coefex_idx(codec, 0x53, 0x01); | ||
3020 | alc_write_coefex_idx(codec, 0x53, 0x01, (val & ~0x000f) | 0x0008); | ||
3021 | /* DAC simple content protection */ | ||
3022 | val = alc_read_coef_idx(codec, 0x1d); | ||
3023 | alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0); | ||
3024 | /* ADC simple content protection */ | ||
3025 | val = alc_read_coef_idx(codec, 0x1f); | ||
3026 | alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0); | ||
3027 | /* DAC ADC Zero Detection */ | ||
3028 | alc_write_coef_idx(codec, 0x21, 0x8804); | ||
3029 | /* PLL */ | ||
3030 | alc_write_coef_idx(codec, 0x2e, 0x2902); | ||
3031 | /* capless control 2 */ | ||
3032 | alc_write_coef_idx(codec, 0x33, 0xa080); | ||
3033 | /* capless control 3 */ | ||
3034 | alc_write_coef_idx(codec, 0x34, 0x3400); | ||
3035 | /* capless control 4 */ | ||
3036 | alc_write_coef_idx(codec, 0x35, 0x2f3e); | ||
3037 | /* capless control 5 */ | ||
3038 | alc_write_coef_idx(codec, 0x36, 0x0); | ||
3039 | /* class D test 2 */ | ||
3040 | val = alc_read_coef_idx(codec, 0x38); | ||
3041 | alc_write_coef_idx(codec, 0x38, (val & ~0x0fff) | 0x0900); | ||
3042 | /* class D test 3 */ | ||
3043 | alc_write_coef_idx(codec, 0x39, 0x110a); | ||
3044 | /* class D test 5 */ | ||
3045 | val = alc_read_coef_idx(codec, 0x3b); | ||
3046 | alc_write_coef_idx(codec, 0x3b, (val & ~0x00f8) | 0x00d8); | ||
3047 | /* class D test 6 */ | ||
3048 | alc_write_coef_idx(codec, 0x3c, 0x0014); | ||
3049 | /* classD OCP */ | ||
3050 | alc_write_coef_idx(codec, 0x3d, 0xc2ba); | ||
3051 | /* classD pure DC test */ | ||
3052 | val = alc_read_coef_idx(codec, 0x42); | ||
3053 | alc_write_coef_idx(codec, 0x42, (val & ~0x0f80) | 0x0); | ||
3054 | /* test mode */ | ||
3055 | alc_write_coef_idx(codec, 0x49, 0x0); | ||
3056 | /* Class D DC enable */ | ||
3057 | val = alc_read_coef_idx(codec, 0x40); | ||
3058 | alc_write_coef_idx(codec, 0x40, (val & ~0xf800) | 0x9800); | ||
3059 | /* DC offset */ | ||
3060 | val = alc_read_coef_idx(codec, 0x42); | ||
3061 | alc_write_coef_idx(codec, 0x42, (val & ~0xf000) | 0x2000); | ||
3062 | /* Class D amp control */ | ||
3063 | alc_write_coef_idx(codec, 0x37, 0xfc06); | ||
3064 | } | 2826 | } |
3065 | 2827 | ||
3066 | static void alc283_init(struct hda_codec *codec) | 2828 | static void alc283_init(struct hda_codec *codec) |
@@ -3068,7 +2830,6 @@ static void alc283_init(struct hda_codec *codec) | |||
3068 | struct alc_spec *spec = codec->spec; | 2830 | struct alc_spec *spec = codec->spec; |
3069 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | 2831 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; |
3070 | bool hp_pin_sense; | 2832 | bool hp_pin_sense; |
3071 | int val; | ||
3072 | 2833 | ||
3073 | if (!spec->gen.autocfg.hp_outs) { | 2834 | if (!spec->gen.autocfg.hp_outs) { |
3074 | if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) | 2835 | if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) |
@@ -3098,8 +2859,7 @@ static void alc283_init(struct hda_codec *codec) | |||
3098 | msleep(85); | 2859 | msleep(85); |
3099 | /* Index 0x46 Combo jack auto switch control 2 */ | 2860 | /* Index 0x46 Combo jack auto switch control 2 */ |
3100 | /* 3k pull low control for Headset jack. */ | 2861 | /* 3k pull low control for Headset jack. */ |
3101 | val = alc_read_coef_idx(codec, 0x46); | 2862 | alc_update_coef_idx(codec, 0x46, 3 << 12, 0); |
3102 | alc_write_coef_idx(codec, 0x46, val & ~(3 << 12)); | ||
3103 | /* Headphone capless set to normal mode */ | 2863 | /* Headphone capless set to normal mode */ |
3104 | alc_write_coef_idx(codec, 0x43, 0x9614); | 2864 | alc_write_coef_idx(codec, 0x43, 0x9614); |
3105 | } | 2865 | } |
@@ -3109,7 +2869,6 @@ static void alc283_shutup(struct hda_codec *codec) | |||
3109 | struct alc_spec *spec = codec->spec; | 2869 | struct alc_spec *spec = codec->spec; |
3110 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | 2870 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; |
3111 | bool hp_pin_sense; | 2871 | bool hp_pin_sense; |
3112 | int val; | ||
3113 | 2872 | ||
3114 | if (!spec->gen.autocfg.hp_outs) { | 2873 | if (!spec->gen.autocfg.hp_outs) { |
3115 | if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) | 2874 | if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) |
@@ -3134,8 +2893,7 @@ static void alc283_shutup(struct hda_codec *codec) | |||
3134 | snd_hda_codec_write(codec, hp_pin, 0, | 2893 | snd_hda_codec_write(codec, hp_pin, 0, |
3135 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | 2894 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); |
3136 | 2895 | ||
3137 | val = alc_read_coef_idx(codec, 0x46); | 2896 | alc_update_coef_idx(codec, 0x46, 0, 3 << 12); |
3138 | alc_write_coef_idx(codec, 0x46, val | (3 << 12)); | ||
3139 | 2897 | ||
3140 | if (hp_pin_sense) | 2898 | if (hp_pin_sense) |
3141 | msleep(100); | 2899 | msleep(100); |
@@ -3268,7 +3026,6 @@ static int alc269_resume(struct hda_codec *codec) | |||
3268 | 3026 | ||
3269 | snd_hda_codec_resume_amp(codec); | 3027 | snd_hda_codec_resume_amp(codec); |
3270 | snd_hda_codec_resume_cache(codec); | 3028 | snd_hda_codec_resume_cache(codec); |
3271 | alc_inv_dmic_sync(codec, true); | ||
3272 | hda_call_check_power_status(codec, 0x01); | 3029 | hda_call_check_power_status(codec, 0x01); |
3273 | 3030 | ||
3274 | /* on some machine, the BIOS will clear the codec gpio data when enter | 3031 | /* on some machine, the BIOS will clear the codec gpio data when enter |
@@ -3298,12 +3055,8 @@ static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, | |||
3298 | static void alc269_fixup_hweq(struct hda_codec *codec, | 3055 | static void alc269_fixup_hweq(struct hda_codec *codec, |
3299 | const struct hda_fixup *fix, int action) | 3056 | const struct hda_fixup *fix, int action) |
3300 | { | 3057 | { |
3301 | int coef; | 3058 | if (action == HDA_FIXUP_ACT_INIT) |
3302 | 3059 | alc_update_coef_idx(codec, 0x1e, 0, 0x80); | |
3303 | if (action != HDA_FIXUP_ACT_INIT) | ||
3304 | return; | ||
3305 | coef = alc_read_coef_idx(codec, 0x1e); | ||
3306 | alc_write_coef_idx(codec, 0x1e, coef | 0x80); | ||
3307 | } | 3060 | } |
3308 | 3061 | ||
3309 | static void alc269_fixup_headset_mic(struct hda_codec *codec, | 3062 | static void alc269_fixup_headset_mic(struct hda_codec *codec, |
@@ -3351,32 +3104,21 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec, | |||
3351 | static void alc269_fixup_stereo_dmic(struct hda_codec *codec, | 3104 | static void alc269_fixup_stereo_dmic(struct hda_codec *codec, |
3352 | const struct hda_fixup *fix, int action) | 3105 | const struct hda_fixup *fix, int action) |
3353 | { | 3106 | { |
3354 | int coef; | ||
3355 | |||
3356 | if (action != HDA_FIXUP_ACT_INIT) | ||
3357 | return; | ||
3358 | /* The digital-mic unit sends PDM (differential signal) instead of | 3107 | /* The digital-mic unit sends PDM (differential signal) instead of |
3359 | * the standard PCM, thus you can't record a valid mono stream as is. | 3108 | * the standard PCM, thus you can't record a valid mono stream as is. |
3360 | * Below is a workaround specific to ALC269 to control the dmic | 3109 | * Below is a workaround specific to ALC269 to control the dmic |
3361 | * signal source as mono. | 3110 | * signal source as mono. |
3362 | */ | 3111 | */ |
3363 | coef = alc_read_coef_idx(codec, 0x07); | 3112 | if (action == HDA_FIXUP_ACT_INIT) |
3364 | alc_write_coef_idx(codec, 0x07, coef | 0x80); | 3113 | alc_update_coef_idx(codec, 0x07, 0, 0x80); |
3365 | } | 3114 | } |
3366 | 3115 | ||
3367 | static void alc269_quanta_automute(struct hda_codec *codec) | 3116 | static void alc269_quanta_automute(struct hda_codec *codec) |
3368 | { | 3117 | { |
3369 | snd_hda_gen_update_outputs(codec); | 3118 | snd_hda_gen_update_outputs(codec); |
3370 | 3119 | ||
3371 | snd_hda_codec_write(codec, 0x20, 0, | 3120 | alc_write_coef_idx(codec, 0x0c, 0x680); |
3372 | AC_VERB_SET_COEF_INDEX, 0x0c); | 3121 | alc_write_coef_idx(codec, 0x0c, 0x480); |
3373 | snd_hda_codec_write(codec, 0x20, 0, | ||
3374 | AC_VERB_SET_PROC_COEF, 0x680); | ||
3375 | |||
3376 | snd_hda_codec_write(codec, 0x20, 0, | ||
3377 | AC_VERB_SET_COEF_INDEX, 0x0c); | ||
3378 | snd_hda_codec_write(codec, 0x20, 0, | ||
3379 | AC_VERB_SET_PROC_COEF, 0x480); | ||
3380 | } | 3122 | } |
3381 | 3123 | ||
3382 | static void alc269_fixup_quanta_mute(struct hda_codec *codec, | 3124 | static void alc269_fixup_quanta_mute(struct hda_codec *codec, |
@@ -3389,7 +3131,7 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, | |||
3389 | } | 3131 | } |
3390 | 3132 | ||
3391 | static void alc269_x101_hp_automute_hook(struct hda_codec *codec, | 3133 | static void alc269_x101_hp_automute_hook(struct hda_codec *codec, |
3392 | struct hda_jack_tbl *jack) | 3134 | struct hda_jack_callback *jack) |
3393 | { | 3135 | { |
3394 | struct alc_spec *spec = codec->spec; | 3136 | struct alc_spec *spec = codec->spec; |
3395 | int vref; | 3137 | int vref; |
@@ -3622,61 +3364,62 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, | |||
3622 | 3364 | ||
3623 | static void alc_headset_mode_unplugged(struct hda_codec *codec) | 3365 | static void alc_headset_mode_unplugged(struct hda_codec *codec) |
3624 | { | 3366 | { |
3625 | int val; | 3367 | static struct coef_fw coef0255[] = { |
3368 | WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */ | ||
3369 | WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ | ||
3370 | UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/ | ||
3371 | WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */ | ||
3372 | WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */ | ||
3373 | {} | ||
3374 | }; | ||
3375 | static struct coef_fw coef0233[] = { | ||
3376 | WRITE_COEF(0x1b, 0x0c0b), | ||
3377 | WRITE_COEF(0x45, 0xc429), | ||
3378 | UPDATE_COEF(0x35, 0x4000, 0), | ||
3379 | WRITE_COEF(0x06, 0x2104), | ||
3380 | WRITE_COEF(0x1a, 0x0001), | ||
3381 | WRITE_COEF(0x26, 0x0004), | ||
3382 | WRITE_COEF(0x32, 0x42a3), | ||
3383 | {} | ||
3384 | }; | ||
3385 | static struct coef_fw coef0292[] = { | ||
3386 | WRITE_COEF(0x76, 0x000e), | ||
3387 | WRITE_COEF(0x6c, 0x2400), | ||
3388 | WRITE_COEF(0x18, 0x7308), | ||
3389 | WRITE_COEF(0x6b, 0xc429), | ||
3390 | {} | ||
3391 | }; | ||
3392 | static struct coef_fw coef0293[] = { | ||
3393 | UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */ | ||
3394 | UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */ | ||
3395 | UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */ | ||
3396 | UPDATE_COEF(0x1a, 1<<3, 1<<3), /* Combo JD gating with LINE1-VREFO */ | ||
3397 | WRITE_COEF(0x45, 0xc429), /* Set to TRS type */ | ||
3398 | UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ | ||
3399 | {} | ||
3400 | }; | ||
3401 | static struct coef_fw coef0668[] = { | ||
3402 | WRITE_COEF(0x15, 0x0d40), | ||
3403 | WRITE_COEF(0xb7, 0x802b), | ||
3404 | {} | ||
3405 | }; | ||
3626 | 3406 | ||
3627 | switch (codec->vendor_id) { | 3407 | switch (codec->vendor_id) { |
3628 | case 0x10ec0255: | 3408 | case 0x10ec0255: |
3629 | /* LDO and MISC control */ | 3409 | alc_process_coef_fw(codec, coef0255); |
3630 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); | ||
3631 | /* UAJ function set to menual mode */ | ||
3632 | alc_write_coef_idx(codec, 0x45, 0xd089); | ||
3633 | /* Direct Drive HP Amp control(Set to verb control)*/ | ||
3634 | val = alc_read_coefex_idx(codec, 0x57, 0x05); | ||
3635 | alc_write_coefex_idx(codec, 0x57, 0x05, val & ~(1<<14)); | ||
3636 | /* Set MIC2 Vref gate with HP */ | ||
3637 | alc_write_coef_idx(codec, 0x06, 0x6104); | ||
3638 | /* Direct Drive HP Amp control */ | ||
3639 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6); | ||
3640 | break; | 3410 | break; |
3641 | case 0x10ec0233: | 3411 | case 0x10ec0233: |
3642 | case 0x10ec0283: | 3412 | case 0x10ec0283: |
3643 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); | 3413 | alc_process_coef_fw(codec, coef0233); |
3644 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
3645 | val = alc_read_coef_idx(codec, 0x35); | ||
3646 | alc_write_coef_idx(codec, 0x35, val & 0xbfff); | ||
3647 | alc_write_coef_idx(codec, 0x06, 0x2104); | ||
3648 | alc_write_coef_idx(codec, 0x1a, 0x0001); | ||
3649 | alc_write_coef_idx(codec, 0x26, 0x0004); | ||
3650 | alc_write_coef_idx(codec, 0x32, 0x42a3); | ||
3651 | break; | 3414 | break; |
3652 | case 0x10ec0292: | 3415 | case 0x10ec0292: |
3653 | alc_write_coef_idx(codec, 0x76, 0x000e); | 3416 | alc_process_coef_fw(codec, coef0292); |
3654 | alc_write_coef_idx(codec, 0x6c, 0x2400); | ||
3655 | alc_write_coef_idx(codec, 0x18, 0x7308); | ||
3656 | alc_write_coef_idx(codec, 0x6b, 0xc429); | ||
3657 | break; | 3417 | break; |
3658 | case 0x10ec0293: | 3418 | case 0x10ec0293: |
3659 | /* SET Line1 JD to 0 */ | 3419 | alc_process_coef_fw(codec, coef0293); |
3660 | val = alc_read_coef_idx(codec, 0x10); | ||
3661 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 6<<8); | ||
3662 | /* SET charge pump by verb */ | ||
3663 | val = alc_read_coefex_idx(codec, 0x57, 0x05); | ||
3664 | alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | 0x0); | ||
3665 | /* SET EN_OSW to 1 */ | ||
3666 | val = alc_read_coefex_idx(codec, 0x57, 0x03); | ||
3667 | alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | (1<<10) ); | ||
3668 | /* Combo JD gating with LINE1-VREFO */ | ||
3669 | val = alc_read_coef_idx(codec, 0x1a); | ||
3670 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | (1<<3)); | ||
3671 | /* Set to TRS type */ | ||
3672 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
3673 | /* Combo Jack auto detect */ | ||
3674 | val = alc_read_coef_idx(codec, 0x4a); | ||
3675 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e); | ||
3676 | break; | 3420 | break; |
3677 | case 0x10ec0668: | 3421 | case 0x10ec0668: |
3678 | alc_write_coef_idx(codec, 0x15, 0x0d40); | 3422 | alc_process_coef_fw(codec, coef0668); |
3679 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
3680 | break; | 3423 | break; |
3681 | } | 3424 | } |
3682 | codec_dbg(codec, "Headset jack set to unplugged mode.\n"); | 3425 | codec_dbg(codec, "Headset jack set to unplugged mode.\n"); |
@@ -3686,55 +3429,65 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3686 | static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | 3429 | static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, |
3687 | hda_nid_t mic_pin) | 3430 | hda_nid_t mic_pin) |
3688 | { | 3431 | { |
3689 | int val; | 3432 | static struct coef_fw coef0255[] = { |
3433 | WRITE_COEFEX(0x57, 0x03, 0x8aa6), | ||
3434 | WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */ | ||
3435 | {} | ||
3436 | }; | ||
3437 | static struct coef_fw coef0233[] = { | ||
3438 | UPDATE_COEF(0x35, 0, 1<<14), | ||
3439 | WRITE_COEF(0x06, 0x2100), | ||
3440 | WRITE_COEF(0x1a, 0x0021), | ||
3441 | WRITE_COEF(0x26, 0x008c), | ||
3442 | {} | ||
3443 | }; | ||
3444 | static struct coef_fw coef0292[] = { | ||
3445 | WRITE_COEF(0x19, 0xa208), | ||
3446 | WRITE_COEF(0x2e, 0xacf0), | ||
3447 | {} | ||
3448 | }; | ||
3449 | static struct coef_fw coef0293[] = { | ||
3450 | UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */ | ||
3451 | UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */ | ||
3452 | UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ | ||
3453 | {} | ||
3454 | }; | ||
3455 | static struct coef_fw coef0688[] = { | ||
3456 | WRITE_COEF(0xb7, 0x802b), | ||
3457 | WRITE_COEF(0xb5, 0x1040), | ||
3458 | UPDATE_COEF(0xc3, 0, 1<<12), | ||
3459 | {} | ||
3460 | }; | ||
3690 | 3461 | ||
3691 | switch (codec->vendor_id) { | 3462 | switch (codec->vendor_id) { |
3692 | case 0x10ec0255: | 3463 | case 0x10ec0255: |
3693 | alc_write_coef_idx(codec, 0x45, 0xc489); | 3464 | alc_write_coef_idx(codec, 0x45, 0xc489); |
3694 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3465 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3695 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6); | 3466 | alc_process_coef_fw(codec, coef0255); |
3696 | /* Set MIC2 Vref gate to normal */ | ||
3697 | alc_write_coef_idx(codec, 0x06, 0x6100); | ||
3698 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3467 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3699 | break; | 3468 | break; |
3700 | case 0x10ec0233: | 3469 | case 0x10ec0233: |
3701 | case 0x10ec0283: | 3470 | case 0x10ec0283: |
3702 | alc_write_coef_idx(codec, 0x45, 0xc429); | 3471 | alc_write_coef_idx(codec, 0x45, 0xc429); |
3703 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3472 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3704 | val = alc_read_coef_idx(codec, 0x35); | 3473 | alc_process_coef_fw(codec, coef0233); |
3705 | alc_write_coef_idx(codec, 0x35, val | 1<<14); | ||
3706 | alc_write_coef_idx(codec, 0x06, 0x2100); | ||
3707 | alc_write_coef_idx(codec, 0x1a, 0x0021); | ||
3708 | alc_write_coef_idx(codec, 0x26, 0x008c); | ||
3709 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3474 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3710 | break; | 3475 | break; |
3711 | case 0x10ec0292: | 3476 | case 0x10ec0292: |
3712 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3477 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3713 | alc_write_coef_idx(codec, 0x19, 0xa208); | 3478 | alc_process_coef_fw(codec, coef0292); |
3714 | alc_write_coef_idx(codec, 0x2e, 0xacf0); | ||
3715 | break; | 3479 | break; |
3716 | case 0x10ec0293: | 3480 | case 0x10ec0293: |
3717 | /* Set to TRS mode */ | 3481 | /* Set to TRS mode */ |
3718 | alc_write_coef_idx(codec, 0x45, 0xc429); | 3482 | alc_write_coef_idx(codec, 0x45, 0xc429); |
3719 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3483 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3720 | /* SET charge pump by verb */ | 3484 | alc_process_coef_fw(codec, coef0293); |
3721 | val = alc_read_coefex_idx(codec, 0x57, 0x05); | ||
3722 | alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | (1<<15|1<<13)); | ||
3723 | /* SET EN_OSW to 0 */ | ||
3724 | val = alc_read_coefex_idx(codec, 0x57, 0x03); | ||
3725 | alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | 0x0); | ||
3726 | /* Combo JD gating without LINE1-VREFO */ | ||
3727 | val = alc_read_coef_idx(codec, 0x1a); | ||
3728 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0); | ||
3729 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3485 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3730 | break; | 3486 | break; |
3731 | case 0x10ec0668: | 3487 | case 0x10ec0668: |
3732 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3488 | alc_write_coef_idx(codec, 0x11, 0x0001); |
3733 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | 3489 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); |
3734 | alc_write_coef_idx(codec, 0xb7, 0x802b); | 3490 | alc_process_coef_fw(codec, coef0688); |
3735 | alc_write_coef_idx(codec, 0xb5, 0x1040); | ||
3736 | val = alc_read_coef_idx(codec, 0xc3); | ||
3737 | alc_write_coef_idx(codec, 0xc3, val | 1<<12); | ||
3738 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 3491 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3739 | break; | 3492 | break; |
3740 | } | 3493 | } |
@@ -3743,40 +3496,54 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3743 | 3496 | ||
3744 | static void alc_headset_mode_default(struct hda_codec *codec) | 3497 | static void alc_headset_mode_default(struct hda_codec *codec) |
3745 | { | 3498 | { |
3746 | int val; | 3499 | static struct coef_fw coef0255[] = { |
3500 | WRITE_COEF(0x45, 0xc089), | ||
3501 | WRITE_COEF(0x45, 0xc489), | ||
3502 | WRITE_COEFEX(0x57, 0x03, 0x8ea6), | ||
3503 | WRITE_COEF(0x49, 0x0049), | ||
3504 | {} | ||
3505 | }; | ||
3506 | static struct coef_fw coef0233[] = { | ||
3507 | WRITE_COEF(0x06, 0x2100), | ||
3508 | WRITE_COEF(0x32, 0x4ea3), | ||
3509 | {} | ||
3510 | }; | ||
3511 | static struct coef_fw coef0292[] = { | ||
3512 | WRITE_COEF(0x76, 0x000e), | ||
3513 | WRITE_COEF(0x6c, 0x2400), | ||
3514 | WRITE_COEF(0x6b, 0xc429), | ||
3515 | WRITE_COEF(0x18, 0x7308), | ||
3516 | {} | ||
3517 | }; | ||
3518 | static struct coef_fw coef0293[] = { | ||
3519 | UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ | ||
3520 | WRITE_COEF(0x45, 0xC429), /* Set to TRS type */ | ||
3521 | UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ | ||
3522 | {} | ||
3523 | }; | ||
3524 | static struct coef_fw coef0688[] = { | ||
3525 | WRITE_COEF(0x11, 0x0041), | ||
3526 | WRITE_COEF(0x15, 0x0d40), | ||
3527 | WRITE_COEF(0xb7, 0x802b), | ||
3528 | {} | ||
3529 | }; | ||
3747 | 3530 | ||
3748 | switch (codec->vendor_id) { | 3531 | switch (codec->vendor_id) { |
3749 | case 0x10ec0255: | 3532 | case 0x10ec0255: |
3750 | alc_write_coef_idx(codec, 0x45, 0xc089); | 3533 | alc_process_coef_fw(codec, coef0255); |
3751 | alc_write_coef_idx(codec, 0x45, 0xc489); | ||
3752 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | ||
3753 | alc_write_coef_idx(codec, 0x49, 0x0049); | ||
3754 | break; | 3534 | break; |
3755 | case 0x10ec0233: | 3535 | case 0x10ec0233: |
3756 | case 0x10ec0283: | 3536 | case 0x10ec0283: |
3757 | alc_write_coef_idx(codec, 0x06, 0x2100); | 3537 | alc_process_coef_fw(codec, coef0233); |
3758 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
3759 | break; | 3538 | break; |
3760 | case 0x10ec0292: | 3539 | case 0x10ec0292: |
3761 | alc_write_coef_idx(codec, 0x76, 0x000e); | 3540 | alc_process_coef_fw(codec, coef0292); |
3762 | alc_write_coef_idx(codec, 0x6c, 0x2400); | ||
3763 | alc_write_coef_idx(codec, 0x6b, 0xc429); | ||
3764 | alc_write_coef_idx(codec, 0x18, 0x7308); | ||
3765 | break; | 3541 | break; |
3766 | case 0x10ec0293: | 3542 | case 0x10ec0293: |
3767 | /* Combo Jack auto detect */ | 3543 | alc_process_coef_fw(codec, coef0293); |
3768 | val = alc_read_coef_idx(codec, 0x4a); | ||
3769 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e); | ||
3770 | /* Set to TRS type */ | ||
3771 | alc_write_coef_idx(codec, 0x45, 0xC429); | ||
3772 | /* Combo JD gating without LINE1-VREFO */ | ||
3773 | val = alc_read_coef_idx(codec, 0x1a); | ||
3774 | alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0); | ||
3775 | break; | 3544 | break; |
3776 | case 0x10ec0668: | 3545 | case 0x10ec0668: |
3777 | alc_write_coef_idx(codec, 0x11, 0x0041); | 3546 | alc_process_coef_fw(codec, coef0688); |
3778 | alc_write_coef_idx(codec, 0x15, 0x0d40); | ||
3779 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
3780 | break; | 3547 | break; |
3781 | } | 3548 | } |
3782 | codec_dbg(codec, "Headset jack set to headphone (default) mode.\n"); | 3549 | codec_dbg(codec, "Headset jack set to headphone (default) mode.\n"); |
@@ -3785,37 +3552,52 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3785 | /* Iphone type */ | 3552 | /* Iphone type */ |
3786 | static void alc_headset_mode_ctia(struct hda_codec *codec) | 3553 | static void alc_headset_mode_ctia(struct hda_codec *codec) |
3787 | { | 3554 | { |
3788 | int val; | 3555 | static struct coef_fw coef0255[] = { |
3556 | WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ | ||
3557 | WRITE_COEF(0x1b, 0x0c2b), | ||
3558 | WRITE_COEFEX(0x57, 0x03, 0x8ea6), | ||
3559 | {} | ||
3560 | }; | ||
3561 | static struct coef_fw coef0233[] = { | ||
3562 | WRITE_COEF(0x45, 0xd429), | ||
3563 | WRITE_COEF(0x1b, 0x0c2b), | ||
3564 | WRITE_COEF(0x32, 0x4ea3), | ||
3565 | {} | ||
3566 | }; | ||
3567 | static struct coef_fw coef0292[] = { | ||
3568 | WRITE_COEF(0x6b, 0xd429), | ||
3569 | WRITE_COEF(0x76, 0x0008), | ||
3570 | WRITE_COEF(0x18, 0x7388), | ||
3571 | {} | ||
3572 | }; | ||
3573 | static struct coef_fw coef0293[] = { | ||
3574 | WRITE_COEF(0x45, 0xd429), /* Set to ctia type */ | ||
3575 | UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ | ||
3576 | {} | ||
3577 | }; | ||
3578 | static struct coef_fw coef0688[] = { | ||
3579 | WRITE_COEF(0x11, 0x0001), | ||
3580 | WRITE_COEF(0x15, 0x0d60), | ||
3581 | WRITE_COEF(0xc3, 0x0000), | ||
3582 | {} | ||
3583 | }; | ||
3789 | 3584 | ||
3790 | switch (codec->vendor_id) { | 3585 | switch (codec->vendor_id) { |
3791 | case 0x10ec0255: | 3586 | case 0x10ec0255: |
3792 | /* Set to CTIA type */ | 3587 | alc_process_coef_fw(codec, coef0255); |
3793 | alc_write_coef_idx(codec, 0x45, 0xd489); | ||
3794 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
3795 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | ||
3796 | break; | 3588 | break; |
3797 | case 0x10ec0233: | 3589 | case 0x10ec0233: |
3798 | case 0x10ec0283: | 3590 | case 0x10ec0283: |
3799 | alc_write_coef_idx(codec, 0x45, 0xd429); | 3591 | alc_process_coef_fw(codec, coef0233); |
3800 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
3801 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
3802 | break; | 3592 | break; |
3803 | case 0x10ec0292: | 3593 | case 0x10ec0292: |
3804 | alc_write_coef_idx(codec, 0x6b, 0xd429); | 3594 | alc_process_coef_fw(codec, coef0292); |
3805 | alc_write_coef_idx(codec, 0x76, 0x0008); | ||
3806 | alc_write_coef_idx(codec, 0x18, 0x7388); | ||
3807 | break; | 3595 | break; |
3808 | case 0x10ec0293: | 3596 | case 0x10ec0293: |
3809 | /* Set to ctia type */ | 3597 | alc_process_coef_fw(codec, coef0293); |
3810 | alc_write_coef_idx(codec, 0x45, 0xd429); | ||
3811 | /* SET Line1 JD to 1 */ | ||
3812 | val = alc_read_coef_idx(codec, 0x10); | ||
3813 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8); | ||
3814 | break; | 3598 | break; |
3815 | case 0x10ec0668: | 3599 | case 0x10ec0668: |
3816 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3600 | alc_process_coef_fw(codec, coef0688); |
3817 | alc_write_coef_idx(codec, 0x15, 0x0d60); | ||
3818 | alc_write_coef_idx(codec, 0xc3, 0x0000); | ||
3819 | break; | 3601 | break; |
3820 | } | 3602 | } |
3821 | codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n"); | 3603 | codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n"); |
@@ -3824,37 +3606,52 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
3824 | /* Nokia type */ | 3606 | /* Nokia type */ |
3825 | static void alc_headset_mode_omtp(struct hda_codec *codec) | 3607 | static void alc_headset_mode_omtp(struct hda_codec *codec) |
3826 | { | 3608 | { |
3827 | int val; | 3609 | static struct coef_fw coef0255[] = { |
3610 | WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */ | ||
3611 | WRITE_COEF(0x1b, 0x0c2b), | ||
3612 | WRITE_COEFEX(0x57, 0x03, 0x8ea6), | ||
3613 | {} | ||
3614 | }; | ||
3615 | static struct coef_fw coef0233[] = { | ||
3616 | WRITE_COEF(0x45, 0xe429), | ||
3617 | WRITE_COEF(0x1b, 0x0c2b), | ||
3618 | WRITE_COEF(0x32, 0x4ea3), | ||
3619 | {} | ||
3620 | }; | ||
3621 | static struct coef_fw coef0292[] = { | ||
3622 | WRITE_COEF(0x6b, 0xe429), | ||
3623 | WRITE_COEF(0x76, 0x0008), | ||
3624 | WRITE_COEF(0x18, 0x7388), | ||
3625 | {} | ||
3626 | }; | ||
3627 | static struct coef_fw coef0293[] = { | ||
3628 | WRITE_COEF(0x45, 0xe429), /* Set to omtp type */ | ||
3629 | UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ | ||
3630 | {} | ||
3631 | }; | ||
3632 | static struct coef_fw coef0688[] = { | ||
3633 | WRITE_COEF(0x11, 0x0001), | ||
3634 | WRITE_COEF(0x15, 0x0d50), | ||
3635 | WRITE_COEF(0xc3, 0x0000), | ||
3636 | {} | ||
3637 | }; | ||
3828 | 3638 | ||
3829 | switch (codec->vendor_id) { | 3639 | switch (codec->vendor_id) { |
3830 | case 0x10ec0255: | 3640 | case 0x10ec0255: |
3831 | /* Set to OMTP Type */ | 3641 | alc_process_coef_fw(codec, coef0255); |
3832 | alc_write_coef_idx(codec, 0x45, 0xe489); | ||
3833 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
3834 | alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6); | ||
3835 | break; | 3642 | break; |
3836 | case 0x10ec0233: | 3643 | case 0x10ec0233: |
3837 | case 0x10ec0283: | 3644 | case 0x10ec0283: |
3838 | alc_write_coef_idx(codec, 0x45, 0xe429); | 3645 | alc_process_coef_fw(codec, coef0233); |
3839 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
3840 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
3841 | break; | 3646 | break; |
3842 | case 0x10ec0292: | 3647 | case 0x10ec0292: |
3843 | alc_write_coef_idx(codec, 0x6b, 0xe429); | 3648 | alc_process_coef_fw(codec, coef0292); |
3844 | alc_write_coef_idx(codec, 0x76, 0x0008); | ||
3845 | alc_write_coef_idx(codec, 0x18, 0x7388); | ||
3846 | break; | 3649 | break; |
3847 | case 0x10ec0293: | 3650 | case 0x10ec0293: |
3848 | /* Set to omtp type */ | 3651 | alc_process_coef_fw(codec, coef0293); |
3849 | alc_write_coef_idx(codec, 0x45, 0xe429); | ||
3850 | /* SET Line1 JD to 1 */ | ||
3851 | val = alc_read_coef_idx(codec, 0x10); | ||
3852 | alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8); | ||
3853 | break; | 3652 | break; |
3854 | case 0x10ec0668: | 3653 | case 0x10ec0668: |
3855 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3654 | alc_process_coef_fw(codec, coef0688); |
3856 | alc_write_coef_idx(codec, 0x15, 0x0d50); | ||
3857 | alc_write_coef_idx(codec, 0xc3, 0x0000); | ||
3858 | break; | 3655 | break; |
3859 | } | 3656 | } |
3860 | codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n"); | 3657 | codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n"); |
@@ -3865,13 +3662,28 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
3865 | int val; | 3662 | int val; |
3866 | bool is_ctia = false; | 3663 | bool is_ctia = false; |
3867 | struct alc_spec *spec = codec->spec; | 3664 | struct alc_spec *spec = codec->spec; |
3665 | static struct coef_fw coef0255[] = { | ||
3666 | WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/ | ||
3667 | WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref | ||
3668 | conteol) */ | ||
3669 | {} | ||
3670 | }; | ||
3671 | static struct coef_fw coef0293[] = { | ||
3672 | UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */ | ||
3673 | WRITE_COEF(0x45, 0xD429), /* Set to ctia type */ | ||
3674 | {} | ||
3675 | }; | ||
3676 | static struct coef_fw coef0688[] = { | ||
3677 | WRITE_COEF(0x11, 0x0001), | ||
3678 | WRITE_COEF(0xb7, 0x802b), | ||
3679 | WRITE_COEF(0x15, 0x0d60), | ||
3680 | WRITE_COEF(0xc3, 0x0c00), | ||
3681 | {} | ||
3682 | }; | ||
3868 | 3683 | ||
3869 | switch (codec->vendor_id) { | 3684 | switch (codec->vendor_id) { |
3870 | case 0x10ec0255: | 3685 | case 0x10ec0255: |
3871 | /* combo jack auto switch control(Check type)*/ | 3686 | alc_process_coef_fw(codec, coef0255); |
3872 | alc_write_coef_idx(codec, 0x45, 0xd089); | ||
3873 | /* combo jack auto switch control(Vref conteol) */ | ||
3874 | alc_write_coef_idx(codec, 0x49, 0x0149); | ||
3875 | msleep(300); | 3687 | msleep(300); |
3876 | val = alc_read_coef_idx(codec, 0x46); | 3688 | val = alc_read_coef_idx(codec, 0x46); |
3877 | is_ctia = (val & 0x0070) == 0x0070; | 3689 | is_ctia = (val & 0x0070) == 0x0070; |
@@ -3890,20 +3702,13 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
3890 | is_ctia = (val & 0x001c) == 0x001c; | 3702 | is_ctia = (val & 0x001c) == 0x001c; |
3891 | break; | 3703 | break; |
3892 | case 0x10ec0293: | 3704 | case 0x10ec0293: |
3893 | /* Combo Jack auto detect */ | 3705 | alc_process_coef_fw(codec, coef0293); |
3894 | val = alc_read_coef_idx(codec, 0x4a); | ||
3895 | alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x0008); | ||
3896 | /* Set to ctia type */ | ||
3897 | alc_write_coef_idx(codec, 0x45, 0xD429); | ||
3898 | msleep(300); | 3706 | msleep(300); |
3899 | val = alc_read_coef_idx(codec, 0x46); | 3707 | val = alc_read_coef_idx(codec, 0x46); |
3900 | is_ctia = (val & 0x0070) == 0x0070; | 3708 | is_ctia = (val & 0x0070) == 0x0070; |
3901 | break; | 3709 | break; |
3902 | case 0x10ec0668: | 3710 | case 0x10ec0668: |
3903 | alc_write_coef_idx(codec, 0x11, 0x0001); | 3711 | alc_process_coef_fw(codec, coef0688); |
3904 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
3905 | alc_write_coef_idx(codec, 0x15, 0x0d60); | ||
3906 | alc_write_coef_idx(codec, 0xc3, 0x0c00); | ||
3907 | msleep(300); | 3712 | msleep(300); |
3908 | val = alc_read_coef_idx(codec, 0xbe); | 3713 | val = alc_read_coef_idx(codec, 0xbe); |
3909 | is_ctia = (val & 0x1c02) == 0x1c02; | 3714 | is_ctia = (val & 0x1c02) == 0x1c02; |
@@ -3980,7 +3785,8 @@ static void alc_update_headset_mode_hook(struct hda_codec *codec, | |||
3980 | alc_update_headset_mode(codec); | 3785 | alc_update_headset_mode(codec); |
3981 | } | 3786 | } |
3982 | 3787 | ||
3983 | static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack) | 3788 | static void alc_update_headset_jack_cb(struct hda_codec *codec, |
3789 | struct hda_jack_callback *jack) | ||
3984 | { | 3790 | { |
3985 | struct alc_spec *spec = codec->spec; | 3791 | struct alc_spec *spec = codec->spec; |
3986 | spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN; | 3792 | spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN; |
@@ -4039,11 +3845,15 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, | |||
4039 | static void alc255_set_default_jack_type(struct hda_codec *codec) | 3845 | static void alc255_set_default_jack_type(struct hda_codec *codec) |
4040 | { | 3846 | { |
4041 | /* Set to iphone type */ | 3847 | /* Set to iphone type */ |
4042 | alc_write_coef_idx(codec, 0x1b, 0x880b); | 3848 | static struct coef_fw fw[] = { |
4043 | alc_write_coef_idx(codec, 0x45, 0xd089); | 3849 | WRITE_COEF(0x1b, 0x880b), |
4044 | alc_write_coef_idx(codec, 0x1b, 0x080b); | 3850 | WRITE_COEF(0x45, 0xd089), |
4045 | alc_write_coef_idx(codec, 0x46, 0x0004); | 3851 | WRITE_COEF(0x1b, 0x080b), |
4046 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); | 3852 | WRITE_COEF(0x46, 0x0004), |
3853 | WRITE_COEF(0x1b, 0x0c0b), | ||
3854 | {} | ||
3855 | }; | ||
3856 | alc_process_coef_fw(codec, fw); | ||
4047 | msleep(30); | 3857 | msleep(30); |
4048 | } | 3858 | } |
4049 | 3859 | ||
@@ -4138,10 +3948,8 @@ static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, | |||
4138 | const struct hda_fixup *fix, int action) | 3948 | const struct hda_fixup *fix, int action) |
4139 | { | 3949 | { |
4140 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 3950 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
4141 | int val; | ||
4142 | alc_write_coef_idx(codec, 0xc4, 0x8000); | 3951 | alc_write_coef_idx(codec, 0xc4, 0x8000); |
4143 | val = alc_read_coef_idx(codec, 0xc2); | 3952 | alc_update_coef_idx(codec, 0xc2, ~0xfe, 0); |
4144 | alc_write_coef_idx(codec, 0xc2, val & 0xfe); | ||
4145 | snd_hda_set_pin_ctl_cache(codec, 0x18, 0); | 3953 | snd_hda_set_pin_ctl_cache(codec, 0x18, 0); |
4146 | } | 3954 | } |
4147 | alc_fixup_headset_mode(codec, fix, action); | 3955 | alc_fixup_headset_mode(codec, fix, action); |
@@ -4218,7 +4026,7 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, | |||
4218 | } | 4026 | } |
4219 | 4027 | ||
4220 | static void alc283_hp_automute_hook(struct hda_codec *codec, | 4028 | static void alc283_hp_automute_hook(struct hda_codec *codec, |
4221 | struct hda_jack_tbl *jack) | 4029 | struct hda_jack_callback *jack) |
4222 | { | 4030 | { |
4223 | struct alc_spec *spec = codec->spec; | 4031 | struct alc_spec *spec = codec->spec; |
4224 | int vref; | 4032 | int vref; |
@@ -4237,7 +4045,6 @@ static void alc283_fixup_chromebook(struct hda_codec *codec, | |||
4237 | const struct hda_fixup *fix, int action) | 4045 | const struct hda_fixup *fix, int action) |
4238 | { | 4046 | { |
4239 | struct alc_spec *spec = codec->spec; | 4047 | struct alc_spec *spec = codec->spec; |
4240 | int val; | ||
4241 | 4048 | ||
4242 | switch (action) { | 4049 | switch (action) { |
4243 | case HDA_FIXUP_ACT_PRE_PROBE: | 4050 | case HDA_FIXUP_ACT_PRE_PROBE: |
@@ -4248,11 +4055,9 @@ static void alc283_fixup_chromebook(struct hda_codec *codec, | |||
4248 | case HDA_FIXUP_ACT_INIT: | 4055 | case HDA_FIXUP_ACT_INIT: |
4249 | /* MIC2-VREF control */ | 4056 | /* MIC2-VREF control */ |
4250 | /* Set to manual mode */ | 4057 | /* Set to manual mode */ |
4251 | val = alc_read_coef_idx(codec, 0x06); | 4058 | alc_update_coef_idx(codec, 0x06, 0x000c, 0); |
4252 | alc_write_coef_idx(codec, 0x06, val & ~0x000c); | ||
4253 | /* Enable Line1 input control by verb */ | 4059 | /* Enable Line1 input control by verb */ |
4254 | val = alc_read_coef_idx(codec, 0x1a); | 4060 | alc_update_coef_idx(codec, 0x1a, 0, 1 << 4); |
4255 | alc_write_coef_idx(codec, 0x1a, val | (1 << 4)); | ||
4256 | break; | 4061 | break; |
4257 | } | 4062 | } |
4258 | } | 4063 | } |
@@ -4261,7 +4066,6 @@ static void alc283_fixup_sense_combo_jack(struct hda_codec *codec, | |||
4261 | const struct hda_fixup *fix, int action) | 4066 | const struct hda_fixup *fix, int action) |
4262 | { | 4067 | { |
4263 | struct alc_spec *spec = codec->spec; | 4068 | struct alc_spec *spec = codec->spec; |
4264 | int val; | ||
4265 | 4069 | ||
4266 | switch (action) { | 4070 | switch (action) { |
4267 | case HDA_FIXUP_ACT_PRE_PROBE: | 4071 | case HDA_FIXUP_ACT_PRE_PROBE: |
@@ -4270,8 +4074,7 @@ static void alc283_fixup_sense_combo_jack(struct hda_codec *codec, | |||
4270 | case HDA_FIXUP_ACT_INIT: | 4074 | case HDA_FIXUP_ACT_INIT: |
4271 | /* MIC2-VREF control */ | 4075 | /* MIC2-VREF control */ |
4272 | /* Set to manual mode */ | 4076 | /* Set to manual mode */ |
4273 | val = alc_read_coef_idx(codec, 0x06); | 4077 | alc_update_coef_idx(codec, 0x06, 0x000c, 0); |
4274 | alc_write_coef_idx(codec, 0x06, val & ~0x000c); | ||
4275 | break; | 4078 | break; |
4276 | } | 4079 | } |
4277 | } | 4080 | } |
@@ -4309,7 +4112,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, | |||
4309 | spec->gen.auto_mute_via_amp = 1; | 4112 | spec->gen.auto_mute_via_amp = 1; |
4310 | spec->gen.automute_hook = asus_tx300_automute; | 4113 | spec->gen.automute_hook = asus_tx300_automute; |
4311 | snd_hda_jack_detect_enable_callback(codec, 0x1b, | 4114 | snd_hda_jack_detect_enable_callback(codec, 0x1b, |
4312 | HDA_GEN_HP_EVENT, | ||
4313 | snd_hda_gen_hp_automute); | 4115 | snd_hda_gen_hp_automute); |
4314 | break; | 4116 | break; |
4315 | case HDA_FIXUP_ACT_BUILD: | 4117 | case HDA_FIXUP_ACT_BUILD: |
@@ -4576,7 +4378,7 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4576 | }, | 4378 | }, |
4577 | [ALC269_FIXUP_INV_DMIC] = { | 4379 | [ALC269_FIXUP_INV_DMIC] = { |
4578 | .type = HDA_FIXUP_FUNC, | 4380 | .type = HDA_FIXUP_FUNC, |
4579 | .v.func = alc_fixup_inv_dmic_0x12, | 4381 | .v.func = alc_fixup_inv_dmic, |
4580 | }, | 4382 | }, |
4581 | [ALC269_FIXUP_NO_SHUTUP] = { | 4383 | [ALC269_FIXUP_NO_SHUTUP] = { |
4582 | .type = HDA_FIXUP_FUNC, | 4384 | .type = HDA_FIXUP_FUNC, |
@@ -4887,122 +4689,45 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4887 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | 4689 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), |
4888 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), | 4690 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), |
4889 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 4691 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
4890 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4891 | SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4892 | SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4893 | SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4894 | SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4895 | SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4896 | SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4897 | SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4898 | SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4899 | SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4900 | SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4901 | SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4902 | SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER), | 4692 | SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER), |
4903 | SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4904 | SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4905 | SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4906 | SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4907 | SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4908 | SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4909 | SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4910 | SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4911 | SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4912 | SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4693 | SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4913 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4694 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4914 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4695 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4915 | SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4916 | SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4917 | SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4918 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4919 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4920 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4921 | SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | 4696 | SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), |
4922 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4923 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4924 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4697 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4925 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4698 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4926 | SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | 4699 | SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), |
4927 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), | 4700 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), |
4928 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4929 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4701 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4930 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4702 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4931 | SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4932 | SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4933 | SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4934 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4935 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
4936 | SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4703 | SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4937 | SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4704 | SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
4938 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | 4705 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
4939 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), | 4706 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), |
4940 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4941 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4942 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4707 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4943 | /* ALC282 */ | 4708 | /* ALC282 */ |
4944 | SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4945 | SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4946 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4947 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4948 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4949 | SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4709 | SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4950 | SND_PCI_QUIRK(0x103c, 0x2211, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4951 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4952 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4953 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4710 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4954 | SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4955 | SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4956 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4711 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
4957 | SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4712 | SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
4958 | SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4713 | SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
4959 | SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4714 | SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
4960 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4961 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4962 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4963 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4964 | SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4965 | SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4715 | SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
4966 | SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4967 | SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4968 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4969 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4970 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4716 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4971 | SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4972 | SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4717 | SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4973 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4718 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4974 | SND_PCI_QUIRK(0x103c, 0x226c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4975 | SND_PCI_QUIRK(0x103c, 0x226d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4976 | SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4719 | SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4977 | SND_PCI_QUIRK(0x103c, 0x226f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4978 | SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4979 | SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4980 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4720 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4981 | SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4982 | SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4721 | SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4983 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4722 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4984 | SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4723 | SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4985 | SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4986 | SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4987 | SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4988 | SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4989 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4990 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4724 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4991 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4992 | SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4993 | SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4994 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4725 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
4995 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4726 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
4996 | SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4727 | SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
4997 | /* ALC290 */ | 4728 | /* ALC290 */ |
4998 | SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4729 | SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
4999 | SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5000 | SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5001 | SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5002 | SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4730 | SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5003 | SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5004 | SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5005 | SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
5006 | SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4731 | SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5007 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4732 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5008 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4733 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
@@ -5017,8 +4742,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5017 | SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4742 | SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5018 | SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4743 | SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5019 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4744 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5020 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5021 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5022 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4745 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5023 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4746 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5024 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4747 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -5026,23 +4749,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5026 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4749 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5027 | SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4750 | SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5028 | SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | 4751 | SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), |
5029 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5030 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5031 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4752 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5032 | SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5033 | SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5034 | SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4753 | SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5035 | SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5036 | SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5037 | SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4754 | SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5038 | SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5039 | SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5040 | SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4755 | SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5041 | SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4756 | SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5042 | SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5043 | SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4757 | SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5044 | SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4758 | SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5045 | SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
5046 | SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4759 | SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5047 | SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4760 | SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
5048 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4761 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -5070,6 +4783,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5070 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), | 4783 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), |
5071 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), | 4784 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), |
5072 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), | 4785 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), |
4786 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), | ||
5073 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), | 4787 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), |
5074 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 4788 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
5075 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 4789 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
@@ -5085,12 +4799,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5085 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK), | 4799 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK), |
5086 | SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK), | 4800 | SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK), |
5087 | SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK), | 4801 | SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK), |
5088 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4802 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK), |
5089 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4803 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5090 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4804 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5091 | SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), | 4805 | SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), |
5092 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4806 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5093 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), | 4807 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), |
4808 | SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK), | ||
5094 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4809 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5095 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4810 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
5096 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 4811 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
@@ -5173,28 +4888,58 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
5173 | {} | 4888 | {} |
5174 | }; | 4889 | }; |
5175 | 4890 | ||
4891 | #define ALC255_STANDARD_PINS \ | ||
4892 | {0x18, 0x411111f0}, \ | ||
4893 | {0x19, 0x411111f0}, \ | ||
4894 | {0x1a, 0x411111f0}, \ | ||
4895 | {0x1b, 0x411111f0}, \ | ||
4896 | {0x1e, 0x411111f0} | ||
4897 | |||
4898 | #define ALC282_STANDARD_PINS \ | ||
4899 | {0x14, 0x90170110}, \ | ||
4900 | {0x18, 0x411111f0}, \ | ||
4901 | {0x1a, 0x411111f0}, \ | ||
4902 | {0x1b, 0x411111f0}, \ | ||
4903 | {0x1e, 0x411111f0} | ||
4904 | |||
4905 | #define ALC290_STANDARD_PINS \ | ||
4906 | {0x12, 0x99a30130}, \ | ||
4907 | {0x13, 0x40000000}, \ | ||
4908 | {0x16, 0x411111f0}, \ | ||
4909 | {0x17, 0x411111f0}, \ | ||
4910 | {0x19, 0x411111f0}, \ | ||
4911 | {0x1b, 0x411111f0}, \ | ||
4912 | {0x1e, 0x411111f0} | ||
4913 | |||
4914 | #define ALC292_STANDARD_PINS \ | ||
4915 | {0x14, 0x90170110}, \ | ||
4916 | {0x15, 0x0221401f}, \ | ||
4917 | {0x1a, 0x411111f0}, \ | ||
4918 | {0x1b, 0x411111f0}, \ | ||
4919 | {0x1d, 0x40700001}, \ | ||
4920 | {0x1e, 0x411111f0} | ||
4921 | |||
5176 | static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | 4922 | static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { |
4923 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, | ||
4924 | ALC255_STANDARD_PINS, | ||
4925 | {0x12, 0x40300000}, | ||
4926 | {0x14, 0x90170110}, | ||
4927 | {0x17, 0x411111f0}, | ||
4928 | {0x1d, 0x40538029}, | ||
4929 | {0x21, 0x02211020}), | ||
5177 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4930 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4931 | ALC255_STANDARD_PINS, | ||
5178 | {0x12, 0x90a60140}, | 4932 | {0x12, 0x90a60140}, |
5179 | {0x14, 0x90170110}, | 4933 | {0x14, 0x90170110}, |
5180 | {0x17, 0x40000000}, | 4934 | {0x17, 0x40000000}, |
5181 | {0x18, 0x411111f0}, | ||
5182 | {0x19, 0x411111f0}, | ||
5183 | {0x1a, 0x411111f0}, | ||
5184 | {0x1b, 0x411111f0}, | ||
5185 | {0x1d, 0x40700001}, | 4935 | {0x1d, 0x40700001}, |
5186 | {0x1e, 0x411111f0}, | ||
5187 | {0x21, 0x02211020}), | 4936 | {0x21, 0x02211020}), |
5188 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4937 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4938 | ALC255_STANDARD_PINS, | ||
5189 | {0x12, 0x90a60160}, | 4939 | {0x12, 0x90a60160}, |
5190 | {0x14, 0x90170120}, | 4940 | {0x14, 0x90170120}, |
5191 | {0x17, 0x40000000}, | 4941 | {0x17, 0x40000000}, |
5192 | {0x18, 0x411111f0}, | ||
5193 | {0x19, 0x411111f0}, | ||
5194 | {0x1a, 0x411111f0}, | ||
5195 | {0x1b, 0x411111f0}, | ||
5196 | {0x1d, 0x40700001}, | 4942 | {0x1d, 0x40700001}, |
5197 | {0x1e, 0x411111f0}, | ||
5198 | {0x21, 0x02211030}), | 4943 | {0x21, 0x02211030}), |
5199 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4944 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
5200 | {0x12, 0x90a60160}, | 4945 | {0x12, 0x90a60160}, |
@@ -5208,70 +4953,101 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5208 | {0x1e, 0x411111f0}, | 4953 | {0x1e, 0x411111f0}, |
5209 | {0x21, 0x0321102f}), | 4954 | {0x21, 0x0321102f}), |
5210 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4955 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4956 | ALC255_STANDARD_PINS, | ||
5211 | {0x12, 0x90a60160}, | 4957 | {0x12, 0x90a60160}, |
5212 | {0x14, 0x90170130}, | 4958 | {0x14, 0x90170130}, |
5213 | {0x17, 0x40000000}, | 4959 | {0x17, 0x40000000}, |
5214 | {0x18, 0x411111f0}, | ||
5215 | {0x19, 0x411111f0}, | ||
5216 | {0x1a, 0x411111f0}, | ||
5217 | {0x1b, 0x411111f0}, | ||
5218 | {0x1d, 0x40700001}, | 4960 | {0x1d, 0x40700001}, |
5219 | {0x1e, 0x411111f0}, | ||
5220 | {0x21, 0x02211040}), | 4961 | {0x21, 0x02211040}), |
5221 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4962 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4963 | ALC255_STANDARD_PINS, | ||
5222 | {0x12, 0x90a60160}, | 4964 | {0x12, 0x90a60160}, |
5223 | {0x14, 0x90170140}, | 4965 | {0x14, 0x90170140}, |
5224 | {0x17, 0x40000000}, | 4966 | {0x17, 0x40000000}, |
5225 | {0x18, 0x411111f0}, | ||
5226 | {0x19, 0x411111f0}, | ||
5227 | {0x1a, 0x411111f0}, | ||
5228 | {0x1b, 0x411111f0}, | ||
5229 | {0x1d, 0x40700001}, | 4967 | {0x1d, 0x40700001}, |
5230 | {0x1e, 0x411111f0}, | ||
5231 | {0x21, 0x02211050}), | 4968 | {0x21, 0x02211050}), |
5232 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4969 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4970 | ALC255_STANDARD_PINS, | ||
5233 | {0x12, 0x90a60170}, | 4971 | {0x12, 0x90a60170}, |
5234 | {0x14, 0x90170120}, | 4972 | {0x14, 0x90170120}, |
5235 | {0x17, 0x40000000}, | 4973 | {0x17, 0x40000000}, |
5236 | {0x18, 0x411111f0}, | ||
5237 | {0x19, 0x411111f0}, | ||
5238 | {0x1a, 0x411111f0}, | ||
5239 | {0x1b, 0x411111f0}, | ||
5240 | {0x1d, 0x40700001}, | 4974 | {0x1d, 0x40700001}, |
5241 | {0x1e, 0x411111f0}, | ||
5242 | {0x21, 0x02211030}), | 4975 | {0x21, 0x02211030}), |
5243 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 4976 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
4977 | ALC255_STANDARD_PINS, | ||
5244 | {0x12, 0x90a60170}, | 4978 | {0x12, 0x90a60170}, |
5245 | {0x14, 0x90170130}, | 4979 | {0x14, 0x90170130}, |
5246 | {0x17, 0x40000000}, | 4980 | {0x17, 0x40000000}, |
5247 | {0x18, 0x411111f0}, | ||
5248 | {0x19, 0x411111f0}, | ||
5249 | {0x1a, 0x411111f0}, | ||
5250 | {0x1b, 0x411111f0}, | ||
5251 | {0x1d, 0x40700001}, | 4981 | {0x1d, 0x40700001}, |
5252 | {0x1e, 0x411111f0}, | ||
5253 | {0x21, 0x02211040}), | 4982 | {0x21, 0x02211040}), |
4983 | SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED, | ||
4984 | {0x12, 0x90a60140}, | ||
4985 | {0x13, 0x40000000}, | ||
4986 | {0x14, 0x90170110}, | ||
4987 | {0x15, 0x0421101f}, | ||
4988 | {0x16, 0x411111f0}, | ||
4989 | {0x17, 0x411111f0}, | ||
4990 | {0x18, 0x02811030}, | ||
4991 | {0x19, 0x411111f0}, | ||
4992 | {0x1a, 0x04a1103f}, | ||
4993 | {0x1b, 0x02011020}, | ||
4994 | {0x1d, 0x40700001}, | ||
4995 | {0x1e, 0x411111f0}), | ||
5254 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1, | 4996 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1, |
4997 | ALC282_STANDARD_PINS, | ||
5255 | {0x12, 0x99a30130}, | 4998 | {0x12, 0x99a30130}, |
5256 | {0x14, 0x90170110}, | ||
5257 | {0x17, 0x40000000}, | 4999 | {0x17, 0x40000000}, |
5258 | {0x18, 0x411111f0}, | ||
5259 | {0x19, 0x03a11020}, | 5000 | {0x19, 0x03a11020}, |
5260 | {0x1a, 0x411111f0}, | ||
5261 | {0x1b, 0x411111f0}, | ||
5262 | {0x1d, 0x40f41905}, | 5001 | {0x1d, 0x40f41905}, |
5263 | {0x1e, 0x411111f0}, | ||
5264 | {0x21, 0x0321101f}), | 5002 | {0x21, 0x0321101f}), |
5003 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5004 | ALC282_STANDARD_PINS, | ||
5005 | {0x12, 0x99a30130}, | ||
5006 | {0x17, 0x40020008}, | ||
5007 | {0x19, 0x03a11020}, | ||
5008 | {0x1d, 0x40e00001}, | ||
5009 | {0x21, 0x03211040}), | ||
5010 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5011 | ALC282_STANDARD_PINS, | ||
5012 | {0x12, 0x99a30130}, | ||
5013 | {0x17, 0x40000000}, | ||
5014 | {0x19, 0x03a11030}, | ||
5015 | {0x1d, 0x40e00001}, | ||
5016 | {0x21, 0x03211020}), | ||
5017 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5018 | ALC282_STANDARD_PINS, | ||
5019 | {0x12, 0x99a30130}, | ||
5020 | {0x17, 0x40000000}, | ||
5021 | {0x19, 0x03a11030}, | ||
5022 | {0x1d, 0x40f00001}, | ||
5023 | {0x21, 0x03211020}), | ||
5024 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5025 | ALC282_STANDARD_PINS, | ||
5026 | {0x12, 0x99a30130}, | ||
5027 | {0x17, 0x40000000}, | ||
5028 | {0x19, 0x04a11020}, | ||
5029 | {0x1d, 0x40f00001}, | ||
5030 | {0x21, 0x0421101f}), | ||
5031 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5032 | ALC282_STANDARD_PINS, | ||
5033 | {0x12, 0x99a30130}, | ||
5034 | {0x17, 0x40000000}, | ||
5035 | {0x19, 0x03a11030}, | ||
5036 | {0x1d, 0x40f00001}, | ||
5037 | {0x21, 0x04211020}), | ||
5038 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED, | ||
5039 | ALC282_STANDARD_PINS, | ||
5040 | {0x12, 0x90a60140}, | ||
5041 | {0x17, 0x40000000}, | ||
5042 | {0x19, 0x04a11030}, | ||
5043 | {0x1d, 0x40f00001}, | ||
5044 | {0x21, 0x04211020}), | ||
5265 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 5045 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
5046 | ALC282_STANDARD_PINS, | ||
5266 | {0x12, 0x90a60130}, | 5047 | {0x12, 0x90a60130}, |
5267 | {0x14, 0x90170110}, | ||
5268 | {0x17, 0x40020008}, | 5048 | {0x17, 0x40020008}, |
5269 | {0x18, 0x411111f0}, | ||
5270 | {0x19, 0x411111f0}, | 5049 | {0x19, 0x411111f0}, |
5271 | {0x1a, 0x411111f0}, | ||
5272 | {0x1b, 0x411111f0}, | ||
5273 | {0x1d, 0x40e00001}, | 5050 | {0x1d, 0x40e00001}, |
5274 | {0x1e, 0x411111f0}, | ||
5275 | {0x21, 0x0321101f}), | 5051 | {0x21, 0x0321101f}), |
5276 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 5052 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
5277 | {0x12, 0x90a60160}, | 5053 | {0x12, 0x90a60160}, |
@@ -5284,42 +5060,97 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5284 | {0x1d, 0x40700001}, | 5060 | {0x1d, 0x40700001}, |
5285 | {0x1e, 0x411111f0}, | 5061 | {0x1e, 0x411111f0}, |
5286 | {0x21, 0x02211030}), | 5062 | {0x21, 0x02211030}), |
5063 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
5064 | ALC282_STANDARD_PINS, | ||
5065 | {0x12, 0x90a60130}, | ||
5066 | {0x17, 0x40020008}, | ||
5067 | {0x19, 0x03a11020}, | ||
5068 | {0x1d, 0x40e00001}, | ||
5069 | {0x21, 0x0321101f}), | ||
5070 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5071 | ALC290_STANDARD_PINS, | ||
5072 | {0x14, 0x411111f0}, | ||
5073 | {0x15, 0x04211040}, | ||
5074 | {0x18, 0x90170112}, | ||
5075 | {0x1a, 0x04a11020}, | ||
5076 | {0x1d, 0x4075812d}), | ||
5077 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5078 | ALC290_STANDARD_PINS, | ||
5079 | {0x14, 0x411111f0}, | ||
5080 | {0x15, 0x04211040}, | ||
5081 | {0x18, 0x90170110}, | ||
5082 | {0x1a, 0x04a11020}, | ||
5083 | {0x1d, 0x4075812d}), | ||
5084 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5085 | ALC290_STANDARD_PINS, | ||
5086 | {0x14, 0x411111f0}, | ||
5087 | {0x15, 0x0421101f}, | ||
5088 | {0x18, 0x411111f0}, | ||
5089 | {0x1a, 0x04a11020}, | ||
5090 | {0x1d, 0x4075812d}), | ||
5091 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5092 | ALC290_STANDARD_PINS, | ||
5093 | {0x14, 0x411111f0}, | ||
5094 | {0x15, 0x04211020}, | ||
5095 | {0x18, 0x411111f0}, | ||
5096 | {0x1a, 0x04a11040}, | ||
5097 | {0x1d, 0x4076a12d}), | ||
5098 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5099 | ALC290_STANDARD_PINS, | ||
5100 | {0x14, 0x90170110}, | ||
5101 | {0x15, 0x04211020}, | ||
5102 | {0x18, 0x411111f0}, | ||
5103 | {0x1a, 0x04a11040}, | ||
5104 | {0x1d, 0x4076a12d}), | ||
5105 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5106 | ALC290_STANDARD_PINS, | ||
5107 | {0x14, 0x90170110}, | ||
5108 | {0x15, 0x04211020}, | ||
5109 | {0x18, 0x411111f0}, | ||
5110 | {0x1a, 0x04a11020}, | ||
5111 | {0x1d, 0x4076a12d}), | ||
5112 | SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5113 | ALC290_STANDARD_PINS, | ||
5114 | {0x14, 0x90170110}, | ||
5115 | {0x15, 0x0421101f}, | ||
5116 | {0x18, 0x411111f0}, | ||
5117 | {0x1a, 0x04a11020}, | ||
5118 | {0x1d, 0x4075812d}), | ||
5119 | SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, | ||
5120 | ALC292_STANDARD_PINS, | ||
5121 | {0x12, 0x90a60140}, | ||
5122 | {0x13, 0x411111f0}, | ||
5123 | {0x16, 0x01014020}, | ||
5124 | {0x18, 0x411111f0}, | ||
5125 | {0x19, 0x01a19030}), | ||
5126 | SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, | ||
5127 | ALC292_STANDARD_PINS, | ||
5128 | {0x12, 0x90a60140}, | ||
5129 | {0x13, 0x411111f0}, | ||
5130 | {0x16, 0x01014020}, | ||
5131 | {0x18, 0x02a19031}, | ||
5132 | {0x19, 0x01a1903e}), | ||
5287 | SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | 5133 | SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, |
5134 | ALC292_STANDARD_PINS, | ||
5288 | {0x12, 0x90a60140}, | 5135 | {0x12, 0x90a60140}, |
5289 | {0x13, 0x411111f0}, | 5136 | {0x13, 0x411111f0}, |
5290 | {0x14, 0x90170110}, | ||
5291 | {0x15, 0x0221401f}, | ||
5292 | {0x16, 0x411111f0}, | 5137 | {0x16, 0x411111f0}, |
5293 | {0x18, 0x411111f0}, | 5138 | {0x18, 0x411111f0}, |
5294 | {0x19, 0x411111f0}, | 5139 | {0x19, 0x411111f0}), |
5295 | {0x1a, 0x411111f0}, | ||
5296 | {0x1b, 0x411111f0}, | ||
5297 | {0x1d, 0x40700001}, | ||
5298 | {0x1e, 0x411111f0}), | ||
5299 | SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | 5140 | SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, |
5141 | ALC292_STANDARD_PINS, | ||
5300 | {0x12, 0x40000000}, | 5142 | {0x12, 0x40000000}, |
5301 | {0x13, 0x90a60140}, | 5143 | {0x13, 0x90a60140}, |
5302 | {0x14, 0x90170110}, | ||
5303 | {0x15, 0x0221401f}, | ||
5304 | {0x16, 0x21014020}, | 5144 | {0x16, 0x21014020}, |
5305 | {0x18, 0x411111f0}, | 5145 | {0x18, 0x411111f0}, |
5306 | {0x19, 0x21a19030}, | 5146 | {0x19, 0x21a19030}), |
5307 | {0x1a, 0x411111f0}, | ||
5308 | {0x1b, 0x411111f0}, | ||
5309 | {0x1d, 0x40700001}, | ||
5310 | {0x1e, 0x411111f0}), | ||
5311 | SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | 5147 | SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, |
5148 | ALC292_STANDARD_PINS, | ||
5312 | {0x12, 0x40000000}, | 5149 | {0x12, 0x40000000}, |
5313 | {0x13, 0x90a60140}, | 5150 | {0x13, 0x90a60140}, |
5314 | {0x14, 0x90170110}, | ||
5315 | {0x15, 0x0221401f}, | ||
5316 | {0x16, 0x411111f0}, | 5151 | {0x16, 0x411111f0}, |
5317 | {0x18, 0x411111f0}, | 5152 | {0x18, 0x411111f0}, |
5318 | {0x19, 0x411111f0}, | 5153 | {0x19, 0x411111f0}), |
5319 | {0x1a, 0x411111f0}, | ||
5320 | {0x1b, 0x411111f0}, | ||
5321 | {0x1d, 0x40700001}, | ||
5322 | {0x1e, 0x411111f0}), | ||
5323 | {} | 5154 | {} |
5324 | }; | 5155 | }; |
5325 | 5156 | ||
@@ -5342,10 +5173,8 @@ static void alc269_fill_coef(struct hda_codec *codec) | |||
5342 | } | 5173 | } |
5343 | 5174 | ||
5344 | if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { | 5175 | if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { |
5345 | val = alc_read_coef_idx(codec, 0x04); | ||
5346 | /* Power up output pin */ | 5176 | /* Power up output pin */ |
5347 | if (val != -1) | 5177 | alc_update_coef_idx(codec, 0x04, 0, 1<<11); |
5348 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | ||
5349 | } | 5178 | } |
5350 | 5179 | ||
5351 | if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { | 5180 | if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { |
@@ -5361,13 +5190,11 @@ static void alc269_fill_coef(struct hda_codec *codec) | |||
5361 | } | 5190 | } |
5362 | } | 5191 | } |
5363 | 5192 | ||
5364 | val = alc_read_coef_idx(codec, 0xd); /* Class D */ | 5193 | /* Class D */ |
5365 | if (val != -1) | 5194 | alc_update_coef_idx(codec, 0xd, 0, 1<<14); |
5366 | alc_write_coef_idx(codec, 0xd, val | (1<<14)); | ||
5367 | 5195 | ||
5368 | val = alc_read_coef_idx(codec, 0x4); /* HP */ | 5196 | /* HP */ |
5369 | if (val != -1) | 5197 | alc_update_coef_idx(codec, 0x4, 0, 1<<11); |
5370 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); | ||
5371 | } | 5198 | } |
5372 | 5199 | ||
5373 | /* | 5200 | /* |
@@ -6012,7 +5839,7 @@ static const struct hda_fixup alc662_fixups[] = { | |||
6012 | }, | 5839 | }, |
6013 | [ALC662_FIXUP_INV_DMIC] = { | 5840 | [ALC662_FIXUP_INV_DMIC] = { |
6014 | .type = HDA_FIXUP_FUNC, | 5841 | .type = HDA_FIXUP_FUNC, |
6015 | .v.func = alc_fixup_inv_dmic_0x12, | 5842 | .v.func = alc_fixup_inv_dmic, |
6016 | }, | 5843 | }, |
6017 | [ALC668_FIXUP_DELL_XPS13] = { | 5844 | [ALC668_FIXUP_DELL_XPS13] = { |
6018 | .type = HDA_FIXUP_FUNC, | 5845 | .type = HDA_FIXUP_FUNC, |
@@ -6247,16 +6074,14 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { | |||
6247 | 6074 | ||
6248 | static void alc662_fill_coef(struct hda_codec *codec) | 6075 | static void alc662_fill_coef(struct hda_codec *codec) |
6249 | { | 6076 | { |
6250 | int val, coef; | 6077 | int coef; |
6251 | 6078 | ||
6252 | coef = alc_get_coef0(codec); | 6079 | coef = alc_get_coef0(codec); |
6253 | 6080 | ||
6254 | switch (codec->vendor_id) { | 6081 | switch (codec->vendor_id) { |
6255 | case 0x10ec0662: | 6082 | case 0x10ec0662: |
6256 | if ((coef & 0x00f0) == 0x0030) { | 6083 | if ((coef & 0x00f0) == 0x0030) |
6257 | val = alc_read_coef_idx(codec, 0x4); /* EAPD Ctrl */ | 6084 | alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */ |
6258 | alc_write_coef_idx(codec, 0x4, val & ~(1<<10)); | ||
6259 | } | ||
6260 | break; | 6085 | break; |
6261 | case 0x10ec0272: | 6086 | case 0x10ec0272: |
6262 | case 0x10ec0273: | 6087 | case 0x10ec0273: |
@@ -6265,8 +6090,7 @@ static void alc662_fill_coef(struct hda_codec *codec) | |||
6265 | case 0x10ec0670: | 6090 | case 0x10ec0670: |
6266 | case 0x10ec0671: | 6091 | case 0x10ec0671: |
6267 | case 0x10ec0672: | 6092 | case 0x10ec0672: |
6268 | val = alc_read_coef_idx(codec, 0xd); /* EAPD Ctrl */ | 6093 | alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */ |
6269 | alc_write_coef_idx(codec, 0xd, val | (1<<14)); | ||
6270 | break; | 6094 | break; |
6271 | } | 6095 | } |
6272 | } | 6096 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 98cd1908c039..4f6413e01c13 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
35 | #include <sound/tlv.h> | ||
36 | #include "hda_codec.h" | 35 | #include "hda_codec.h" |
37 | #include "hda_local.h" | 36 | #include "hda_local.h" |
38 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
@@ -41,11 +40,6 @@ | |||
41 | #include "hda_generic.h" | 40 | #include "hda_generic.h" |
42 | 41 | ||
43 | enum { | 42 | enum { |
44 | STAC_VREF_EVENT = 8, | ||
45 | STAC_PWR_EVENT, | ||
46 | }; | ||
47 | |||
48 | enum { | ||
49 | STAC_REF, | 43 | STAC_REF, |
50 | STAC_9200_OQO, | 44 | STAC_9200_OQO, |
51 | STAC_9200_DELL_D21, | 45 | STAC_9200_DELL_D21, |
@@ -487,7 +481,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | |||
487 | 481 | ||
488 | /* update power bit per jack plug/unplug */ | 482 | /* update power bit per jack plug/unplug */ |
489 | static void jack_update_power(struct hda_codec *codec, | 483 | static void jack_update_power(struct hda_codec *codec, |
490 | struct hda_jack_tbl *jack) | 484 | struct hda_jack_callback *jack) |
491 | { | 485 | { |
492 | struct sigmatel_spec *spec = codec->spec; | 486 | struct sigmatel_spec *spec = codec->spec; |
493 | int i; | 487 | int i; |
@@ -495,9 +489,9 @@ static void jack_update_power(struct hda_codec *codec, | |||
495 | if (!spec->num_pwrs) | 489 | if (!spec->num_pwrs) |
496 | return; | 490 | return; |
497 | 491 | ||
498 | if (jack && jack->nid) { | 492 | if (jack && jack->tbl->nid) { |
499 | stac_toggle_power_map(codec, jack->nid, | 493 | stac_toggle_power_map(codec, jack->tbl->nid, |
500 | snd_hda_jack_detect(codec, jack->nid), | 494 | snd_hda_jack_detect(codec, jack->tbl->nid), |
501 | true); | 495 | true); |
502 | return; | 496 | return; |
503 | } | 497 | } |
@@ -505,42 +499,19 @@ static void jack_update_power(struct hda_codec *codec, | |||
505 | /* update all jacks */ | 499 | /* update all jacks */ |
506 | for (i = 0; i < spec->num_pwrs; i++) { | 500 | for (i = 0; i < spec->num_pwrs; i++) { |
507 | hda_nid_t nid = spec->pwr_nids[i]; | 501 | hda_nid_t nid = spec->pwr_nids[i]; |
508 | jack = snd_hda_jack_tbl_get(codec, nid); | 502 | if (!snd_hda_jack_tbl_get(codec, nid)) |
509 | if (!jack || !jack->action) | ||
510 | continue; | 503 | continue; |
511 | if (jack->action == STAC_PWR_EVENT || | 504 | stac_toggle_power_map(codec, nid, |
512 | jack->action <= HDA_GEN_LAST_EVENT) | 505 | snd_hda_jack_detect(codec, nid), |
513 | stac_toggle_power_map(codec, nid, | 506 | false); |
514 | snd_hda_jack_detect(codec, nid), | ||
515 | false); | ||
516 | } | 507 | } |
517 | 508 | ||
518 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, | 509 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, |
519 | spec->power_map_bits); | 510 | spec->power_map_bits); |
520 | } | 511 | } |
521 | 512 | ||
522 | static void stac_hp_automute(struct hda_codec *codec, | 513 | static void stac_vref_event(struct hda_codec *codec, |
523 | struct hda_jack_tbl *jack) | 514 | struct hda_jack_callback *event) |
524 | { | ||
525 | snd_hda_gen_hp_automute(codec, jack); | ||
526 | jack_update_power(codec, jack); | ||
527 | } | ||
528 | |||
529 | static void stac_line_automute(struct hda_codec *codec, | ||
530 | struct hda_jack_tbl *jack) | ||
531 | { | ||
532 | snd_hda_gen_line_automute(codec, jack); | ||
533 | jack_update_power(codec, jack); | ||
534 | } | ||
535 | |||
536 | static void stac_mic_autoswitch(struct hda_codec *codec, | ||
537 | struct hda_jack_tbl *jack) | ||
538 | { | ||
539 | snd_hda_gen_mic_autoswitch(codec, jack); | ||
540 | jack_update_power(codec, jack); | ||
541 | } | ||
542 | |||
543 | static void stac_vref_event(struct hda_codec *codec, struct hda_jack_tbl *event) | ||
544 | { | 515 | { |
545 | unsigned int data; | 516 | unsigned int data; |
546 | 517 | ||
@@ -563,13 +534,10 @@ static void stac_init_power_map(struct hda_codec *codec) | |||
563 | hda_nid_t nid = spec->pwr_nids[i]; | 534 | hda_nid_t nid = spec->pwr_nids[i]; |
564 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 535 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
565 | def_conf = get_defcfg_connect(def_conf); | 536 | def_conf = get_defcfg_connect(def_conf); |
566 | if (snd_hda_jack_tbl_get(codec, nid)) | ||
567 | continue; | ||
568 | if (def_conf == AC_JACK_PORT_COMPLEX && | 537 | if (def_conf == AC_JACK_PORT_COMPLEX && |
569 | spec->vref_mute_led_nid != nid && | 538 | spec->vref_mute_led_nid != nid && |
570 | is_jack_detectable(codec, nid)) { | 539 | is_jack_detectable(codec, nid)) { |
571 | snd_hda_jack_detect_enable_callback(codec, nid, | 540 | snd_hda_jack_detect_enable_callback(codec, nid, |
572 | STAC_PWR_EVENT, | ||
573 | jack_update_power); | 541 | jack_update_power); |
574 | } else { | 542 | } else { |
575 | if (def_conf == AC_JACK_PORT_NONE) | 543 | if (def_conf == AC_JACK_PORT_NONE) |
@@ -3020,7 +2988,7 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, | |||
3020 | const struct hda_fixup *fix, int action) | 2988 | const struct hda_fixup *fix, int action) |
3021 | { | 2989 | { |
3022 | struct sigmatel_spec *spec = codec->spec; | 2990 | struct sigmatel_spec *spec = codec->spec; |
3023 | struct hda_jack_tbl *jack; | 2991 | struct hda_jack_callback *jack; |
3024 | 2992 | ||
3025 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2993 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3026 | return; | 2994 | return; |
@@ -3028,11 +2996,9 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, | |||
3028 | /* Enable VREF power saving on GPIO1 detect */ | 2996 | /* Enable VREF power saving on GPIO1 detect */ |
3029 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 2997 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
3030 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 2998 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
3031 | snd_hda_jack_detect_enable_callback(codec, codec->afg, | 2999 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, |
3032 | STAC_VREF_EVENT, | 3000 | stac_vref_event); |
3033 | stac_vref_event); | 3001 | if (!IS_ERR(jack)) |
3034 | jack = snd_hda_jack_tbl_get(codec, codec->afg); | ||
3035 | if (jack) | ||
3036 | jack->private_data = 0x02; | 3002 | jack->private_data = 0x02; |
3037 | 3003 | ||
3038 | spec->gpio_mask |= 0x02; | 3004 | spec->gpio_mask |= 0x02; |
@@ -4044,7 +4010,7 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, | |||
4044 | const struct hda_fixup *fix, int action) | 4010 | const struct hda_fixup *fix, int action) |
4045 | { | 4011 | { |
4046 | struct sigmatel_spec *spec = codec->spec; | 4012 | struct sigmatel_spec *spec = codec->spec; |
4047 | struct hda_jack_tbl *jack; | 4013 | struct hda_jack_callback *jack; |
4048 | 4014 | ||
4049 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 4015 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
4050 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); | 4016 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); |
@@ -4052,11 +4018,9 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec, | |||
4052 | /* Enable unsol response for GPIO4/Dock HP connection */ | 4018 | /* Enable unsol response for GPIO4/Dock HP connection */ |
4053 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4019 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4054 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 4020 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4055 | snd_hda_jack_detect_enable_callback(codec, codec->afg, | 4021 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, |
4056 | STAC_VREF_EVENT, | 4022 | stac_vref_event); |
4057 | stac_vref_event); | 4023 | if (!IS_ERR(jack)) |
4058 | jack = snd_hda_jack_tbl_get(codec, codec->afg); | ||
4059 | if (jack) | ||
4060 | jack->private_data = 0x01; | 4024 | jack->private_data = 0x01; |
4061 | 4025 | ||
4062 | spec->gpio_dir = 0x0b; | 4026 | spec->gpio_dir = 0x0b; |
@@ -4219,17 +4183,11 @@ static int stac_parse_auto_config(struct hda_codec *codec) | |||
4219 | spec->gen.pcm_capture_hook = stac_capture_pcm_hook; | 4183 | spec->gen.pcm_capture_hook = stac_capture_pcm_hook; |
4220 | 4184 | ||
4221 | spec->gen.automute_hook = stac_update_outputs; | 4185 | spec->gen.automute_hook = stac_update_outputs; |
4222 | spec->gen.hp_automute_hook = stac_hp_automute; | ||
4223 | spec->gen.line_automute_hook = stac_line_automute; | ||
4224 | spec->gen.mic_autoswitch_hook = stac_mic_autoswitch; | ||
4225 | 4186 | ||
4226 | err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); | 4187 | err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); |
4227 | if (err < 0) | 4188 | if (err < 0) |
4228 | return err; | 4189 | return err; |
4229 | 4190 | ||
4230 | /* minimum value is actually mute */ | ||
4231 | spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
4232 | |||
4233 | /* setup analog beep controls */ | 4191 | /* setup analog beep controls */ |
4234 | if (spec->anabeep_nid > 0) { | 4192 | if (spec->anabeep_nid > 0) { |
4235 | err = stac_auto_create_beep_ctls(codec, | 4193 | err = stac_auto_create_beep_ctls(codec, |
@@ -4276,16 +4234,8 @@ static int stac_parse_auto_config(struct hda_codec *codec) | |||
4276 | return err; | 4234 | return err; |
4277 | } | 4235 | } |
4278 | 4236 | ||
4279 | return 0; | ||
4280 | } | ||
4281 | |||
4282 | static int stac_build_controls(struct hda_codec *codec) | ||
4283 | { | ||
4284 | int err = snd_hda_gen_build_controls(codec); | ||
4285 | |||
4286 | if (err < 0) | ||
4287 | return err; | ||
4288 | stac_init_power_map(codec); | 4237 | stac_init_power_map(codec); |
4238 | |||
4289 | return 0; | 4239 | return 0; |
4290 | } | 4240 | } |
4291 | 4241 | ||
@@ -4399,7 +4349,7 @@ static int stac_suspend(struct hda_codec *codec) | |||
4399 | #endif /* CONFIG_PM */ | 4349 | #endif /* CONFIG_PM */ |
4400 | 4350 | ||
4401 | static const struct hda_codec_ops stac_patch_ops = { | 4351 | static const struct hda_codec_ops stac_patch_ops = { |
4402 | .build_controls = stac_build_controls, | 4352 | .build_controls = snd_hda_gen_build_controls, |
4403 | .build_pcms = snd_hda_gen_build_pcms, | 4353 | .build_pcms = snd_hda_gen_build_pcms, |
4404 | .init = stac_init, | 4354 | .init = stac_init, |
4405 | .free = stac_free, | 4355 | .free = stac_free, |
@@ -4420,6 +4370,7 @@ static int alloc_stac_spec(struct hda_codec *codec) | |||
4420 | snd_hda_gen_spec_init(&spec->gen); | 4370 | snd_hda_gen_spec_init(&spec->gen); |
4421 | codec->spec = spec; | 4371 | codec->spec = spec; |
4422 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ | 4372 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ |
4373 | spec->gen.dac_min_mute = true; | ||
4423 | return 0; | 4374 | return 0; |
4424 | } | 4375 | } |
4425 | 4376 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 778166259b3e..6c206b6c8d65 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -118,7 +118,6 @@ static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, | |||
118 | struct hda_codec *codec, | 118 | struct hda_codec *codec, |
119 | struct snd_pcm_substream *substream, | 119 | struct snd_pcm_substream *substream, |
120 | int action); | 120 | int action); |
121 | static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl); | ||
122 | 121 | ||
123 | static struct via_spec *via_new_spec(struct hda_codec *codec) | 122 | static struct via_spec *via_new_spec(struct hda_codec *codec) |
124 | { | 123 | { |
@@ -575,25 +574,12 @@ static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = { | |||
575 | {} /* terminator */ | 574 | {} /* terminator */ |
576 | }; | 575 | }; |
577 | 576 | ||
578 | static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl) | 577 | static void via_jack_powerstate_event(struct hda_codec *codec, |
578 | struct hda_jack_callback *tbl) | ||
579 | { | 579 | { |
580 | set_widgets_power_state(codec); | 580 | set_widgets_power_state(codec); |
581 | snd_hda_gen_hp_automute(codec, tbl); | ||
582 | } | 581 | } |
583 | 582 | ||
584 | static void via_line_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl) | ||
585 | { | ||
586 | set_widgets_power_state(codec); | ||
587 | snd_hda_gen_line_automute(codec, tbl); | ||
588 | } | ||
589 | |||
590 | static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl) | ||
591 | { | ||
592 | set_widgets_power_state(codec); | ||
593 | } | ||
594 | |||
595 | #define VIA_JACK_EVENT (HDA_GEN_LAST_EVENT + 1) | ||
596 | |||
597 | static void via_set_jack_unsol_events(struct hda_codec *codec) | 583 | static void via_set_jack_unsol_events(struct hda_codec *codec) |
598 | { | 584 | { |
599 | struct via_spec *spec = codec->spec; | 585 | struct via_spec *spec = codec->spec; |
@@ -601,25 +587,17 @@ static void via_set_jack_unsol_events(struct hda_codec *codec) | |||
601 | hda_nid_t pin; | 587 | hda_nid_t pin; |
602 | int i; | 588 | int i; |
603 | 589 | ||
604 | spec->gen.hp_automute_hook = via_hp_automute; | ||
605 | if (cfg->speaker_pins[0]) | ||
606 | spec->gen.line_automute_hook = via_line_automute; | ||
607 | |||
608 | for (i = 0; i < cfg->line_outs; i++) { | 590 | for (i = 0; i < cfg->line_outs; i++) { |
609 | pin = cfg->line_out_pins[i]; | 591 | pin = cfg->line_out_pins[i]; |
610 | if (pin && !snd_hda_jack_tbl_get(codec, pin) && | 592 | if (pin && is_jack_detectable(codec, pin)) |
611 | is_jack_detectable(codec, pin)) | ||
612 | snd_hda_jack_detect_enable_callback(codec, pin, | 593 | snd_hda_jack_detect_enable_callback(codec, pin, |
613 | VIA_JACK_EVENT, | ||
614 | via_jack_powerstate_event); | 594 | via_jack_powerstate_event); |
615 | } | 595 | } |
616 | 596 | ||
617 | for (i = 0; i < cfg->num_inputs; i++) { | 597 | for (i = 0; i < cfg->num_inputs; i++) { |
618 | pin = cfg->line_out_pins[i]; | 598 | pin = cfg->line_out_pins[i]; |
619 | if (pin && !snd_hda_jack_tbl_get(codec, pin) && | 599 | if (pin && is_jack_detectable(codec, pin)) |
620 | is_jack_detectable(codec, pin)) | ||
621 | snd_hda_jack_detect_enable_callback(codec, pin, | 600 | snd_hda_jack_detect_enable_callback(codec, pin, |
622 | VIA_JACK_EVENT, | ||
623 | via_jack_powerstate_event); | 601 | via_jack_powerstate_event); |
624 | } | 602 | } |
625 | } | 603 | } |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 87f7fc41d4f2..206ed2cbcef9 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2528,7 +2528,7 @@ static int snd_ice1712_free(struct snd_ice1712 *ice) | |||
2528 | if (!ice->port) | 2528 | if (!ice->port) |
2529 | goto __hw_end; | 2529 | goto __hw_end; |
2530 | /* mask all interrupts */ | 2530 | /* mask all interrupts */ |
2531 | outb(0xc0, ICEMT(ice, IRQ)); | 2531 | outb(ICE1712_MULTI_CAPTURE | ICE1712_MULTI_PLAYBACK, ICEMT(ice, IRQ)); |
2532 | outb(0xff, ICEREG(ice, IRQMASK)); | 2532 | outb(0xff, ICEREG(ice, IRQMASK)); |
2533 | /* --- */ | 2533 | /* --- */ |
2534 | __hw_end: | 2534 | __hw_end: |
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index a671f0865f71..601315a1f58f 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c | |||
@@ -279,7 +279,6 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream | |||
279 | { | 279 | { |
280 | struct lx6464es *chip = snd_pcm_substream_chip(substream); | 280 | struct lx6464es *chip = snd_pcm_substream_chip(substream); |
281 | snd_pcm_uframes_t pos; | 281 | snd_pcm_uframes_t pos; |
282 | unsigned long flags; | ||
283 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 282 | int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
284 | 283 | ||
285 | struct lx_stream *lx_stream = is_capture ? &chip->capture_stream : | 284 | struct lx_stream *lx_stream = is_capture ? &chip->capture_stream : |
@@ -287,9 +286,9 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream | |||
287 | 286 | ||
288 | dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n"); | 287 | dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n"); |
289 | 288 | ||
290 | spin_lock_irqsave(&chip->lock, flags); | 289 | mutex_lock(&chip->lock); |
291 | pos = lx_stream->frame_pos * substream->runtime->period_size; | 290 | pos = lx_stream->frame_pos * substream->runtime->period_size; |
292 | spin_unlock_irqrestore(&chip->lock, flags); | 291 | mutex_unlock(&chip->lock); |
293 | 292 | ||
294 | dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos); | 293 | dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos); |
295 | return pos; | 294 | return pos; |
@@ -485,8 +484,8 @@ static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream) | |||
485 | 484 | ||
486 | } | 485 | } |
487 | 486 | ||
488 | static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip, | 487 | static void lx_trigger_dispatch_stream(struct lx6464es *chip, |
489 | struct lx_stream *lx_stream) | 488 | struct lx_stream *lx_stream) |
490 | { | 489 | { |
491 | switch (lx_stream->status) { | 490 | switch (lx_stream->status) { |
492 | case LX_STREAM_STATUS_SCHEDULE_RUN: | 491 | case LX_STREAM_STATUS_SCHEDULE_RUN: |
@@ -502,24 +501,12 @@ static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip, | |||
502 | } | 501 | } |
503 | } | 502 | } |
504 | 503 | ||
505 | static void lx_trigger_tasklet(unsigned long data) | ||
506 | { | ||
507 | struct lx6464es *chip = (struct lx6464es *)data; | ||
508 | unsigned long flags; | ||
509 | |||
510 | dev_dbg(chip->card->dev, "->lx_trigger_tasklet\n"); | ||
511 | |||
512 | spin_lock_irqsave(&chip->lock, flags); | ||
513 | lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream); | ||
514 | lx_trigger_tasklet_dispatch_stream(chip, &chip->playback_stream); | ||
515 | spin_unlock_irqrestore(&chip->lock, flags); | ||
516 | } | ||
517 | |||
518 | static int lx_pcm_trigger_dispatch(struct lx6464es *chip, | 504 | static int lx_pcm_trigger_dispatch(struct lx6464es *chip, |
519 | struct lx_stream *lx_stream, int cmd) | 505 | struct lx_stream *lx_stream, int cmd) |
520 | { | 506 | { |
521 | int err = 0; | 507 | int err = 0; |
522 | 508 | ||
509 | mutex_lock(&chip->lock); | ||
523 | switch (cmd) { | 510 | switch (cmd) { |
524 | case SNDRV_PCM_TRIGGER_START: | 511 | case SNDRV_PCM_TRIGGER_START: |
525 | lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN; | 512 | lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN; |
@@ -533,9 +520,12 @@ static int lx_pcm_trigger_dispatch(struct lx6464es *chip, | |||
533 | err = -EINVAL; | 520 | err = -EINVAL; |
534 | goto exit; | 521 | goto exit; |
535 | } | 522 | } |
536 | tasklet_schedule(&chip->trigger_tasklet); | 523 | |
524 | lx_trigger_dispatch_stream(chip, &chip->capture_stream); | ||
525 | lx_trigger_dispatch_stream(chip, &chip->playback_stream); | ||
537 | 526 | ||
538 | exit: | 527 | exit: |
528 | mutex_unlock(&chip->lock); | ||
539 | return err; | 529 | return err; |
540 | } | 530 | } |
541 | 531 | ||
@@ -861,6 +851,7 @@ static int lx_pcm_create(struct lx6464es *chip) | |||
861 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture); | 851 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture); |
862 | 852 | ||
863 | pcm->info_flags = 0; | 853 | pcm->info_flags = 0; |
854 | pcm->nonatomic = true; | ||
864 | strcpy(pcm->name, card_name); | 855 | strcpy(pcm->name, card_name); |
865 | 856 | ||
866 | err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 857 | err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
@@ -1009,15 +1000,9 @@ static int snd_lx6464es_create(struct snd_card *card, | |||
1009 | chip->irq = -1; | 1000 | chip->irq = -1; |
1010 | 1001 | ||
1011 | /* initialize synchronization structs */ | 1002 | /* initialize synchronization structs */ |
1012 | spin_lock_init(&chip->lock); | 1003 | mutex_init(&chip->lock); |
1013 | spin_lock_init(&chip->msg_lock); | 1004 | mutex_init(&chip->msg_lock); |
1014 | mutex_init(&chip->setup_mutex); | 1005 | mutex_init(&chip->setup_mutex); |
1015 | tasklet_init(&chip->trigger_tasklet, lx_trigger_tasklet, | ||
1016 | (unsigned long)chip); | ||
1017 | tasklet_init(&chip->tasklet_capture, lx_tasklet_capture, | ||
1018 | (unsigned long)chip); | ||
1019 | tasklet_init(&chip->tasklet_playback, lx_tasklet_playback, | ||
1020 | (unsigned long)chip); | ||
1021 | 1006 | ||
1022 | /* request resources */ | 1007 | /* request resources */ |
1023 | err = pci_request_regions(pci, card_name); | 1008 | err = pci_request_regions(pci, card_name); |
@@ -1032,8 +1017,8 @@ static int snd_lx6464es_create(struct snd_card *card, | |||
1032 | /* dsp port */ | 1017 | /* dsp port */ |
1033 | chip->port_dsp_bar = pci_ioremap_bar(pci, 2); | 1018 | chip->port_dsp_bar = pci_ioremap_bar(pci, 2); |
1034 | 1019 | ||
1035 | err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED, | 1020 | err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq, |
1036 | KBUILD_MODNAME, chip); | 1021 | IRQF_SHARED, KBUILD_MODNAME, chip); |
1037 | if (err) { | 1022 | if (err) { |
1038 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); | 1023 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); |
1039 | goto request_irq_failed; | 1024 | goto request_irq_failed; |
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h index 6792eda9c9a5..1bec187d772f 100644 --- a/sound/pci/lx6464es/lx6464es.h +++ b/sound/pci/lx6464es/lx6464es.h | |||
@@ -71,14 +71,10 @@ struct lx6464es { | |||
71 | 71 | ||
72 | u8 mac_address[6]; | 72 | u8 mac_address[6]; |
73 | 73 | ||
74 | spinlock_t lock; /* interrupt spinlock */ | 74 | struct mutex lock; /* interrupt lock */ |
75 | struct mutex setup_mutex; /* mutex used in hw_params, open | 75 | struct mutex setup_mutex; /* mutex used in hw_params, open |
76 | * and close */ | 76 | * and close */ |
77 | 77 | ||
78 | struct tasklet_struct trigger_tasklet; /* trigger tasklet */ | ||
79 | struct tasklet_struct tasklet_capture; | ||
80 | struct tasklet_struct tasklet_playback; | ||
81 | |||
82 | /* ports */ | 78 | /* ports */ |
83 | unsigned long port_plx; /* io port (size=256) */ | 79 | unsigned long port_plx; /* io port (size=256) */ |
84 | void __iomem *port_plx_remapped; /* remapped plx port */ | 80 | void __iomem *port_plx_remapped; /* remapped plx port */ |
@@ -87,8 +83,9 @@ struct lx6464es { | |||
87 | * size=8K) */ | 83 | * size=8K) */ |
88 | 84 | ||
89 | /* messaging */ | 85 | /* messaging */ |
90 | spinlock_t msg_lock; /* message spinlock */ | 86 | struct mutex msg_lock; /* message lock */ |
91 | struct lx_rmh rmh; | 87 | struct lx_rmh rmh; |
88 | u32 irqsrc; | ||
92 | 89 | ||
93 | /* configuration */ | 90 | /* configuration */ |
94 | uint freq_ratio : 2; | 91 | uint freq_ratio : 2; |
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index e8f38e5df10a..f3d62020ef66 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c | |||
@@ -332,27 +332,25 @@ polling_successful: | |||
332 | int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version) | 332 | int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version) |
333 | { | 333 | { |
334 | u16 ret; | 334 | u16 ret; |
335 | unsigned long flags; | ||
336 | 335 | ||
337 | spin_lock_irqsave(&chip->msg_lock, flags); | 336 | mutex_lock(&chip->msg_lock); |
338 | 337 | ||
339 | lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); | 338 | lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); |
340 | ret = lx_message_send_atomic(chip, &chip->rmh); | 339 | ret = lx_message_send_atomic(chip, &chip->rmh); |
341 | 340 | ||
342 | *rdsp_version = chip->rmh.stat[1]; | 341 | *rdsp_version = chip->rmh.stat[1]; |
343 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 342 | mutex_unlock(&chip->msg_lock); |
344 | return ret; | 343 | return ret; |
345 | } | 344 | } |
346 | 345 | ||
347 | int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) | 346 | int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) |
348 | { | 347 | { |
349 | u16 ret = 0; | 348 | u16 ret = 0; |
350 | unsigned long flags; | ||
351 | u32 freq_raw = 0; | 349 | u32 freq_raw = 0; |
352 | u32 freq = 0; | 350 | u32 freq = 0; |
353 | u32 frequency = 0; | 351 | u32 frequency = 0; |
354 | 352 | ||
355 | spin_lock_irqsave(&chip->msg_lock, flags); | 353 | mutex_lock(&chip->msg_lock); |
356 | 354 | ||
357 | lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); | 355 | lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); |
358 | ret = lx_message_send_atomic(chip, &chip->rmh); | 356 | ret = lx_message_send_atomic(chip, &chip->rmh); |
@@ -370,7 +368,7 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) | |||
370 | frequency = 48000; | 368 | frequency = 48000; |
371 | } | 369 | } |
372 | 370 | ||
373 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 371 | mutex_unlock(&chip->msg_lock); |
374 | 372 | ||
375 | *rfreq = frequency * chip->freq_ratio; | 373 | *rfreq = frequency * chip->freq_ratio; |
376 | 374 | ||
@@ -398,25 +396,23 @@ int lx_dsp_get_mac(struct lx6464es *chip) | |||
398 | 396 | ||
399 | int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran) | 397 | int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran) |
400 | { | 398 | { |
401 | unsigned long flags; | ||
402 | int ret; | 399 | int ret; |
403 | 400 | ||
404 | spin_lock_irqsave(&chip->msg_lock, flags); | 401 | mutex_lock(&chip->msg_lock); |
405 | 402 | ||
406 | lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY); | 403 | lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY); |
407 | chip->rmh.cmd[0] |= gran; | 404 | chip->rmh.cmd[0] |= gran; |
408 | 405 | ||
409 | ret = lx_message_send_atomic(chip, &chip->rmh); | 406 | ret = lx_message_send_atomic(chip, &chip->rmh); |
410 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 407 | mutex_unlock(&chip->msg_lock); |
411 | return ret; | 408 | return ret; |
412 | } | 409 | } |
413 | 410 | ||
414 | int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) | 411 | int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) |
415 | { | 412 | { |
416 | unsigned long flags; | ||
417 | int ret; | 413 | int ret; |
418 | 414 | ||
419 | spin_lock_irqsave(&chip->msg_lock, flags); | 415 | mutex_lock(&chip->msg_lock); |
420 | 416 | ||
421 | lx_message_init(&chip->rmh, CMD_04_GET_EVENT); | 417 | lx_message_init(&chip->rmh, CMD_04_GET_EVENT); |
422 | chip->rmh.stat_len = 9; /* we don't necessarily need the full length */ | 418 | chip->rmh.stat_len = 9; /* we don't necessarily need the full length */ |
@@ -426,7 +422,7 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) | |||
426 | if (!ret) | 422 | if (!ret) |
427 | memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32)); | 423 | memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32)); |
428 | 424 | ||
429 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 425 | mutex_unlock(&chip->msg_lock); |
430 | return ret; | 426 | return ret; |
431 | } | 427 | } |
432 | 428 | ||
@@ -440,18 +436,16 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, | |||
440 | int channels) | 436 | int channels) |
441 | { | 437 | { |
442 | int err; | 438 | int err; |
443 | unsigned long flags; | ||
444 | |||
445 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 439 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
446 | 440 | ||
447 | spin_lock_irqsave(&chip->msg_lock, flags); | 441 | mutex_lock(&chip->msg_lock); |
448 | lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE); | 442 | lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE); |
449 | 443 | ||
450 | chip->rmh.cmd[0] |= pipe_cmd; | 444 | chip->rmh.cmd[0] |= pipe_cmd; |
451 | chip->rmh.cmd[0] |= channels; | 445 | chip->rmh.cmd[0] |= channels; |
452 | 446 | ||
453 | err = lx_message_send_atomic(chip, &chip->rmh); | 447 | err = lx_message_send_atomic(chip, &chip->rmh); |
454 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 448 | mutex_unlock(&chip->msg_lock); |
455 | 449 | ||
456 | if (err != 0) | 450 | if (err != 0) |
457 | dev_err(chip->card->dev, "could not allocate pipe\n"); | 451 | dev_err(chip->card->dev, "could not allocate pipe\n"); |
@@ -462,17 +456,15 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, | |||
462 | int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture) | 456 | int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture) |
463 | { | 457 | { |
464 | int err; | 458 | int err; |
465 | unsigned long flags; | ||
466 | |||
467 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 459 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
468 | 460 | ||
469 | spin_lock_irqsave(&chip->msg_lock, flags); | 461 | mutex_lock(&chip->msg_lock); |
470 | lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE); | 462 | lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE); |
471 | 463 | ||
472 | chip->rmh.cmd[0] |= pipe_cmd; | 464 | chip->rmh.cmd[0] |= pipe_cmd; |
473 | 465 | ||
474 | err = lx_message_send_atomic(chip, &chip->rmh); | 466 | err = lx_message_send_atomic(chip, &chip->rmh); |
475 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 467 | mutex_unlock(&chip->msg_lock); |
476 | 468 | ||
477 | return err; | 469 | return err; |
478 | } | 470 | } |
@@ -481,8 +473,6 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
481 | u32 *r_needed, u32 *r_freed, u32 *size_array) | 473 | u32 *r_needed, u32 *r_freed, u32 *size_array) |
482 | { | 474 | { |
483 | int err; | 475 | int err; |
484 | unsigned long flags; | ||
485 | |||
486 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 476 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
487 | 477 | ||
488 | #ifdef CONFIG_SND_DEBUG | 478 | #ifdef CONFIG_SND_DEBUG |
@@ -493,7 +483,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
493 | *r_needed = 0; | 483 | *r_needed = 0; |
494 | *r_freed = 0; | 484 | *r_freed = 0; |
495 | 485 | ||
496 | spin_lock_irqsave(&chip->msg_lock, flags); | 486 | mutex_lock(&chip->msg_lock); |
497 | lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS); | 487 | lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS); |
498 | 488 | ||
499 | chip->rmh.cmd[0] |= pipe_cmd; | 489 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -527,7 +517,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
527 | } | 517 | } |
528 | } | 518 | } |
529 | 519 | ||
530 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 520 | mutex_unlock(&chip->msg_lock); |
531 | return err; | 521 | return err; |
532 | } | 522 | } |
533 | 523 | ||
@@ -535,36 +525,32 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, | |||
535 | int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture) | 525 | int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture) |
536 | { | 526 | { |
537 | int err; | 527 | int err; |
538 | unsigned long flags; | ||
539 | |||
540 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 528 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
541 | 529 | ||
542 | spin_lock_irqsave(&chip->msg_lock, flags); | 530 | mutex_lock(&chip->msg_lock); |
543 | lx_message_init(&chip->rmh, CMD_09_STOP_PIPE); | 531 | lx_message_init(&chip->rmh, CMD_09_STOP_PIPE); |
544 | 532 | ||
545 | chip->rmh.cmd[0] |= pipe_cmd; | 533 | chip->rmh.cmd[0] |= pipe_cmd; |
546 | 534 | ||
547 | err = lx_message_send_atomic(chip, &chip->rmh); | 535 | err = lx_message_send_atomic(chip, &chip->rmh); |
548 | 536 | ||
549 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 537 | mutex_unlock(&chip->msg_lock); |
550 | return err; | 538 | return err; |
551 | } | 539 | } |
552 | 540 | ||
553 | static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture) | 541 | static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture) |
554 | { | 542 | { |
555 | int err; | 543 | int err; |
556 | unsigned long flags; | ||
557 | |||
558 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 544 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
559 | 545 | ||
560 | spin_lock_irqsave(&chip->msg_lock, flags); | 546 | mutex_lock(&chip->msg_lock); |
561 | lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE); | 547 | lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE); |
562 | 548 | ||
563 | chip->rmh.cmd[0] |= pipe_cmd; | 549 | chip->rmh.cmd[0] |= pipe_cmd; |
564 | 550 | ||
565 | err = lx_message_send_atomic(chip, &chip->rmh); | 551 | err = lx_message_send_atomic(chip, &chip->rmh); |
566 | 552 | ||
567 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 553 | mutex_unlock(&chip->msg_lock); |
568 | return err; | 554 | return err; |
569 | } | 555 | } |
570 | 556 | ||
@@ -600,11 +586,9 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, | |||
600 | u64 *rsample_count) | 586 | u64 *rsample_count) |
601 | { | 587 | { |
602 | int err; | 588 | int err; |
603 | unsigned long flags; | ||
604 | |||
605 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 589 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
606 | 590 | ||
607 | spin_lock_irqsave(&chip->msg_lock, flags); | 591 | mutex_lock(&chip->msg_lock); |
608 | lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); | 592 | lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); |
609 | 593 | ||
610 | chip->rmh.cmd[0] |= pipe_cmd; | 594 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -621,18 +605,16 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, | |||
621 | + chip->rmh.stat[1]; /* lo part */ | 605 | + chip->rmh.stat[1]; /* lo part */ |
622 | } | 606 | } |
623 | 607 | ||
624 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 608 | mutex_unlock(&chip->msg_lock); |
625 | return err; | 609 | return err; |
626 | } | 610 | } |
627 | 611 | ||
628 | int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) | 612 | int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) |
629 | { | 613 | { |
630 | int err; | 614 | int err; |
631 | unsigned long flags; | ||
632 | |||
633 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 615 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
634 | 616 | ||
635 | spin_lock_irqsave(&chip->msg_lock, flags); | 617 | mutex_lock(&chip->msg_lock); |
636 | lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); | 618 | lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); |
637 | 619 | ||
638 | chip->rmh.cmd[0] |= pipe_cmd; | 620 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -644,7 +626,7 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) | |||
644 | else | 626 | else |
645 | *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F; | 627 | *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F; |
646 | 628 | ||
647 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 629 | mutex_unlock(&chip->msg_lock); |
648 | return err; | 630 | return err; |
649 | } | 631 | } |
650 | 632 | ||
@@ -686,18 +668,16 @@ int lx_stream_set_state(struct lx6464es *chip, u32 pipe, | |||
686 | int is_capture, enum stream_state_t state) | 668 | int is_capture, enum stream_state_t state) |
687 | { | 669 | { |
688 | int err; | 670 | int err; |
689 | unsigned long flags; | ||
690 | |||
691 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 671 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
692 | 672 | ||
693 | spin_lock_irqsave(&chip->msg_lock, flags); | 673 | mutex_lock(&chip->msg_lock); |
694 | lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE); | 674 | lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE); |
695 | 675 | ||
696 | chip->rmh.cmd[0] |= pipe_cmd; | 676 | chip->rmh.cmd[0] |= pipe_cmd; |
697 | chip->rmh.cmd[0] |= state; | 677 | chip->rmh.cmd[0] |= state; |
698 | 678 | ||
699 | err = lx_message_send_atomic(chip, &chip->rmh); | 679 | err = lx_message_send_atomic(chip, &chip->rmh); |
700 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 680 | mutex_unlock(&chip->msg_lock); |
701 | 681 | ||
702 | return err; | 682 | return err; |
703 | } | 683 | } |
@@ -706,17 +686,14 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, | |||
706 | u32 pipe, int is_capture) | 686 | u32 pipe, int is_capture) |
707 | { | 687 | { |
708 | int err; | 688 | int err; |
709 | unsigned long flags; | ||
710 | |||
711 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 689 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
712 | |||
713 | u32 channels = runtime->channels; | 690 | u32 channels = runtime->channels; |
714 | 691 | ||
715 | if (runtime->channels != channels) | 692 | if (runtime->channels != channels) |
716 | dev_err(chip->card->dev, "channel count mismatch: %d vs %d", | 693 | dev_err(chip->card->dev, "channel count mismatch: %d vs %d", |
717 | runtime->channels, channels); | 694 | runtime->channels, channels); |
718 | 695 | ||
719 | spin_lock_irqsave(&chip->msg_lock, flags); | 696 | mutex_lock(&chip->msg_lock); |
720 | lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM); | 697 | lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM); |
721 | 698 | ||
722 | chip->rmh.cmd[0] |= pipe_cmd; | 699 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -732,7 +709,7 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, | |||
732 | chip->rmh.cmd[0] |= channels-1; | 709 | chip->rmh.cmd[0] |= channels-1; |
733 | 710 | ||
734 | err = lx_message_send_atomic(chip, &chip->rmh); | 711 | err = lx_message_send_atomic(chip, &chip->rmh); |
735 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 712 | mutex_unlock(&chip->msg_lock); |
736 | 713 | ||
737 | return err; | 714 | return err; |
738 | } | 715 | } |
@@ -741,11 +718,9 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, | |||
741 | int *rstate) | 718 | int *rstate) |
742 | { | 719 | { |
743 | int err; | 720 | int err; |
744 | unsigned long flags; | ||
745 | |||
746 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 721 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
747 | 722 | ||
748 | spin_lock_irqsave(&chip->msg_lock, flags); | 723 | mutex_lock(&chip->msg_lock); |
749 | lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); | 724 | lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); |
750 | 725 | ||
751 | chip->rmh.cmd[0] |= pipe_cmd; | 726 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -754,7 +729,7 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, | |||
754 | 729 | ||
755 | *rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE; | 730 | *rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE; |
756 | 731 | ||
757 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 732 | mutex_unlock(&chip->msg_lock); |
758 | return err; | 733 | return err; |
759 | } | 734 | } |
760 | 735 | ||
@@ -762,11 +737,9 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, | |||
762 | u64 *r_bytepos) | 737 | u64 *r_bytepos) |
763 | { | 738 | { |
764 | int err; | 739 | int err; |
765 | unsigned long flags; | ||
766 | |||
767 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 740 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
768 | 741 | ||
769 | spin_lock_irqsave(&chip->msg_lock, flags); | 742 | mutex_lock(&chip->msg_lock); |
770 | lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); | 743 | lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); |
771 | 744 | ||
772 | chip->rmh.cmd[0] |= pipe_cmd; | 745 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -777,7 +750,7 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, | |||
777 | << 32) /* hi part */ | 750 | << 32) /* hi part */ |
778 | + chip->rmh.stat[1]; /* lo part */ | 751 | + chip->rmh.stat[1]; /* lo part */ |
779 | 752 | ||
780 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 753 | mutex_unlock(&chip->msg_lock); |
781 | return err; | 754 | return err; |
782 | } | 755 | } |
783 | 756 | ||
@@ -787,11 +760,9 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, | |||
787 | u32 *r_buffer_index) | 760 | u32 *r_buffer_index) |
788 | { | 761 | { |
789 | int err; | 762 | int err; |
790 | unsigned long flags; | ||
791 | |||
792 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 763 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
793 | 764 | ||
794 | spin_lock_irqsave(&chip->msg_lock, flags); | 765 | mutex_lock(&chip->msg_lock); |
795 | lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER); | 766 | lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER); |
796 | 767 | ||
797 | chip->rmh.cmd[0] |= pipe_cmd; | 768 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -828,7 +799,7 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, | |||
828 | "lx_buffer_give EB_CMD_REFUSED\n"); | 799 | "lx_buffer_give EB_CMD_REFUSED\n"); |
829 | 800 | ||
830 | done: | 801 | done: |
831 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 802 | mutex_unlock(&chip->msg_lock); |
832 | return err; | 803 | return err; |
833 | } | 804 | } |
834 | 805 | ||
@@ -836,11 +807,9 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, | |||
836 | u32 *r_buffer_size) | 807 | u32 *r_buffer_size) |
837 | { | 808 | { |
838 | int err; | 809 | int err; |
839 | unsigned long flags; | ||
840 | |||
841 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 810 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
842 | 811 | ||
843 | spin_lock_irqsave(&chip->msg_lock, flags); | 812 | mutex_lock(&chip->msg_lock); |
844 | lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); | 813 | lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); |
845 | 814 | ||
846 | chip->rmh.cmd[0] |= pipe_cmd; | 815 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -852,7 +821,7 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, | |||
852 | if (err == 0) | 821 | if (err == 0) |
853 | *r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE; | 822 | *r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE; |
854 | 823 | ||
855 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 824 | mutex_unlock(&chip->msg_lock); |
856 | return err; | 825 | return err; |
857 | } | 826 | } |
858 | 827 | ||
@@ -860,11 +829,9 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, | |||
860 | u32 buffer_index) | 829 | u32 buffer_index) |
861 | { | 830 | { |
862 | int err; | 831 | int err; |
863 | unsigned long flags; | ||
864 | |||
865 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); | 832 | u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); |
866 | 833 | ||
867 | spin_lock_irqsave(&chip->msg_lock, flags); | 834 | mutex_lock(&chip->msg_lock); |
868 | lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); | 835 | lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); |
869 | 836 | ||
870 | chip->rmh.cmd[0] |= pipe_cmd; | 837 | chip->rmh.cmd[0] |= pipe_cmd; |
@@ -872,7 +839,7 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, | |||
872 | 839 | ||
873 | err = lx_message_send_atomic(chip, &chip->rmh); | 840 | err = lx_message_send_atomic(chip, &chip->rmh); |
874 | 841 | ||
875 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 842 | mutex_unlock(&chip->msg_lock); |
876 | return err; | 843 | return err; |
877 | } | 844 | } |
878 | 845 | ||
@@ -885,12 +852,10 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, | |||
885 | int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) | 852 | int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) |
886 | { | 853 | { |
887 | int err; | 854 | int err; |
888 | unsigned long flags; | ||
889 | |||
890 | /* bit set to 1: channel muted */ | 855 | /* bit set to 1: channel muted */ |
891 | u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU; | 856 | u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU; |
892 | 857 | ||
893 | spin_lock_irqsave(&chip->msg_lock, flags); | 858 | mutex_lock(&chip->msg_lock); |
894 | lx_message_init(&chip->rmh, CMD_0D_SET_MUTE); | 859 | lx_message_init(&chip->rmh, CMD_0D_SET_MUTE); |
895 | 860 | ||
896 | chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0); | 861 | chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0); |
@@ -904,7 +869,7 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) | |||
904 | 869 | ||
905 | err = lx_message_send_atomic(chip, &chip->rmh); | 870 | err = lx_message_send_atomic(chip, &chip->rmh); |
906 | 871 | ||
907 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 872 | mutex_unlock(&chip->msg_lock); |
908 | return err; | 873 | return err; |
909 | } | 874 | } |
910 | 875 | ||
@@ -931,10 +896,9 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, | |||
931 | u32 *r_levels) | 896 | u32 *r_levels) |
932 | { | 897 | { |
933 | int err = 0; | 898 | int err = 0; |
934 | unsigned long flags; | ||
935 | int i; | 899 | int i; |
936 | spin_lock_irqsave(&chip->msg_lock, flags); | ||
937 | 900 | ||
901 | mutex_lock(&chip->msg_lock); | ||
938 | for (i = 0; i < channels; i += 4) { | 902 | for (i = 0; i < channels; i += 4) { |
939 | u32 s0, s1, s2, s3; | 903 | u32 s0, s1, s2, s3; |
940 | 904 | ||
@@ -959,7 +923,7 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, | |||
959 | r_levels += 4; | 923 | r_levels += 4; |
960 | } | 924 | } |
961 | 925 | ||
962 | spin_unlock_irqrestore(&chip->msg_lock, flags); | 926 | mutex_unlock(&chip->msg_lock); |
963 | return err; | 927 | return err; |
964 | } | 928 | } |
965 | 929 | ||
@@ -1075,7 +1039,6 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, | |||
1075 | struct snd_pcm_substream *substream = lx_stream->stream; | 1039 | struct snd_pcm_substream *substream = lx_stream->stream; |
1076 | const unsigned int is_capture = lx_stream->is_capture; | 1040 | const unsigned int is_capture = lx_stream->is_capture; |
1077 | int err; | 1041 | int err; |
1078 | unsigned long flags; | ||
1079 | 1042 | ||
1080 | const u32 channels = substream->runtime->channels; | 1043 | const u32 channels = substream->runtime->channels; |
1081 | const u32 bytes_per_frame = channels * 3; | 1044 | const u32 bytes_per_frame = channels * 3; |
@@ -1095,7 +1058,7 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, | |||
1095 | 1058 | ||
1096 | dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n"); | 1059 | dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n"); |
1097 | 1060 | ||
1098 | spin_lock_irqsave(&chip->lock, flags); | 1061 | mutex_lock(&chip->lock); |
1099 | 1062 | ||
1100 | err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); | 1063 | err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); |
1101 | dev_dbg(chip->card->dev, | 1064 | dev_dbg(chip->card->dev, |
@@ -1109,85 +1072,28 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip, | |||
1109 | buffer_index, (unsigned long)buf, period_bytes); | 1072 | buffer_index, (unsigned long)buf, period_bytes); |
1110 | 1073 | ||
1111 | lx_stream->frame_pos = next_pos; | 1074 | lx_stream->frame_pos = next_pos; |
1112 | spin_unlock_irqrestore(&chip->lock, flags); | 1075 | mutex_unlock(&chip->lock); |
1113 | 1076 | ||
1114 | return err; | 1077 | return err; |
1115 | } | 1078 | } |
1116 | 1079 | ||
1117 | void lx_tasklet_playback(unsigned long data) | ||
1118 | { | ||
1119 | struct lx6464es *chip = (struct lx6464es *)data; | ||
1120 | struct lx_stream *lx_stream = &chip->playback_stream; | ||
1121 | int err; | ||
1122 | |||
1123 | dev_dbg(chip->card->dev, "->lx_tasklet_playback\n"); | ||
1124 | |||
1125 | err = lx_interrupt_request_new_buffer(chip, lx_stream); | ||
1126 | if (err < 0) | ||
1127 | dev_err(chip->card->dev, | ||
1128 | "cannot request new buffer for playback\n"); | ||
1129 | |||
1130 | snd_pcm_period_elapsed(lx_stream->stream); | ||
1131 | } | ||
1132 | |||
1133 | void lx_tasklet_capture(unsigned long data) | ||
1134 | { | ||
1135 | struct lx6464es *chip = (struct lx6464es *)data; | ||
1136 | struct lx_stream *lx_stream = &chip->capture_stream; | ||
1137 | int err; | ||
1138 | |||
1139 | dev_dbg(chip->card->dev, "->lx_tasklet_capture\n"); | ||
1140 | err = lx_interrupt_request_new_buffer(chip, lx_stream); | ||
1141 | if (err < 0) | ||
1142 | dev_err(chip->card->dev, | ||
1143 | "cannot request new buffer for capture\n"); | ||
1144 | |||
1145 | snd_pcm_period_elapsed(lx_stream->stream); | ||
1146 | } | ||
1147 | |||
1148 | |||
1149 | |||
1150 | static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip, | ||
1151 | u64 notified_in_pipe_mask, | ||
1152 | u64 notified_out_pipe_mask) | ||
1153 | { | ||
1154 | int err = 0; | ||
1155 | |||
1156 | if (notified_in_pipe_mask) { | ||
1157 | dev_dbg(chip->card->dev, | ||
1158 | "requesting audio transfer for capture\n"); | ||
1159 | tasklet_hi_schedule(&chip->tasklet_capture); | ||
1160 | } | ||
1161 | |||
1162 | if (notified_out_pipe_mask) { | ||
1163 | dev_dbg(chip->card->dev, | ||
1164 | "requesting audio transfer for playback\n"); | ||
1165 | tasklet_hi_schedule(&chip->tasklet_playback); | ||
1166 | } | ||
1167 | |||
1168 | return err; | ||
1169 | } | ||
1170 | |||
1171 | |||
1172 | irqreturn_t lx_interrupt(int irq, void *dev_id) | 1080 | irqreturn_t lx_interrupt(int irq, void *dev_id) |
1173 | { | 1081 | { |
1174 | struct lx6464es *chip = dev_id; | 1082 | struct lx6464es *chip = dev_id; |
1175 | int async_pending, async_escmd; | 1083 | int async_pending, async_escmd; |
1176 | u32 irqsrc; | 1084 | u32 irqsrc; |
1177 | 1085 | bool wake_thread = false; | |
1178 | spin_lock(&chip->lock); | ||
1179 | 1086 | ||
1180 | dev_dbg(chip->card->dev, | 1087 | dev_dbg(chip->card->dev, |
1181 | "**************************************************\n"); | 1088 | "**************************************************\n"); |
1182 | 1089 | ||
1183 | if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) { | 1090 | if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) { |
1184 | spin_unlock(&chip->lock); | ||
1185 | dev_dbg(chip->card->dev, "IRQ_NONE\n"); | 1091 | dev_dbg(chip->card->dev, "IRQ_NONE\n"); |
1186 | return IRQ_NONE; /* this device did not cause the interrupt */ | 1092 | return IRQ_NONE; /* this device did not cause the interrupt */ |
1187 | } | 1093 | } |
1188 | 1094 | ||
1189 | if (irqsrc & MASK_SYS_STATUS_CMD_DONE) | 1095 | if (irqsrc & MASK_SYS_STATUS_CMD_DONE) |
1190 | goto exit; | 1096 | return IRQ_HANDLED; |
1191 | 1097 | ||
1192 | if (irqsrc & MASK_SYS_STATUS_EOBI) | 1098 | if (irqsrc & MASK_SYS_STATUS_EOBI) |
1193 | dev_dbg(chip->card->dev, "interrupt: EOBI\n"); | 1099 | dev_dbg(chip->card->dev, "interrupt: EOBI\n"); |
@@ -1202,27 +1108,8 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1202 | dev_dbg(chip->card->dev, "interrupt: ORUN\n"); | 1108 | dev_dbg(chip->card->dev, "interrupt: ORUN\n"); |
1203 | 1109 | ||
1204 | if (async_pending) { | 1110 | if (async_pending) { |
1205 | u64 notified_in_pipe_mask = 0; | 1111 | wake_thread = true; |
1206 | u64 notified_out_pipe_mask = 0; | 1112 | chip->irqsrc = irqsrc; |
1207 | int freq_changed; | ||
1208 | int err; | ||
1209 | |||
1210 | /* handle async events */ | ||
1211 | err = lx_interrupt_handle_async_events(chip, irqsrc, | ||
1212 | &freq_changed, | ||
1213 | ¬ified_in_pipe_mask, | ||
1214 | ¬ified_out_pipe_mask); | ||
1215 | if (err) | ||
1216 | dev_err(chip->card->dev, | ||
1217 | "error handling async events\n"); | ||
1218 | |||
1219 | err = lx_interrupt_handle_audio_transfer(chip, | ||
1220 | notified_in_pipe_mask, | ||
1221 | notified_out_pipe_mask | ||
1222 | ); | ||
1223 | if (err) | ||
1224 | dev_err(chip->card->dev, | ||
1225 | "error during audio transfer\n"); | ||
1226 | } | 1113 | } |
1227 | 1114 | ||
1228 | if (async_escmd) { | 1115 | if (async_escmd) { |
@@ -1235,9 +1122,50 @@ irqreturn_t lx_interrupt(int irq, void *dev_id) | |||
1235 | dev_dbg(chip->card->dev, "interrupt requests escmd handling\n"); | 1122 | dev_dbg(chip->card->dev, "interrupt requests escmd handling\n"); |
1236 | } | 1123 | } |
1237 | 1124 | ||
1238 | exit: | 1125 | return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED; |
1239 | spin_unlock(&chip->lock); | 1126 | } |
1240 | return IRQ_HANDLED; /* this device caused the interrupt */ | 1127 | |
1128 | irqreturn_t lx_threaded_irq(int irq, void *dev_id) | ||
1129 | { | ||
1130 | struct lx6464es *chip = dev_id; | ||
1131 | u64 notified_in_pipe_mask = 0; | ||
1132 | u64 notified_out_pipe_mask = 0; | ||
1133 | int freq_changed; | ||
1134 | int err; | ||
1135 | |||
1136 | /* handle async events */ | ||
1137 | err = lx_interrupt_handle_async_events(chip, chip->irqsrc, | ||
1138 | &freq_changed, | ||
1139 | ¬ified_in_pipe_mask, | ||
1140 | ¬ified_out_pipe_mask); | ||
1141 | if (err) | ||
1142 | dev_err(chip->card->dev, "error handling async events\n"); | ||
1143 | |||
1144 | if (notified_in_pipe_mask) { | ||
1145 | struct lx_stream *lx_stream = &chip->capture_stream; | ||
1146 | |||
1147 | dev_dbg(chip->card->dev, | ||
1148 | "requesting audio transfer for capture\n"); | ||
1149 | err = lx_interrupt_request_new_buffer(chip, lx_stream); | ||
1150 | if (err < 0) | ||
1151 | dev_err(chip->card->dev, | ||
1152 | "cannot request new buffer for capture\n"); | ||
1153 | snd_pcm_period_elapsed(lx_stream->stream); | ||
1154 | } | ||
1155 | |||
1156 | if (notified_out_pipe_mask) { | ||
1157 | struct lx_stream *lx_stream = &chip->playback_stream; | ||
1158 | |||
1159 | dev_dbg(chip->card->dev, | ||
1160 | "requesting audio transfer for playback\n"); | ||
1161 | err = lx_interrupt_request_new_buffer(chip, lx_stream); | ||
1162 | if (err < 0) | ||
1163 | dev_err(chip->card->dev, | ||
1164 | "cannot request new buffer for playback\n"); | ||
1165 | snd_pcm_period_elapsed(lx_stream->stream); | ||
1166 | } | ||
1167 | |||
1168 | return IRQ_HANDLED; | ||
1241 | } | 1169 | } |
1242 | 1170 | ||
1243 | 1171 | ||
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h index 5ec5e04da1a5..0cc140ca98e3 100644 --- a/sound/pci/lx6464es/lx_core.h +++ b/sound/pci/lx6464es/lx_core.h | |||
@@ -181,12 +181,10 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, | |||
181 | 181 | ||
182 | /* interrupt handling */ | 182 | /* interrupt handling */ |
183 | irqreturn_t lx_interrupt(int irq, void *dev_id); | 183 | irqreturn_t lx_interrupt(int irq, void *dev_id); |
184 | irqreturn_t lx_threaded_irq(int irq, void *dev_id); | ||
184 | void lx_irq_enable(struct lx6464es *chip); | 185 | void lx_irq_enable(struct lx6464es *chip); |
185 | void lx_irq_disable(struct lx6464es *chip); | 186 | void lx_irq_disable(struct lx6464es *chip); |
186 | 187 | ||
187 | void lx_tasklet_capture(unsigned long data); | ||
188 | void lx_tasklet_playback(unsigned long data); | ||
189 | |||
190 | 188 | ||
191 | /* Stream Format Header Defines (for LIN and IEEE754) */ | 189 | /* Stream Format Header Defines (for LIN and IEEE754) */ |
192 | #define HEADER_FMT_BASE HEADER_FMT_BASE_LIN | 190 | #define HEADER_FMT_BASE HEADER_FMT_BASE_LIN |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 75fc342cff2a..1faf47e81570 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -986,6 +986,7 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip) | |||
986 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); | 986 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); |
987 | 987 | ||
988 | pcm->info_flags = 0; | 988 | pcm->info_flags = 0; |
989 | pcm->nonatomic = true; | ||
989 | strcpy(pcm->name, name); | 990 | strcpy(pcm->name, name); |
990 | 991 | ||
991 | preallocate_buffers(chip, pcm); | 992 | preallocate_buffers(chip, pcm); |
@@ -1018,6 +1019,7 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip) | |||
1018 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); | 1019 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); |
1019 | 1020 | ||
1020 | pcm->info_flags = 0; | 1021 | pcm->info_flags = 0; |
1022 | pcm->nonatomic = true; | ||
1021 | strcpy(pcm->name, name); | 1023 | strcpy(pcm->name, name); |
1022 | 1024 | ||
1023 | preallocate_buffers(chip, pcm); | 1025 | preallocate_buffers(chip, pcm); |
@@ -1303,8 +1305,9 @@ static int snd_mixart_probe(struct pci_dev *pci, | |||
1303 | } | 1305 | } |
1304 | } | 1306 | } |
1305 | 1307 | ||
1306 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, | 1308 | if (request_threaded_irq(pci->irq, snd_mixart_interrupt, |
1307 | KBUILD_MODNAME, mgr)) { | 1309 | snd_mixart_threaded_irq, IRQF_SHARED, |
1310 | KBUILD_MODNAME, mgr)) { | ||
1308 | dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); | 1311 | dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); |
1309 | snd_mixart_free(mgr); | 1312 | snd_mixart_free(mgr); |
1310 | return -EBUSY; | 1313 | return -EBUSY; |
@@ -1314,24 +1317,18 @@ static int snd_mixart_probe(struct pci_dev *pci, | |||
1314 | sprintf(mgr->shortname, "Digigram miXart"); | 1317 | sprintf(mgr->shortname, "Digigram miXart"); |
1315 | sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq); | 1318 | sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq); |
1316 | 1319 | ||
1317 | /* ISR spinlock */ | ||
1318 | spin_lock_init(&mgr->lock); | ||
1319 | |||
1320 | /* init mailbox */ | 1320 | /* init mailbox */ |
1321 | mgr->msg_fifo_readptr = 0; | 1321 | mgr->msg_fifo_readptr = 0; |
1322 | mgr->msg_fifo_writeptr = 0; | 1322 | mgr->msg_fifo_writeptr = 0; |
1323 | 1323 | ||
1324 | spin_lock_init(&mgr->msg_lock); | 1324 | mutex_init(&mgr->lock); |
1325 | mutex_init(&mgr->msg_mutex); | 1325 | mutex_init(&mgr->msg_lock); |
1326 | init_waitqueue_head(&mgr->msg_sleep); | 1326 | init_waitqueue_head(&mgr->msg_sleep); |
1327 | atomic_set(&mgr->msg_processed, 0); | 1327 | atomic_set(&mgr->msg_processed, 0); |
1328 | 1328 | ||
1329 | /* init setup mutex*/ | 1329 | /* init setup mutex*/ |
1330 | mutex_init(&mgr->setup_mutex); | 1330 | mutex_init(&mgr->setup_mutex); |
1331 | 1331 | ||
1332 | /* init message taslket */ | ||
1333 | tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); | ||
1334 | |||
1335 | /* card assignment */ | 1332 | /* card assignment */ |
1336 | mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */ | 1333 | mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */ |
1337 | for (i = 0; i < mgr->num_cards; i++) { | 1334 | for (i = 0; i < mgr->num_cards; i++) { |
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h index 561634d5c007..0cc17e0ea34a 100644 --- a/sound/pci/mixart/mixart.h +++ b/sound/pci/mixart/mixart.h | |||
@@ -78,22 +78,18 @@ struct mixart_mgr { | |||
78 | char shortname[32]; /* short name of this soundcard */ | 78 | char shortname[32]; /* short name of this soundcard */ |
79 | char longname[80]; /* name of this soundcard */ | 79 | char longname[80]; /* name of this soundcard */ |
80 | 80 | ||
81 | /* message tasklet */ | ||
82 | struct tasklet_struct msg_taskq; | ||
83 | |||
84 | /* one and only blocking message or notification may be pending */ | 81 | /* one and only blocking message or notification may be pending */ |
85 | u32 pending_event; | 82 | u32 pending_event; |
86 | wait_queue_head_t msg_sleep; | 83 | wait_queue_head_t msg_sleep; |
87 | 84 | ||
88 | /* messages stored for tasklet */ | 85 | /* messages fifo */ |
89 | u32 msg_fifo[MSG_FIFO_SIZE]; | 86 | u32 msg_fifo[MSG_FIFO_SIZE]; |
90 | int msg_fifo_readptr; | 87 | int msg_fifo_readptr; |
91 | int msg_fifo_writeptr; | 88 | int msg_fifo_writeptr; |
92 | atomic_t msg_processed; /* number of messages to be processed in takslet */ | 89 | atomic_t msg_processed; /* number of messages to be processed in takslet */ |
93 | 90 | ||
94 | spinlock_t lock; /* interrupt spinlock */ | 91 | struct mutex lock; /* interrupt lock */ |
95 | spinlock_t msg_lock; /* mailbox spinlock */ | 92 | struct mutex msg_lock; /* mailbox lock */ |
96 | struct mutex msg_mutex; /* mutex for blocking_requests */ | ||
97 | 93 | ||
98 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ | 94 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ |
99 | 95 | ||
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 84f67450924e..fe80313674d9 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -76,7 +76,6 @@ static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame) | |||
76 | static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, | 76 | static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, |
77 | u32 msg_frame_address ) | 77 | u32 msg_frame_address ) |
78 | { | 78 | { |
79 | unsigned long flags; | ||
80 | u32 headptr; | 79 | u32 headptr; |
81 | u32 size; | 80 | u32 size; |
82 | int err; | 81 | int err; |
@@ -84,7 +83,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, | |||
84 | unsigned int i; | 83 | unsigned int i; |
85 | #endif | 84 | #endif |
86 | 85 | ||
87 | spin_lock_irqsave(&mgr->msg_lock, flags); | 86 | mutex_lock(&mgr->msg_lock); |
88 | err = 0; | 87 | err = 0; |
89 | 88 | ||
90 | /* copy message descriptor from miXart to driver */ | 89 | /* copy message descriptor from miXart to driver */ |
@@ -133,7 +132,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, | |||
133 | writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); | 132 | writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); |
134 | 133 | ||
135 | _clean_exit: | 134 | _clean_exit: |
136 | spin_unlock_irqrestore(&mgr->msg_lock, flags); | 135 | mutex_unlock(&mgr->msg_lock); |
137 | 136 | ||
138 | return err; | 137 | return err; |
139 | } | 138 | } |
@@ -243,28 +242,24 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
243 | wait_queue_t wait; | 242 | wait_queue_t wait; |
244 | long timeout; | 243 | long timeout; |
245 | 244 | ||
246 | mutex_lock(&mgr->msg_mutex); | ||
247 | |||
248 | init_waitqueue_entry(&wait, current); | 245 | init_waitqueue_entry(&wait, current); |
249 | 246 | ||
250 | spin_lock_irq(&mgr->msg_lock); | 247 | mutex_lock(&mgr->msg_lock); |
251 | /* send the message */ | 248 | /* send the message */ |
252 | err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ | 249 | err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ |
253 | if (err) { | 250 | if (err) { |
254 | spin_unlock_irq(&mgr->msg_lock); | 251 | mutex_unlock(&mgr->msg_lock); |
255 | mutex_unlock(&mgr->msg_mutex); | ||
256 | return err; | 252 | return err; |
257 | } | 253 | } |
258 | 254 | ||
259 | set_current_state(TASK_UNINTERRUPTIBLE); | 255 | set_current_state(TASK_UNINTERRUPTIBLE); |
260 | add_wait_queue(&mgr->msg_sleep, &wait); | 256 | add_wait_queue(&mgr->msg_sleep, &wait); |
261 | spin_unlock_irq(&mgr->msg_lock); | 257 | mutex_unlock(&mgr->msg_lock); |
262 | timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); | 258 | timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); |
263 | remove_wait_queue(&mgr->msg_sleep, &wait); | 259 | remove_wait_queue(&mgr->msg_sleep, &wait); |
264 | 260 | ||
265 | if (! timeout) { | 261 | if (! timeout) { |
266 | /* error - no ack */ | 262 | /* error - no ack */ |
267 | mutex_unlock(&mgr->msg_mutex); | ||
268 | dev_err(&mgr->pci->dev, | 263 | dev_err(&mgr->pci->dev, |
269 | "error: no response on msg %x\n", msg_frame); | 264 | "error: no response on msg %x\n", msg_frame); |
270 | return -EIO; | 265 | return -EIO; |
@@ -281,7 +276,6 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
281 | if( request->message_id != resp.message_id ) | 276 | if( request->message_id != resp.message_id ) |
282 | dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); | 277 | dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); |
283 | 278 | ||
284 | mutex_unlock(&mgr->msg_mutex); | ||
285 | return err; | 279 | return err; |
286 | } | 280 | } |
287 | 281 | ||
@@ -300,34 +294,29 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, | |||
300 | if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK)) | 294 | if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK)) |
301 | return -EINVAL; | 295 | return -EINVAL; |
302 | 296 | ||
303 | mutex_lock(&mgr->msg_mutex); | ||
304 | |||
305 | init_waitqueue_entry(&wait, current); | 297 | init_waitqueue_entry(&wait, current); |
306 | 298 | ||
307 | spin_lock_irq(&mgr->msg_lock); | 299 | mutex_lock(&mgr->msg_lock); |
308 | /* send the message */ | 300 | /* send the message */ |
309 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ | 301 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ |
310 | if(err) { | 302 | if(err) { |
311 | spin_unlock_irq(&mgr->msg_lock); | 303 | mutex_unlock(&mgr->msg_lock); |
312 | mutex_unlock(&mgr->msg_mutex); | ||
313 | return err; | 304 | return err; |
314 | } | 305 | } |
315 | 306 | ||
316 | set_current_state(TASK_UNINTERRUPTIBLE); | 307 | set_current_state(TASK_UNINTERRUPTIBLE); |
317 | add_wait_queue(&mgr->msg_sleep, &wait); | 308 | add_wait_queue(&mgr->msg_sleep, &wait); |
318 | spin_unlock_irq(&mgr->msg_lock); | 309 | mutex_unlock(&mgr->msg_lock); |
319 | timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); | 310 | timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); |
320 | remove_wait_queue(&mgr->msg_sleep, &wait); | 311 | remove_wait_queue(&mgr->msg_sleep, &wait); |
321 | 312 | ||
322 | if (! timeout) { | 313 | if (! timeout) { |
323 | /* error - no ack */ | 314 | /* error - no ack */ |
324 | mutex_unlock(&mgr->msg_mutex); | ||
325 | dev_err(&mgr->pci->dev, | 315 | dev_err(&mgr->pci->dev, |
326 | "error: notification %x not received\n", notif_event); | 316 | "error: notification %x not received\n", notif_event); |
327 | return -EIO; | 317 | return -EIO; |
328 | } | 318 | } |
329 | 319 | ||
330 | mutex_unlock(&mgr->msg_mutex); | ||
331 | return 0; | 320 | return 0; |
332 | } | 321 | } |
333 | 322 | ||
@@ -335,13 +324,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, | |||
335 | int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request) | 324 | int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request) |
336 | { | 325 | { |
337 | u32 message_frame; | 326 | u32 message_frame; |
338 | unsigned long flags; | ||
339 | int err; | 327 | int err; |
340 | 328 | ||
341 | /* just send the message (do not mark it as a pending one) */ | 329 | /* just send the message (do not mark it as a pending one) */ |
342 | spin_lock_irqsave(&mgr->msg_lock, flags); | 330 | mutex_lock(&mgr->msg_lock); |
343 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame); | 331 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame); |
344 | spin_unlock_irqrestore(&mgr->msg_lock, flags); | 332 | mutex_unlock(&mgr->msg_lock); |
345 | 333 | ||
346 | /* the answer will be handled by snd_struct mixart_msgasklet() */ | 334 | /* the answer will be handled by snd_struct mixart_msgasklet() */ |
347 | atomic_inc(&mgr->msg_processed); | 335 | atomic_inc(&mgr->msg_processed); |
@@ -350,19 +338,16 @@ int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *requ | |||
350 | } | 338 | } |
351 | 339 | ||
352 | 340 | ||
353 | /* common buffer of tasklet and interrupt to send/receive messages */ | 341 | /* common buffer of interrupt to send/receive messages */ |
354 | static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4]; | 342 | static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4]; |
355 | 343 | ||
356 | 344 | ||
357 | void snd_mixart_msg_tasklet(unsigned long arg) | 345 | static void snd_mixart_process_msg(struct mixart_mgr *mgr) |
358 | { | 346 | { |
359 | struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg); | ||
360 | struct mixart_msg resp; | 347 | struct mixart_msg resp; |
361 | u32 msg, addr, type; | 348 | u32 msg, addr, type; |
362 | int err; | 349 | int err; |
363 | 350 | ||
364 | spin_lock(&mgr->lock); | ||
365 | |||
366 | while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) { | 351 | while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) { |
367 | msg = mgr->msg_fifo[mgr->msg_fifo_readptr]; | 352 | msg = mgr->msg_fifo[mgr->msg_fifo_readptr]; |
368 | mgr->msg_fifo_readptr++; | 353 | mgr->msg_fifo_readptr++; |
@@ -381,7 +366,7 @@ void snd_mixart_msg_tasklet(unsigned long arg) | |||
381 | err = get_msg(mgr, &resp, addr); | 366 | err = get_msg(mgr, &resp, addr); |
382 | if( err < 0 ) { | 367 | if( err < 0 ) { |
383 | dev_err(&mgr->pci->dev, | 368 | dev_err(&mgr->pci->dev, |
384 | "tasklet: error(%d) reading mf %x\n", | 369 | "error(%d) reading mf %x\n", |
385 | err, msg); | 370 | err, msg); |
386 | break; | 371 | break; |
387 | } | 372 | } |
@@ -393,12 +378,12 @@ void snd_mixart_msg_tasklet(unsigned long arg) | |||
393 | case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET: | 378 | case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET: |
394 | if(mixart_msg_data[0]) | 379 | if(mixart_msg_data[0]) |
395 | dev_err(&mgr->pci->dev, | 380 | dev_err(&mgr->pci->dev, |
396 | "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", | 381 | "error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", |
397 | mixart_msg_data[0]); | 382 | mixart_msg_data[0]); |
398 | break; | 383 | break; |
399 | default: | 384 | default: |
400 | dev_dbg(&mgr->pci->dev, | 385 | dev_dbg(&mgr->pci->dev, |
401 | "tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n", | 386 | "received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n", |
402 | msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size); | 387 | msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size); |
403 | break; | 388 | break; |
404 | } | 389 | } |
@@ -409,7 +394,7 @@ void snd_mixart_msg_tasklet(unsigned long arg) | |||
409 | /* get_msg() necessary */ | 394 | /* get_msg() necessary */ |
410 | default: | 395 | default: |
411 | dev_err(&mgr->pci->dev, | 396 | dev_err(&mgr->pci->dev, |
412 | "tasklet doesn't know what to do with message %x\n", | 397 | "doesn't know what to do with message %x\n", |
413 | msg); | 398 | msg); |
414 | } /* switch type */ | 399 | } /* switch type */ |
415 | 400 | ||
@@ -417,26 +402,17 @@ void snd_mixart_msg_tasklet(unsigned long arg) | |||
417 | atomic_dec(&mgr->msg_processed); | 402 | atomic_dec(&mgr->msg_processed); |
418 | 403 | ||
419 | } /* while there is a msg in fifo */ | 404 | } /* while there is a msg in fifo */ |
420 | |||
421 | spin_unlock(&mgr->lock); | ||
422 | } | 405 | } |
423 | 406 | ||
424 | 407 | ||
425 | irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | 408 | irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) |
426 | { | 409 | { |
427 | struct mixart_mgr *mgr = dev_id; | 410 | struct mixart_mgr *mgr = dev_id; |
428 | int err; | ||
429 | struct mixart_msg resp; | ||
430 | |||
431 | u32 msg; | ||
432 | u32 it_reg; | 411 | u32 it_reg; |
433 | 412 | ||
434 | spin_lock(&mgr->lock); | ||
435 | |||
436 | it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET)); | 413 | it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET)); |
437 | if( !(it_reg & MIXART_OIDI) ) { | 414 | if( !(it_reg & MIXART_OIDI) ) { |
438 | /* this device did not cause the interrupt */ | 415 | /* this device did not cause the interrupt */ |
439 | spin_unlock(&mgr->lock); | ||
440 | return IRQ_NONE; | 416 | return IRQ_NONE; |
441 | } | 417 | } |
442 | 418 | ||
@@ -450,6 +426,17 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | |||
450 | /* clear interrupt */ | 426 | /* clear interrupt */ |
451 | writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) ); | 427 | writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) ); |
452 | 428 | ||
429 | return IRQ_WAKE_THREAD; | ||
430 | } | ||
431 | |||
432 | irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) | ||
433 | { | ||
434 | struct mixart_mgr *mgr = dev_id; | ||
435 | int err; | ||
436 | struct mixart_msg resp; | ||
437 | u32 msg; | ||
438 | |||
439 | mutex_lock(&mgr->lock); | ||
453 | /* process interrupt */ | 440 | /* process interrupt */ |
454 | while (retrieve_msg_frame(mgr, &msg)) { | 441 | while (retrieve_msg_frame(mgr, &msg)) { |
455 | 442 | ||
@@ -518,9 +505,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | |||
518 | stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed ); | 505 | stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed ); |
519 | 506 | ||
520 | if(elapsed) { | 507 | if(elapsed) { |
521 | spin_unlock(&mgr->lock); | 508 | mutex_unlock(&mgr->lock); |
522 | snd_pcm_period_elapsed(stream->substream); | 509 | snd_pcm_period_elapsed(stream->substream); |
523 | spin_lock(&mgr->lock); | 510 | mutex_lock(&mgr->lock); |
524 | } | 511 | } |
525 | } | 512 | } |
526 | } | 513 | } |
@@ -556,7 +543,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | |||
556 | /* no break, continue ! */ | 543 | /* no break, continue ! */ |
557 | case MSG_TYPE_ANSWER: | 544 | case MSG_TYPE_ANSWER: |
558 | /* answer or notification to a message we are waiting for*/ | 545 | /* answer or notification to a message we are waiting for*/ |
559 | spin_lock(&mgr->msg_lock); | 546 | mutex_lock(&mgr->msg_lock); |
560 | if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) { | 547 | if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) { |
561 | wake_up(&mgr->msg_sleep); | 548 | wake_up(&mgr->msg_sleep); |
562 | mgr->pending_event = 0; | 549 | mgr->pending_event = 0; |
@@ -566,9 +553,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | |||
566 | mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; | 553 | mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; |
567 | mgr->msg_fifo_writeptr++; | 554 | mgr->msg_fifo_writeptr++; |
568 | mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; | 555 | mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; |
569 | tasklet_schedule(&mgr->msg_taskq); | 556 | snd_mixart_process_msg(mgr); |
570 | } | 557 | } |
571 | spin_unlock(&mgr->msg_lock); | 558 | mutex_unlock(&mgr->msg_lock); |
572 | break; | 559 | break; |
573 | case MSG_TYPE_REQUEST: | 560 | case MSG_TYPE_REQUEST: |
574 | default: | 561 | default: |
@@ -582,7 +569,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) | |||
582 | /* allow interrupt again */ | 569 | /* allow interrupt again */ |
583 | writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); | 570 | writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); |
584 | 571 | ||
585 | spin_unlock(&mgr->lock); | 572 | mutex_unlock(&mgr->lock); |
586 | 573 | ||
587 | return IRQ_HANDLED; | 574 | return IRQ_HANDLED; |
588 | } | 575 | } |
diff --git a/sound/pci/mixart/mixart_core.h b/sound/pci/mixart/mixart_core.h index c919b734756f..d1722e575409 100644 --- a/sound/pci/mixart/mixart_core.h +++ b/sound/pci/mixart/mixart_core.h | |||
@@ -564,7 +564,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *r | |||
564 | int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request); | 564 | int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request); |
565 | 565 | ||
566 | irqreturn_t snd_mixart_interrupt(int irq, void *dev_id); | 566 | irqreturn_t snd_mixart_interrupt(int irq, void *dev_id); |
567 | void snd_mixart_msg_tasklet(unsigned long arg); | 567 | irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id); |
568 | 568 | ||
569 | void snd_mixart_reset_board(struct mixart_mgr *mgr); | 569 | void snd_mixart_reset_board(struct mixart_mgr *mgr); |
570 | 570 | ||
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index cc0bcd9f3350..02828240ba15 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -29,6 +29,9 @@ | |||
29 | /* the multichannel DMA channel has a 24-bit counter */ | 29 | /* the multichannel DMA channel has a 24-bit counter */ |
30 | #define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4) | 30 | #define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4) |
31 | 31 | ||
32 | #define FIFO_BYTES 256 | ||
33 | #define FIFO_BYTES_MULTICH 1024 | ||
34 | |||
32 | #define PERIOD_BYTES_MIN 64 | 35 | #define PERIOD_BYTES_MIN 64 |
33 | 36 | ||
34 | #define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2) | 37 | #define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2) |
@@ -60,6 +63,7 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = { | |||
60 | .period_bytes_max = BUFFER_BYTES_MAX, | 63 | .period_bytes_max = BUFFER_BYTES_MAX, |
61 | .periods_min = 1, | 64 | .periods_min = 1, |
62 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 65 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
66 | .fifo_size = FIFO_BYTES, | ||
63 | }; | 67 | }; |
64 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | 68 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { |
65 | .info = SNDRV_PCM_INFO_MMAP | | 69 | .info = SNDRV_PCM_INFO_MMAP | |
@@ -87,6 +91,7 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | |||
87 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, | 91 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
88 | .periods_min = 1, | 92 | .periods_min = 1, |
89 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, | 93 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, |
94 | .fifo_size = FIFO_BYTES_MULTICH, | ||
90 | }; | 95 | }; |
91 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { | 96 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { |
92 | .info = SNDRV_PCM_INFO_MMAP | | 97 | .info = SNDRV_PCM_INFO_MMAP | |
@@ -106,6 +111,7 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = { | |||
106 | .period_bytes_max = BUFFER_BYTES_MAX, | 111 | .period_bytes_max = BUFFER_BYTES_MAX, |
107 | .periods_min = 1, | 112 | .periods_min = 1, |
108 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 113 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
114 | .fifo_size = FIFO_BYTES, | ||
109 | }; | 115 | }; |
110 | 116 | ||
111 | static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = { | 117 | static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = { |
@@ -141,6 +147,10 @@ static int oxygen_open(struct snd_pcm_substream *substream, | |||
141 | runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | | 147 | runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | |
142 | SNDRV_PCM_RATE_64000); | 148 | SNDRV_PCM_RATE_64000); |
143 | runtime->hw.rate_min = 44100; | 149 | runtime->hw.rate_min = 44100; |
150 | /* fall through */ | ||
151 | case PCM_A: | ||
152 | case PCM_B: | ||
153 | runtime->hw.fifo_size = 0; | ||
144 | break; | 154 | break; |
145 | case PCM_MULTICH: | 155 | case PCM_MULTICH: |
146 | runtime->hw.channels_max = chip->model.dac_channels_pcm; | 156 | runtime->hw.channels_max = chip->model.dac_channels_pcm; |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 7b317a28a19c..83de6fb01021 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -52,6 +52,7 @@ static const struct pci_device_id xonar_ids[] = { | |||
52 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, | 52 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, |
53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, | 53 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, |
54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, | 54 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, |
55 | { OXYGEN_PCI_SUBID(0x1043, 0x8428) }, | ||
55 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, | 56 | { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, |
56 | { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, | 57 | { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, |
57 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | 58 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index e02605931669..24109d37ca09 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -212,6 +212,9 @@ | |||
212 | #define GPIO_ST_MAGIC 0x0040 | 212 | #define GPIO_ST_MAGIC 0x0040 |
213 | #define GPIO_ST_HP 0x0080 | 213 | #define GPIO_ST_HP 0x0080 |
214 | 214 | ||
215 | #define GPIO_XENSE_OUTPUT_ENABLE (0x0001 | 0x0010 | 0x0020) | ||
216 | #define GPIO_XENSE_SPEAKERS 0x0080 | ||
217 | |||
215 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ | 218 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ |
216 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ | 219 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ |
217 | 220 | ||
@@ -419,6 +422,7 @@ static void xonar_st_init_common(struct oxygen *chip) | |||
419 | 422 | ||
420 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 423 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
421 | data->dacs = chip->model.dac_channels_mixer / 2; | 424 | data->dacs = chip->model.dac_channels_mixer / 2; |
425 | data->h6 = chip->model.dac_channels_mixer > 2; | ||
422 | data->hp_gain_offset = 2*-18; | 426 | data->hp_gain_offset = 2*-18; |
423 | 427 | ||
424 | pcm1796_init(chip); | 428 | pcm1796_init(chip); |
@@ -499,6 +503,51 @@ static void xonar_stx_init(struct oxygen *chip) | |||
499 | xonar_st_init_common(chip); | 503 | xonar_st_init_common(chip); |
500 | } | 504 | } |
501 | 505 | ||
506 | static void xonar_xense_init(struct oxygen *chip) | ||
507 | { | ||
508 | struct xonar_pcm179x *data = chip->model_data; | ||
509 | |||
510 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; | ||
511 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
512 | data->generic.ext_power_bit = GPI_EXT_POWER; | ||
513 | xonar_init_ext_power(chip); | ||
514 | |||
515 | data->generic.anti_pop_delay = 100; | ||
516 | data->has_cs2000 = 1; | ||
517 | data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; | ||
518 | |||
519 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
520 | OXYGEN_RATE_48000 | | ||
521 | OXYGEN_I2S_FORMAT_I2S | | ||
522 | OXYGEN_I2S_MCLK(MCLK_512) | | ||
523 | OXYGEN_I2S_BITS_16 | | ||
524 | OXYGEN_I2S_MASTER | | ||
525 | OXYGEN_I2S_BCLK_64); | ||
526 | |||
527 | xonar_st_init_i2c(chip); | ||
528 | cs2000_registers_init(chip); | ||
529 | |||
530 | data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE; | ||
531 | data->dacs = 1; | ||
532 | data->hp_gain_offset = 2*-18; | ||
533 | |||
534 | pcm1796_init(chip); | ||
535 | |||
536 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
537 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | | ||
538 | GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS); | ||
539 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
540 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | | ||
541 | GPIO_XENSE_SPEAKERS); | ||
542 | |||
543 | xonar_init_cs53x1(chip); | ||
544 | xonar_enable_output(chip); | ||
545 | |||
546 | snd_component_add(chip->card, "PCM1796"); | ||
547 | snd_component_add(chip->card, "CS5381"); | ||
548 | snd_component_add(chip->card, "CS2000"); | ||
549 | } | ||
550 | |||
502 | static void xonar_d2_cleanup(struct oxygen *chip) | 551 | static void xonar_d2_cleanup(struct oxygen *chip) |
503 | { | 552 | { |
504 | xonar_disable_output(chip); | 553 | xonar_disable_output(chip); |
@@ -795,11 +844,11 @@ static int st_output_switch_put(struct snd_kcontrol *ctl, | |||
795 | static int st_hp_volume_offset_info(struct snd_kcontrol *ctl, | 844 | static int st_hp_volume_offset_info(struct snd_kcontrol *ctl, |
796 | struct snd_ctl_elem_info *info) | 845 | struct snd_ctl_elem_info *info) |
797 | { | 846 | { |
798 | static const char *const names[3] = { | 847 | static const char *const names[4] = { |
799 | "< 64 ohms", "64-300 ohms", "300-600 ohms" | 848 | "< 32 ohms", "32-64 ohms", "64-300 ohms", "300-600 ohms" |
800 | }; | 849 | }; |
801 | 850 | ||
802 | return snd_ctl_enum_info(info, 1, 3, names); | 851 | return snd_ctl_enum_info(info, 1, 4, names); |
803 | } | 852 | } |
804 | 853 | ||
805 | static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, | 854 | static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, |
@@ -809,12 +858,14 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, | |||
809 | struct xonar_pcm179x *data = chip->model_data; | 858 | struct xonar_pcm179x *data = chip->model_data; |
810 | 859 | ||
811 | mutex_lock(&chip->mutex); | 860 | mutex_lock(&chip->mutex); |
812 | if (data->hp_gain_offset < 2*-6) | 861 | if (data->hp_gain_offset < 2*-12) |
813 | value->value.enumerated.item[0] = 0; | 862 | value->value.enumerated.item[0] = 0; |
814 | else if (data->hp_gain_offset < 0) | 863 | else if (data->hp_gain_offset < 2*-6) |
815 | value->value.enumerated.item[0] = 1; | 864 | value->value.enumerated.item[0] = 1; |
816 | else | 865 | else if (data->hp_gain_offset < 0) |
817 | value->value.enumerated.item[0] = 2; | 866 | value->value.enumerated.item[0] = 2; |
867 | else | ||
868 | value->value.enumerated.item[0] = 3; | ||
818 | mutex_unlock(&chip->mutex); | 869 | mutex_unlock(&chip->mutex); |
819 | return 0; | 870 | return 0; |
820 | } | 871 | } |
@@ -823,13 +874,13 @@ static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, | |||
823 | static int st_hp_volume_offset_put(struct snd_kcontrol *ctl, | 874 | static int st_hp_volume_offset_put(struct snd_kcontrol *ctl, |
824 | struct snd_ctl_elem_value *value) | 875 | struct snd_ctl_elem_value *value) |
825 | { | 876 | { |
826 | static const s8 offsets[] = { 2*-18, 2*-6, 0 }; | 877 | static const s8 offsets[] = { 2*-18, 2*-12, 2*-6, 0 }; |
827 | struct oxygen *chip = ctl->private_data; | 878 | struct oxygen *chip = ctl->private_data; |
828 | struct xonar_pcm179x *data = chip->model_data; | 879 | struct xonar_pcm179x *data = chip->model_data; |
829 | s8 offset; | 880 | s8 offset; |
830 | int changed; | 881 | int changed; |
831 | 882 | ||
832 | if (value->value.enumerated.item[0] > 2) | 883 | if (value->value.enumerated.item[0] > 3) |
833 | return -EINVAL; | 884 | return -EINVAL; |
834 | offset = offsets[value->value.enumerated.item[0]]; | 885 | offset = offsets[value->value.enumerated.item[0]]; |
835 | mutex_lock(&chip->mutex); | 886 | mutex_lock(&chip->mutex); |
@@ -859,6 +910,67 @@ static const struct snd_kcontrol_new st_controls[] = { | |||
859 | }, | 910 | }, |
860 | }; | 911 | }; |
861 | 912 | ||
913 | static int xense_output_switch_get(struct snd_kcontrol *ctl, | ||
914 | struct snd_ctl_elem_value *value) | ||
915 | { | ||
916 | struct oxygen *chip = ctl->private_data; | ||
917 | u16 gpio; | ||
918 | |||
919 | gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
920 | if (gpio & GPIO_XENSE_SPEAKERS) | ||
921 | value->value.enumerated.item[0] = 0; | ||
922 | else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR)) | ||
923 | value->value.enumerated.item[0] = 1; | ||
924 | else | ||
925 | value->value.enumerated.item[0] = 2; | ||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | static int xense_output_switch_put(struct snd_kcontrol *ctl, | ||
930 | struct snd_ctl_elem_value *value) | ||
931 | { | ||
932 | struct oxygen *chip = ctl->private_data; | ||
933 | struct xonar_pcm179x *data = chip->model_data; | ||
934 | u16 gpio_old, gpio; | ||
935 | |||
936 | mutex_lock(&chip->mutex); | ||
937 | gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
938 | gpio = gpio_old; | ||
939 | switch (value->value.enumerated.item[0]) { | ||
940 | case 0: | ||
941 | gpio |= GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR; | ||
942 | break; | ||
943 | case 1: | ||
944 | gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS; | ||
945 | break; | ||
946 | case 2: | ||
947 | gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR); | ||
948 | break; | ||
949 | } | ||
950 | oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); | ||
951 | data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS); | ||
952 | update_pcm1796_volume(chip); | ||
953 | mutex_unlock(&chip->mutex); | ||
954 | return gpio != gpio_old; | ||
955 | } | ||
956 | |||
957 | static const struct snd_kcontrol_new xense_controls[] = { | ||
958 | { | ||
959 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
960 | .name = "Analog Output", | ||
961 | .info = st_output_switch_info, | ||
962 | .get = xense_output_switch_get, | ||
963 | .put = xense_output_switch_put, | ||
964 | }, | ||
965 | { | ||
966 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
967 | .name = "Headphones Impedance Playback Enum", | ||
968 | .info = st_hp_volume_offset_info, | ||
969 | .get = st_hp_volume_offset_get, | ||
970 | .put = st_hp_volume_offset_put, | ||
971 | }, | ||
972 | }; | ||
973 | |||
862 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, | 974 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, |
863 | unsigned int reg, unsigned int mute) | 975 | unsigned int reg, unsigned int mute) |
864 | { | 976 | { |
@@ -946,6 +1058,23 @@ static int xonar_st_mixer_init(struct oxygen *chip) | |||
946 | return 0; | 1058 | return 0; |
947 | } | 1059 | } |
948 | 1060 | ||
1061 | static int xonar_xense_mixer_init(struct oxygen *chip) | ||
1062 | { | ||
1063 | unsigned int i; | ||
1064 | int err; | ||
1065 | |||
1066 | for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) { | ||
1067 | err = snd_ctl_add(chip->card, | ||
1068 | snd_ctl_new1(&xense_controls[i], chip)); | ||
1069 | if (err < 0) | ||
1070 | return err; | ||
1071 | } | ||
1072 | err = add_pcm1796_controls(chip); | ||
1073 | if (err < 0) | ||
1074 | return err; | ||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
949 | static void dump_pcm1796_registers(struct oxygen *chip, | 1078 | static void dump_pcm1796_registers(struct oxygen *chip, |
950 | struct snd_info_buffer *buffer) | 1079 | struct snd_info_buffer *buffer) |
951 | { | 1080 | { |
@@ -1140,12 +1269,29 @@ int get_xonar_pcm179x_model(struct oxygen *chip, | |||
1140 | break; | 1269 | break; |
1141 | case 0x85f4: | 1270 | case 0x85f4: |
1142 | chip->model = model_xonar_st; | 1271 | chip->model = model_xonar_st; |
1143 | /* TODO: daughterboard support */ | 1272 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK); |
1144 | chip->model.shortname = "Xonar STX II"; | 1273 | switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) { |
1274 | default: | ||
1275 | chip->model.shortname = "Xonar STX II"; | ||
1276 | break; | ||
1277 | case GPIO_DB_H6: | ||
1278 | chip->model.shortname = "Xonar STX II+H6"; | ||
1279 | chip->model.dac_channels_pcm = 8; | ||
1280 | chip->model.dac_channels_mixer = 8; | ||
1281 | chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); | ||
1282 | break; | ||
1283 | } | ||
1145 | chip->model.init = xonar_stx_init; | 1284 | chip->model.init = xonar_stx_init; |
1146 | chip->model.resume = xonar_stx_resume; | 1285 | chip->model.resume = xonar_stx_resume; |
1147 | chip->model.set_dac_params = set_pcm1796_params; | 1286 | chip->model.set_dac_params = set_pcm1796_params; |
1148 | break; | 1287 | break; |
1288 | case 0x8428: | ||
1289 | chip->model = model_xonar_st; | ||
1290 | chip->model.shortname = "Xonar Xense"; | ||
1291 | chip->model.chip = "AV100"; | ||
1292 | chip->model.init = xonar_xense_init; | ||
1293 | chip->model.mixer_init = xonar_xense_mixer_init; | ||
1294 | break; | ||
1149 | default: | 1295 | default: |
1150 | return -EINVAL; | 1296 | return -EINVAL; |
1151 | } | 1297 | } |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 68a37a7906c1..b854fc5e01f5 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -702,13 +702,11 @@ static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream, | |||
702 | return 0; | 702 | return 0; |
703 | } | 703 | } |
704 | 704 | ||
705 | static void pcxhr_trigger_tasklet(unsigned long arg) | 705 | static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr) |
706 | { | 706 | { |
707 | unsigned long flags; | ||
708 | int i, j, err; | 707 | int i, j, err; |
709 | struct pcxhr_pipe *pipe; | 708 | struct pcxhr_pipe *pipe; |
710 | struct snd_pcxhr *chip; | 709 | struct snd_pcxhr *chip; |
711 | struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg); | ||
712 | int capture_mask = 0; | 710 | int capture_mask = 0; |
713 | int playback_mask = 0; | 711 | int playback_mask = 0; |
714 | 712 | ||
@@ -736,11 +734,11 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
736 | } | 734 | } |
737 | if (capture_mask == 0 && playback_mask == 0) { | 735 | if (capture_mask == 0 && playback_mask == 0) { |
738 | mutex_unlock(&mgr->setup_mutex); | 736 | mutex_unlock(&mgr->setup_mutex); |
739 | dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : no pipes\n"); | 737 | dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n"); |
740 | return; | 738 | return; |
741 | } | 739 | } |
742 | 740 | ||
743 | dev_dbg(&mgr->pci->dev, "pcxhr_trigger_tasklet : " | 741 | dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : " |
744 | "playback_mask=%x capture_mask=%x\n", | 742 | "playback_mask=%x capture_mask=%x\n", |
745 | playback_mask, capture_mask); | 743 | playback_mask, capture_mask); |
746 | 744 | ||
@@ -748,7 +746,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
748 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); | 746 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); |
749 | if (err) { | 747 | if (err) { |
750 | mutex_unlock(&mgr->setup_mutex); | 748 | mutex_unlock(&mgr->setup_mutex); |
751 | dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " | 749 | dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : " |
752 | "error stop pipes (P%x C%x)\n", | 750 | "error stop pipes (P%x C%x)\n", |
753 | playback_mask, capture_mask); | 751 | playback_mask, capture_mask); |
754 | return; | 752 | return; |
@@ -793,7 +791,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
793 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); | 791 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); |
794 | if (err) { | 792 | if (err) { |
795 | mutex_unlock(&mgr->setup_mutex); | 793 | mutex_unlock(&mgr->setup_mutex); |
796 | dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " | 794 | dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : " |
797 | "error start pipes (P%x C%x)\n", | 795 | "error start pipes (P%x C%x)\n", |
798 | playback_mask, capture_mask); | 796 | playback_mask, capture_mask); |
799 | return; | 797 | return; |
@@ -802,7 +800,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
802 | /* put the streams into the running state now | 800 | /* put the streams into the running state now |
803 | * (increment pointer by interrupt) | 801 | * (increment pointer by interrupt) |
804 | */ | 802 | */ |
805 | spin_lock_irqsave(&mgr->lock, flags); | 803 | mutex_lock(&mgr->lock); |
806 | for ( i =0; i < mgr->num_cards; i++) { | 804 | for ( i =0; i < mgr->num_cards; i++) { |
807 | struct pcxhr_stream *stream; | 805 | struct pcxhr_stream *stream; |
808 | chip = mgr->chip[i]; | 806 | chip = mgr->chip[i]; |
@@ -820,13 +818,13 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
820 | } | 818 | } |
821 | } | 819 | } |
822 | } | 820 | } |
823 | spin_unlock_irqrestore(&mgr->lock, flags); | 821 | mutex_unlock(&mgr->lock); |
824 | 822 | ||
825 | mutex_unlock(&mgr->setup_mutex); | 823 | mutex_unlock(&mgr->setup_mutex); |
826 | 824 | ||
827 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 825 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
828 | do_gettimeofday(&my_tv2); | 826 | do_gettimeofday(&my_tv2); |
829 | dev_dbg(&mgr->pci->dev, "***TRIGGER TASKLET*** TIME = %ld (err = %x)\n", | 827 | dev_dbg(&mgr->pci->dev, "***TRIGGER START*** TIME = %ld (err = %x)\n", |
830 | (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); | 828 | (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); |
831 | #endif | 829 | #endif |
832 | } | 830 | } |
@@ -853,7 +851,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) | |||
853 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; | 851 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; |
854 | snd_pcm_trigger_done(s, subs); | 852 | snd_pcm_trigger_done(s, subs); |
855 | } | 853 | } |
856 | tasklet_schedule(&chip->mgr->trigger_taskq); | 854 | pcxhr_start_linked_stream(chip->mgr); |
857 | } else { | 855 | } else { |
858 | stream = subs->runtime->private_data; | 856 | stream = subs->runtime->private_data; |
859 | snd_printdd("Only one Substream %c %d\n", | 857 | snd_printdd("Only one Substream %c %d\n", |
@@ -1127,20 +1125,19 @@ static int pcxhr_close(struct snd_pcm_substream *subs) | |||
1127 | 1125 | ||
1128 | static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) | 1126 | static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) |
1129 | { | 1127 | { |
1130 | unsigned long flags; | ||
1131 | u_int32_t timer_period_frag; | 1128 | u_int32_t timer_period_frag; |
1132 | int timer_buf_periods; | 1129 | int timer_buf_periods; |
1133 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); | 1130 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); |
1134 | struct snd_pcm_runtime *runtime = subs->runtime; | 1131 | struct snd_pcm_runtime *runtime = subs->runtime; |
1135 | struct pcxhr_stream *stream = runtime->private_data; | 1132 | struct pcxhr_stream *stream = runtime->private_data; |
1136 | 1133 | ||
1137 | spin_lock_irqsave(&chip->mgr->lock, flags); | 1134 | mutex_lock(&chip->mgr->lock); |
1138 | 1135 | ||
1139 | /* get the period fragment and the nb of periods in the buffer */ | 1136 | /* get the period fragment and the nb of periods in the buffer */ |
1140 | timer_period_frag = stream->timer_period_frag; | 1137 | timer_period_frag = stream->timer_period_frag; |
1141 | timer_buf_periods = stream->timer_buf_periods; | 1138 | timer_buf_periods = stream->timer_buf_periods; |
1142 | 1139 | ||
1143 | spin_unlock_irqrestore(&chip->mgr->lock, flags); | 1140 | mutex_unlock(&chip->mgr->lock); |
1144 | 1141 | ||
1145 | return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) + | 1142 | return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) + |
1146 | timer_period_frag); | 1143 | timer_period_frag); |
@@ -1181,6 +1178,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip) | |||
1181 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops); | 1178 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops); |
1182 | 1179 | ||
1183 | pcm->info_flags = 0; | 1180 | pcm->info_flags = 0; |
1181 | pcm->nonatomic = true; | ||
1184 | strcpy(pcm->name, name); | 1182 | strcpy(pcm->name, name); |
1185 | 1183 | ||
1186 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1184 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
@@ -1588,8 +1586,9 @@ static int pcxhr_probe(struct pci_dev *pci, | |||
1588 | mgr->pci = pci; | 1586 | mgr->pci = pci; |
1589 | mgr->irq = -1; | 1587 | mgr->irq = -1; |
1590 | 1588 | ||
1591 | if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, | 1589 | if (request_threaded_irq(pci->irq, pcxhr_interrupt, |
1592 | KBUILD_MODNAME, mgr)) { | 1590 | pcxhr_threaded_irq, IRQF_SHARED, |
1591 | KBUILD_MODNAME, mgr)) { | ||
1593 | dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); | 1592 | dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); |
1594 | pcxhr_free(mgr); | 1593 | pcxhr_free(mgr); |
1595 | return -EBUSY; | 1594 | return -EBUSY; |
@@ -1601,19 +1600,13 @@ static int pcxhr_probe(struct pci_dev *pci, | |||
1601 | mgr->shortname, | 1600 | mgr->shortname, |
1602 | mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq); | 1601 | mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq); |
1603 | 1602 | ||
1604 | /* ISR spinlock */ | 1603 | /* ISR lock */ |
1605 | spin_lock_init(&mgr->lock); | 1604 | mutex_init(&mgr->lock); |
1606 | spin_lock_init(&mgr->msg_lock); | 1605 | mutex_init(&mgr->msg_lock); |
1607 | 1606 | ||
1608 | /* init setup mutex*/ | 1607 | /* init setup mutex*/ |
1609 | mutex_init(&mgr->setup_mutex); | 1608 | mutex_init(&mgr->setup_mutex); |
1610 | 1609 | ||
1611 | /* init taslket */ | ||
1612 | tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, | ||
1613 | (unsigned long) mgr); | ||
1614 | tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, | ||
1615 | (unsigned long) mgr); | ||
1616 | |||
1617 | mgr->prmh = kmalloc(sizeof(*mgr->prmh) + | 1610 | mgr->prmh = kmalloc(sizeof(*mgr->prmh) + |
1618 | sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - | 1611 | sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - |
1619 | PCXHR_SIZE_MAX_STATUS), | 1612 | PCXHR_SIZE_MAX_STATUS), |
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index a4c602c45173..9e39e509a3ef 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h | |||
@@ -78,14 +78,10 @@ struct pcxhr_mgr { | |||
78 | char shortname[32]; /* short name of this soundcard */ | 78 | char shortname[32]; /* short name of this soundcard */ |
79 | char longname[96]; /* name of this soundcard */ | 79 | char longname[96]; /* name of this soundcard */ |
80 | 80 | ||
81 | /* message tasklet */ | ||
82 | struct tasklet_struct msg_taskq; | ||
83 | struct pcxhr_rmh *prmh; | 81 | struct pcxhr_rmh *prmh; |
84 | /* trigger tasklet */ | ||
85 | struct tasklet_struct trigger_taskq; | ||
86 | 82 | ||
87 | spinlock_t lock; /* interrupt spinlock */ | 83 | struct mutex lock; /* interrupt lock */ |
88 | spinlock_t msg_lock; /* message spinlock */ | 84 | struct mutex msg_lock; /* message lock */ |
89 | 85 | ||
90 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ | 86 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ |
91 | struct mutex mixer_mutex; /* mutex for mixer */ | 87 | struct mutex mixer_mutex; /* mutex for mixer */ |
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index df9371918601..a584acb61c00 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -767,11 +767,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, | |||
767 | */ | 767 | */ |
768 | int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) | 768 | int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) |
769 | { | 769 | { |
770 | unsigned long flags; | ||
771 | int err; | 770 | int err; |
772 | spin_lock_irqsave(&mgr->msg_lock, flags); | 771 | |
772 | mutex_lock(&mgr->msg_lock); | ||
773 | err = pcxhr_send_msg_nolock(mgr, rmh); | 773 | err = pcxhr_send_msg_nolock(mgr, rmh); |
774 | spin_unlock_irqrestore(&mgr->msg_lock, flags); | 774 | mutex_unlock(&mgr->msg_lock); |
775 | return err; | 775 | return err; |
776 | } | 776 | } |
777 | 777 | ||
@@ -971,17 +971,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, | |||
971 | unsigned int value, int *changed) | 971 | unsigned int value, int *changed) |
972 | { | 972 | { |
973 | struct pcxhr_rmh rmh; | 973 | struct pcxhr_rmh rmh; |
974 | unsigned long flags; | ||
975 | int err; | 974 | int err; |
976 | 975 | ||
977 | spin_lock_irqsave(&mgr->msg_lock, flags); | 976 | mutex_lock(&mgr->msg_lock); |
978 | if ((mgr->io_num_reg_cont & mask) == value) { | 977 | if ((mgr->io_num_reg_cont & mask) == value) { |
979 | dev_dbg(&mgr->pci->dev, | 978 | dev_dbg(&mgr->pci->dev, |
980 | "IO_NUM_REG_CONT mask %x already is set to %x\n", | 979 | "IO_NUM_REG_CONT mask %x already is set to %x\n", |
981 | mask, value); | 980 | mask, value); |
982 | if (changed) | 981 | if (changed) |
983 | *changed = 0; | 982 | *changed = 0; |
984 | spin_unlock_irqrestore(&mgr->msg_lock, flags); | 983 | mutex_unlock(&mgr->msg_lock); |
985 | return 0; /* already programmed */ | 984 | return 0; /* already programmed */ |
986 | } | 985 | } |
987 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); | 986 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); |
@@ -996,7 +995,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, | |||
996 | if (changed) | 995 | if (changed) |
997 | *changed = 1; | 996 | *changed = 1; |
998 | } | 997 | } |
999 | spin_unlock_irqrestore(&mgr->msg_lock, flags); | 998 | mutex_unlock(&mgr->msg_lock); |
1000 | return err; | 999 | return err; |
1001 | } | 1000 | } |
1002 | 1001 | ||
@@ -1043,22 +1042,21 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, | |||
1043 | } | 1042 | } |
1044 | 1043 | ||
1045 | 1044 | ||
1046 | void pcxhr_msg_tasklet(unsigned long arg) | 1045 | static void pcxhr_msg_thread(struct pcxhr_mgr *mgr) |
1047 | { | 1046 | { |
1048 | struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg); | ||
1049 | struct pcxhr_rmh *prmh = mgr->prmh; | 1047 | struct pcxhr_rmh *prmh = mgr->prmh; |
1050 | int err; | 1048 | int err; |
1051 | int i, j; | 1049 | int i, j; |
1052 | 1050 | ||
1053 | if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) | 1051 | if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) |
1054 | dev_dbg(&mgr->pci->dev, | 1052 | dev_dbg(&mgr->pci->dev, |
1055 | "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); | 1053 | "PCXHR_IRQ_FREQ_CHANGE event occurred\n"); |
1056 | if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) | 1054 | if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) |
1057 | dev_dbg(&mgr->pci->dev, | 1055 | dev_dbg(&mgr->pci->dev, |
1058 | "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); | 1056 | "PCXHR_IRQ_TIME_CODE event occurred\n"); |
1059 | if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) | 1057 | if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) |
1060 | dev_dbg(&mgr->pci->dev, | 1058 | dev_dbg(&mgr->pci->dev, |
1061 | "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); | 1059 | "PCXHR_IRQ_NOTIFY event occurred\n"); |
1062 | if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { | 1060 | if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { |
1063 | /* clear events FREQ_CHANGE and TIME_CODE */ | 1061 | /* clear events FREQ_CHANGE and TIME_CODE */ |
1064 | pcxhr_init_rmh(prmh, CMD_TEST_IT); | 1062 | pcxhr_init_rmh(prmh, CMD_TEST_IT); |
@@ -1068,7 +1066,7 @@ void pcxhr_msg_tasklet(unsigned long arg) | |||
1068 | } | 1066 | } |
1069 | if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { | 1067 | if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { |
1070 | dev_dbg(&mgr->pci->dev, | 1068 | dev_dbg(&mgr->pci->dev, |
1071 | "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); | 1069 | "PCXHR_IRQ_ASYNC event occurred\n"); |
1072 | 1070 | ||
1073 | pcxhr_init_rmh(prmh, CMD_ASYNC); | 1071 | pcxhr_init_rmh(prmh, CMD_ASYNC); |
1074 | prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ | 1072 | prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ |
@@ -1076,7 +1074,7 @@ void pcxhr_msg_tasklet(unsigned long arg) | |||
1076 | prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; | 1074 | prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; |
1077 | err = pcxhr_send_msg(mgr, prmh); | 1075 | err = pcxhr_send_msg(mgr, prmh); |
1078 | if (err) | 1076 | if (err) |
1079 | dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n", | 1077 | dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n", |
1080 | err); | 1078 | err); |
1081 | i = 1; | 1079 | i = 1; |
1082 | while (i < prmh->stat_len) { | 1080 | while (i < prmh->stat_len) { |
@@ -1220,9 +1218,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, | |||
1220 | } | 1218 | } |
1221 | 1219 | ||
1222 | if (elapsed) { | 1220 | if (elapsed) { |
1223 | spin_unlock(&mgr->lock); | 1221 | mutex_unlock(&mgr->lock); |
1224 | snd_pcm_period_elapsed(stream->substream); | 1222 | snd_pcm_period_elapsed(stream->substream); |
1225 | spin_lock(&mgr->lock); | 1223 | mutex_lock(&mgr->lock); |
1226 | } | 1224 | } |
1227 | } | 1225 | } |
1228 | } | 1226 | } |
@@ -1231,14 +1229,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) | |||
1231 | { | 1229 | { |
1232 | struct pcxhr_mgr *mgr = dev_id; | 1230 | struct pcxhr_mgr *mgr = dev_id; |
1233 | unsigned int reg; | 1231 | unsigned int reg; |
1234 | int i, j; | 1232 | bool wake_thread = false; |
1235 | struct snd_pcxhr *chip; | ||
1236 | |||
1237 | spin_lock(&mgr->lock); | ||
1238 | 1233 | ||
1239 | reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); | 1234 | reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); |
1240 | if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { | 1235 | if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { |
1241 | spin_unlock(&mgr->lock); | ||
1242 | /* this device did not cause the interrupt */ | 1236 | /* this device did not cause the interrupt */ |
1243 | return IRQ_NONE; | 1237 | return IRQ_NONE; |
1244 | } | 1238 | } |
@@ -1250,6 +1244,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) | |||
1250 | /* timer irq occurred */ | 1244 | /* timer irq occurred */ |
1251 | if (reg & PCXHR_IRQ_TIMER) { | 1245 | if (reg & PCXHR_IRQ_TIMER) { |
1252 | int timer_toggle = reg & PCXHR_IRQ_TIMER; | 1246 | int timer_toggle = reg & PCXHR_IRQ_TIMER; |
1247 | if (timer_toggle == mgr->timer_toggle) { | ||
1248 | dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n"); | ||
1249 | mgr->dsp_time_err++; | ||
1250 | } | ||
1251 | |||
1252 | mgr->timer_toggle = timer_toggle; | ||
1253 | mgr->src_it_dsp = reg; | ||
1254 | wake_thread = true; | ||
1255 | } | ||
1256 | |||
1257 | /* other irq's handled in the thread */ | ||
1258 | if (reg & PCXHR_IRQ_MASK) { | ||
1259 | if (reg & PCXHR_IRQ_ASYNC) { | ||
1260 | /* as we didn't request any async notifications, | ||
1261 | * some kind of xrun error will probably occurred | ||
1262 | */ | ||
1263 | /* better resynchronize all streams next interrupt : */ | ||
1264 | mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; | ||
1265 | } | ||
1266 | mgr->src_it_dsp = reg; | ||
1267 | wake_thread = true; | ||
1268 | } | ||
1269 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
1270 | if (reg & PCXHR_FATAL_DSP_ERR) | ||
1271 | dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg); | ||
1272 | #endif | ||
1273 | |||
1274 | return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED; | ||
1275 | } | ||
1276 | |||
1277 | irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id) | ||
1278 | { | ||
1279 | struct pcxhr_mgr *mgr = dev_id; | ||
1280 | int i, j; | ||
1281 | struct snd_pcxhr *chip; | ||
1282 | |||
1283 | mutex_lock(&mgr->lock); | ||
1284 | if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) { | ||
1253 | /* is a 24 bit counter */ | 1285 | /* is a 24 bit counter */ |
1254 | int dsp_time_new = | 1286 | int dsp_time_new = |
1255 | PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; | 1287 | PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; |
@@ -1290,13 +1322,6 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) | |||
1290 | #endif | 1322 | #endif |
1291 | mgr->dsp_time_last = dsp_time_new; | 1323 | mgr->dsp_time_last = dsp_time_new; |
1292 | 1324 | ||
1293 | if (timer_toggle == mgr->timer_toggle) { | ||
1294 | dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n"); | ||
1295 | mgr->dsp_time_err++; | ||
1296 | } | ||
1297 | mgr->timer_toggle = timer_toggle; | ||
1298 | |||
1299 | reg &= ~PCXHR_IRQ_TIMER; | ||
1300 | for (i = 0; i < mgr->num_cards; i++) { | 1325 | for (i = 0; i < mgr->num_cards; i++) { |
1301 | chip = mgr->chip[i]; | 1326 | chip = mgr->chip[i]; |
1302 | for (j = 0; j < chip->nb_streams_capt; j++) | 1327 | for (j = 0; j < chip->nb_streams_capt; j++) |
@@ -1312,22 +1337,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) | |||
1312 | dsp_time_diff); | 1337 | dsp_time_diff); |
1313 | } | 1338 | } |
1314 | } | 1339 | } |
1315 | /* other irq's handled in the tasklet */ | 1340 | |
1316 | if (reg & PCXHR_IRQ_MASK) { | 1341 | pcxhr_msg_thread(mgr); |
1317 | if (reg & PCXHR_IRQ_ASYNC) { | 1342 | return IRQ_HANDLED; |
1318 | /* as we didn't request any async notifications, | ||
1319 | * some kind of xrun error will probably occurred | ||
1320 | */ | ||
1321 | /* better resynchronize all streams next interrupt : */ | ||
1322 | mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; | ||
1323 | } | ||
1324 | mgr->src_it_dsp = reg; | ||
1325 | tasklet_schedule(&mgr->msg_taskq); | ||
1326 | } | ||
1327 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
1328 | if (reg & PCXHR_FATAL_DSP_ERR) | ||
1329 | dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg); | ||
1330 | #endif | ||
1331 | spin_unlock(&mgr->lock); | ||
1332 | return IRQ_HANDLED; /* this device caused the interrupt */ | ||
1333 | } | 1343 | } |
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index a81ab6b811e7..dc267e4c1074 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h | |||
@@ -200,6 +200,6 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, | |||
200 | 200 | ||
201 | /* interrupt handling */ | 201 | /* interrupt handling */ |
202 | irqreturn_t pcxhr_interrupt(int irq, void *dev_id); | 202 | irqreturn_t pcxhr_interrupt(int irq, void *dev_id); |
203 | void pcxhr_msg_tasklet(unsigned long arg); | 203 | irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id); |
204 | 204 | ||
205 | #endif /* __SOUND_PCXHR_CORE_H */ | 205 | #endif /* __SOUND_PCXHR_CORE_H */ |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 3dc4732142ee..c5a25e39e3a8 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -168,8 +168,9 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, | |||
168 | for (i = 0; i < 2; i++) | 168 | for (i = 0; i < 2; i++) |
169 | vx->port[i] = pci_resource_start(pci, i + 1); | 169 | vx->port[i] = pci_resource_start(pci, i + 1); |
170 | 170 | ||
171 | if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED, | 171 | if (request_threaded_irq(pci->irq, snd_vx_irq_handler, |
172 | KBUILD_MODNAME, chip)) { | 172 | snd_vx_threaded_irq_handler, IRQF_SHARED, |
173 | KBUILD_MODNAME, chip)) { | ||
173 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); | 174 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); |
174 | snd_vx222_free(chip); | 175 | snd_vx222_free(chip); |
175 | return -EBUSY; | 176 | return -EBUSY; |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 56bda124cd4a..07f4b33db3af 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -61,6 +61,7 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev); | |||
61 | 61 | ||
62 | static void pdacf_release(struct pcmcia_device *link) | 62 | static void pdacf_release(struct pcmcia_device *link) |
63 | { | 63 | { |
64 | free_irq(link->irq, link->priv); | ||
64 | pcmcia_disable_device(link); | 65 | pcmcia_disable_device(link); |
65 | } | 66 | } |
66 | 67 | ||
@@ -220,11 +221,13 @@ static int pdacf_config(struct pcmcia_device *link) | |||
220 | 221 | ||
221 | ret = pcmcia_request_io(link); | 222 | ret = pcmcia_request_io(link); |
222 | if (ret) | 223 | if (ret) |
223 | goto failed; | 224 | goto failed_preirq; |
224 | 225 | ||
225 | ret = pcmcia_request_irq(link, pdacf_interrupt); | 226 | ret = request_threaded_irq(link->irq, pdacf_interrupt, |
227 | pdacf_threaded_irq, | ||
228 | IRQF_SHARED, link->devname, link->priv); | ||
226 | if (ret) | 229 | if (ret) |
227 | goto failed; | 230 | goto failed_preirq; |
228 | 231 | ||
229 | ret = pcmcia_enable_device(link); | 232 | ret = pcmcia_enable_device(link); |
230 | if (ret) | 233 | if (ret) |
@@ -236,7 +239,9 @@ static int pdacf_config(struct pcmcia_device *link) | |||
236 | 239 | ||
237 | return 0; | 240 | return 0; |
238 | 241 | ||
239 | failed: | 242 | failed: |
243 | free_irq(link->irq, link->priv); | ||
244 | failed_preirq: | ||
240 | pcmcia_disable_device(link); | 245 | pcmcia_disable_device(link); |
241 | return -ENODEV; | 246 | return -ENODEV; |
242 | } | 247 | } |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index ea41e57d7179..e9a7d3a784f7 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h | |||
@@ -88,10 +88,9 @@ struct snd_pdacf { | |||
88 | unsigned long port; | 88 | unsigned long port; |
89 | int irq; | 89 | int irq; |
90 | 90 | ||
91 | spinlock_t reg_lock; | 91 | struct mutex reg_lock; |
92 | unsigned short regmap[8]; | 92 | unsigned short regmap[8]; |
93 | unsigned short suspend_reg_scr; | 93 | unsigned short suspend_reg_scr; |
94 | struct tasklet_struct tq; | ||
95 | 94 | ||
96 | spinlock_t ak4117_lock; | 95 | spinlock_t ak4117_lock; |
97 | struct ak4117 *ak4117; | 96 | struct ak4117 *ak4117; |
@@ -136,7 +135,7 @@ int snd_pdacf_resume(struct snd_pdacf *chip); | |||
136 | #endif | 135 | #endif |
137 | int snd_pdacf_pcm_new(struct snd_pdacf *chip); | 136 | int snd_pdacf_pcm_new(struct snd_pdacf *chip); |
138 | irqreturn_t pdacf_interrupt(int irq, void *dev); | 137 | irqreturn_t pdacf_interrupt(int irq, void *dev); |
139 | void pdacf_tasklet(unsigned long private_data); | 138 | irqreturn_t pdacf_threaded_irq(int irq, void *dev); |
140 | void pdacf_reinit(struct snd_pdacf *chip, int resume); | 139 | void pdacf_reinit(struct snd_pdacf *chip, int resume); |
141 | 140 | ||
142 | #endif /* __PDAUDIOCF_H */ | 141 | #endif /* __PDAUDIOCF_H */ |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index ea0adfb984ad..d724ab0653cf 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | |||
@@ -162,9 +162,8 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card) | |||
162 | if (chip == NULL) | 162 | if (chip == NULL) |
163 | return NULL; | 163 | return NULL; |
164 | chip->card = card; | 164 | chip->card = card; |
165 | spin_lock_init(&chip->reg_lock); | 165 | mutex_init(&chip->reg_lock); |
166 | spin_lock_init(&chip->ak4117_lock); | 166 | spin_lock_init(&chip->ak4117_lock); |
167 | tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip); | ||
168 | card->private_data = chip; | 167 | card->private_data = chip; |
169 | 168 | ||
170 | pdacf_proc_init(chip); | 169 | pdacf_proc_init(chip); |
@@ -174,19 +173,18 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card) | |||
174 | static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1) | 173 | static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1) |
175 | { | 174 | { |
176 | struct snd_pdacf *chip = ak4117->change_callback_private; | 175 | struct snd_pdacf *chip = ak4117->change_callback_private; |
177 | unsigned long flags; | ||
178 | u16 val; | 176 | u16 val; |
179 | 177 | ||
180 | if (!(c0 & AK4117_UNLCK)) | 178 | if (!(c0 & AK4117_UNLCK)) |
181 | return; | 179 | return; |
182 | spin_lock_irqsave(&chip->reg_lock, flags); | 180 | mutex_lock(&chip->reg_lock); |
183 | val = chip->regmap[PDAUDIOCF_REG_SCR>>1]; | 181 | val = chip->regmap[PDAUDIOCF_REG_SCR>>1]; |
184 | if (ak4117->rcs0 & AK4117_UNLCK) | 182 | if (ak4117->rcs0 & AK4117_UNLCK) |
185 | val |= PDAUDIOCF_BLUE_LED_OFF; | 183 | val |= PDAUDIOCF_BLUE_LED_OFF; |
186 | else | 184 | else |
187 | val &= ~PDAUDIOCF_BLUE_LED_OFF; | 185 | val &= ~PDAUDIOCF_BLUE_LED_OFF; |
188 | pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); | 186 | pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); |
189 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 187 | mutex_unlock(&chip->reg_lock); |
190 | } | 188 | } |
191 | 189 | ||
192 | int snd_pdacf_ak4117_create(struct snd_pdacf *chip) | 190 | int snd_pdacf_ak4117_create(struct snd_pdacf *chip) |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c index dcd32201bc8c..ecf0fbd91794 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | |||
@@ -30,6 +30,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev) | |||
30 | { | 30 | { |
31 | struct snd_pdacf *chip = dev; | 31 | struct snd_pdacf *chip = dev; |
32 | unsigned short stat; | 32 | unsigned short stat; |
33 | bool wake_thread = false; | ||
33 | 34 | ||
34 | if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE| | 35 | if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE| |
35 | PDAUDIOCF_STAT_IS_CONFIGURED| | 36 | PDAUDIOCF_STAT_IS_CONFIGURED| |
@@ -41,13 +42,13 @@ irqreturn_t pdacf_interrupt(int irq, void *dev) | |||
41 | if (stat & PDAUDIOCF_IRQOVR) /* should never happen */ | 42 | if (stat & PDAUDIOCF_IRQOVR) /* should never happen */ |
42 | snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n"); | 43 | snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n"); |
43 | if (chip->pcm_substream) | 44 | if (chip->pcm_substream) |
44 | tasklet_schedule(&chip->tq); | 45 | wake_thread = true; |
45 | if (!(stat & PDAUDIOCF_IRQAKM)) | 46 | if (!(stat & PDAUDIOCF_IRQAKM)) |
46 | stat |= PDAUDIOCF_IRQAKM; /* check rate */ | 47 | stat |= PDAUDIOCF_IRQAKM; /* check rate */ |
47 | } | 48 | } |
48 | if (get_irq_regs() != NULL) | 49 | if (get_irq_regs() != NULL) |
49 | snd_ak4117_check_rate_and_errors(chip->ak4117, 0); | 50 | snd_ak4117_check_rate_and_errors(chip->ak4117, 0); |
50 | return IRQ_HANDLED; | 51 | return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED; |
51 | } | 52 | } |
52 | 53 | ||
53 | static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) | 54 | static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) |
@@ -256,16 +257,16 @@ static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned i | |||
256 | } | 257 | } |
257 | } | 258 | } |
258 | 259 | ||
259 | void pdacf_tasklet(unsigned long private_data) | 260 | irqreturn_t pdacf_threaded_irq(int irq, void *dev) |
260 | { | 261 | { |
261 | struct snd_pdacf *chip = (struct snd_pdacf *) private_data; | 262 | struct snd_pdacf *chip = dev; |
262 | int size, off, cont, rdp, wdp; | 263 | int size, off, cont, rdp, wdp; |
263 | 264 | ||
264 | if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED) | 265 | if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED) |
265 | return; | 266 | return IRQ_HANDLED; |
266 | 267 | ||
267 | if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream)) | 268 | if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream)) |
268 | return; | 269 | return IRQ_HANDLED; |
269 | 270 | ||
270 | rdp = inw(chip->port + PDAUDIOCF_REG_RDP); | 271 | rdp = inw(chip->port + PDAUDIOCF_REG_RDP); |
271 | wdp = inw(chip->port + PDAUDIOCF_REG_WDP); | 272 | wdp = inw(chip->port + PDAUDIOCF_REG_WDP); |
@@ -311,15 +312,15 @@ void pdacf_tasklet(unsigned long private_data) | |||
311 | size -= cont; | 312 | size -= cont; |
312 | } | 313 | } |
313 | #endif | 314 | #endif |
314 | spin_lock(&chip->reg_lock); | 315 | mutex_lock(&chip->reg_lock); |
315 | while (chip->pcm_tdone >= chip->pcm_period) { | 316 | while (chip->pcm_tdone >= chip->pcm_period) { |
316 | chip->pcm_hwptr += chip->pcm_period; | 317 | chip->pcm_hwptr += chip->pcm_period; |
317 | chip->pcm_hwptr %= chip->pcm_size; | 318 | chip->pcm_hwptr %= chip->pcm_size; |
318 | chip->pcm_tdone -= chip->pcm_period; | 319 | chip->pcm_tdone -= chip->pcm_period; |
319 | spin_unlock(&chip->reg_lock); | 320 | mutex_unlock(&chip->reg_lock); |
320 | snd_pcm_period_elapsed(chip->pcm_substream); | 321 | snd_pcm_period_elapsed(chip->pcm_substream); |
321 | spin_lock(&chip->reg_lock); | 322 | mutex_lock(&chip->reg_lock); |
322 | } | 323 | } |
323 | spin_unlock(&chip->reg_lock); | 324 | mutex_unlock(&chip->reg_lock); |
324 | /* printk(KERN_DEBUG "TASKLET: end\n"); */ | 325 | return IRQ_HANDLED; |
325 | } | 326 | } |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 43f995a3f960..b48aa0a78c19 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | |||
@@ -77,7 +77,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) | |||
77 | default: | 77 | default: |
78 | return -EINVAL; | 78 | return -EINVAL; |
79 | } | 79 | } |
80 | spin_lock(&chip->reg_lock); | 80 | mutex_lock(&chip->reg_lock); |
81 | chip->pcm_running += inc; | 81 | chip->pcm_running += inc; |
82 | tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); | 82 | tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); |
83 | if (chip->pcm_running) { | 83 | if (chip->pcm_running) { |
@@ -91,7 +91,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) | |||
91 | tmp |= val; | 91 | tmp |= val; |
92 | pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); | 92 | pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); |
93 | __end: | 93 | __end: |
94 | spin_unlock(&chip->reg_lock); | 94 | mutex_unlock(&chip->reg_lock); |
95 | snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); | 95 | snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); |
96 | return ret; | 96 | return ret; |
97 | } | 97 | } |
@@ -296,6 +296,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip) | |||
296 | 296 | ||
297 | pcm->private_data = chip; | 297 | pcm->private_data = chip; |
298 | pcm->info_flags = 0; | 298 | pcm->info_flags = 0; |
299 | pcm->nonatomic = true; | ||
299 | strcpy(pcm->name, chip->card->shortname); | 300 | strcpy(pcm->name, chip->card->shortname); |
300 | chip->pcm = pcm; | 301 | chip->pcm = pcm; |
301 | 302 | ||
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index fe33e122e372..281972913c32 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c | |||
@@ -468,12 +468,11 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da | |||
468 | void vx_set_mic_boost(struct vx_core *chip, int boost) | 468 | void vx_set_mic_boost(struct vx_core *chip, int boost) |
469 | { | 469 | { |
470 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; | 470 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; |
471 | unsigned long flags; | ||
472 | 471 | ||
473 | if (chip->chip_status & VX_STAT_IS_STALE) | 472 | if (chip->chip_status & VX_STAT_IS_STALE) |
474 | return; | 473 | return; |
475 | 474 | ||
476 | spin_lock_irqsave(&chip->lock, flags); | 475 | mutex_lock(&chip->lock); |
477 | if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) { | 476 | if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) { |
478 | if (boost) { | 477 | if (boost) { |
479 | /* boost: 38 dB */ | 478 | /* boost: 38 dB */ |
@@ -486,7 +485,7 @@ void vx_set_mic_boost(struct vx_core *chip, int boost) | |||
486 | } | 485 | } |
487 | vx_outb(chip, CDSP, pchip->regCDSP); | 486 | vx_outb(chip, CDSP, pchip->regCDSP); |
488 | } | 487 | } |
489 | spin_unlock_irqrestore(&chip->lock, flags); | 488 | mutex_unlock(&chip->lock); |
490 | } | 489 | } |
491 | 490 | ||
492 | /* | 491 | /* |
@@ -511,17 +510,16 @@ static int vx_compute_mic_level(int level) | |||
511 | void vx_set_mic_level(struct vx_core *chip, int level) | 510 | void vx_set_mic_level(struct vx_core *chip, int level) |
512 | { | 511 | { |
513 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; | 512 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; |
514 | unsigned long flags; | ||
515 | 513 | ||
516 | if (chip->chip_status & VX_STAT_IS_STALE) | 514 | if (chip->chip_status & VX_STAT_IS_STALE) |
517 | return; | 515 | return; |
518 | 516 | ||
519 | spin_lock_irqsave(&chip->lock, flags); | 517 | mutex_lock(&chip->lock); |
520 | if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) { | 518 | if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) { |
521 | level = vx_compute_mic_level(level); | 519 | level = vx_compute_mic_level(level); |
522 | vx_outb(chip, MICRO, level); | 520 | vx_outb(chip, MICRO, level); |
523 | } | 521 | } |
524 | spin_unlock_irqrestore(&chip->lock, flags); | 522 | mutex_unlock(&chip->lock); |
525 | } | 523 | } |
526 | 524 | ||
527 | 525 | ||
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 786e7e139c9e..92ec11456e3a 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -62,6 +62,7 @@ static unsigned int card_alloc; | |||
62 | */ | 62 | */ |
63 | static void vxpocket_release(struct pcmcia_device *link) | 63 | static void vxpocket_release(struct pcmcia_device *link) |
64 | { | 64 | { |
65 | free_irq(link->irq, link->priv); | ||
65 | pcmcia_disable_device(link); | 66 | pcmcia_disable_device(link); |
66 | } | 67 | } |
67 | 68 | ||
@@ -227,11 +228,13 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
227 | 228 | ||
228 | ret = pcmcia_request_io(link); | 229 | ret = pcmcia_request_io(link); |
229 | if (ret) | 230 | if (ret) |
230 | goto failed; | 231 | goto failed_preirq; |
231 | 232 | ||
232 | ret = pcmcia_request_irq(link, snd_vx_irq_handler); | 233 | ret = request_threaded_irq(link->irq, snd_vx_irq_handler, |
234 | snd_vx_threaded_irq_handler, | ||
235 | IRQF_SHARED, link->devname, link->priv); | ||
233 | if (ret) | 236 | if (ret) |
234 | goto failed; | 237 | goto failed_preirq; |
235 | 238 | ||
236 | ret = pcmcia_enable_device(link); | 239 | ret = pcmcia_enable_device(link); |
237 | if (ret) | 240 | if (ret) |
@@ -245,7 +248,9 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
245 | 248 | ||
246 | return 0; | 249 | return 0; |
247 | 250 | ||
248 | failed: | 251 | failed: |
252 | free_irq(link->irq, link->priv); | ||
253 | failed_preirq: | ||
249 | pcmcia_disable_device(link); | 254 | pcmcia_disable_device(link); |
250 | return -ENODEV; | 255 | return -ENODEV; |
251 | } | 256 | } |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 922006dd0583..e88a6b67f781 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -146,7 +146,7 @@ struct pm860x_priv { | |||
146 | struct pm860x_det det; | 146 | struct pm860x_det det; |
147 | 147 | ||
148 | int irq[4]; | 148 | int irq[4]; |
149 | unsigned char name[4][MAX_NAME_LEN]; | 149 | unsigned char name[4][MAX_NAME_LEN+1]; |
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ | 152 | /* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ |
@@ -1337,8 +1337,6 @@ static int pm860x_probe(struct snd_soc_codec *codec) | |||
1337 | } | 1337 | } |
1338 | } | 1338 | } |
1339 | 1339 | ||
1340 | pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1341 | |||
1342 | return 0; | 1340 | return 0; |
1343 | 1341 | ||
1344 | out: | 1342 | out: |
@@ -1354,7 +1352,6 @@ static int pm860x_remove(struct snd_soc_codec *codec) | |||
1354 | 1352 | ||
1355 | for (i = 3; i >= 0; i--) | 1353 | for (i = 3; i >= 0; i--) |
1356 | free_irq(pm860x->irq[i], pm860x); | 1354 | free_irq(pm860x->irq[i], pm860x); |
1357 | pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1358 | return 0; | 1355 | return 0; |
1359 | } | 1356 | } |
1360 | 1357 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8838838e25ed..a68d1731a8fd 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS | |||
43 | select SND_SOC_ALC5623 if I2C | 43 | select SND_SOC_ALC5623 if I2C |
44 | select SND_SOC_ALC5632 if I2C | 44 | select SND_SOC_ALC5632 if I2C |
45 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC | 45 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC |
46 | select SND_SOC_CS35L32 if I2C | ||
46 | select SND_SOC_CS42L51_I2C if I2C | 47 | select SND_SOC_CS42L51_I2C if I2C |
47 | select SND_SOC_CS42L52 if I2C && INPUT | 48 | select SND_SOC_CS42L52 if I2C && INPUT |
48 | select SND_SOC_CS42L56 if I2C && INPUT | 49 | select SND_SOC_CS42L56 if I2C && INPUT |
@@ -56,7 +57,10 @@ config SND_SOC_ALL_CODECS | |||
56 | select SND_SOC_DA7213 if I2C | 57 | select SND_SOC_DA7213 if I2C |
57 | select SND_SOC_DA732X if I2C | 58 | select SND_SOC_DA732X if I2C |
58 | select SND_SOC_DA9055 if I2C | 59 | select SND_SOC_DA9055 if I2C |
60 | select SND_SOC_DMIC | ||
59 | select SND_SOC_BT_SCO | 61 | select SND_SOC_BT_SCO |
62 | select SND_SOC_ES8328_SPI if SPI_MASTER | ||
63 | select SND_SOC_ES8328_I2C if I2C | ||
60 | select SND_SOC_ISABELLE if I2C | 64 | select SND_SOC_ISABELLE if I2C |
61 | select SND_SOC_JZ4740_CODEC | 65 | select SND_SOC_JZ4740_CODEC |
62 | select SND_SOC_LM4857 if I2C | 66 | select SND_SOC_LM4857 if I2C |
@@ -90,6 +94,7 @@ config SND_SOC_ALL_CODECS | |||
90 | select SND_SOC_SSM2518 if I2C | 94 | select SND_SOC_SSM2518 if I2C |
91 | select SND_SOC_SSM2602_SPI if SPI_MASTER | 95 | select SND_SOC_SSM2602_SPI if SPI_MASTER |
92 | select SND_SOC_SSM2602_I2C if I2C | 96 | select SND_SOC_SSM2602_I2C if I2C |
97 | select SND_SOC_SSM4567 if I2C | ||
93 | select SND_SOC_STA32X if I2C | 98 | select SND_SOC_STA32X if I2C |
94 | select SND_SOC_STA350 if I2C | 99 | select SND_SOC_STA350 if I2C |
95 | select SND_SOC_STA529 if I2C | 100 | select SND_SOC_STA529 if I2C |
@@ -323,6 +328,10 @@ config SND_SOC_ALC5632 | |||
323 | config SND_SOC_CQ0093VC | 328 | config SND_SOC_CQ0093VC |
324 | tristate | 329 | tristate |
325 | 330 | ||
331 | config SND_SOC_CS35L32 | ||
332 | tristate "Cirrus Logic CS35L32 CODEC" | ||
333 | depends on I2C | ||
334 | |||
326 | config SND_SOC_CS42L51 | 335 | config SND_SOC_CS42L51 |
327 | tristate | 336 | tristate |
328 | 337 | ||
@@ -405,6 +414,17 @@ config SND_SOC_DMIC | |||
405 | config SND_SOC_HDMI_CODEC | 414 | config SND_SOC_HDMI_CODEC |
406 | tristate "HDMI stub CODEC" | 415 | tristate "HDMI stub CODEC" |
407 | 416 | ||
417 | config SND_SOC_ES8328 | ||
418 | tristate "Everest Semi ES8328 CODEC" | ||
419 | |||
420 | config SND_SOC_ES8328_I2C | ||
421 | tristate | ||
422 | select SND_SOC_ES8328 | ||
423 | |||
424 | config SND_SOC_ES8328_SPI | ||
425 | tristate | ||
426 | select SND_SOC_ES8328 | ||
427 | |||
408 | config SND_SOC_ISABELLE | 428 | config SND_SOC_ISABELLE |
409 | tristate | 429 | tristate |
410 | 430 | ||
@@ -464,6 +484,7 @@ config SND_SOC_RL6231 | |||
464 | 484 | ||
465 | config SND_SOC_RT286 | 485 | config SND_SOC_RT286 |
466 | tristate | 486 | tristate |
487 | depends on I2C | ||
467 | 488 | ||
468 | config SND_SOC_RT5631 | 489 | config SND_SOC_RT5631 |
469 | tristate | 490 | tristate |
@@ -520,12 +541,20 @@ config SND_SOC_SSM2602 | |||
520 | tristate | 541 | tristate |
521 | 542 | ||
522 | config SND_SOC_SSM2602_SPI | 543 | config SND_SOC_SSM2602_SPI |
544 | tristate "Analog Devices SSM2602 CODEC - SPI" | ||
545 | depends on SPI_MASTER | ||
523 | select SND_SOC_SSM2602 | 546 | select SND_SOC_SSM2602 |
524 | tristate | 547 | select REGMAP_SPI |
525 | 548 | ||
526 | config SND_SOC_SSM2602_I2C | 549 | config SND_SOC_SSM2602_I2C |
550 | tristate "Analog Devices SSM2602 CODEC - I2C" | ||
551 | depends on I2C | ||
527 | select SND_SOC_SSM2602 | 552 | select SND_SOC_SSM2602 |
528 | tristate | 553 | select REGMAP_I2C |
554 | |||
555 | config SND_SOC_SSM4567 | ||
556 | tristate "Analog Devices ssm4567 amplifier driver support" | ||
557 | depends on I2C | ||
529 | 558 | ||
530 | config SND_SOC_STA32X | 559 | config SND_SOC_STA32X |
531 | tristate | 560 | tristate |
@@ -712,7 +741,8 @@ config SND_SOC_WM8974 | |||
712 | tristate | 741 | tristate |
713 | 742 | ||
714 | config SND_SOC_WM8978 | 743 | config SND_SOC_WM8978 |
715 | tristate | 744 | tristate "Wolfson Microelectronics WM8978 codec" |
745 | depends on I2C | ||
716 | 746 | ||
717 | config SND_SOC_WM8983 | 747 | config SND_SOC_WM8983 |
718 | tristate | 748 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 20afe0f0c5be..5dce451661e4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -32,6 +32,7 @@ snd-soc-ak4671-objs := ak4671.o | |||
32 | snd-soc-ak5386-objs := ak5386.o | 32 | snd-soc-ak5386-objs := ak5386.o |
33 | snd-soc-arizona-objs := arizona.o | 33 | snd-soc-arizona-objs := arizona.o |
34 | snd-soc-cq93vc-objs := cq93vc.o | 34 | snd-soc-cq93vc-objs := cq93vc.o |
35 | snd-soc-cs35l32-objs := cs35l32.o | ||
35 | snd-soc-cs42l51-objs := cs42l51.o | 36 | snd-soc-cs42l51-objs := cs42l51.o |
36 | snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o | 37 | snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o |
37 | snd-soc-cs42l52-objs := cs42l52.o | 38 | snd-soc-cs42l52-objs := cs42l52.o |
@@ -49,6 +50,9 @@ snd-soc-da732x-objs := da732x.o | |||
49 | snd-soc-da9055-objs := da9055.o | 50 | snd-soc-da9055-objs := da9055.o |
50 | snd-soc-bt-sco-objs := bt-sco.o | 51 | snd-soc-bt-sco-objs := bt-sco.o |
51 | snd-soc-dmic-objs := dmic.o | 52 | snd-soc-dmic-objs := dmic.o |
53 | snd-soc-es8328-objs := es8328.o | ||
54 | snd-soc-es8328-i2c-objs := es8328-i2c.o | ||
55 | snd-soc-es8328-spi-objs := es8328-spi.o | ||
52 | snd-soc-isabelle-objs := isabelle.o | 56 | snd-soc-isabelle-objs := isabelle.o |
53 | snd-soc-jz4740-codec-objs := jz4740.o | 57 | snd-soc-jz4740-codec-objs := jz4740.o |
54 | snd-soc-l3-objs := l3.o | 58 | snd-soc-l3-objs := l3.o |
@@ -91,6 +95,7 @@ snd-soc-ssm2518-objs := ssm2518.o | |||
91 | snd-soc-ssm2602-objs := ssm2602.o | 95 | snd-soc-ssm2602-objs := ssm2602.o |
92 | snd-soc-ssm2602-spi-objs := ssm2602-spi.o | 96 | snd-soc-ssm2602-spi-objs := ssm2602-spi.o |
93 | snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o | 97 | snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o |
98 | snd-soc-ssm4567-objs := ssm4567.o | ||
94 | snd-soc-sta32x-objs := sta32x.o | 99 | snd-soc-sta32x-objs := sta32x.o |
95 | snd-soc-sta350-objs := sta350.o | 100 | snd-soc-sta350-objs := sta350.o |
96 | snd-soc-sta529-objs := sta529.o | 101 | snd-soc-sta529-objs := sta529.o |
@@ -203,6 +208,7 @@ obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | |||
203 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o | 208 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o |
204 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o | 209 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o |
205 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o | 210 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o |
211 | obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o | ||
206 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o | 212 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
207 | obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o | 213 | obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o |
208 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o | 214 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
@@ -220,6 +226,9 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | |||
220 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | 226 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o |
221 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o | 227 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o |
222 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 228 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
229 | obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o | ||
230 | obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o | ||
231 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o | ||
223 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 232 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
224 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 233 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
225 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 234 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
@@ -258,6 +267,7 @@ obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o | |||
258 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 267 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
259 | obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o | 268 | obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o |
260 | obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o | 269 | obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o |
270 | obj-$(CONFIG_SND_SOC_SSM4567) += snd-soc-ssm4567.o | ||
261 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 271 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
262 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o | 272 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o |
263 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 273 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 1fb4402bf72d..fd43827bb856 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -56,8 +56,7 @@ | |||
56 | #define GPIO31_DIR_OUTPUT 0x40 | 56 | #define GPIO31_DIR_OUTPUT 0x40 |
57 | 57 | ||
58 | /* Macrocell register definitions */ | 58 | /* Macrocell register definitions */ |
59 | #define AB8500_CTRL3_REG 0x0200 | 59 | #define AB8500_GPIO_DIR4_REG 0x13 /* Bank AB8500_MISC */ |
60 | #define AB8500_GPIO_DIR4_REG 0x1013 | ||
61 | 60 | ||
62 | /* Nr of FIR/IIR-coeff banks in ANC-block */ | 61 | /* Nr of FIR/IIR-coeff banks in ANC-block */ |
63 | #define AB8500_NR_OF_ANC_COEFF_BANKS 2 | 62 | #define AB8500_NR_OF_ANC_COEFF_BANKS 2 |
@@ -126,6 +125,8 @@ struct ab8500_codec_drvdata_dbg { | |||
126 | 125 | ||
127 | /* Private data for AB8500 device-driver */ | 126 | /* Private data for AB8500 device-driver */ |
128 | struct ab8500_codec_drvdata { | 127 | struct ab8500_codec_drvdata { |
128 | struct regmap *regmap; | ||
129 | |||
129 | /* Sidetone */ | 130 | /* Sidetone */ |
130 | long *sid_fir_values; | 131 | long *sid_fir_values; |
131 | enum sid_state sid_status; | 132 | enum sid_state sid_status; |
@@ -166,49 +167,35 @@ static inline const char *amic_type_str(enum amic_type type) | |||
166 | */ | 167 | */ |
167 | 168 | ||
168 | /* Read a register from the audio-bank of AB8500 */ | 169 | /* Read a register from the audio-bank of AB8500 */ |
169 | static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec, | 170 | static int ab8500_codec_read_reg(void *context, unsigned int reg, |
170 | unsigned int reg) | 171 | unsigned int *value) |
171 | { | 172 | { |
173 | struct device *dev = context; | ||
172 | int status; | 174 | int status; |
173 | unsigned int value = 0; | ||
174 | 175 | ||
175 | u8 value8; | 176 | u8 value8; |
176 | status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO, | 177 | status = abx500_get_register_interruptible(dev, AB8500_AUDIO, |
177 | reg, &value8); | 178 | reg, &value8); |
178 | if (status < 0) { | 179 | *value = (unsigned int)value8; |
179 | dev_err(codec->dev, | ||
180 | "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n", | ||
181 | __func__, (u8)AB8500_AUDIO, (u8)reg, status); | ||
182 | } else { | ||
183 | dev_dbg(codec->dev, | ||
184 | "%s: Read 0x%02x from register 0x%02x:0x%02x\n", | ||
185 | __func__, value8, (u8)AB8500_AUDIO, (u8)reg); | ||
186 | value = (unsigned int)value8; | ||
187 | } | ||
188 | 180 | ||
189 | return value; | 181 | return status; |
190 | } | 182 | } |
191 | 183 | ||
192 | /* Write to a register in the audio-bank of AB8500 */ | 184 | /* Write to a register in the audio-bank of AB8500 */ |
193 | static int ab8500_codec_write_reg(struct snd_soc_codec *codec, | 185 | static int ab8500_codec_write_reg(void *context, unsigned int reg, |
194 | unsigned int reg, unsigned int value) | 186 | unsigned int value) |
195 | { | 187 | { |
196 | int status; | 188 | struct device *dev = context; |
197 | |||
198 | status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO, | ||
199 | reg, value); | ||
200 | if (status < 0) | ||
201 | dev_err(codec->dev, | ||
202 | "%s: ERROR: Register (%02x:%02x) write failed (%d).\n", | ||
203 | __func__, (u8)AB8500_AUDIO, (u8)reg, status); | ||
204 | else | ||
205 | dev_dbg(codec->dev, | ||
206 | "%s: Wrote 0x%02x into register %02x:%02x\n", | ||
207 | __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg); | ||
208 | 189 | ||
209 | return status; | 190 | return abx500_set_register_interruptible(dev, AB8500_AUDIO, |
191 | reg, value); | ||
210 | } | 192 | } |
211 | 193 | ||
194 | static const struct regmap_config ab8500_codec_regmap = { | ||
195 | .reg_read = ab8500_codec_read_reg, | ||
196 | .reg_write = ab8500_codec_write_reg, | ||
197 | }; | ||
198 | |||
212 | /* | 199 | /* |
213 | * Controls - DAPM | 200 | * Controls - DAPM |
214 | */ | 201 | */ |
@@ -1968,16 +1955,16 @@ static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, | |||
1968 | dev_dbg(codec->dev, "%s: Enter.\n", __func__); | 1955 | dev_dbg(codec->dev, "%s: Enter.\n", __func__); |
1969 | 1956 | ||
1970 | /* Set DMic-clocks to outputs */ | 1957 | /* Set DMic-clocks to outputs */ |
1971 | status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC, | 1958 | status = abx500_get_register_interruptible(codec->dev, AB8500_MISC, |
1972 | (u8)AB8500_GPIO_DIR4_REG, | 1959 | AB8500_GPIO_DIR4_REG, |
1973 | &value8); | 1960 | &value8); |
1974 | if (status < 0) | 1961 | if (status < 0) |
1975 | return status; | 1962 | return status; |
1976 | value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | | 1963 | value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | |
1977 | GPIO31_DIR_OUTPUT; | 1964 | GPIO31_DIR_OUTPUT; |
1978 | status = abx500_set_register_interruptible(codec->dev, | 1965 | status = abx500_set_register_interruptible(codec->dev, |
1979 | (u8)AB8500_MISC, | 1966 | AB8500_MISC, |
1980 | (u8)AB8500_GPIO_DIR4_REG, | 1967 | AB8500_GPIO_DIR4_REG, |
1981 | value); | 1968 | value); |
1982 | if (status < 0) | 1969 | if (status < 0) |
1983 | return status; | 1970 | return status; |
@@ -2565,9 +2552,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2565 | 2552 | ||
2566 | static struct snd_soc_codec_driver ab8500_codec_driver = { | 2553 | static struct snd_soc_codec_driver ab8500_codec_driver = { |
2567 | .probe = ab8500_codec_probe, | 2554 | .probe = ab8500_codec_probe, |
2568 | .read = ab8500_codec_read_reg, | ||
2569 | .write = ab8500_codec_write_reg, | ||
2570 | .reg_word_size = sizeof(u8), | ||
2571 | .controls = ab8500_ctrls, | 2555 | .controls = ab8500_ctrls, |
2572 | .num_controls = ARRAY_SIZE(ab8500_ctrls), | 2556 | .num_controls = ARRAY_SIZE(ab8500_ctrls), |
2573 | .dapm_widgets = ab8500_dapm_widgets, | 2557 | .dapm_widgets = ab8500_dapm_widgets, |
@@ -2592,6 +2576,15 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev) | |||
2592 | drvdata->anc_status = ANC_UNCONFIGURED; | 2576 | drvdata->anc_status = ANC_UNCONFIGURED; |
2593 | dev_set_drvdata(&pdev->dev, drvdata); | 2577 | dev_set_drvdata(&pdev->dev, drvdata); |
2594 | 2578 | ||
2579 | drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev, | ||
2580 | &ab8500_codec_regmap); | ||
2581 | if (IS_ERR(drvdata->regmap)) { | ||
2582 | status = PTR_ERR(drvdata->regmap); | ||
2583 | dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n", | ||
2584 | __func__, status); | ||
2585 | return status; | ||
2586 | } | ||
2587 | |||
2595 | dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); | 2588 | dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); |
2596 | status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, | 2589 | status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, |
2597 | ab8500_codec_dai, | 2590 | ab8500_codec_dai, |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index e889e1b84192..bd9b1839c8b0 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -69,19 +69,6 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
69 | .ops = &ac97_dai_ops, | 69 | .ops = &ac97_dai_ops, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static unsigned int ac97_read(struct snd_soc_codec *codec, | ||
73 | unsigned int reg) | ||
74 | { | ||
75 | return soc_ac97_ops->read(codec->ac97, reg); | ||
76 | } | ||
77 | |||
78 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | ||
79 | unsigned int val) | ||
80 | { | ||
81 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int ac97_soc_probe(struct snd_soc_codec *codec) | 72 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
86 | { | 73 | { |
87 | struct snd_ac97_bus *ac97_bus; | 74 | struct snd_ac97_bus *ac97_bus; |
@@ -122,8 +109,6 @@ static int ac97_soc_resume(struct snd_soc_codec *codec) | |||
122 | #endif | 109 | #endif |
123 | 110 | ||
124 | static struct snd_soc_codec_driver soc_codec_dev_ac97 = { | 111 | static struct snd_soc_codec_driver soc_codec_dev_ac97 = { |
125 | .write = ac97_write, | ||
126 | .read = ac97_read, | ||
127 | .probe = ac97_soc_probe, | 112 | .probe = ac97_soc_probe, |
128 | .suspend = ac97_soc_suspend, | 113 | .suspend = ac97_soc_suspend, |
129 | .resume = ac97_soc_resume, | 114 | .resume = ac97_soc_resume, |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1ff7d4d027e9..7c784ad3e8b2 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -1448,29 +1448,10 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec, | |||
1448 | return 0; | 1448 | return 0; |
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | static int adau1373_remove(struct snd_soc_codec *codec) | ||
1452 | { | ||
1453 | adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1454 | return 0; | ||
1455 | } | ||
1456 | |||
1457 | static int adau1373_suspend(struct snd_soc_codec *codec) | ||
1458 | { | ||
1459 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
1460 | int ret; | ||
1461 | |||
1462 | ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1463 | regcache_cache_only(adau1373->regmap, true); | ||
1464 | |||
1465 | return ret; | ||
1466 | } | ||
1467 | |||
1468 | static int adau1373_resume(struct snd_soc_codec *codec) | 1451 | static int adau1373_resume(struct snd_soc_codec *codec) |
1469 | { | 1452 | { |
1470 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 1453 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
1471 | 1454 | ||
1472 | regcache_cache_only(adau1373->regmap, false); | ||
1473 | adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1474 | regcache_sync(adau1373->regmap); | 1455 | regcache_sync(adau1373->regmap); |
1475 | 1456 | ||
1476 | return 0; | 1457 | return 0; |
@@ -1501,8 +1482,6 @@ static const struct regmap_config adau1373_regmap_config = { | |||
1501 | 1482 | ||
1502 | static struct snd_soc_codec_driver adau1373_codec_driver = { | 1483 | static struct snd_soc_codec_driver adau1373_codec_driver = { |
1503 | .probe = adau1373_probe, | 1484 | .probe = adau1373_probe, |
1504 | .remove = adau1373_remove, | ||
1505 | .suspend = adau1373_suspend, | ||
1506 | .resume = adau1373_resume, | 1485 | .resume = adau1373_resume, |
1507 | .set_bias_level = adau1373_set_bias_level, | 1486 | .set_bias_level = adau1373_set_bias_level, |
1508 | .idle_bias_off = true, | 1487 | .idle_bias_off = true, |
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 848cab839553..5518ebd6947c 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -714,9 +714,9 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) | |||
714 | 714 | ||
715 | static const struct snd_soc_codec_driver adau1761_codec_driver = { | 715 | static const struct snd_soc_codec_driver adau1761_codec_driver = { |
716 | .probe = adau1761_codec_probe, | 716 | .probe = adau1761_codec_probe, |
717 | .suspend = adau17x1_suspend, | ||
718 | .resume = adau17x1_resume, | 717 | .resume = adau17x1_resume, |
719 | .set_bias_level = adau1761_set_bias_level, | 718 | .set_bias_level = adau1761_set_bias_level, |
719 | .suspend_bias_off = true, | ||
720 | 720 | ||
721 | .controls = adau1761_controls, | 721 | .controls = adau1761_controls, |
722 | .num_controls = ARRAY_SIZE(adau1761_controls), | 722 | .num_controls = ARRAY_SIZE(adau1761_controls), |
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index 045a61413840..e9fc00fb13dd 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c | |||
@@ -446,9 +446,9 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) | |||
446 | 446 | ||
447 | static const struct snd_soc_codec_driver adau1781_codec_driver = { | 447 | static const struct snd_soc_codec_driver adau1781_codec_driver = { |
448 | .probe = adau1781_codec_probe, | 448 | .probe = adau1781_codec_probe, |
449 | .suspend = adau17x1_suspend, | ||
450 | .resume = adau17x1_resume, | 449 | .resume = adau17x1_resume, |
451 | .set_bias_level = adau1781_set_bias_level, | 450 | .set_bias_level = adau1781_set_bias_level, |
451 | .suspend_bias_off = true, | ||
452 | 452 | ||
453 | .controls = adau1781_controls, | 453 | .controls = adau1781_controls, |
454 | .num_controls = ARRAY_SIZE(adau1781_controls), | 454 | .num_controls = ARRAY_SIZE(adau1781_controls), |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 0b659704e60c..3e16c1c64115 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -815,13 +815,6 @@ int adau17x1_add_routes(struct snd_soc_codec *codec) | |||
815 | } | 815 | } |
816 | EXPORT_SYMBOL_GPL(adau17x1_add_routes); | 816 | EXPORT_SYMBOL_GPL(adau17x1_add_routes); |
817 | 817 | ||
818 | int adau17x1_suspend(struct snd_soc_codec *codec) | ||
819 | { | ||
820 | codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
821 | return 0; | ||
822 | } | ||
823 | EXPORT_SYMBOL_GPL(adau17x1_suspend); | ||
824 | |||
825 | int adau17x1_resume(struct snd_soc_codec *codec) | 818 | int adau17x1_resume(struct snd_soc_codec *codec) |
826 | { | 819 | { |
827 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 820 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
@@ -829,7 +822,6 @@ int adau17x1_resume(struct snd_soc_codec *codec) | |||
829 | if (adau->switch_mode) | 822 | if (adau->switch_mode) |
830 | adau->switch_mode(codec->dev); | 823 | adau->switch_mode(codec->dev); |
831 | 824 | ||
832 | codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
833 | regcache_sync(adau->regmap); | 825 | regcache_sync(adau->regmap); |
834 | 826 | ||
835 | return 0; | 827 | return 0; |
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index 3ffabaf4c7a8..e4a557fd7155 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h | |||
@@ -52,7 +52,6 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, | |||
52 | enum adau17x1_micbias_voltage micbias); | 52 | enum adau17x1_micbias_voltage micbias); |
53 | bool adau17x1_readable_register(struct device *dev, unsigned int reg); | 53 | bool adau17x1_readable_register(struct device *dev, unsigned int reg); |
54 | bool adau17x1_volatile_register(struct device *dev, unsigned int reg); | 54 | bool adau17x1_volatile_register(struct device *dev, unsigned int reg); |
55 | int adau17x1_suspend(struct snd_soc_codec *codec); | ||
56 | int adau17x1_resume(struct snd_soc_codec *codec); | 55 | int adau17x1_resume(struct snd_soc_codec *codec); |
57 | 56 | ||
58 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; | 57 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index c43b93fdf0df..ce3cdca9fc62 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -812,42 +812,23 @@ static int adav80x_probe(struct snd_soc_codec *codec) | |||
812 | /* Disable DAC zero flag */ | 812 | /* Disable DAC zero flag */ |
813 | regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); | 813 | regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); |
814 | 814 | ||
815 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 815 | return 0; |
816 | } | ||
817 | |||
818 | static int adav80x_suspend(struct snd_soc_codec *codec) | ||
819 | { | ||
820 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
821 | int ret; | ||
822 | |||
823 | ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
824 | regcache_cache_only(adav80x->regmap, true); | ||
825 | |||
826 | return ret; | ||
827 | } | 816 | } |
828 | 817 | ||
829 | static int adav80x_resume(struct snd_soc_codec *codec) | 818 | static int adav80x_resume(struct snd_soc_codec *codec) |
830 | { | 819 | { |
831 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 820 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
832 | 821 | ||
833 | regcache_cache_only(adav80x->regmap, false); | ||
834 | adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
835 | regcache_sync(adav80x->regmap); | 822 | regcache_sync(adav80x->regmap); |
836 | 823 | ||
837 | return 0; | 824 | return 0; |
838 | } | 825 | } |
839 | 826 | ||
840 | static int adav80x_remove(struct snd_soc_codec *codec) | ||
841 | { | ||
842 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
843 | } | ||
844 | |||
845 | static struct snd_soc_codec_driver adav80x_codec_driver = { | 827 | static struct snd_soc_codec_driver adav80x_codec_driver = { |
846 | .probe = adav80x_probe, | 828 | .probe = adav80x_probe, |
847 | .remove = adav80x_remove, | ||
848 | .suspend = adav80x_suspend, | ||
849 | .resume = adav80x_resume, | 829 | .resume = adav80x_resume, |
850 | .set_bias_level = adav80x_set_bias_level, | 830 | .set_bias_level = adav80x_set_bias_level, |
831 | .suspend_bias_off = true, | ||
851 | 832 | ||
852 | .set_pll = adav80x_set_pll, | 833 | .set_pll = adav80x_set_pll, |
853 | .set_sysclk = adav80x_set_sysclk, | 834 | .set_sysclk = adav80x_set_sysclk, |
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c new file mode 100644 index 000000000000..c125925da92e --- /dev/null +++ b/sound/soc/codecs/cs35l32.c | |||
@@ -0,0 +1,631 @@ | |||
1 | /* | ||
2 | * cs35l32.c -- CS35L32 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 CirrusLogic, Inc. | ||
5 | * | ||
6 | * Author: Brian Austin <brian.austin@cirrus.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 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/regulator/consumer.h> | ||
26 | #include <linux/gpio/consumer.h> | ||
27 | #include <linux/of_device.h> | ||
28 | #include <sound/core.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include <sound/soc-dapm.h> | ||
33 | #include <sound/initval.h> | ||
34 | #include <sound/tlv.h> | ||
35 | #include <dt-bindings/sound/cs35l32.h> | ||
36 | |||
37 | #include "cs35l32.h" | ||
38 | |||
39 | #define CS35L32_NUM_SUPPLIES 2 | ||
40 | static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = { | ||
41 | "VA", | ||
42 | "VP", | ||
43 | }; | ||
44 | |||
45 | struct cs35l32_private { | ||
46 | struct regmap *regmap; | ||
47 | struct snd_soc_codec *codec; | ||
48 | struct regulator_bulk_data supplies[CS35L32_NUM_SUPPLIES]; | ||
49 | struct cs35l32_platform_data pdata; | ||
50 | struct gpio_desc *reset_gpio; | ||
51 | }; | ||
52 | |||
53 | static const struct reg_default cs35l32_reg_defaults[] = { | ||
54 | |||
55 | { 0x06, 0x04 }, /* Power Ctl 1 */ | ||
56 | { 0x07, 0xE8 }, /* Power Ctl 2 */ | ||
57 | { 0x08, 0x40 }, /* Clock Ctl */ | ||
58 | { 0x09, 0x20 }, /* Low Battery Threshold */ | ||
59 | { 0x0A, 0x00 }, /* Voltage Monitor [RO] */ | ||
60 | { 0x0B, 0x40 }, /* Conv Peak Curr Protection CTL */ | ||
61 | { 0x0C, 0x07 }, /* IMON Scaling */ | ||
62 | { 0x0D, 0x03 }, /* Audio/LED Pwr Manager */ | ||
63 | { 0x0F, 0x20 }, /* Serial Port Control */ | ||
64 | { 0x10, 0x14 }, /* Class D Amp CTL */ | ||
65 | { 0x11, 0x00 }, /* Protection Release CTL */ | ||
66 | { 0x12, 0xFF }, /* Interrupt Mask 1 */ | ||
67 | { 0x13, 0xFF }, /* Interrupt Mask 2 */ | ||
68 | { 0x14, 0xFF }, /* Interrupt Mask 3 */ | ||
69 | { 0x19, 0x00 }, /* LED Flash Mode Current */ | ||
70 | { 0x1A, 0x00 }, /* LED Movie Mode Current */ | ||
71 | { 0x1B, 0x20 }, /* LED Flash Timer */ | ||
72 | { 0x1C, 0x00 }, /* LED Flash Inhibit Current */ | ||
73 | }; | ||
74 | |||
75 | static bool cs35l32_readable_register(struct device *dev, unsigned int reg) | ||
76 | { | ||
77 | switch (reg) { | ||
78 | case CS35L32_DEVID_AB: | ||
79 | case CS35L32_DEVID_CD: | ||
80 | case CS35L32_DEVID_E: | ||
81 | case CS35L32_FAB_ID: | ||
82 | case CS35L32_REV_ID: | ||
83 | case CS35L32_PWRCTL1: | ||
84 | case CS35L32_PWRCTL2: | ||
85 | case CS35L32_CLK_CTL: | ||
86 | case CS35L32_BATT_THRESHOLD: | ||
87 | case CS35L32_VMON: | ||
88 | case CS35L32_BST_CPCP_CTL: | ||
89 | case CS35L32_IMON_SCALING: | ||
90 | case CS35L32_AUDIO_LED_MNGR: | ||
91 | case CS35L32_ADSP_CTL: | ||
92 | case CS35L32_CLASSD_CTL: | ||
93 | case CS35L32_PROTECT_CTL: | ||
94 | case CS35L32_INT_MASK_1: | ||
95 | case CS35L32_INT_MASK_2: | ||
96 | case CS35L32_INT_MASK_3: | ||
97 | case CS35L32_INT_STATUS_1: | ||
98 | case CS35L32_INT_STATUS_2: | ||
99 | case CS35L32_INT_STATUS_3: | ||
100 | case CS35L32_LED_STATUS: | ||
101 | case CS35L32_FLASH_MODE: | ||
102 | case CS35L32_MOVIE_MODE: | ||
103 | case CS35L32_FLASH_TIMER: | ||
104 | case CS35L32_FLASH_INHIBIT: | ||
105 | return true; | ||
106 | default: | ||
107 | return false; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static bool cs35l32_volatile_register(struct device *dev, unsigned int reg) | ||
112 | { | ||
113 | switch (reg) { | ||
114 | case CS35L32_DEVID_AB: | ||
115 | case CS35L32_DEVID_CD: | ||
116 | case CS35L32_DEVID_E: | ||
117 | case CS35L32_FAB_ID: | ||
118 | case CS35L32_REV_ID: | ||
119 | case CS35L32_INT_STATUS_1: | ||
120 | case CS35L32_INT_STATUS_2: | ||
121 | case CS35L32_INT_STATUS_3: | ||
122 | case CS35L32_LED_STATUS: | ||
123 | return true; | ||
124 | default: | ||
125 | return false; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static bool cs35l32_precious_register(struct device *dev, unsigned int reg) | ||
130 | { | ||
131 | switch (reg) { | ||
132 | case CS35L32_INT_STATUS_1: | ||
133 | case CS35L32_INT_STATUS_2: | ||
134 | case CS35L32_INT_STATUS_3: | ||
135 | case CS35L32_LED_STATUS: | ||
136 | return true; | ||
137 | default: | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static DECLARE_TLV_DB_SCALE(classd_ctl_tlv, 900, 300, 0); | ||
143 | |||
144 | static const struct snd_kcontrol_new imon_ctl = | ||
145 | SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 6, 1, 1); | ||
146 | |||
147 | static const struct snd_kcontrol_new vmon_ctl = | ||
148 | SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 7, 1, 1); | ||
149 | |||
150 | static const struct snd_kcontrol_new vpmon_ctl = | ||
151 | SOC_DAPM_SINGLE("Switch", CS35L32_PWRCTL2, 5, 1, 1); | ||
152 | |||
153 | static const struct snd_kcontrol_new cs35l32_snd_controls[] = { | ||
154 | SOC_SINGLE_TLV("Speaker Volume", CS35L32_CLASSD_CTL, | ||
155 | 3, 0x04, 1, classd_ctl_tlv), | ||
156 | SOC_SINGLE("Zero Cross Switch", CS35L32_CLASSD_CTL, 2, 1, 0), | ||
157 | SOC_SINGLE("Gain Manager Switch", CS35L32_AUDIO_LED_MNGR, 3, 1, 0), | ||
158 | }; | ||
159 | |||
160 | static const struct snd_soc_dapm_widget cs35l32_dapm_widgets[] = { | ||
161 | |||
162 | SND_SOC_DAPM_SUPPLY("BOOST", CS35L32_PWRCTL1, 2, 1, NULL, 0), | ||
163 | SND_SOC_DAPM_OUT_DRV("Speaker", CS35L32_PWRCTL1, 7, 1, NULL, 0), | ||
164 | |||
165 | SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L32_PWRCTL2, 3, 1), | ||
166 | |||
167 | SND_SOC_DAPM_INPUT("VP"), | ||
168 | SND_SOC_DAPM_INPUT("ISENSE"), | ||
169 | SND_SOC_DAPM_INPUT("VSENSE"), | ||
170 | |||
171 | SND_SOC_DAPM_SWITCH("VMON ADC", CS35L32_PWRCTL2, 7, 1, &vmon_ctl), | ||
172 | SND_SOC_DAPM_SWITCH("IMON ADC", CS35L32_PWRCTL2, 6, 1, &imon_ctl), | ||
173 | SND_SOC_DAPM_SWITCH("VPMON ADC", CS35L32_PWRCTL2, 5, 1, &vpmon_ctl), | ||
174 | }; | ||
175 | |||
176 | static const struct snd_soc_dapm_route cs35l32_audio_map[] = { | ||
177 | |||
178 | {"Speaker", NULL, "BOOST"}, | ||
179 | |||
180 | {"VMON ADC", NULL, "VSENSE"}, | ||
181 | {"IMON ADC", NULL, "ISENSE"}, | ||
182 | {"VPMON ADC", NULL, "VP"}, | ||
183 | |||
184 | {"SDOUT", "Switch", "VMON ADC"}, | ||
185 | {"SDOUT", "Switch", "IMON ADC"}, | ||
186 | {"SDOUT", "Switch", "VPMON ADC"}, | ||
187 | |||
188 | {"Capture", NULL, "SDOUT"}, | ||
189 | }; | ||
190 | |||
191 | static int cs35l32_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
192 | { | ||
193 | struct snd_soc_codec *codec = codec_dai->codec; | ||
194 | |||
195 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
196 | case SND_SOC_DAIFMT_CBM_CFM: | ||
197 | snd_soc_update_bits(codec, CS35L32_ADSP_CTL, | ||
198 | CS35L32_ADSP_MASTER_MASK, | ||
199 | CS35L32_ADSP_MASTER_MASK); | ||
200 | break; | ||
201 | case SND_SOC_DAIFMT_CBS_CFS: | ||
202 | snd_soc_update_bits(codec, CS35L32_ADSP_CTL, | ||
203 | CS35L32_ADSP_MASTER_MASK, 0); | ||
204 | break; | ||
205 | default: | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int cs35l32_set_tristate(struct snd_soc_dai *dai, int tristate) | ||
213 | { | ||
214 | struct snd_soc_codec *codec = dai->codec; | ||
215 | |||
216 | return snd_soc_update_bits(codec, CS35L32_PWRCTL2, | ||
217 | CS35L32_SDOUT_3ST, tristate << 3); | ||
218 | } | ||
219 | |||
220 | static const struct snd_soc_dai_ops cs35l32_ops = { | ||
221 | .set_fmt = cs35l32_set_dai_fmt, | ||
222 | .set_tristate = cs35l32_set_tristate, | ||
223 | }; | ||
224 | |||
225 | static struct snd_soc_dai_driver cs35l32_dai[] = { | ||
226 | { | ||
227 | .name = "cs35l32-monitor", | ||
228 | .id = 0, | ||
229 | .capture = { | ||
230 | .stream_name = "Capture", | ||
231 | .channels_min = 2, | ||
232 | .channels_max = 2, | ||
233 | .rates = CS35L32_RATES, | ||
234 | .formats = CS35L32_FORMATS, | ||
235 | }, | ||
236 | .ops = &cs35l32_ops, | ||
237 | .symmetric_rates = 1, | ||
238 | } | ||
239 | }; | ||
240 | |||
241 | static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, | ||
242 | int clk_id, int source, unsigned int freq, int dir) | ||
243 | { | ||
244 | unsigned int val; | ||
245 | |||
246 | switch (freq) { | ||
247 | case 6000000: | ||
248 | val = CS35L32_MCLK_RATIO; | ||
249 | break; | ||
250 | case 12000000: | ||
251 | val = CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO; | ||
252 | break; | ||
253 | case 6144000: | ||
254 | val = 0; | ||
255 | break; | ||
256 | case 12288000: | ||
257 | val = CS35L32_MCLK_DIV2_MASK; | ||
258 | break; | ||
259 | default: | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | return snd_soc_update_bits(codec, CS35L32_CLK_CTL, | ||
264 | CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val); | ||
265 | } | ||
266 | |||
267 | static struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { | ||
268 | .set_sysclk = cs35l32_codec_set_sysclk, | ||
269 | |||
270 | .dapm_widgets = cs35l32_dapm_widgets, | ||
271 | .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), | ||
272 | .dapm_routes = cs35l32_audio_map, | ||
273 | .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), | ||
274 | |||
275 | .controls = cs35l32_snd_controls, | ||
276 | .num_controls = ARRAY_SIZE(cs35l32_snd_controls), | ||
277 | }; | ||
278 | |||
279 | /* Current and threshold powerup sequence Pg37 in datasheet */ | ||
280 | static const struct reg_default cs35l32_monitor_patch[] = { | ||
281 | |||
282 | { 0x00, 0x99 }, | ||
283 | { 0x48, 0x17 }, | ||
284 | { 0x49, 0x56 }, | ||
285 | { 0x43, 0x01 }, | ||
286 | { 0x3B, 0x62 }, | ||
287 | { 0x3C, 0x80 }, | ||
288 | { 0x00, 0x00 }, | ||
289 | }; | ||
290 | |||
291 | static struct regmap_config cs35l32_regmap = { | ||
292 | .reg_bits = 8, | ||
293 | .val_bits = 8, | ||
294 | |||
295 | .max_register = CS35L32_MAX_REGISTER, | ||
296 | .reg_defaults = cs35l32_reg_defaults, | ||
297 | .num_reg_defaults = ARRAY_SIZE(cs35l32_reg_defaults), | ||
298 | .volatile_reg = cs35l32_volatile_register, | ||
299 | .readable_reg = cs35l32_readable_register, | ||
300 | .precious_reg = cs35l32_precious_register, | ||
301 | .cache_type = REGCACHE_RBTREE, | ||
302 | }; | ||
303 | |||
304 | static int cs35l32_handle_of_data(struct i2c_client *i2c_client, | ||
305 | struct cs35l32_platform_data *pdata) | ||
306 | { | ||
307 | struct device_node *np = i2c_client->dev.of_node; | ||
308 | unsigned int val; | ||
309 | |||
310 | if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0) | ||
311 | pdata->sdout_share = val; | ||
312 | |||
313 | of_property_read_u32(np, "cirrus,boost-manager", &val); | ||
314 | switch (val) { | ||
315 | case CS35L32_BOOST_MGR_AUTO: | ||
316 | case CS35L32_BOOST_MGR_AUTO_AUDIO: | ||
317 | case CS35L32_BOOST_MGR_BYPASS: | ||
318 | case CS35L32_BOOST_MGR_FIXED: | ||
319 | pdata->boost_mng = val; | ||
320 | break; | ||
321 | default: | ||
322 | dev_err(&i2c_client->dev, | ||
323 | "Wrong cirrus,boost-manager DT value %d\n", val); | ||
324 | pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS; | ||
325 | } | ||
326 | |||
327 | of_property_read_u32(np, "cirrus,sdout-datacfg", &val); | ||
328 | switch (val) { | ||
329 | case CS35L32_DATA_CFG_LR_VP: | ||
330 | case CS35L32_DATA_CFG_LR_STAT: | ||
331 | case CS35L32_DATA_CFG_LR: | ||
332 | case CS35L32_DATA_CFG_LR_VPSTAT: | ||
333 | pdata->sdout_datacfg = val; | ||
334 | break; | ||
335 | default: | ||
336 | dev_err(&i2c_client->dev, | ||
337 | "Wrong cirrus,sdout-datacfg DT value %d\n", val); | ||
338 | pdata->sdout_datacfg = CS35L32_DATA_CFG_LR; | ||
339 | } | ||
340 | |||
341 | of_property_read_u32(np, "cirrus,battery-threshold", &val); | ||
342 | switch (val) { | ||
343 | case CS35L32_BATT_THRESH_3_1V: | ||
344 | case CS35L32_BATT_THRESH_3_2V: | ||
345 | case CS35L32_BATT_THRESH_3_3V: | ||
346 | case CS35L32_BATT_THRESH_3_4V: | ||
347 | pdata->batt_thresh = val; | ||
348 | break; | ||
349 | default: | ||
350 | dev_err(&i2c_client->dev, | ||
351 | "Wrong cirrus,battery-threshold DT value %d\n", val); | ||
352 | pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V; | ||
353 | } | ||
354 | |||
355 | of_property_read_u32(np, "cirrus,battery-recovery", &val); | ||
356 | switch (val) { | ||
357 | case CS35L32_BATT_RECOV_3_1V: | ||
358 | case CS35L32_BATT_RECOV_3_2V: | ||
359 | case CS35L32_BATT_RECOV_3_3V: | ||
360 | case CS35L32_BATT_RECOV_3_4V: | ||
361 | case CS35L32_BATT_RECOV_3_5V: | ||
362 | case CS35L32_BATT_RECOV_3_6V: | ||
363 | pdata->batt_recov = val; | ||
364 | break; | ||
365 | default: | ||
366 | dev_err(&i2c_client->dev, | ||
367 | "Wrong cirrus,battery-recovery DT value %d\n", val); | ||
368 | pdata->batt_recov = CS35L32_BATT_RECOV_3_4V; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int cs35l32_i2c_probe(struct i2c_client *i2c_client, | ||
375 | const struct i2c_device_id *id) | ||
376 | { | ||
377 | struct cs35l32_private *cs35l32; | ||
378 | struct cs35l32_platform_data *pdata = | ||
379 | dev_get_platdata(&i2c_client->dev); | ||
380 | int ret, i; | ||
381 | unsigned int devid = 0; | ||
382 | unsigned int reg; | ||
383 | |||
384 | |||
385 | cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l32_private), | ||
386 | GFP_KERNEL); | ||
387 | if (!cs35l32) { | ||
388 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
389 | return -ENOMEM; | ||
390 | } | ||
391 | |||
392 | i2c_set_clientdata(i2c_client, cs35l32); | ||
393 | |||
394 | cs35l32->regmap = devm_regmap_init_i2c(i2c_client, &cs35l32_regmap); | ||
395 | if (IS_ERR(cs35l32->regmap)) { | ||
396 | ret = PTR_ERR(cs35l32->regmap); | ||
397 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | if (pdata) { | ||
402 | cs35l32->pdata = *pdata; | ||
403 | } else { | ||
404 | pdata = devm_kzalloc(&i2c_client->dev, | ||
405 | sizeof(struct cs35l32_platform_data), | ||
406 | GFP_KERNEL); | ||
407 | if (!pdata) { | ||
408 | dev_err(&i2c_client->dev, "could not allocate pdata\n"); | ||
409 | return -ENOMEM; | ||
410 | } | ||
411 | if (i2c_client->dev.of_node) { | ||
412 | ret = cs35l32_handle_of_data(i2c_client, | ||
413 | &cs35l32->pdata); | ||
414 | if (ret != 0) | ||
415 | return ret; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | for (i = 0; i < ARRAY_SIZE(cs35l32->supplies); i++) | ||
420 | cs35l32->supplies[i].supply = cs35l32_supply_names[i]; | ||
421 | |||
422 | ret = devm_regulator_bulk_get(&i2c_client->dev, | ||
423 | ARRAY_SIZE(cs35l32->supplies), | ||
424 | cs35l32->supplies); | ||
425 | if (ret != 0) { | ||
426 | dev_err(&i2c_client->dev, | ||
427 | "Failed to request supplies: %d\n", ret); | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | ret = regulator_bulk_enable(ARRAY_SIZE(cs35l32->supplies), | ||
432 | cs35l32->supplies); | ||
433 | if (ret != 0) { | ||
434 | dev_err(&i2c_client->dev, | ||
435 | "Failed to enable supplies: %d\n", ret); | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | /* Reset the Device */ | ||
440 | cs35l32->reset_gpio = devm_gpiod_get(&i2c_client->dev, | ||
441 | "reset-gpios"); | ||
442 | if (IS_ERR(cs35l32->reset_gpio)) { | ||
443 | ret = PTR_ERR(cs35l32->reset_gpio); | ||
444 | if (ret != -ENOENT && ret != -ENOSYS) | ||
445 | return ret; | ||
446 | |||
447 | cs35l32->reset_gpio = NULL; | ||
448 | } else { | ||
449 | ret = gpiod_direction_output(cs35l32->reset_gpio, 0); | ||
450 | if (ret) | ||
451 | return ret; | ||
452 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); | ||
453 | } | ||
454 | |||
455 | /* initialize codec */ | ||
456 | ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, ®); | ||
457 | devid = (reg & 0xFF) << 12; | ||
458 | |||
459 | ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_CD, ®); | ||
460 | devid |= (reg & 0xFF) << 4; | ||
461 | |||
462 | ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_E, ®); | ||
463 | devid |= (reg & 0xF0) >> 4; | ||
464 | |||
465 | if (devid != CS35L32_CHIP_ID) { | ||
466 | ret = -ENODEV; | ||
467 | dev_err(&i2c_client->dev, | ||
468 | "CS35L32 Device ID (%X). Expected %X\n", | ||
469 | devid, CS35L32_CHIP_ID); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | ret = regmap_read(cs35l32->regmap, CS35L32_REV_ID, ®); | ||
474 | if (ret < 0) { | ||
475 | dev_err(&i2c_client->dev, "Get Revision ID failed\n"); | ||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | ret = regmap_register_patch(cs35l32->regmap, cs35l32_monitor_patch, | ||
480 | ARRAY_SIZE(cs35l32_monitor_patch)); | ||
481 | if (ret < 0) { | ||
482 | dev_err(&i2c_client->dev, "Failed to apply errata patch\n"); | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | dev_info(&i2c_client->dev, | ||
487 | "Cirrus Logic CS35L32, Revision: %02X\n", reg & 0xFF); | ||
488 | |||
489 | /* Setup VBOOST Management */ | ||
490 | if (cs35l32->pdata.boost_mng) | ||
491 | regmap_update_bits(cs35l32->regmap, CS35L32_AUDIO_LED_MNGR, | ||
492 | CS35L32_BOOST_MASK, | ||
493 | cs35l32->pdata.boost_mng); | ||
494 | |||
495 | /* Setup ADSP Format Config */ | ||
496 | if (cs35l32->pdata.sdout_share) | ||
497 | regmap_update_bits(cs35l32->regmap, CS35L32_ADSP_CTL, | ||
498 | CS35L32_ADSP_SHARE_MASK, | ||
499 | cs35l32->pdata.sdout_share << 3); | ||
500 | |||
501 | /* Setup ADSP Data Configuration */ | ||
502 | if (cs35l32->pdata.sdout_datacfg) | ||
503 | regmap_update_bits(cs35l32->regmap, CS35L32_ADSP_CTL, | ||
504 | CS35L32_ADSP_DATACFG_MASK, | ||
505 | cs35l32->pdata.sdout_datacfg << 4); | ||
506 | |||
507 | /* Setup Low Battery Recovery */ | ||
508 | if (cs35l32->pdata.batt_recov) | ||
509 | regmap_update_bits(cs35l32->regmap, CS35L32_BATT_THRESHOLD, | ||
510 | CS35L32_BATT_REC_MASK, | ||
511 | cs35l32->pdata.batt_recov << 1); | ||
512 | |||
513 | /* Setup Low Battery Threshold */ | ||
514 | if (cs35l32->pdata.batt_thresh) | ||
515 | regmap_update_bits(cs35l32->regmap, CS35L32_BATT_THRESHOLD, | ||
516 | CS35L32_BATT_THRESH_MASK, | ||
517 | cs35l32->pdata.batt_thresh << 4); | ||
518 | |||
519 | /* Power down the AMP */ | ||
520 | regmap_update_bits(cs35l32->regmap, CS35L32_PWRCTL1, CS35L32_PDN_AMP, | ||
521 | CS35L32_PDN_AMP); | ||
522 | |||
523 | /* Clear MCLK Error Bit since we don't have the clock yet */ | ||
524 | ret = regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, ®); | ||
525 | |||
526 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
527 | &soc_codec_dev_cs35l32, cs35l32_dai, | ||
528 | ARRAY_SIZE(cs35l32_dai)); | ||
529 | if (ret < 0) | ||
530 | goto err_disable; | ||
531 | |||
532 | return 0; | ||
533 | |||
534 | err_disable: | ||
535 | regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), | ||
536 | cs35l32->supplies); | ||
537 | return ret; | ||
538 | } | ||
539 | |||
540 | static int cs35l32_i2c_remove(struct i2c_client *i2c_client) | ||
541 | { | ||
542 | struct cs35l32_private *cs35l32 = i2c_get_clientdata(i2c_client); | ||
543 | |||
544 | snd_soc_unregister_codec(&i2c_client->dev); | ||
545 | |||
546 | /* Hold down reset */ | ||
547 | if (cs35l32->reset_gpio) | ||
548 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | #ifdef CONFIG_PM_RUNTIME | ||
554 | static int cs35l32_runtime_suspend(struct device *dev) | ||
555 | { | ||
556 | struct cs35l32_private *cs35l32 = dev_get_drvdata(dev); | ||
557 | |||
558 | regcache_cache_only(cs35l32->regmap, true); | ||
559 | regcache_mark_dirty(cs35l32->regmap); | ||
560 | |||
561 | /* Hold down reset */ | ||
562 | if (cs35l32->reset_gpio) | ||
563 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); | ||
564 | |||
565 | /* remove power */ | ||
566 | regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), | ||
567 | cs35l32->supplies); | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | static int cs35l32_runtime_resume(struct device *dev) | ||
573 | { | ||
574 | struct cs35l32_private *cs35l32 = dev_get_drvdata(dev); | ||
575 | int ret; | ||
576 | |||
577 | /* Enable power */ | ||
578 | ret = regulator_bulk_enable(ARRAY_SIZE(cs35l32->supplies), | ||
579 | cs35l32->supplies); | ||
580 | if (ret != 0) { | ||
581 | dev_err(dev, "Failed to enable supplies: %d\n", | ||
582 | ret); | ||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | if (cs35l32->reset_gpio) | ||
587 | gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); | ||
588 | |||
589 | regcache_cache_only(cs35l32->regmap, false); | ||
590 | regcache_sync(cs35l32->regmap); | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | #endif | ||
595 | |||
596 | static const struct dev_pm_ops cs35l32_runtime_pm = { | ||
597 | SET_RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume, | ||
598 | NULL) | ||
599 | }; | ||
600 | |||
601 | static const struct of_device_id cs35l32_of_match[] = { | ||
602 | { .compatible = "cirrus,cs35l32", }, | ||
603 | {}, | ||
604 | }; | ||
605 | MODULE_DEVICE_TABLE(of, cs35l32_of_match); | ||
606 | |||
607 | |||
608 | static const struct i2c_device_id cs35l32_id[] = { | ||
609 | {"cs35l32", 0}, | ||
610 | {} | ||
611 | }; | ||
612 | |||
613 | MODULE_DEVICE_TABLE(i2c, cs35l32_id); | ||
614 | |||
615 | static struct i2c_driver cs35l32_i2c_driver = { | ||
616 | .driver = { | ||
617 | .name = "cs35l32", | ||
618 | .owner = THIS_MODULE, | ||
619 | .pm = &cs35l32_runtime_pm, | ||
620 | .of_match_table = cs35l32_of_match, | ||
621 | }, | ||
622 | .id_table = cs35l32_id, | ||
623 | .probe = cs35l32_i2c_probe, | ||
624 | .remove = cs35l32_i2c_remove, | ||
625 | }; | ||
626 | |||
627 | module_i2c_driver(cs35l32_i2c_driver); | ||
628 | |||
629 | MODULE_DESCRIPTION("ASoC CS35L32 driver"); | ||
630 | MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>"); | ||
631 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs35l32.h b/sound/soc/codecs/cs35l32.h new file mode 100644 index 000000000000..31ab804a22bc --- /dev/null +++ b/sound/soc/codecs/cs35l32.h | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * cs35l32.h -- CS35L32 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2014 CirrusLogic, Inc. | ||
5 | * | ||
6 | * Author: Brian Austin <brian.austin@cirrus.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 | |||
14 | #ifndef __CS35L32_H__ | ||
15 | #define __CS35L32_H__ | ||
16 | |||
17 | struct cs35l32_platform_data { | ||
18 | /* Low Battery Threshold */ | ||
19 | unsigned int batt_thresh; | ||
20 | /* Low Battery Recovery */ | ||
21 | unsigned int batt_recov; | ||
22 | /* LED Current Management*/ | ||
23 | unsigned int led_mng; | ||
24 | /* Audio Gain w/ LED */ | ||
25 | unsigned int audiogain_mng; | ||
26 | /* Boost Management */ | ||
27 | unsigned int boost_mng; | ||
28 | /* Data CFG for DUAL device */ | ||
29 | unsigned int sdout_datacfg; | ||
30 | /* SDOUT Sharing */ | ||
31 | unsigned int sdout_share; | ||
32 | }; | ||
33 | |||
34 | #define CS35L32_CHIP_ID 0x00035A32 | ||
35 | #define CS35L32_DEVID_AB 0x01 /* Device ID A & B [RO] */ | ||
36 | #define CS35L32_DEVID_CD 0x02 /* Device ID C & D [RO] */ | ||
37 | #define CS35L32_DEVID_E 0x03 /* Device ID E [RO] */ | ||
38 | #define CS35L32_FAB_ID 0x04 /* Fab ID [RO] */ | ||
39 | #define CS35L32_REV_ID 0x05 /* Revision ID [RO] */ | ||
40 | #define CS35L32_PWRCTL1 0x06 /* Power Ctl 1 */ | ||
41 | #define CS35L32_PWRCTL2 0x07 /* Power Ctl 2 */ | ||
42 | #define CS35L32_CLK_CTL 0x08 /* Clock Ctl */ | ||
43 | #define CS35L32_BATT_THRESHOLD 0x09 /* Low Battery Threshold */ | ||
44 | #define CS35L32_VMON 0x0A /* Voltage Monitor [RO] */ | ||
45 | #define CS35L32_BST_CPCP_CTL 0x0B /* Conv Peak Curr Protection CTL */ | ||
46 | #define CS35L32_IMON_SCALING 0x0C /* IMON Scaling */ | ||
47 | #define CS35L32_AUDIO_LED_MNGR 0x0D /* Audio/LED Pwr Manager */ | ||
48 | #define CS35L32_ADSP_CTL 0x0F /* Serial Port Control */ | ||
49 | #define CS35L32_CLASSD_CTL 0x10 /* Class D Amp CTL */ | ||
50 | #define CS35L32_PROTECT_CTL 0x11 /* Protection Release CTL */ | ||
51 | #define CS35L32_INT_MASK_1 0x12 /* Interrupt Mask 1 */ | ||
52 | #define CS35L32_INT_MASK_2 0x13 /* Interrupt Mask 2 */ | ||
53 | #define CS35L32_INT_MASK_3 0x14 /* Interrupt Mask 3 */ | ||
54 | #define CS35L32_INT_STATUS_1 0x15 /* Interrupt Status 1 [RO] */ | ||
55 | #define CS35L32_INT_STATUS_2 0x16 /* Interrupt Status 2 [RO] */ | ||
56 | #define CS35L32_INT_STATUS_3 0x17 /* Interrupt Status 3 [RO] */ | ||
57 | #define CS35L32_LED_STATUS 0x18 /* LED Lighting Status [RO] */ | ||
58 | #define CS35L32_FLASH_MODE 0x19 /* LED Flash Mode Current */ | ||
59 | #define CS35L32_MOVIE_MODE 0x1A /* LED Movie Mode Current */ | ||
60 | #define CS35L32_FLASH_TIMER 0x1B /* LED Flash Timer */ | ||
61 | #define CS35L32_FLASH_INHIBIT 0x1C /* LED Flash Inhibit Current */ | ||
62 | #define CS35L32_MAX_REGISTER 0x1C | ||
63 | |||
64 | #define CS35L32_MCLK_DIV2 0x01 | ||
65 | #define CS35L32_MCLK_RATIO 0x01 | ||
66 | #define CS35L32_MCLKDIS 0x80 | ||
67 | #define CS35L32_PDN_ALL 0x01 | ||
68 | #define CS35L32_PDN_AMP 0x80 | ||
69 | #define CS35L32_PDN_BOOST 0x04 | ||
70 | #define CS35L32_PDN_IMON 0x40 | ||
71 | #define CS35L32_PDN_VMON 0x80 | ||
72 | #define CS35L32_PDN_VPMON 0x20 | ||
73 | #define CS35L32_PDN_ADSP 0x08 | ||
74 | |||
75 | #define CS35L32_MCLK_DIV2_MASK 0x40 | ||
76 | #define CS35L32_MCLK_RATIO_MASK 0x01 | ||
77 | #define CS35L32_MCLK_MASK 0x41 | ||
78 | #define CS35L32_ADSP_MASTER_MASK 0x40 | ||
79 | #define CS35L32_BOOST_MASK 0x03 | ||
80 | #define CS35L32_GAIN_MGR_MASK 0x08 | ||
81 | #define CS35L32_ADSP_SHARE_MASK 0x08 | ||
82 | #define CS35L32_ADSP_DATACFG_MASK 0x30 | ||
83 | #define CS35L32_SDOUT_3ST 0x80 | ||
84 | #define CS35L32_BATT_REC_MASK 0x0E | ||
85 | #define CS35L32_BATT_THRESH_MASK 0x30 | ||
86 | |||
87 | #define CS35L32_RATES (SNDRV_PCM_RATE_48000) | ||
88 | #define CS35L32_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
89 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
90 | SNDRV_PCM_FMTBIT_S32_LE) | ||
91 | |||
92 | |||
93 | #endif | ||
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 69a85164357c..4fdd47d700e3 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -77,6 +77,7 @@ static bool cs4265_readable_register(struct device *dev, unsigned int reg) | |||
77 | case CS4265_INT_MASK: | 77 | case CS4265_INT_MASK: |
78 | case CS4265_STATUS_MODE_MSB: | 78 | case CS4265_STATUS_MODE_MSB: |
79 | case CS4265_STATUS_MODE_LSB: | 79 | case CS4265_STATUS_MODE_LSB: |
80 | case CS4265_CHIP_ID: | ||
80 | return true; | 81 | return true; |
81 | default: | 82 | default: |
82 | return false; | 83 | return false; |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 969167d8b71e..35fbef743fbe 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -176,9 +176,9 @@ static bool cs42l52_volatile_register(struct device *dev, unsigned int reg) | |||
176 | case CS42L52_BATT_LEVEL: | 176 | case CS42L52_BATT_LEVEL: |
177 | case CS42L52_SPK_STATUS: | 177 | case CS42L52_SPK_STATUS: |
178 | case CS42L52_CHARGE_PUMP: | 178 | case CS42L52_CHARGE_PUMP: |
179 | return 1; | 179 | return true; |
180 | default: | 180 | default: |
181 | return 0; | 181 | return false; |
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
@@ -946,20 +946,6 @@ static struct snd_soc_dai_driver cs42l52_dai = { | |||
946 | .ops = &cs42l52_ops, | 946 | .ops = &cs42l52_ops, |
947 | }; | 947 | }; |
948 | 948 | ||
949 | static int cs42l52_suspend(struct snd_soc_codec *codec) | ||
950 | { | ||
951 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
952 | |||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int cs42l52_resume(struct snd_soc_codec *codec) | ||
957 | { | ||
958 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static int beep_rates[] = { | 949 | static int beep_rates[] = { |
964 | 261, 522, 585, 667, 706, 774, 889, 1000, | 950 | 261, 522, 585, 667, 706, 774, 889, 1000, |
965 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 | 951 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 |
@@ -1104,8 +1090,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec) | |||
1104 | 1090 | ||
1105 | cs42l52_init_beep(codec); | 1091 | cs42l52_init_beep(codec); |
1106 | 1092 | ||
1107 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1108 | |||
1109 | cs42l52->sysclk = CS42L52_DEFAULT_CLK; | 1093 | cs42l52->sysclk = CS42L52_DEFAULT_CLK; |
1110 | cs42l52->config.format = CS42L52_DEFAULT_FORMAT; | 1094 | cs42l52->config.format = CS42L52_DEFAULT_FORMAT; |
1111 | 1095 | ||
@@ -1115,7 +1099,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec) | |||
1115 | static int cs42l52_remove(struct snd_soc_codec *codec) | 1099 | static int cs42l52_remove(struct snd_soc_codec *codec) |
1116 | { | 1100 | { |
1117 | cs42l52_free_beep(codec); | 1101 | cs42l52_free_beep(codec); |
1118 | cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1119 | 1102 | ||
1120 | return 0; | 1103 | return 0; |
1121 | } | 1104 | } |
@@ -1123,9 +1106,8 @@ static int cs42l52_remove(struct snd_soc_codec *codec) | |||
1123 | static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { | 1106 | static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { |
1124 | .probe = cs42l52_probe, | 1107 | .probe = cs42l52_probe, |
1125 | .remove = cs42l52_remove, | 1108 | .remove = cs42l52_remove, |
1126 | .suspend = cs42l52_suspend, | ||
1127 | .resume = cs42l52_resume, | ||
1128 | .set_bias_level = cs42l52_set_bias_level, | 1109 | .set_bias_level = cs42l52_set_bias_level, |
1110 | .suspend_bias_off = true, | ||
1129 | 1111 | ||
1130 | .dapm_widgets = cs42l52_dapm_widgets, | 1112 | .dapm_widgets = cs42l52_dapm_widgets, |
1131 | .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), | 1113 | .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), |
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index c766a5a9ce80..2ddc7ac10ad7 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -171,9 +171,9 @@ static bool cs42l56_volatile_register(struct device *dev, unsigned int reg) | |||
171 | { | 171 | { |
172 | switch (reg) { | 172 | switch (reg) { |
173 | case CS42L56_INT_STATUS: | 173 | case CS42L56_INT_STATUS: |
174 | return 1; | 174 | return true; |
175 | default: | 175 | default: |
176 | return 0; | 176 | return false; |
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
@@ -1016,20 +1016,6 @@ static struct snd_soc_dai_driver cs42l56_dai = { | |||
1016 | .ops = &cs42l56_ops, | 1016 | .ops = &cs42l56_ops, |
1017 | }; | 1017 | }; |
1018 | 1018 | ||
1019 | static int cs42l56_suspend(struct snd_soc_codec *codec) | ||
1020 | { | ||
1021 | cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static int cs42l56_resume(struct snd_soc_codec *codec) | ||
1027 | { | ||
1028 | cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static int beep_freq[] = { | 1019 | static int beep_freq[] = { |
1034 | 261, 522, 585, 667, 706, 774, 889, 1000, | 1020 | 261, 522, 585, 667, 706, 774, 889, 1000, |
1035 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 | 1021 | 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 |
@@ -1168,18 +1154,12 @@ static int cs42l56_probe(struct snd_soc_codec *codec) | |||
1168 | { | 1154 | { |
1169 | cs42l56_init_beep(codec); | 1155 | cs42l56_init_beep(codec); |
1170 | 1156 | ||
1171 | cs42l56_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1172 | |||
1173 | return 0; | 1157 | return 0; |
1174 | } | 1158 | } |
1175 | 1159 | ||
1176 | static int cs42l56_remove(struct snd_soc_codec *codec) | 1160 | static int cs42l56_remove(struct snd_soc_codec *codec) |
1177 | { | 1161 | { |
1178 | struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec); | ||
1179 | |||
1180 | cs42l56_free_beep(codec); | 1162 | cs42l56_free_beep(codec); |
1181 | cs42l56_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1182 | regulator_bulk_free(ARRAY_SIZE(cs42l56->supplies), cs42l56->supplies); | ||
1183 | 1163 | ||
1184 | return 0; | 1164 | return 0; |
1185 | } | 1165 | } |
@@ -1187,9 +1167,8 @@ static int cs42l56_remove(struct snd_soc_codec *codec) | |||
1187 | static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { | 1167 | static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { |
1188 | .probe = cs42l56_probe, | 1168 | .probe = cs42l56_probe, |
1189 | .remove = cs42l56_remove, | 1169 | .remove = cs42l56_remove, |
1190 | .suspend = cs42l56_suspend, | ||
1191 | .resume = cs42l56_resume, | ||
1192 | .set_bias_level = cs42l56_set_bias_level, | 1170 | .set_bias_level = cs42l56_set_bias_level, |
1171 | .suspend_bias_off = true, | ||
1193 | 1172 | ||
1194 | .dapm_widgets = cs42l56_dapm_widgets, | 1173 | .dapm_widgets = cs42l56_dapm_widgets, |
1195 | .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), | 1174 | .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 0e7b9eb2ba61..2f8b94683e83 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -1330,25 +1330,10 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { | |||
1330 | } | 1330 | } |
1331 | }; | 1331 | }; |
1332 | 1332 | ||
1333 | static int cs42l73_suspend(struct snd_soc_codec *codec) | ||
1334 | { | ||
1335 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1336 | |||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static int cs42l73_resume(struct snd_soc_codec *codec) | ||
1341 | { | ||
1342 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1343 | return 0; | ||
1344 | } | ||
1345 | |||
1346 | static int cs42l73_probe(struct snd_soc_codec *codec) | 1333 | static int cs42l73_probe(struct snd_soc_codec *codec) |
1347 | { | 1334 | { |
1348 | struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); | 1335 | struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); |
1349 | 1336 | ||
1350 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1351 | |||
1352 | /* Set Charge Pump Frequency */ | 1337 | /* Set Charge Pump Frequency */ |
1353 | if (cs42l73->pdata.chgfreq) | 1338 | if (cs42l73->pdata.chgfreq) |
1354 | snd_soc_update_bits(codec, CS42L73_CPFCHC, | 1339 | snd_soc_update_bits(codec, CS42L73_CPFCHC, |
@@ -1362,18 +1347,10 @@ static int cs42l73_probe(struct snd_soc_codec *codec) | |||
1362 | return 0; | 1347 | return 0; |
1363 | } | 1348 | } |
1364 | 1349 | ||
1365 | static int cs42l73_remove(struct snd_soc_codec *codec) | ||
1366 | { | ||
1367 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1368 | return 0; | ||
1369 | } | ||
1370 | |||
1371 | static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { | 1350 | static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { |
1372 | .probe = cs42l73_probe, | 1351 | .probe = cs42l73_probe, |
1373 | .remove = cs42l73_remove, | ||
1374 | .suspend = cs42l73_suspend, | ||
1375 | .resume = cs42l73_resume, | ||
1376 | .set_bias_level = cs42l73_set_bias_level, | 1352 | .set_bias_level = cs42l73_set_bias_level, |
1353 | .suspend_bias_off = true, | ||
1377 | 1354 | ||
1378 | .dapm_widgets = cs42l73_dapm_widgets, | 1355 | .dapm_widgets = cs42l73_dapm_widgets, |
1379 | .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), | 1356 | .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), |
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 2fae31cb0067..61b2f9a2eef1 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | struct da732x_priv { | 36 | struct da732x_priv { |
37 | struct regmap *regmap; | 37 | struct regmap *regmap; |
38 | struct snd_soc_codec *codec; | ||
39 | 38 | ||
40 | unsigned int sysclk; | 39 | unsigned int sysclk; |
41 | bool pll_en; | 40 | bool pll_en; |
@@ -217,7 +216,7 @@ static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state) | |||
217 | snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS); | 216 | snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS); |
218 | break; | 217 | break; |
219 | default: | 218 | default: |
220 | pr_err(KERN_ERR "Wrong charge pump state\n"); | 219 | pr_err("Wrong charge pump state\n"); |
221 | break; | 220 | break; |
222 | } | 221 | } |
223 | } | 222 | } |
@@ -1508,31 +1507,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, | |||
1508 | return 0; | 1507 | return 0; |
1509 | } | 1508 | } |
1510 | 1509 | ||
1511 | static int da732x_probe(struct snd_soc_codec *codec) | ||
1512 | { | ||
1513 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | ||
1514 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1515 | |||
1516 | da732x->codec = codec; | ||
1517 | |||
1518 | dapm->idle_bias_off = false; | ||
1519 | |||
1520 | da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1521 | |||
1522 | return 0; | ||
1523 | } | ||
1524 | |||
1525 | static int da732x_remove(struct snd_soc_codec *codec) | ||
1526 | { | ||
1527 | |||
1528 | da732x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1529 | |||
1530 | return 0; | ||
1531 | } | ||
1532 | |||
1533 | static struct snd_soc_codec_driver soc_codec_dev_da732x = { | 1510 | static struct snd_soc_codec_driver soc_codec_dev_da732x = { |
1534 | .probe = da732x_probe, | ||
1535 | .remove = da732x_remove, | ||
1536 | .set_bias_level = da732x_set_bias_level, | 1511 | .set_bias_level = da732x_set_bias_level, |
1537 | .controls = da732x_snd_controls, | 1512 | .controls = da732x_snd_controls, |
1538 | .num_controls = ARRAY_SIZE(da732x_snd_controls), | 1513 | .num_controls = ARRAY_SIZE(da732x_snd_controls), |
diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c new file mode 100644 index 000000000000..aae410d122ee --- /dev/null +++ b/sound/soc/codecs/es8328-i2c.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * es8328-i2c.c -- ES8328 ALSA SoC I2C Audio driver | ||
3 | * | ||
4 | * Copyright 2014 Sutajio Ko-Usagi PTE LTD | ||
5 | * | ||
6 | * Author: Sean Cross <xobs@kosagi.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/i2c.h> | ||
15 | #include <linux/regmap.h> | ||
16 | |||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #include "es8328.h" | ||
20 | |||
21 | static const struct i2c_device_id es8328_id[] = { | ||
22 | { "everest,es8328", 0 }, | ||
23 | { } | ||
24 | }; | ||
25 | MODULE_DEVICE_TABLE(i2c, es8328_id); | ||
26 | |||
27 | static const struct of_device_id es8328_of_match[] = { | ||
28 | { .compatible = "everest,es8328", }, | ||
29 | { } | ||
30 | }; | ||
31 | MODULE_DEVICE_TABLE(of, es8328_of_match); | ||
32 | |||
33 | static int es8328_i2c_probe(struct i2c_client *i2c, | ||
34 | const struct i2c_device_id *id) | ||
35 | { | ||
36 | return es8328_probe(&i2c->dev, | ||
37 | devm_regmap_init_i2c(i2c, &es8328_regmap_config)); | ||
38 | } | ||
39 | |||
40 | static int es8328_i2c_remove(struct i2c_client *i2c) | ||
41 | { | ||
42 | snd_soc_unregister_codec(&i2c->dev); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static struct i2c_driver es8328_i2c_driver = { | ||
47 | .driver = { | ||
48 | .name = "es8328", | ||
49 | .of_match_table = es8328_of_match, | ||
50 | }, | ||
51 | .probe = es8328_i2c_probe, | ||
52 | .remove = es8328_i2c_remove, | ||
53 | .id_table = es8328_id, | ||
54 | }; | ||
55 | |||
56 | module_i2c_driver(es8328_i2c_driver); | ||
57 | |||
58 | MODULE_DESCRIPTION("ASoC ES8328 audio CODEC I2C driver"); | ||
59 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
60 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/es8328-spi.c b/sound/soc/codecs/es8328-spi.c new file mode 100644 index 000000000000..8fbd935e1c76 --- /dev/null +++ b/sound/soc/codecs/es8328-spi.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * es8328.c -- ES8328 ALSA SoC SPI Audio driver | ||
3 | * | ||
4 | * Copyright 2014 Sutajio Ko-Usagi PTE LTD | ||
5 | * | ||
6 | * Author: Sean Cross <xobs@kosagi.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/regmap.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <sound/soc.h> | ||
17 | #include "es8328.h" | ||
18 | |||
19 | static const struct of_device_id es8328_of_match[] = { | ||
20 | { .compatible = "everest,es8328", }, | ||
21 | { } | ||
22 | }; | ||
23 | MODULE_DEVICE_TABLE(of, es8328_of_match); | ||
24 | |||
25 | static int es8328_spi_probe(struct spi_device *spi) | ||
26 | { | ||
27 | return es8328_probe(&spi->dev, | ||
28 | devm_regmap_init_spi(spi, &es8328_regmap_config)); | ||
29 | } | ||
30 | |||
31 | static int es8328_spi_remove(struct spi_device *spi) | ||
32 | { | ||
33 | snd_soc_unregister_codec(&spi->dev); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static struct spi_driver es8328_spi_driver = { | ||
38 | .driver = { | ||
39 | .name = "es8328", | ||
40 | .of_match_table = es8328_of_match, | ||
41 | }, | ||
42 | .probe = es8328_spi_probe, | ||
43 | .remove = es8328_spi_remove, | ||
44 | }; | ||
45 | |||
46 | module_spi_driver(es8328_spi_driver); | ||
47 | MODULE_DESCRIPTION("ASoC ES8328 audio CODEC SPI driver"); | ||
48 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
49 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c new file mode 100644 index 000000000000..f27325155ace --- /dev/null +++ b/sound/soc/codecs/es8328.c | |||
@@ -0,0 +1,756 @@ | |||
1 | /* | ||
2 | * es8328.c -- ES8328 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2014 Sutajio Ko-Usagi PTE LTD | ||
5 | * | ||
6 | * Author: Sean Cross <xobs@kosagi.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/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/of_device.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/regulator/consumer.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/tlv.h> | ||
27 | #include "es8328.h" | ||
28 | |||
29 | #define ES8328_SYSCLK_RATE_1X 11289600 | ||
30 | #define ES8328_SYSCLK_RATE_2X 22579200 | ||
31 | |||
32 | /* Run the codec at 22.5792 or 11.2896 MHz to support these rates */ | ||
33 | static struct { | ||
34 | int rate; | ||
35 | u8 ratio; | ||
36 | } mclk_ratios[] = { | ||
37 | { 8000, 9 }, | ||
38 | {11025, 7 }, | ||
39 | {22050, 4 }, | ||
40 | {44100, 2 }, | ||
41 | }; | ||
42 | |||
43 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ | ||
44 | enum sgtl5000_regulator_supplies { | ||
45 | DVDD, | ||
46 | AVDD, | ||
47 | PVDD, | ||
48 | HPVDD, | ||
49 | ES8328_SUPPLY_NUM | ||
50 | }; | ||
51 | |||
52 | /* vddd is optional supply */ | ||
53 | static const char * const supply_names[ES8328_SUPPLY_NUM] = { | ||
54 | "DVDD", | ||
55 | "AVDD", | ||
56 | "PVDD", | ||
57 | "HPVDD", | ||
58 | }; | ||
59 | |||
60 | #define ES8328_RATES (SNDRV_PCM_RATE_44100 | \ | ||
61 | SNDRV_PCM_RATE_22050 | \ | ||
62 | SNDRV_PCM_RATE_11025) | ||
63 | #define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | ||
64 | |||
65 | struct es8328_priv { | ||
66 | struct regmap *regmap; | ||
67 | struct clk *clk; | ||
68 | int playback_fs; | ||
69 | bool deemph; | ||
70 | struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM]; | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * ES8328 Controls | ||
75 | */ | ||
76 | |||
77 | static const char * const adcpol_txt[] = {"Normal", "L Invert", "R Invert", | ||
78 | "L + R Invert"}; | ||
79 | static SOC_ENUM_SINGLE_DECL(adcpol, | ||
80 | ES8328_ADCCONTROL6, 6, adcpol_txt); | ||
81 | |||
82 | static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); | ||
83 | static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); | ||
84 | static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); | ||
85 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | ||
86 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); | ||
87 | |||
88 | static const int deemph_settings[] = { 0, 32000, 44100, 48000 }; | ||
89 | |||
90 | static int es8328_set_deemph(struct snd_soc_codec *codec) | ||
91 | { | ||
92 | struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec); | ||
93 | int val, i, best; | ||
94 | |||
95 | /* | ||
96 | * If we're using deemphasis select the nearest available sample | ||
97 | * rate. | ||
98 | */ | ||
99 | if (es8328->deemph) { | ||
100 | best = 1; | ||
101 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { | ||
102 | if (abs(deemph_settings[i] - es8328->playback_fs) < | ||
103 | abs(deemph_settings[best] - es8328->playback_fs)) | ||
104 | best = i; | ||
105 | } | ||
106 | |||
107 | val = best << 1; | ||
108 | } else { | ||
109 | val = 0; | ||
110 | } | ||
111 | |||
112 | dev_dbg(codec->dev, "Set deemphasis %d\n", val); | ||
113 | |||
114 | return snd_soc_update_bits(codec, ES8328_DACCONTROL6, 0x6, val); | ||
115 | } | ||
116 | |||
117 | static int es8328_get_deemph(struct snd_kcontrol *kcontrol, | ||
118 | struct snd_ctl_elem_value *ucontrol) | ||
119 | { | ||
120 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
121 | struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec); | ||
122 | |||
123 | ucontrol->value.enumerated.item[0] = es8328->deemph; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int es8328_put_deemph(struct snd_kcontrol *kcontrol, | ||
128 | struct snd_ctl_elem_value *ucontrol) | ||
129 | { | ||
130 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | ||
131 | struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec); | ||
132 | int deemph = ucontrol->value.enumerated.item[0]; | ||
133 | int ret; | ||
134 | |||
135 | if (deemph > 1) | ||
136 | return -EINVAL; | ||
137 | |||
138 | ret = es8328_set_deemph(codec); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | es8328->deemph = deemph; | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | |||
148 | |||
149 | static const struct snd_kcontrol_new es8328_snd_controls[] = { | ||
150 | SOC_DOUBLE_R_TLV("Capture Digital Volume", | ||
151 | ES8328_ADCCONTROL8, ES8328_ADCCONTROL9, | ||
152 | 0, 0xc0, 1, dac_adc_tlv), | ||
153 | SOC_SINGLE("Capture ZC Switch", ES8328_ADCCONTROL7, 6, 1, 0), | ||
154 | |||
155 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, | ||
156 | es8328_get_deemph, es8328_put_deemph), | ||
157 | |||
158 | SOC_ENUM("Capture Polarity", adcpol), | ||
159 | |||
160 | SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", | ||
161 | ES8328_DACCONTROL17, 3, 7, 1, bypass_tlv), | ||
162 | SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", | ||
163 | ES8328_DACCONTROL19, 3, 7, 1, bypass_tlv), | ||
164 | SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", | ||
165 | ES8328_DACCONTROL18, 3, 7, 1, bypass_tlv), | ||
166 | SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", | ||
167 | ES8328_DACCONTROL20, 3, 7, 1, bypass_tlv), | ||
168 | |||
169 | SOC_DOUBLE_R_TLV("PCM Volume", | ||
170 | ES8328_LDACVOL, ES8328_RDACVOL, | ||
171 | 0, ES8328_DACVOL_MAX, 1, dac_adc_tlv), | ||
172 | |||
173 | SOC_DOUBLE_R_TLV("Output 1 Playback Volume", | ||
174 | ES8328_LOUT1VOL, ES8328_ROUT1VOL, | ||
175 | 0, ES8328_OUT1VOL_MAX, 0, play_tlv), | ||
176 | |||
177 | SOC_DOUBLE_R_TLV("Output 2 Playback Volume", | ||
178 | ES8328_LOUT2VOL, ES8328_ROUT2VOL, | ||
179 | 0, ES8328_OUT2VOL_MAX, 0, play_tlv), | ||
180 | |||
181 | SOC_DOUBLE_TLV("Mic PGA Volume", ES8328_ADCCONTROL1, | ||
182 | 4, 0, 8, 0, mic_tlv), | ||
183 | }; | ||
184 | |||
185 | /* | ||
186 | * DAPM Controls | ||
187 | */ | ||
188 | |||
189 | static const char * const es8328_line_texts[] = { | ||
190 | "Line 1", "Line 2", "PGA", "Differential"}; | ||
191 | |||
192 | static const struct soc_enum es8328_lline_enum = | ||
193 | SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 3, | ||
194 | ARRAY_SIZE(es8328_line_texts), | ||
195 | es8328_line_texts); | ||
196 | static const struct snd_kcontrol_new es8328_left_line_controls = | ||
197 | SOC_DAPM_ENUM("Route", es8328_lline_enum); | ||
198 | |||
199 | static const struct soc_enum es8328_rline_enum = | ||
200 | SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 0, | ||
201 | ARRAY_SIZE(es8328_line_texts), | ||
202 | es8328_line_texts); | ||
203 | static const struct snd_kcontrol_new es8328_right_line_controls = | ||
204 | SOC_DAPM_ENUM("Route", es8328_lline_enum); | ||
205 | |||
206 | /* Left Mixer */ | ||
207 | static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { | ||
208 | SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL17, 8, 1, 0), | ||
209 | SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 7, 1, 0), | ||
210 | SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 8, 1, 0), | ||
211 | SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 7, 1, 0), | ||
212 | }; | ||
213 | |||
214 | /* Right Mixer */ | ||
215 | static const struct snd_kcontrol_new es8328_right_mixer_controls[] = { | ||
216 | SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 8, 1, 0), | ||
217 | SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 7, 1, 0), | ||
218 | SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL20, 8, 1, 0), | ||
219 | SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 7, 1, 0), | ||
220 | }; | ||
221 | |||
222 | static const char * const es8328_pga_sel[] = { | ||
223 | "Line 1", "Line 2", "Line 3", "Differential"}; | ||
224 | |||
225 | /* Left PGA Mux */ | ||
226 | static const struct soc_enum es8328_lpga_enum = | ||
227 | SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 6, | ||
228 | ARRAY_SIZE(es8328_pga_sel), | ||
229 | es8328_pga_sel); | ||
230 | static const struct snd_kcontrol_new es8328_left_pga_controls = | ||
231 | SOC_DAPM_ENUM("Route", es8328_lpga_enum); | ||
232 | |||
233 | /* Right PGA Mux */ | ||
234 | static const struct soc_enum es8328_rpga_enum = | ||
235 | SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 4, | ||
236 | ARRAY_SIZE(es8328_pga_sel), | ||
237 | es8328_pga_sel); | ||
238 | static const struct snd_kcontrol_new es8328_right_pga_controls = | ||
239 | SOC_DAPM_ENUM("Route", es8328_rpga_enum); | ||
240 | |||
241 | /* Differential Mux */ | ||
242 | static const char * const es8328_diff_sel[] = {"Line 1", "Line 2"}; | ||
243 | static SOC_ENUM_SINGLE_DECL(diffmux, | ||
244 | ES8328_ADCCONTROL3, 7, es8328_diff_sel); | ||
245 | static const struct snd_kcontrol_new es8328_diffmux_controls = | ||
246 | SOC_DAPM_ENUM("Route", diffmux); | ||
247 | |||
248 | /* Mono ADC Mux */ | ||
249 | static const char * const es8328_mono_mux[] = {"Stereo", "Mono (Left)", | ||
250 | "Mono (Right)", "Digital Mono"}; | ||
251 | static SOC_ENUM_SINGLE_DECL(monomux, | ||
252 | ES8328_ADCCONTROL3, 3, es8328_mono_mux); | ||
253 | static const struct snd_kcontrol_new es8328_monomux_controls = | ||
254 | SOC_DAPM_ENUM("Route", monomux); | ||
255 | |||
256 | static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = { | ||
257 | SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, | ||
258 | &es8328_diffmux_controls), | ||
259 | SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, | ||
260 | &es8328_monomux_controls), | ||
261 | SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, | ||
262 | &es8328_monomux_controls), | ||
263 | |||
264 | SND_SOC_DAPM_MUX("Left PGA Mux", ES8328_ADCPOWER, | ||
265 | ES8328_ADCPOWER_AINL_OFF, 1, | ||
266 | &es8328_left_pga_controls), | ||
267 | SND_SOC_DAPM_MUX("Right PGA Mux", ES8328_ADCPOWER, | ||
268 | ES8328_ADCPOWER_AINR_OFF, 1, | ||
269 | &es8328_right_pga_controls), | ||
270 | |||
271 | SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, | ||
272 | &es8328_left_line_controls), | ||
273 | SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, | ||
274 | &es8328_right_line_controls), | ||
275 | |||
276 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ES8328_ADCPOWER, | ||
277 | ES8328_ADCPOWER_ADCR_OFF, 1), | ||
278 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8328_ADCPOWER, | ||
279 | ES8328_ADCPOWER_ADCL_OFF, 1), | ||
280 | |||
281 | SND_SOC_DAPM_SUPPLY("Mic Bias", ES8328_ADCPOWER, | ||
282 | ES8328_ADCPOWER_MIC_BIAS_OFF, 1, NULL, 0), | ||
283 | SND_SOC_DAPM_SUPPLY("Mic Bias Gen", ES8328_ADCPOWER, | ||
284 | ES8328_ADCPOWER_ADC_BIAS_GEN_OFF, 1, NULL, 0), | ||
285 | |||
286 | SND_SOC_DAPM_SUPPLY("DAC STM", ES8328_CHIPPOWER, | ||
287 | ES8328_CHIPPOWER_DACSTM_RESET, 1, NULL, 0), | ||
288 | SND_SOC_DAPM_SUPPLY("ADC STM", ES8328_CHIPPOWER, | ||
289 | ES8328_CHIPPOWER_ADCSTM_RESET, 1, NULL, 0), | ||
290 | |||
291 | SND_SOC_DAPM_SUPPLY("DAC DIG", ES8328_CHIPPOWER, | ||
292 | ES8328_CHIPPOWER_DACDIG_OFF, 1, NULL, 0), | ||
293 | SND_SOC_DAPM_SUPPLY("ADC DIG", ES8328_CHIPPOWER, | ||
294 | ES8328_CHIPPOWER_ADCDIG_OFF, 1, NULL, 0), | ||
295 | |||
296 | SND_SOC_DAPM_SUPPLY("DAC DLL", ES8328_CHIPPOWER, | ||
297 | ES8328_CHIPPOWER_DACDLL_OFF, 1, NULL, 0), | ||
298 | SND_SOC_DAPM_SUPPLY("ADC DLL", ES8328_CHIPPOWER, | ||
299 | ES8328_CHIPPOWER_ADCDLL_OFF, 1, NULL, 0), | ||
300 | |||
301 | SND_SOC_DAPM_SUPPLY("ADC Vref", ES8328_CHIPPOWER, | ||
302 | ES8328_CHIPPOWER_ADCVREF_OFF, 1, NULL, 0), | ||
303 | SND_SOC_DAPM_SUPPLY("DAC Vref", ES8328_CHIPPOWER, | ||
304 | ES8328_CHIPPOWER_DACVREF_OFF, 1, NULL, 0), | ||
305 | |||
306 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8328_DACPOWER, | ||
307 | ES8328_DACPOWER_RDAC_OFF, 1), | ||
308 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER, | ||
309 | ES8328_DACPOWER_LDAC_OFF, 1), | ||
310 | |||
311 | SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, | ||
312 | &es8328_left_mixer_controls[0], | ||
313 | ARRAY_SIZE(es8328_left_mixer_controls)), | ||
314 | SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, | ||
315 | &es8328_right_mixer_controls[0], | ||
316 | ARRAY_SIZE(es8328_right_mixer_controls)), | ||
317 | |||
318 | SND_SOC_DAPM_PGA("Right Out 2", ES8328_DACPOWER, | ||
319 | ES8328_DACPOWER_ROUT2_ON, 0, NULL, 0), | ||
320 | SND_SOC_DAPM_PGA("Left Out 2", ES8328_DACPOWER, | ||
321 | ES8328_DACPOWER_LOUT2_ON, 0, NULL, 0), | ||
322 | SND_SOC_DAPM_PGA("Right Out 1", ES8328_DACPOWER, | ||
323 | ES8328_DACPOWER_ROUT1_ON, 0, NULL, 0), | ||
324 | SND_SOC_DAPM_PGA("Left Out 1", ES8328_DACPOWER, | ||
325 | ES8328_DACPOWER_LOUT1_ON, 0, NULL, 0), | ||
326 | |||
327 | SND_SOC_DAPM_OUTPUT("LOUT1"), | ||
328 | SND_SOC_DAPM_OUTPUT("ROUT1"), | ||
329 | SND_SOC_DAPM_OUTPUT("LOUT2"), | ||
330 | SND_SOC_DAPM_OUTPUT("ROUT2"), | ||
331 | |||
332 | SND_SOC_DAPM_INPUT("LINPUT1"), | ||
333 | SND_SOC_DAPM_INPUT("LINPUT2"), | ||
334 | SND_SOC_DAPM_INPUT("RINPUT1"), | ||
335 | SND_SOC_DAPM_INPUT("RINPUT2"), | ||
336 | }; | ||
337 | |||
338 | static const struct snd_soc_dapm_route es8328_dapm_routes[] = { | ||
339 | |||
340 | { "Left Line Mux", "Line 1", "LINPUT1" }, | ||
341 | { "Left Line Mux", "Line 2", "LINPUT2" }, | ||
342 | { "Left Line Mux", "PGA", "Left PGA Mux" }, | ||
343 | { "Left Line Mux", "Differential", "Differential Mux" }, | ||
344 | |||
345 | { "Right Line Mux", "Line 1", "RINPUT1" }, | ||
346 | { "Right Line Mux", "Line 2", "RINPUT2" }, | ||
347 | { "Right Line Mux", "PGA", "Right PGA Mux" }, | ||
348 | { "Right Line Mux", "Differential", "Differential Mux" }, | ||
349 | |||
350 | { "Left PGA Mux", "Line 1", "LINPUT1" }, | ||
351 | { "Left PGA Mux", "Line 2", "LINPUT2" }, | ||
352 | { "Left PGA Mux", "Differential", "Differential Mux" }, | ||
353 | |||
354 | { "Right PGA Mux", "Line 1", "RINPUT1" }, | ||
355 | { "Right PGA Mux", "Line 2", "RINPUT2" }, | ||
356 | { "Right PGA Mux", "Differential", "Differential Mux" }, | ||
357 | |||
358 | { "Differential Mux", "Line 1", "LINPUT1" }, | ||
359 | { "Differential Mux", "Line 1", "RINPUT1" }, | ||
360 | { "Differential Mux", "Line 2", "LINPUT2" }, | ||
361 | { "Differential Mux", "Line 2", "RINPUT2" }, | ||
362 | |||
363 | { "Left ADC Mux", "Stereo", "Left PGA Mux" }, | ||
364 | { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" }, | ||
365 | { "Left ADC Mux", "Digital Mono", "Left PGA Mux" }, | ||
366 | |||
367 | { "Right ADC Mux", "Stereo", "Right PGA Mux" }, | ||
368 | { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" }, | ||
369 | { "Right ADC Mux", "Digital Mono", "Right PGA Mux" }, | ||
370 | |||
371 | { "Left ADC", NULL, "Left ADC Mux" }, | ||
372 | { "Right ADC", NULL, "Right ADC Mux" }, | ||
373 | |||
374 | { "ADC DIG", NULL, "ADC STM" }, | ||
375 | { "ADC DIG", NULL, "ADC Vref" }, | ||
376 | { "ADC DIG", NULL, "ADC DLL" }, | ||
377 | |||
378 | { "Left ADC", NULL, "ADC DIG" }, | ||
379 | { "Right ADC", NULL, "ADC DIG" }, | ||
380 | |||
381 | { "Mic Bias", NULL, "Mic Bias Gen" }, | ||
382 | |||
383 | { "Left Line Mux", "Line 1", "LINPUT1" }, | ||
384 | { "Left Line Mux", "Line 2", "LINPUT2" }, | ||
385 | { "Left Line Mux", "PGA", "Left PGA Mux" }, | ||
386 | { "Left Line Mux", "Differential", "Differential Mux" }, | ||
387 | |||
388 | { "Right Line Mux", "Line 1", "RINPUT1" }, | ||
389 | { "Right Line Mux", "Line 2", "RINPUT2" }, | ||
390 | { "Right Line Mux", "PGA", "Right PGA Mux" }, | ||
391 | { "Right Line Mux", "Differential", "Differential Mux" }, | ||
392 | |||
393 | { "Left Out 1", NULL, "Left DAC" }, | ||
394 | { "Right Out 1", NULL, "Right DAC" }, | ||
395 | { "Left Out 2", NULL, "Left DAC" }, | ||
396 | { "Right Out 2", NULL, "Right DAC" }, | ||
397 | |||
398 | { "Left Mixer", "Playback Switch", "Left DAC" }, | ||
399 | { "Left Mixer", "Left Bypass Switch", "Left Line Mux" }, | ||
400 | { "Left Mixer", "Right Playback Switch", "Right DAC" }, | ||
401 | { "Left Mixer", "Right Bypass Switch", "Right Line Mux" }, | ||
402 | |||
403 | { "Right Mixer", "Left Playback Switch", "Left DAC" }, | ||
404 | { "Right Mixer", "Left Bypass Switch", "Left Line Mux" }, | ||
405 | { "Right Mixer", "Playback Switch", "Right DAC" }, | ||
406 | { "Right Mixer", "Right Bypass Switch", "Right Line Mux" }, | ||
407 | |||
408 | { "DAC DIG", NULL, "DAC STM" }, | ||
409 | { "DAC DIG", NULL, "DAC Vref" }, | ||
410 | { "DAC DIG", NULL, "DAC DLL" }, | ||
411 | |||
412 | { "Left DAC", NULL, "DAC DIG" }, | ||
413 | { "Right DAC", NULL, "DAC DIG" }, | ||
414 | |||
415 | { "Left Out 1", NULL, "Left Mixer" }, | ||
416 | { "LOUT1", NULL, "Left Out 1" }, | ||
417 | { "Right Out 1", NULL, "Right Mixer" }, | ||
418 | { "ROUT1", NULL, "Right Out 1" }, | ||
419 | |||
420 | { "Left Out 2", NULL, "Left Mixer" }, | ||
421 | { "LOUT2", NULL, "Left Out 2" }, | ||
422 | { "Right Out 2", NULL, "Right Mixer" }, | ||
423 | { "ROUT2", NULL, "Right Out 2" }, | ||
424 | }; | ||
425 | |||
426 | static int es8328_mute(struct snd_soc_dai *dai, int mute) | ||
427 | { | ||
428 | return snd_soc_update_bits(dai->codec, ES8328_DACCONTROL3, | ||
429 | ES8328_DACCONTROL3_DACMUTE, | ||
430 | mute ? ES8328_DACCONTROL3_DACMUTE : 0); | ||
431 | } | ||
432 | |||
433 | static int es8328_hw_params(struct snd_pcm_substream *substream, | ||
434 | struct snd_pcm_hw_params *params, | ||
435 | struct snd_soc_dai *dai) | ||
436 | { | ||
437 | struct snd_soc_codec *codec = dai->codec; | ||
438 | struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec); | ||
439 | int clk_rate; | ||
440 | int i; | ||
441 | int reg; | ||
442 | u8 ratio; | ||
443 | |||
444 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
445 | reg = ES8328_DACCONTROL2; | ||
446 | else | ||
447 | reg = ES8328_ADCCONTROL5; | ||
448 | |||
449 | clk_rate = clk_get_rate(es8328->clk); | ||
450 | |||
451 | if ((clk_rate != ES8328_SYSCLK_RATE_1X) && | ||
452 | (clk_rate != ES8328_SYSCLK_RATE_2X)) { | ||
453 | dev_err(codec->dev, | ||
454 | "%s: clock is running at %d Hz, not %d or %d Hz\n", | ||
455 | __func__, clk_rate, | ||
456 | ES8328_SYSCLK_RATE_1X, ES8328_SYSCLK_RATE_2X); | ||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | /* find master mode MCLK to sampling frequency ratio */ | ||
461 | ratio = mclk_ratios[0].rate; | ||
462 | for (i = 1; i < ARRAY_SIZE(mclk_ratios); i++) | ||
463 | if (params_rate(params) <= mclk_ratios[i].rate) | ||
464 | ratio = mclk_ratios[i].ratio; | ||
465 | |||
466 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
467 | es8328->playback_fs = params_rate(params); | ||
468 | es8328_set_deemph(codec); | ||
469 | } | ||
470 | |||
471 | return snd_soc_update_bits(codec, reg, ES8328_RATEMASK, ratio); | ||
472 | } | ||
473 | |||
474 | static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
475 | unsigned int fmt) | ||
476 | { | ||
477 | struct snd_soc_codec *codec = codec_dai->codec; | ||
478 | struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec); | ||
479 | int clk_rate; | ||
480 | u8 mode = ES8328_DACCONTROL1_DACWL_16; | ||
481 | |||
482 | /* set master/slave audio interface */ | ||
483 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBM_CFM) | ||
484 | return -EINVAL; | ||
485 | |||
486 | /* interface format */ | ||
487 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
488 | case SND_SOC_DAIFMT_I2S: | ||
489 | mode |= ES8328_DACCONTROL1_DACFORMAT_I2S; | ||
490 | break; | ||
491 | case SND_SOC_DAIFMT_RIGHT_J: | ||
492 | mode |= ES8328_DACCONTROL1_DACFORMAT_RJUST; | ||
493 | break; | ||
494 | case SND_SOC_DAIFMT_LEFT_J: | ||
495 | mode |= ES8328_DACCONTROL1_DACFORMAT_LJUST; | ||
496 | break; | ||
497 | default: | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | /* clock inversion */ | ||
502 | if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) | ||
503 | return -EINVAL; | ||
504 | |||
505 | snd_soc_write(codec, ES8328_DACCONTROL1, mode); | ||
506 | snd_soc_write(codec, ES8328_ADCCONTROL4, mode); | ||
507 | |||
508 | /* Master serial port mode, with BCLK generated automatically */ | ||
509 | clk_rate = clk_get_rate(es8328->clk); | ||
510 | if (clk_rate == ES8328_SYSCLK_RATE_1X) | ||
511 | snd_soc_write(codec, ES8328_MASTERMODE, | ||
512 | ES8328_MASTERMODE_MSC); | ||
513 | else | ||
514 | snd_soc_write(codec, ES8328_MASTERMODE, | ||
515 | ES8328_MASTERMODE_MCLKDIV2 | | ||
516 | ES8328_MASTERMODE_MSC); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int es8328_set_bias_level(struct snd_soc_codec *codec, | ||
522 | enum snd_soc_bias_level level) | ||
523 | { | ||
524 | switch (level) { | ||
525 | case SND_SOC_BIAS_ON: | ||
526 | break; | ||
527 | |||
528 | case SND_SOC_BIAS_PREPARE: | ||
529 | /* VREF, VMID=2x50k, digital enabled */ | ||
530 | snd_soc_write(codec, ES8328_CHIPPOWER, 0); | ||
531 | snd_soc_update_bits(codec, ES8328_CONTROL1, | ||
532 | ES8328_CONTROL1_VMIDSEL_MASK | | ||
533 | ES8328_CONTROL1_ENREF, | ||
534 | ES8328_CONTROL1_VMIDSEL_50k | | ||
535 | ES8328_CONTROL1_ENREF); | ||
536 | break; | ||
537 | |||
538 | case SND_SOC_BIAS_STANDBY: | ||
539 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
540 | snd_soc_update_bits(codec, ES8328_CONTROL1, | ||
541 | ES8328_CONTROL1_VMIDSEL_MASK | | ||
542 | ES8328_CONTROL1_ENREF, | ||
543 | ES8328_CONTROL1_VMIDSEL_5k | | ||
544 | ES8328_CONTROL1_ENREF); | ||
545 | |||
546 | /* Charge caps */ | ||
547 | msleep(100); | ||
548 | } | ||
549 | |||
550 | snd_soc_write(codec, ES8328_CONTROL2, | ||
551 | ES8328_CONTROL2_OVERCURRENT_ON | | ||
552 | ES8328_CONTROL2_THERMAL_SHUTDOWN_ON); | ||
553 | |||
554 | /* VREF, VMID=2*500k, digital stopped */ | ||
555 | snd_soc_update_bits(codec, ES8328_CONTROL1, | ||
556 | ES8328_CONTROL1_VMIDSEL_MASK | | ||
557 | ES8328_CONTROL1_ENREF, | ||
558 | ES8328_CONTROL1_VMIDSEL_500k | | ||
559 | ES8328_CONTROL1_ENREF); | ||
560 | break; | ||
561 | |||
562 | case SND_SOC_BIAS_OFF: | ||
563 | snd_soc_update_bits(codec, ES8328_CONTROL1, | ||
564 | ES8328_CONTROL1_VMIDSEL_MASK | | ||
565 | ES8328_CONTROL1_ENREF, | ||
566 | 0); | ||
567 | break; | ||
568 | } | ||
569 | codec->dapm.bias_level = level; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static const struct snd_soc_dai_ops es8328_dai_ops = { | ||
574 | .hw_params = es8328_hw_params, | ||
575 | .digital_mute = es8328_mute, | ||
576 | .set_fmt = es8328_set_dai_fmt, | ||
577 | }; | ||
578 | |||
579 | static struct snd_soc_dai_driver es8328_dai = { | ||
580 | .name = "es8328-hifi-analog", | ||
581 | .playback = { | ||
582 | .stream_name = "Playback", | ||
583 | .channels_min = 2, | ||
584 | .channels_max = 2, | ||
585 | .rates = ES8328_RATES, | ||
586 | .formats = ES8328_FORMATS, | ||
587 | }, | ||
588 | .capture = { | ||
589 | .stream_name = "Capture", | ||
590 | .channels_min = 2, | ||
591 | .channels_max = 2, | ||
592 | .rates = ES8328_RATES, | ||
593 | .formats = ES8328_FORMATS, | ||
594 | }, | ||
595 | .ops = &es8328_dai_ops, | ||
596 | }; | ||
597 | |||
598 | static int es8328_suspend(struct snd_soc_codec *codec) | ||
599 | { | ||
600 | struct es8328_priv *es8328; | ||
601 | int ret; | ||
602 | |||
603 | es8328 = snd_soc_codec_get_drvdata(codec); | ||
604 | |||
605 | clk_disable_unprepare(es8328->clk); | ||
606 | |||
607 | ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), | ||
608 | es8328->supplies); | ||
609 | if (ret) { | ||
610 | dev_err(codec->dev, "unable to disable regulators\n"); | ||
611 | return ret; | ||
612 | } | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static int es8328_resume(struct snd_soc_codec *codec) | ||
617 | { | ||
618 | struct regmap *regmap = dev_get_regmap(codec->dev, NULL); | ||
619 | struct es8328_priv *es8328; | ||
620 | int ret; | ||
621 | |||
622 | es8328 = snd_soc_codec_get_drvdata(codec); | ||
623 | |||
624 | ret = clk_prepare_enable(es8328->clk); | ||
625 | if (ret) { | ||
626 | dev_err(codec->dev, "unable to enable clock\n"); | ||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies), | ||
631 | es8328->supplies); | ||
632 | if (ret) { | ||
633 | dev_err(codec->dev, "unable to enable regulators\n"); | ||
634 | return ret; | ||
635 | } | ||
636 | |||
637 | regcache_mark_dirty(regmap); | ||
638 | ret = regcache_sync(regmap); | ||
639 | if (ret) { | ||
640 | dev_err(codec->dev, "unable to sync regcache\n"); | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static int es8328_codec_probe(struct snd_soc_codec *codec) | ||
648 | { | ||
649 | struct es8328_priv *es8328; | ||
650 | int ret; | ||
651 | |||
652 | es8328 = snd_soc_codec_get_drvdata(codec); | ||
653 | |||
654 | ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies), | ||
655 | es8328->supplies); | ||
656 | if (ret) { | ||
657 | dev_err(codec->dev, "unable to enable regulators\n"); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | /* Setup clocks */ | ||
662 | es8328->clk = devm_clk_get(codec->dev, NULL); | ||
663 | if (IS_ERR(es8328->clk)) { | ||
664 | dev_err(codec->dev, "codec clock missing or invalid\n"); | ||
665 | ret = PTR_ERR(es8328->clk); | ||
666 | goto clk_fail; | ||
667 | } | ||
668 | |||
669 | ret = clk_prepare_enable(es8328->clk); | ||
670 | if (ret) { | ||
671 | dev_err(codec->dev, "unable to prepare codec clk\n"); | ||
672 | goto clk_fail; | ||
673 | } | ||
674 | |||
675 | return 0; | ||
676 | |||
677 | clk_fail: | ||
678 | regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), | ||
679 | es8328->supplies); | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int es8328_remove(struct snd_soc_codec *codec) | ||
684 | { | ||
685 | struct es8328_priv *es8328; | ||
686 | |||
687 | es8328 = snd_soc_codec_get_drvdata(codec); | ||
688 | |||
689 | if (es8328->clk) | ||
690 | clk_disable_unprepare(es8328->clk); | ||
691 | |||
692 | regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), | ||
693 | es8328->supplies); | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | const struct regmap_config es8328_regmap_config = { | ||
699 | .reg_bits = 8, | ||
700 | .val_bits = 8, | ||
701 | .max_register = ES8328_REG_MAX, | ||
702 | .cache_type = REGCACHE_RBTREE, | ||
703 | }; | ||
704 | EXPORT_SYMBOL_GPL(es8328_regmap_config); | ||
705 | |||
706 | static struct snd_soc_codec_driver es8328_codec_driver = { | ||
707 | .probe = es8328_codec_probe, | ||
708 | .suspend = es8328_suspend, | ||
709 | .resume = es8328_resume, | ||
710 | .remove = es8328_remove, | ||
711 | .set_bias_level = es8328_set_bias_level, | ||
712 | .suspend_bias_off = true, | ||
713 | |||
714 | .controls = es8328_snd_controls, | ||
715 | .num_controls = ARRAY_SIZE(es8328_snd_controls), | ||
716 | .dapm_widgets = es8328_dapm_widgets, | ||
717 | .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), | ||
718 | .dapm_routes = es8328_dapm_routes, | ||
719 | .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), | ||
720 | }; | ||
721 | |||
722 | int es8328_probe(struct device *dev, struct regmap *regmap) | ||
723 | { | ||
724 | struct es8328_priv *es8328; | ||
725 | int ret; | ||
726 | int i; | ||
727 | |||
728 | if (IS_ERR(regmap)) | ||
729 | return PTR_ERR(regmap); | ||
730 | |||
731 | es8328 = devm_kzalloc(dev, sizeof(*es8328), GFP_KERNEL); | ||
732 | if (es8328 == NULL) | ||
733 | return -ENOMEM; | ||
734 | |||
735 | es8328->regmap = regmap; | ||
736 | |||
737 | for (i = 0; i < ARRAY_SIZE(es8328->supplies); i++) | ||
738 | es8328->supplies[i].supply = supply_names[i]; | ||
739 | |||
740 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(es8328->supplies), | ||
741 | es8328->supplies); | ||
742 | if (ret) { | ||
743 | dev_err(dev, "unable to get regulators\n"); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | dev_set_drvdata(dev, es8328); | ||
748 | |||
749 | return snd_soc_register_codec(dev, | ||
750 | &es8328_codec_driver, &es8328_dai, 1); | ||
751 | } | ||
752 | EXPORT_SYMBOL_GPL(es8328_probe); | ||
753 | |||
754 | MODULE_DESCRIPTION("ASoC ES8328 driver"); | ||
755 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
756 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/es8328.h b/sound/soc/codecs/es8328.h new file mode 100644 index 000000000000..cb36afe10c0e --- /dev/null +++ b/sound/soc/codecs/es8328.h | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * es8328.h -- ES8328 ALSA SoC Audio driver | ||
3 | */ | ||
4 | |||
5 | #ifndef _ES8328_H | ||
6 | #define _ES8328_H | ||
7 | |||
8 | #include <linux/regmap.h> | ||
9 | |||
10 | struct device; | ||
11 | |||
12 | extern const struct regmap_config es8328_regmap_config; | ||
13 | int es8328_probe(struct device *dev, struct regmap *regmap); | ||
14 | |||
15 | #define ES8328_DACLVOL 46 | ||
16 | #define ES8328_DACRVOL 47 | ||
17 | #define ES8328_DACCTL 28 | ||
18 | #define ES8328_RATEMASK (0x1f << 0) | ||
19 | |||
20 | #define ES8328_CONTROL1 0x00 | ||
21 | #define ES8328_CONTROL1_VMIDSEL_OFF (0 << 0) | ||
22 | #define ES8328_CONTROL1_VMIDSEL_50k (1 << 0) | ||
23 | #define ES8328_CONTROL1_VMIDSEL_500k (2 << 0) | ||
24 | #define ES8328_CONTROL1_VMIDSEL_5k (3 << 0) | ||
25 | #define ES8328_CONTROL1_VMIDSEL_MASK (7 << 0) | ||
26 | #define ES8328_CONTROL1_ENREF (1 << 2) | ||
27 | #define ES8328_CONTROL1_SEQEN (1 << 3) | ||
28 | #define ES8328_CONTROL1_SAMEFS (1 << 4) | ||
29 | #define ES8328_CONTROL1_DACMCLK_ADC (0 << 5) | ||
30 | #define ES8328_CONTROL1_DACMCLK_DAC (1 << 5) | ||
31 | #define ES8328_CONTROL1_LRCM (1 << 6) | ||
32 | #define ES8328_CONTROL1_SCP_RESET (1 << 7) | ||
33 | |||
34 | #define ES8328_CONTROL2 0x01 | ||
35 | #define ES8328_CONTROL2_VREF_BUF_OFF (1 << 0) | ||
36 | #define ES8328_CONTROL2_VREF_LOWPOWER (1 << 1) | ||
37 | #define ES8328_CONTROL2_IBIASGEN_OFF (1 << 2) | ||
38 | #define ES8328_CONTROL2_ANALOG_OFF (1 << 3) | ||
39 | #define ES8328_CONTROL2_VREF_BUF_LOWPOWER (1 << 4) | ||
40 | #define ES8328_CONTROL2_VCM_MOD_LOWPOWER (1 << 5) | ||
41 | #define ES8328_CONTROL2_OVERCURRENT_ON (1 << 6) | ||
42 | #define ES8328_CONTROL2_THERMAL_SHUTDOWN_ON (1 << 7) | ||
43 | |||
44 | #define ES8328_CHIPPOWER 0x02 | ||
45 | #define ES8328_CHIPPOWER_DACVREF_OFF 0 | ||
46 | #define ES8328_CHIPPOWER_ADCVREF_OFF 1 | ||
47 | #define ES8328_CHIPPOWER_DACDLL_OFF 2 | ||
48 | #define ES8328_CHIPPOWER_ADCDLL_OFF 3 | ||
49 | #define ES8328_CHIPPOWER_DACSTM_RESET 4 | ||
50 | #define ES8328_CHIPPOWER_ADCSTM_RESET 5 | ||
51 | #define ES8328_CHIPPOWER_DACDIG_OFF 6 | ||
52 | #define ES8328_CHIPPOWER_ADCDIG_OFF 7 | ||
53 | |||
54 | #define ES8328_ADCPOWER 0x03 | ||
55 | #define ES8328_ADCPOWER_INT1_LOWPOWER 0 | ||
56 | #define ES8328_ADCPOWER_FLASH_ADC_LOWPOWER 1 | ||
57 | #define ES8328_ADCPOWER_ADC_BIAS_GEN_OFF 2 | ||
58 | #define ES8328_ADCPOWER_MIC_BIAS_OFF 3 | ||
59 | #define ES8328_ADCPOWER_ADCR_OFF 4 | ||
60 | #define ES8328_ADCPOWER_ADCL_OFF 5 | ||
61 | #define ES8328_ADCPOWER_AINR_OFF 6 | ||
62 | #define ES8328_ADCPOWER_AINL_OFF 7 | ||
63 | |||
64 | #define ES8328_DACPOWER 0x04 | ||
65 | #define ES8328_DACPOWER_OUT3_ON 0 | ||
66 | #define ES8328_DACPOWER_MONO_ON 1 | ||
67 | #define ES8328_DACPOWER_ROUT2_ON 2 | ||
68 | #define ES8328_DACPOWER_LOUT2_ON 3 | ||
69 | #define ES8328_DACPOWER_ROUT1_ON 4 | ||
70 | #define ES8328_DACPOWER_LOUT1_ON 5 | ||
71 | #define ES8328_DACPOWER_RDAC_OFF 6 | ||
72 | #define ES8328_DACPOWER_LDAC_OFF 7 | ||
73 | |||
74 | #define ES8328_CHIPLOPOW1 0x05 | ||
75 | #define ES8328_CHIPLOPOW2 0x06 | ||
76 | #define ES8328_ANAVOLMANAG 0x07 | ||
77 | |||
78 | #define ES8328_MASTERMODE 0x08 | ||
79 | #define ES8328_MASTERMODE_BCLKDIV (0 << 0) | ||
80 | #define ES8328_MASTERMODE_BCLK_INV (1 << 5) | ||
81 | #define ES8328_MASTERMODE_MCLKDIV2 (1 << 6) | ||
82 | #define ES8328_MASTERMODE_MSC (1 << 7) | ||
83 | |||
84 | #define ES8328_ADCCONTROL1 0x09 | ||
85 | #define ES8328_ADCCONTROL2 0x0a | ||
86 | #define ES8328_ADCCONTROL3 0x0b | ||
87 | #define ES8328_ADCCONTROL4 0x0c | ||
88 | #define ES8328_ADCCONTROL5 0x0d | ||
89 | #define ES8328_ADCCONTROL5_RATEMASK (0x1f << 0) | ||
90 | |||
91 | #define ES8328_ADCCONTROL6 0x0e | ||
92 | |||
93 | #define ES8328_ADCCONTROL7 0x0f | ||
94 | #define ES8328_ADCCONTROL7_ADC_MUTE (1 << 2) | ||
95 | #define ES8328_ADCCONTROL7_ADC_LER (1 << 3) | ||
96 | #define ES8328_ADCCONTROL7_ADC_ZERO_CROSS (1 << 4) | ||
97 | #define ES8328_ADCCONTROL7_ADC_SOFT_RAMP (1 << 5) | ||
98 | #define ES8328_ADCCONTROL7_ADC_RAMP_RATE_4 (0 << 6) | ||
99 | #define ES8328_ADCCONTROL7_ADC_RAMP_RATE_8 (1 << 6) | ||
100 | #define ES8328_ADCCONTROL7_ADC_RAMP_RATE_16 (2 << 6) | ||
101 | #define ES8328_ADCCONTROL7_ADC_RAMP_RATE_32 (3 << 6) | ||
102 | |||
103 | #define ES8328_ADCCONTROL8 0x10 | ||
104 | #define ES8328_ADCCONTROL9 0x11 | ||
105 | #define ES8328_ADCCONTROL10 0x12 | ||
106 | #define ES8328_ADCCONTROL11 0x13 | ||
107 | #define ES8328_ADCCONTROL12 0x14 | ||
108 | #define ES8328_ADCCONTROL13 0x15 | ||
109 | #define ES8328_ADCCONTROL14 0x16 | ||
110 | |||
111 | #define ES8328_DACCONTROL1 0x17 | ||
112 | #define ES8328_DACCONTROL1_DACFORMAT_I2S (0 << 1) | ||
113 | #define ES8328_DACCONTROL1_DACFORMAT_LJUST (1 << 1) | ||
114 | #define ES8328_DACCONTROL1_DACFORMAT_RJUST (2 << 1) | ||
115 | #define ES8328_DACCONTROL1_DACFORMAT_PCM (3 << 1) | ||
116 | #define ES8328_DACCONTROL1_DACWL_24 (0 << 3) | ||
117 | #define ES8328_DACCONTROL1_DACWL_20 (1 << 3) | ||
118 | #define ES8328_DACCONTROL1_DACWL_18 (2 << 3) | ||
119 | #define ES8328_DACCONTROL1_DACWL_16 (3 << 3) | ||
120 | #define ES8328_DACCONTROL1_DACWL_32 (4 << 3) | ||
121 | #define ES8328_DACCONTROL1_DACLRP_I2S_POL_NORMAL (0 << 6) | ||
122 | #define ES8328_DACCONTROL1_DACLRP_I2S_POL_INV (1 << 6) | ||
123 | #define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK2 (0 << 6) | ||
124 | #define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK1 (1 << 6) | ||
125 | #define ES8328_DACCONTROL1_LRSWAP (1 << 7) | ||
126 | |||
127 | #define ES8328_DACCONTROL2 0x18 | ||
128 | #define ES8328_DACCONTROL2_RATEMASK (0x1f << 0) | ||
129 | #define ES8328_DACCONTROL2_DOUBLESPEED (1 << 5) | ||
130 | |||
131 | #define ES8328_DACCONTROL3 0x19 | ||
132 | #define ES8328_DACCONTROL3_AUTOMUTE (1 << 2) | ||
133 | #define ES8328_DACCONTROL3_DACMUTE (1 << 2) | ||
134 | #define ES8328_DACCONTROL3_LEFTGAINVOL (1 << 3) | ||
135 | #define ES8328_DACCONTROL3_DACZEROCROSS (1 << 4) | ||
136 | #define ES8328_DACCONTROL3_DACSOFTRAMP (1 << 5) | ||
137 | #define ES8328_DACCONTROL3_DACRAMPRATE (3 << 6) | ||
138 | |||
139 | #define ES8328_LDACVOL 0x1a | ||
140 | #define ES8328_LDACVOL_MASK (0 << 0) | ||
141 | #define ES8328_LDACVOL_MAX (0xc0) | ||
142 | |||
143 | #define ES8328_RDACVOL 0x1b | ||
144 | #define ES8328_RDACVOL_MASK (0 << 0) | ||
145 | #define ES8328_RDACVOL_MAX (0xc0) | ||
146 | |||
147 | #define ES8328_DACVOL_MAX (0xc0) | ||
148 | |||
149 | #define ES8328_DACCONTROL4 0x1a | ||
150 | #define ES8328_DACCONTROL5 0x1b | ||
151 | |||
152 | #define ES8328_DACCONTROL6 0x1c | ||
153 | #define ES8328_DACCONTROL6_CLICKFREE (1 << 3) | ||
154 | #define ES8328_DACCONTROL6_DAC_INVR (1 << 4) | ||
155 | #define ES8328_DACCONTROL6_DAC_INVL (1 << 5) | ||
156 | #define ES8328_DACCONTROL6_DEEMPH_OFF (0 << 6) | ||
157 | #define ES8328_DACCONTROL6_DEEMPH_32k (1 << 6) | ||
158 | #define ES8328_DACCONTROL6_DEEMPH_44_1k (2 << 6) | ||
159 | #define ES8328_DACCONTROL6_DEEMPH_48k (3 << 6) | ||
160 | |||
161 | #define ES8328_DACCONTROL7 0x1d | ||
162 | #define ES8328_DACCONTROL7_VPP_SCALE_3p5 (0 << 0) | ||
163 | #define ES8328_DACCONTROL7_VPP_SCALE_4p0 (1 << 0) | ||
164 | #define ES8328_DACCONTROL7_VPP_SCALE_3p0 (2 << 0) | ||
165 | #define ES8328_DACCONTROL7_VPP_SCALE_2p5 (3 << 0) | ||
166 | #define ES8328_DACCONTROL7_SHELVING_STRENGTH (1 << 2) /* In eights */ | ||
167 | #define ES8328_DACCONTROL7_MONO (1 << 5) | ||
168 | #define ES8328_DACCONTROL7_ZEROR (1 << 6) | ||
169 | #define ES8328_DACCONTROL7_ZEROL (1 << 7) | ||
170 | |||
171 | /* Shelving filter */ | ||
172 | #define ES8328_DACCONTROL8 0x1e | ||
173 | #define ES8328_DACCONTROL9 0x1f | ||
174 | #define ES8328_DACCONTROL10 0x20 | ||
175 | #define ES8328_DACCONTROL11 0x21 | ||
176 | #define ES8328_DACCONTROL12 0x22 | ||
177 | #define ES8328_DACCONTROL13 0x23 | ||
178 | #define ES8328_DACCONTROL14 0x24 | ||
179 | #define ES8328_DACCONTROL15 0x25 | ||
180 | |||
181 | #define ES8328_DACCONTROL16 0x26 | ||
182 | #define ES8328_DACCONTROL16_RMIXSEL_RIN1 (0 << 0) | ||
183 | #define ES8328_DACCONTROL16_RMIXSEL_RIN2 (1 << 0) | ||
184 | #define ES8328_DACCONTROL16_RMIXSEL_RIN3 (2 << 0) | ||
185 | #define ES8328_DACCONTROL16_RMIXSEL_RADC (3 << 0) | ||
186 | #define ES8328_DACCONTROL16_LMIXSEL_LIN1 (0 << 3) | ||
187 | #define ES8328_DACCONTROL16_LMIXSEL_LIN2 (1 << 3) | ||
188 | #define ES8328_DACCONTROL16_LMIXSEL_LIN3 (2 << 3) | ||
189 | #define ES8328_DACCONTROL16_LMIXSEL_LADC (3 << 3) | ||
190 | |||
191 | #define ES8328_DACCONTROL17 0x27 | ||
192 | #define ES8328_DACCONTROL17_LI2LOVOL (7 << 3) | ||
193 | #define ES8328_DACCONTROL17_LI2LO (1 << 6) | ||
194 | #define ES8328_DACCONTROL17_LD2LO (1 << 7) | ||
195 | |||
196 | #define ES8328_DACCONTROL18 0x28 | ||
197 | #define ES8328_DACCONTROL18_RI2LOVOL (7 << 3) | ||
198 | #define ES8328_DACCONTROL18_RI2LO (1 << 6) | ||
199 | #define ES8328_DACCONTROL18_RD2LO (1 << 7) | ||
200 | |||
201 | #define ES8328_DACCONTROL19 0x29 | ||
202 | #define ES8328_DACCONTROL19_LI2ROVOL (7 << 3) | ||
203 | #define ES8328_DACCONTROL19_LI2RO (1 << 6) | ||
204 | #define ES8328_DACCONTROL19_LD2RO (1 << 7) | ||
205 | |||
206 | #define ES8328_DACCONTROL20 0x2a | ||
207 | #define ES8328_DACCONTROL20_RI2ROVOL (7 << 3) | ||
208 | #define ES8328_DACCONTROL20_RI2RO (1 << 6) | ||
209 | #define ES8328_DACCONTROL20_RD2RO (1 << 7) | ||
210 | |||
211 | #define ES8328_DACCONTROL21 0x2b | ||
212 | #define ES8328_DACCONTROL21_LI2MOVOL (7 << 3) | ||
213 | #define ES8328_DACCONTROL21_LI2MO (1 << 6) | ||
214 | #define ES8328_DACCONTROL21_LD2MO (1 << 7) | ||
215 | |||
216 | #define ES8328_DACCONTROL22 0x2c | ||
217 | #define ES8328_DACCONTROL22_RI2MOVOL (7 << 3) | ||
218 | #define ES8328_DACCONTROL22_RI2MO (1 << 6) | ||
219 | #define ES8328_DACCONTROL22_RD2MO (1 << 7) | ||
220 | |||
221 | #define ES8328_DACCONTROL23 0x2d | ||
222 | #define ES8328_DACCONTROL23_MOUTINV (1 << 1) | ||
223 | #define ES8328_DACCONTROL23_HPSWPOL (1 << 2) | ||
224 | #define ES8328_DACCONTROL23_HPSWEN (1 << 3) | ||
225 | #define ES8328_DACCONTROL23_VROI_1p5k (0 << 4) | ||
226 | #define ES8328_DACCONTROL23_VROI_40k (1 << 4) | ||
227 | #define ES8328_DACCONTROL23_OUT3_VREF (0 << 5) | ||
228 | #define ES8328_DACCONTROL23_OUT3_ROUT1 (1 << 5) | ||
229 | #define ES8328_DACCONTROL23_OUT3_MONOOUT (2 << 5) | ||
230 | #define ES8328_DACCONTROL23_OUT3_RIGHT_MIXER (3 << 5) | ||
231 | #define ES8328_DACCONTROL23_ROUT2INV (1 << 7) | ||
232 | |||
233 | /* LOUT1 Amplifier */ | ||
234 | #define ES8328_LOUT1VOL 0x2e | ||
235 | #define ES8328_LOUT1VOL_MASK (0 << 5) | ||
236 | #define ES8328_LOUT1VOL_MAX (0x24) | ||
237 | |||
238 | /* ROUT1 Amplifier */ | ||
239 | #define ES8328_ROUT1VOL 0x2f | ||
240 | #define ES8328_ROUT1VOL_MASK (0 << 5) | ||
241 | #define ES8328_ROUT1VOL_MAX (0x24) | ||
242 | |||
243 | #define ES8328_OUT1VOL_MAX (0x24) | ||
244 | |||
245 | /* LOUT2 Amplifier */ | ||
246 | #define ES8328_LOUT2VOL 0x30 | ||
247 | #define ES8328_LOUT2VOL_MASK (0 << 5) | ||
248 | #define ES8328_LOUT2VOL_MAX (0x24) | ||
249 | |||
250 | /* ROUT2 Amplifier */ | ||
251 | #define ES8328_ROUT2VOL 0x31 | ||
252 | #define ES8328_ROUT2VOL_MASK (0 << 5) | ||
253 | #define ES8328_ROUT2VOL_MAX (0x24) | ||
254 | |||
255 | #define ES8328_OUT2VOL_MAX (0x24) | ||
256 | |||
257 | /* Mono Out Amplifier */ | ||
258 | #define ES8328_MONOOUTVOL 0x32 | ||
259 | #define ES8328_MONOOUTVOL_MASK (0 << 5) | ||
260 | #define ES8328_MONOOUTVOL_MAX (0x24) | ||
261 | |||
262 | #define ES8328_DACCONTROL29 0x33 | ||
263 | #define ES8328_DACCONTROL30 0x34 | ||
264 | |||
265 | #define ES8328_SYSCLK 0 | ||
266 | |||
267 | #define ES8328_REG_MAX 0x35 | ||
268 | |||
269 | #define ES8328_PLL1 0 | ||
270 | #define ES8328_PLL2 1 | ||
271 | |||
272 | /* clock inputs */ | ||
273 | #define ES8328_MCLK 0 | ||
274 | #define ES8328_PCMCLK 1 | ||
275 | |||
276 | /* clock divider id's */ | ||
277 | #define ES8328_PCMDIV 0 | ||
278 | #define ES8328_BCLKDIV 1 | ||
279 | #define ES8328_VXCLKDIV 2 | ||
280 | |||
281 | /* PCM clock dividers */ | ||
282 | #define ES8328_PCM_DIV_1 (0 << 6) | ||
283 | #define ES8328_PCM_DIV_3 (2 << 6) | ||
284 | #define ES8328_PCM_DIV_5_5 (3 << 6) | ||
285 | #define ES8328_PCM_DIV_2 (4 << 6) | ||
286 | #define ES8328_PCM_DIV_4 (5 << 6) | ||
287 | #define ES8328_PCM_DIV_6 (6 << 6) | ||
288 | #define ES8328_PCM_DIV_8 (7 << 6) | ||
289 | |||
290 | /* BCLK clock dividers */ | ||
291 | #define ES8328_BCLK_DIV_1 (0 << 7) | ||
292 | #define ES8328_BCLK_DIV_2 (1 << 7) | ||
293 | #define ES8328_BCLK_DIV_4 (2 << 7) | ||
294 | #define ES8328_BCLK_DIV_8 (3 << 7) | ||
295 | |||
296 | /* VXCLK clock dividers */ | ||
297 | #define ES8328_VXCLK_DIV_1 (0 << 6) | ||
298 | #define ES8328_VXCLK_DIV_2 (1 << 6) | ||
299 | #define ES8328_VXCLK_DIV_4 (2 << 6) | ||
300 | #define ES8328_VXCLK_DIV_8 (3 << 6) | ||
301 | #define ES8328_VXCLK_DIV_16 (4 << 6) | ||
302 | |||
303 | #define ES8328_DAI_HIFI 0 | ||
304 | #define ES8328_DAI_VOICE 1 | ||
305 | |||
306 | #define ES8328_1536FS 1536 | ||
307 | #define ES8328_1024FS 1024 | ||
308 | #define ES8328_768FS 768 | ||
309 | #define ES8328_512FS 512 | ||
310 | #define ES8328_384FS 384 | ||
311 | #define ES8328_256FS 256 | ||
312 | #define ES8328_128FS 128 | ||
313 | |||
314 | #endif | ||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index bcebd1a9ce31..df7c01cf7072 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -293,41 +293,13 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) | |||
293 | regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1, | 293 | regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1, |
294 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); | 294 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); |
295 | 295 | ||
296 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
297 | |||
298 | return 0; | 296 | return 0; |
299 | } | 297 | } |
300 | 298 | ||
301 | static int jz4740_codec_dev_remove(struct snd_soc_codec *codec) | ||
302 | { | ||
303 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | #ifdef CONFIG_PM_SLEEP | ||
309 | |||
310 | static int jz4740_codec_suspend(struct snd_soc_codec *codec) | ||
311 | { | ||
312 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
313 | } | ||
314 | |||
315 | static int jz4740_codec_resume(struct snd_soc_codec *codec) | ||
316 | { | ||
317 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
318 | } | ||
319 | |||
320 | #else | ||
321 | #define jz4740_codec_suspend NULL | ||
322 | #define jz4740_codec_resume NULL | ||
323 | #endif | ||
324 | |||
325 | static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { | 299 | static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { |
326 | .probe = jz4740_codec_dev_probe, | 300 | .probe = jz4740_codec_dev_probe, |
327 | .remove = jz4740_codec_dev_remove, | ||
328 | .suspend = jz4740_codec_suspend, | ||
329 | .resume = jz4740_codec_resume, | ||
330 | .set_bias_level = jz4740_codec_set_bias_level, | 301 | .set_bias_level = jz4740_codec_set_bias_level, |
302 | .suspend_bias_off = true, | ||
331 | 303 | ||
332 | .controls = jz4740_codec_controls, | 304 | .controls = jz4740_codec_controls, |
333 | .num_controls = ARRAY_SIZE(jz4740_codec_controls), | 305 | .num_controls = ARRAY_SIZE(jz4740_codec_controls), |
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 275b3f72f3f4..c1ae5764983f 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -1395,18 +1395,6 @@ static struct snd_soc_dai_driver lm49453_dai[] = { | |||
1395 | }, | 1395 | }, |
1396 | }; | 1396 | }; |
1397 | 1397 | ||
1398 | static int lm49453_suspend(struct snd_soc_codec *codec) | ||
1399 | { | ||
1400 | lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int lm49453_resume(struct snd_soc_codec *codec) | ||
1405 | { | ||
1406 | lm49453_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | /* power down chip */ | 1398 | /* power down chip */ |
1411 | static int lm49453_remove(struct snd_soc_codec *codec) | 1399 | static int lm49453_remove(struct snd_soc_codec *codec) |
1412 | { | 1400 | { |
@@ -1416,8 +1404,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) | |||
1416 | 1404 | ||
1417 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { | 1405 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { |
1418 | .remove = lm49453_remove, | 1406 | .remove = lm49453_remove, |
1419 | .suspend = lm49453_suspend, | ||
1420 | .resume = lm49453_resume, | ||
1421 | .set_bias_level = lm49453_set_bias_level, | 1407 | .set_bias_level = lm49453_set_bias_level, |
1422 | .controls = lm49453_snd_controls, | 1408 | .controls = lm49453_snd_controls, |
1423 | .num_controls = ARRAY_SIZE(lm49453_snd_controls), | 1409 | .num_controls = ARRAY_SIZE(lm49453_snd_controls), |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 4a063fa88526..d519294f57c7 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -1311,8 +1311,6 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1311 | {"MIC1 Input", NULL, "MIC1"}, | 1311 | {"MIC1 Input", NULL, "MIC1"}, |
1312 | {"MIC2 Input", NULL, "MIC2"}, | 1312 | {"MIC2 Input", NULL, "MIC2"}, |
1313 | 1313 | ||
1314 | {"DMICL", NULL, "DMICL_ENA"}, | ||
1315 | {"DMICR", NULL, "DMICR_ENA"}, | ||
1316 | {"DMICL", NULL, "AHPF"}, | 1314 | {"DMICL", NULL, "AHPF"}, |
1317 | {"DMICR", NULL, "AHPF"}, | 1315 | {"DMICR", NULL, "AHPF"}, |
1318 | 1316 | ||
@@ -1370,6 +1368,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1370 | {"DMIC Mux", "ADC", "ADCR"}, | 1368 | {"DMIC Mux", "ADC", "ADCR"}, |
1371 | {"DMIC Mux", "DMIC", "DMICL"}, | 1369 | {"DMIC Mux", "DMIC", "DMICL"}, |
1372 | {"DMIC Mux", "DMIC", "DMICR"}, | 1370 | {"DMIC Mux", "DMIC", "DMICR"}, |
1371 | {"DMIC Mux", "DMIC", "DMICL_ENA"}, | ||
1372 | {"DMIC Mux", "DMIC", "DMICR_ENA"}, | ||
1373 | 1373 | ||
1374 | {"LBENL Mux", "Normal", "DMIC Mux"}, | 1374 | {"LBENL Mux", "Normal", "DMIC Mux"}, |
1375 | {"LBENL Mux", "Loopback", "LTENL Mux"}, | 1375 | {"LBENL Mux", "Loopback", "LTENL Mux"}, |
@@ -1972,6 +1972,102 @@ static int max98090_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1972 | return 0; | 1972 | return 0; |
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | static int max98090_dai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
1976 | struct snd_soc_dai *dai) | ||
1977 | { | ||
1978 | struct snd_soc_codec *codec = dai->codec; | ||
1979 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | ||
1980 | |||
1981 | switch (cmd) { | ||
1982 | case SNDRV_PCM_TRIGGER_START: | ||
1983 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1984 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1985 | if (!max98090->master && dai->active == 1) | ||
1986 | queue_delayed_work(system_power_efficient_wq, | ||
1987 | &max98090->pll_det_enable_work, | ||
1988 | msecs_to_jiffies(10)); | ||
1989 | break; | ||
1990 | case SNDRV_PCM_TRIGGER_STOP: | ||
1991 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1992 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1993 | if (!max98090->master && dai->active == 1) | ||
1994 | schedule_work(&max98090->pll_det_disable_work); | ||
1995 | break; | ||
1996 | default: | ||
1997 | break; | ||
1998 | } | ||
1999 | |||
2000 | return 0; | ||
2001 | } | ||
2002 | |||
2003 | static void max98090_pll_det_enable_work(struct work_struct *work) | ||
2004 | { | ||
2005 | struct max98090_priv *max98090 = | ||
2006 | container_of(work, struct max98090_priv, | ||
2007 | pll_det_enable_work.work); | ||
2008 | struct snd_soc_codec *codec = max98090->codec; | ||
2009 | unsigned int status, mask; | ||
2010 | |||
2011 | /* | ||
2012 | * Clear status register in order to clear possibly already occurred | ||
2013 | * PLL unlock. If PLL hasn't still locked, the status will be set | ||
2014 | * again and PLL unlock interrupt will occur. | ||
2015 | * Note this will clear all status bits | ||
2016 | */ | ||
2017 | regmap_read(max98090->regmap, M98090_REG_DEVICE_STATUS, &status); | ||
2018 | |||
2019 | /* | ||
2020 | * Queue jack work in case jack state has just changed but handler | ||
2021 | * hasn't run yet | ||
2022 | */ | ||
2023 | regmap_read(max98090->regmap, M98090_REG_INTERRUPT_S, &mask); | ||
2024 | status &= mask; | ||
2025 | if (status & M98090_JDET_MASK) | ||
2026 | queue_delayed_work(system_power_efficient_wq, | ||
2027 | &max98090->jack_work, | ||
2028 | msecs_to_jiffies(100)); | ||
2029 | |||
2030 | /* Enable PLL unlock interrupt */ | ||
2031 | snd_soc_update_bits(codec, M98090_REG_INTERRUPT_S, | ||
2032 | M98090_IULK_MASK, | ||
2033 | 1 << M98090_IULK_SHIFT); | ||
2034 | } | ||
2035 | |||
2036 | static void max98090_pll_det_disable_work(struct work_struct *work) | ||
2037 | { | ||
2038 | struct max98090_priv *max98090 = | ||
2039 | container_of(work, struct max98090_priv, pll_det_disable_work); | ||
2040 | struct snd_soc_codec *codec = max98090->codec; | ||
2041 | |||
2042 | cancel_delayed_work_sync(&max98090->pll_det_enable_work); | ||
2043 | |||
2044 | /* Disable PLL unlock interrupt */ | ||
2045 | snd_soc_update_bits(codec, M98090_REG_INTERRUPT_S, | ||
2046 | M98090_IULK_MASK, 0); | ||
2047 | } | ||
2048 | |||
2049 | static void max98090_pll_work(struct work_struct *work) | ||
2050 | { | ||
2051 | struct max98090_priv *max98090 = | ||
2052 | container_of(work, struct max98090_priv, pll_work); | ||
2053 | struct snd_soc_codec *codec = max98090->codec; | ||
2054 | |||
2055 | if (!snd_soc_codec_is_active(codec)) | ||
2056 | return; | ||
2057 | |||
2058 | dev_info(codec->dev, "PLL unlocked\n"); | ||
2059 | |||
2060 | /* Toggle shutdown OFF then ON */ | ||
2061 | snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN, | ||
2062 | M98090_SHDNN_MASK, 0); | ||
2063 | msleep(10); | ||
2064 | snd_soc_update_bits(codec, M98090_REG_DEVICE_SHUTDOWN, | ||
2065 | M98090_SHDNN_MASK, M98090_SHDNN_MASK); | ||
2066 | |||
2067 | /* Give PLL time to lock */ | ||
2068 | msleep(10); | ||
2069 | } | ||
2070 | |||
1975 | static void max98090_jack_work(struct work_struct *work) | 2071 | static void max98090_jack_work(struct work_struct *work) |
1976 | { | 2072 | { |
1977 | struct max98090_priv *max98090 = container_of(work, | 2073 | struct max98090_priv *max98090 = container_of(work, |
@@ -2063,12 +2159,16 @@ static void max98090_jack_work(struct work_struct *work) | |||
2063 | 2159 | ||
2064 | static irqreturn_t max98090_interrupt(int irq, void *data) | 2160 | static irqreturn_t max98090_interrupt(int irq, void *data) |
2065 | { | 2161 | { |
2066 | struct snd_soc_codec *codec = data; | 2162 | struct max98090_priv *max98090 = data; |
2067 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 2163 | struct snd_soc_codec *codec = max98090->codec; |
2068 | int ret; | 2164 | int ret; |
2069 | unsigned int mask; | 2165 | unsigned int mask; |
2070 | unsigned int active; | 2166 | unsigned int active; |
2071 | 2167 | ||
2168 | /* Treat interrupt before codec is initialized as spurious */ | ||
2169 | if (codec == NULL) | ||
2170 | return IRQ_NONE; | ||
2171 | |||
2072 | dev_dbg(codec->dev, "***** max98090_interrupt *****\n"); | 2172 | dev_dbg(codec->dev, "***** max98090_interrupt *****\n"); |
2073 | 2173 | ||
2074 | ret = regmap_read(max98090->regmap, M98090_REG_INTERRUPT_S, &mask); | 2174 | ret = regmap_read(max98090->regmap, M98090_REG_INTERRUPT_S, &mask); |
@@ -2103,8 +2203,10 @@ static irqreturn_t max98090_interrupt(int irq, void *data) | |||
2103 | if (active & M98090_SLD_MASK) | 2203 | if (active & M98090_SLD_MASK) |
2104 | dev_dbg(codec->dev, "M98090_SLD_MASK\n"); | 2204 | dev_dbg(codec->dev, "M98090_SLD_MASK\n"); |
2105 | 2205 | ||
2106 | if (active & M98090_ULK_MASK) | 2206 | if (active & M98090_ULK_MASK) { |
2107 | dev_err(codec->dev, "M98090_ULK_MASK\n"); | 2207 | dev_dbg(codec->dev, "M98090_ULK_MASK\n"); |
2208 | schedule_work(&max98090->pll_work); | ||
2209 | } | ||
2108 | 2210 | ||
2109 | if (active & M98090_JDET_MASK) { | 2211 | if (active & M98090_JDET_MASK) { |
2110 | dev_dbg(codec->dev, "M98090_JDET_MASK\n"); | 2212 | dev_dbg(codec->dev, "M98090_JDET_MASK\n"); |
@@ -2177,6 +2279,7 @@ static struct snd_soc_dai_ops max98090_dai_ops = { | |||
2177 | .set_tdm_slot = max98090_set_tdm_slot, | 2279 | .set_tdm_slot = max98090_set_tdm_slot, |
2178 | .hw_params = max98090_dai_hw_params, | 2280 | .hw_params = max98090_dai_hw_params, |
2179 | .digital_mute = max98090_dai_digital_mute, | 2281 | .digital_mute = max98090_dai_digital_mute, |
2282 | .trigger = max98090_dai_trigger, | ||
2180 | }; | 2283 | }; |
2181 | 2284 | ||
2182 | static struct snd_soc_dai_driver max98090_dai[] = { | 2285 | static struct snd_soc_dai_driver max98090_dai[] = { |
@@ -2230,7 +2333,6 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2230 | max98090->lin_state = 0; | 2333 | max98090->lin_state = 0; |
2231 | max98090->pa1en = 0; | 2334 | max98090->pa1en = 0; |
2232 | max98090->pa2en = 0; | 2335 | max98090->pa2en = 0; |
2233 | max98090->extmic_mux = 0; | ||
2234 | 2336 | ||
2235 | ret = snd_soc_read(codec, M98090_REG_REVISION_ID); | 2337 | ret = snd_soc_read(codec, M98090_REG_REVISION_ID); |
2236 | if (ret < 0) { | 2338 | if (ret < 0) { |
@@ -2258,22 +2360,16 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2258 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; | 2360 | max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; |
2259 | 2361 | ||
2260 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); | 2362 | INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); |
2363 | INIT_DELAYED_WORK(&max98090->pll_det_enable_work, | ||
2364 | max98090_pll_det_enable_work); | ||
2365 | INIT_WORK(&max98090->pll_det_disable_work, | ||
2366 | max98090_pll_det_disable_work); | ||
2367 | INIT_WORK(&max98090->pll_work, max98090_pll_work); | ||
2261 | 2368 | ||
2262 | /* Enable jack detection */ | 2369 | /* Enable jack detection */ |
2263 | snd_soc_write(codec, M98090_REG_JACK_DETECT, | 2370 | snd_soc_write(codec, M98090_REG_JACK_DETECT, |
2264 | M98090_JDETEN_MASK | M98090_JDEB_25MS); | 2371 | M98090_JDETEN_MASK | M98090_JDEB_25MS); |
2265 | 2372 | ||
2266 | /* Register for interrupts */ | ||
2267 | dev_dbg(codec->dev, "irq = %d\n", max98090->irq); | ||
2268 | |||
2269 | ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, | ||
2270 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
2271 | "max98090_interrupt", codec); | ||
2272 | if (ret < 0) { | ||
2273 | dev_err(codec->dev, "request_irq failed: %d\n", | ||
2274 | ret); | ||
2275 | } | ||
2276 | |||
2277 | /* | 2373 | /* |
2278 | * Clear any old interrupts. | 2374 | * Clear any old interrupts. |
2279 | * An old interrupt ocurring prior to installing the ISR | 2375 | * An old interrupt ocurring prior to installing the ISR |
@@ -2310,6 +2406,10 @@ static int max98090_remove(struct snd_soc_codec *codec) | |||
2310 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); | 2406 | struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); |
2311 | 2407 | ||
2312 | cancel_delayed_work_sync(&max98090->jack_work); | 2408 | cancel_delayed_work_sync(&max98090->jack_work); |
2409 | cancel_delayed_work_sync(&max98090->pll_det_enable_work); | ||
2410 | cancel_work_sync(&max98090->pll_det_disable_work); | ||
2411 | cancel_work_sync(&max98090->pll_work); | ||
2412 | max98090->codec = NULL; | ||
2313 | 2413 | ||
2314 | return 0; | 2414 | return 0; |
2315 | } | 2415 | } |
@@ -2362,7 +2462,6 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2362 | max98090->devtype = driver_data; | 2462 | max98090->devtype = driver_data; |
2363 | i2c_set_clientdata(i2c, max98090); | 2463 | i2c_set_clientdata(i2c, max98090); |
2364 | max98090->pdata = i2c->dev.platform_data; | 2464 | max98090->pdata = i2c->dev.platform_data; |
2365 | max98090->irq = i2c->irq; | ||
2366 | 2465 | ||
2367 | max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); | 2466 | max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); |
2368 | if (IS_ERR(max98090->regmap)) { | 2467 | if (IS_ERR(max98090->regmap)) { |
@@ -2371,6 +2470,15 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2371 | goto err_enable; | 2470 | goto err_enable; |
2372 | } | 2471 | } |
2373 | 2472 | ||
2473 | ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, | ||
2474 | max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
2475 | "max98090_interrupt", max98090); | ||
2476 | if (ret < 0) { | ||
2477 | dev_err(&i2c->dev, "request_irq failed: %d\n", | ||
2478 | ret); | ||
2479 | return ret; | ||
2480 | } | ||
2481 | |||
2374 | ret = snd_soc_register_codec(&i2c->dev, | 2482 | ret = snd_soc_register_codec(&i2c->dev, |
2375 | &soc_codec_dev_max98090, max98090_dai, | 2483 | &soc_codec_dev_max98090, max98090_dai, |
2376 | ARRAY_SIZE(max98090_dai)); | 2484 | ARRAY_SIZE(max98090_dai)); |
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index cf1b6062ba8c..a5f6bada06da 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h | |||
@@ -11,11 +11,6 @@ | |||
11 | #ifndef _MAX98090_H | 11 | #ifndef _MAX98090_H |
12 | #define _MAX98090_H | 12 | #define _MAX98090_H |
13 | 13 | ||
14 | #include <linux/version.h> | ||
15 | |||
16 | /* One can override the Linux version here with an explicit version number */ | ||
17 | #define M98090_LINUX_VERSION LINUX_VERSION_CODE | ||
18 | |||
19 | /* | 14 | /* |
20 | * MAX98090 Register Definitions | 15 | * MAX98090 Register Definitions |
21 | */ | 16 | */ |
@@ -1502,9 +1497,6 @@ | |||
1502 | #define M98090_REVID_WIDTH 8 | 1497 | #define M98090_REVID_WIDTH 8 |
1503 | #define M98090_REVID_NUM (1<<M98090_REVID_WIDTH) | 1498 | #define M98090_REVID_NUM (1<<M98090_REVID_WIDTH) |
1504 | 1499 | ||
1505 | #define M98090_BYTE1(w) ((w >> 8) & 0xff) | ||
1506 | #define M98090_BYTE0(w) (w & 0xff) | ||
1507 | |||
1508 | /* Silicon revision number */ | 1500 | /* Silicon revision number */ |
1509 | #define M98090_REVA 0x40 | 1501 | #define M98090_REVA 0x40 |
1510 | #define M98091_REVA 0x50 | 1502 | #define M98091_REVA 0x50 |
@@ -1529,9 +1521,11 @@ struct max98090_priv { | |||
1529 | unsigned int bclk; | 1521 | unsigned int bclk; |
1530 | unsigned int lrclk; | 1522 | unsigned int lrclk; |
1531 | struct max98090_cdata dai[1]; | 1523 | struct max98090_cdata dai[1]; |
1532 | int irq; | ||
1533 | int jack_state; | 1524 | int jack_state; |
1534 | struct delayed_work jack_work; | 1525 | struct delayed_work jack_work; |
1526 | struct delayed_work pll_det_enable_work; | ||
1527 | struct work_struct pll_det_disable_work; | ||
1528 | struct work_struct pll_work; | ||
1535 | struct snd_soc_jack *jack; | 1529 | struct snd_soc_jack *jack; |
1536 | unsigned int dai_fmt; | 1530 | unsigned int dai_fmt; |
1537 | int tdm_slots; | 1531 | int tdm_slots; |
@@ -1539,7 +1533,6 @@ struct max98090_priv { | |||
1539 | u8 lin_state; | 1533 | u8 lin_state; |
1540 | unsigned int pa1en; | 1534 | unsigned int pa1en; |
1541 | unsigned int pa2en; | 1535 | unsigned int pa2en; |
1542 | unsigned int extmic_mux; | ||
1543 | unsigned int sidetone; | 1536 | unsigned int sidetone; |
1544 | bool master; | 1537 | bool master; |
1545 | }; | 1538 | }; |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 388f90a597fa..71f775aad7c7 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -765,12 +765,18 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
765 | return -ENOSYS; | 765 | return -ENOSYS; |
766 | 766 | ||
767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); | 767 | ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); |
768 | if (ret) | 768 | if (ret) { |
769 | goto out; | 769 | of_node_put(np); |
770 | return ret; | ||
771 | } | ||
770 | 772 | ||
771 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); | 773 | ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); |
772 | if (ret) | 774 | if (ret) { |
773 | goto out; | 775 | of_node_put(np); |
776 | return ret; | ||
777 | } | ||
778 | |||
779 | of_node_put(np); | ||
774 | } | 780 | } |
775 | 781 | ||
776 | dev_set_drvdata(&pdev->dev, priv); | 782 | dev_set_drvdata(&pdev->dev, priv); |
@@ -783,8 +789,6 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) | |||
783 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, | 789 | ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, |
784 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); | 790 | mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); |
785 | 791 | ||
786 | out: | ||
787 | of_node_put(np); | ||
788 | return ret; | 792 | return ret; |
789 | } | 793 | } |
790 | 794 | ||
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index e661e8420e3d..711f55039522 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -565,41 +565,19 @@ static struct snd_soc_dai_driver ml26124_dai = { | |||
565 | .symmetric_rates = 1, | 565 | .symmetric_rates = 1, |
566 | }; | 566 | }; |
567 | 567 | ||
568 | #ifdef CONFIG_PM | ||
569 | static int ml26124_suspend(struct snd_soc_codec *codec) | ||
570 | { | ||
571 | ml26124_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int ml26124_resume(struct snd_soc_codec *codec) | ||
577 | { | ||
578 | ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | #else | ||
583 | #define ml26124_suspend NULL | ||
584 | #define ml26124_resume NULL | ||
585 | #endif | ||
586 | |||
587 | static int ml26124_probe(struct snd_soc_codec *codec) | 568 | static int ml26124_probe(struct snd_soc_codec *codec) |
588 | { | 569 | { |
589 | /* Software Reset */ | 570 | /* Software Reset */ |
590 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); | 571 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); |
591 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); | 572 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); |
592 | 573 | ||
593 | ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
594 | |||
595 | return 0; | 574 | return 0; |
596 | } | 575 | } |
597 | 576 | ||
598 | static struct snd_soc_codec_driver soc_codec_dev_ml26124 = { | 577 | static struct snd_soc_codec_driver soc_codec_dev_ml26124 = { |
599 | .probe = ml26124_probe, | 578 | .probe = ml26124_probe, |
600 | .suspend = ml26124_suspend, | ||
601 | .resume = ml26124_resume, | ||
602 | .set_bias_level = ml26124_set_bias_level, | 579 | .set_bias_level = ml26124_set_bias_level, |
580 | .suspend_bias_off = true, | ||
603 | .dapm_widgets = ml26124_dapm_widgets, | 581 | .dapm_widgets = ml26124_dapm_widgets, |
604 | .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), | 582 | .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), |
605 | .dapm_routes = ml26124_intercon, | 583 | .dapm_routes = ml26124_intercon, |
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index b86b426f159d..4aa555cbcca8 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -269,6 +269,7 @@ static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | |||
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
272 | #ifdef CONFIG_PM | ||
272 | static void rt286_index_sync(struct snd_soc_codec *codec) | 273 | static void rt286_index_sync(struct snd_soc_codec *codec) |
273 | { | 274 | { |
274 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | 275 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); |
@@ -279,6 +280,7 @@ static void rt286_index_sync(struct snd_soc_codec *codec) | |||
279 | rt286->index_cache[i].def); | 280 | rt286->index_cache[i].def); |
280 | } | 281 | } |
281 | } | 282 | } |
283 | #endif | ||
282 | 284 | ||
283 | static int rt286_support_power_controls[] = { | 285 | static int rt286_support_power_controls[] = { |
284 | RT286_DAC_OUT1, | 286 | RT286_DAC_OUT1, |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index f1ec6e6bd08a..c3f2decd643c 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -1906,6 +1906,32 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, | |||
1906 | return 0; | 1906 | return 0; |
1907 | } | 1907 | } |
1908 | 1908 | ||
1909 | int rt5640_dmic_enable(struct snd_soc_codec *codec, | ||
1910 | bool dmic1_data_pin, bool dmic2_data_pin) | ||
1911 | { | ||
1912 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | ||
1913 | |||
1914 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
1915 | RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL); | ||
1916 | |||
1917 | if (dmic1_data_pin) { | ||
1918 | regmap_update_bits(rt5640->regmap, RT5640_DMIC, | ||
1919 | RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3); | ||
1920 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
1921 | RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA); | ||
1922 | } | ||
1923 | |||
1924 | if (dmic2_data_pin) { | ||
1925 | regmap_update_bits(rt5640->regmap, RT5640_DMIC, | ||
1926 | RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4); | ||
1927 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
1928 | RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA); | ||
1929 | } | ||
1930 | |||
1931 | return 0; | ||
1932 | } | ||
1933 | EXPORT_SYMBOL_GPL(rt5640_dmic_enable); | ||
1934 | |||
1909 | static int rt5640_probe(struct snd_soc_codec *codec) | 1935 | static int rt5640_probe(struct snd_soc_codec *codec) |
1910 | { | 1936 | { |
1911 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1937 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
@@ -1945,6 +1971,10 @@ static int rt5640_probe(struct snd_soc_codec *codec) | |||
1945 | return -ENODEV; | 1971 | return -ENODEV; |
1946 | } | 1972 | } |
1947 | 1973 | ||
1974 | if (rt5640->pdata.dmic_en) | ||
1975 | rt5640_dmic_enable(codec, rt5640->pdata.dmic1_data_pin, | ||
1976 | rt5640->pdata.dmic2_data_pin); | ||
1977 | |||
1948 | return 0; | 1978 | return 0; |
1949 | } | 1979 | } |
1950 | 1980 | ||
@@ -2195,25 +2225,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2195 | regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4, | 2225 | regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4, |
2196 | RT5640_IN_DF2, RT5640_IN_DF2); | 2226 | RT5640_IN_DF2, RT5640_IN_DF2); |
2197 | 2227 | ||
2198 | if (rt5640->pdata.dmic_en) { | ||
2199 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
2200 | RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL); | ||
2201 | |||
2202 | if (rt5640->pdata.dmic1_data_pin) { | ||
2203 | regmap_update_bits(rt5640->regmap, RT5640_DMIC, | ||
2204 | RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3); | ||
2205 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
2206 | RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA); | ||
2207 | } | ||
2208 | |||
2209 | if (rt5640->pdata.dmic2_data_pin) { | ||
2210 | regmap_update_bits(rt5640->regmap, RT5640_DMIC, | ||
2211 | RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4); | ||
2212 | regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1, | ||
2213 | RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA); | ||
2214 | } | ||
2215 | } | ||
2216 | |||
2217 | rt5640->hp_mute = 1; | 2228 | rt5640->hp_mute = 1; |
2218 | 2229 | ||
2219 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, | 2230 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, |
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 58ebe96b86da..3deb8babeabb 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h | |||
@@ -2097,4 +2097,7 @@ struct rt5640_priv { | |||
2097 | bool hp_mute; | 2097 | bool hp_mute; |
2098 | }; | 2098 | }; |
2099 | 2099 | ||
2100 | int rt5640_dmic_enable(struct snd_soc_codec *codec, | ||
2101 | bool dmic1_data_pin, bool dmic2_data_pin); | ||
2102 | |||
2100 | #endif | 2103 | #endif |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index a7762d0a623e..3fb83bf09768 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/gpio.h> | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
@@ -2103,6 +2104,77 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2103 | return 0; | 2104 | return 0; |
2104 | } | 2105 | } |
2105 | 2106 | ||
2107 | static int rt5645_jack_detect(struct snd_soc_codec *codec, | ||
2108 | struct snd_soc_jack *jack) | ||
2109 | { | ||
2110 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2111 | int gpio_state, jack_type = 0; | ||
2112 | unsigned int val; | ||
2113 | |||
2114 | gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); | ||
2115 | |||
2116 | dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, | ||
2117 | gpio_state); | ||
2118 | |||
2119 | if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || | ||
2120 | (!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) { | ||
2121 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1"); | ||
2122 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2"); | ||
2123 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | ||
2124 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power"); | ||
2125 | snd_soc_dapm_sync(&codec->dapm); | ||
2126 | |||
2127 | snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006); | ||
2128 | snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0); | ||
2129 | |||
2130 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | ||
2131 | RT5645_CBJ_MN_JD, 0); | ||
2132 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | ||
2133 | RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD); | ||
2134 | |||
2135 | msleep(400); | ||
2136 | val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7; | ||
2137 | dev_dbg(codec->dev, "val = %d\n", val); | ||
2138 | |||
2139 | if (val == 1 || val == 2) | ||
2140 | jack_type = SND_JACK_HEADSET; | ||
2141 | else | ||
2142 | jack_type = SND_JACK_HEADPHONE; | ||
2143 | |||
2144 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); | ||
2145 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); | ||
2146 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); | ||
2147 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | ||
2148 | snd_soc_dapm_sync(&codec->dapm); | ||
2149 | } | ||
2150 | |||
2151 | snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET); | ||
2152 | |||
2153 | return 0; | ||
2154 | } | ||
2155 | |||
2156 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | ||
2157 | struct snd_soc_jack *jack) | ||
2158 | { | ||
2159 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2160 | |||
2161 | rt5645->jack = jack; | ||
2162 | |||
2163 | rt5645_jack_detect(codec, rt5645->jack); | ||
2164 | |||
2165 | return 0; | ||
2166 | } | ||
2167 | EXPORT_SYMBOL_GPL(rt5645_set_jack_detect); | ||
2168 | |||
2169 | static irqreturn_t rt5645_irq(int irq, void *data) | ||
2170 | { | ||
2171 | struct rt5645_priv *rt5645 = data; | ||
2172 | |||
2173 | rt5645_jack_detect(rt5645->codec, rt5645->jack); | ||
2174 | |||
2175 | return IRQ_HANDLED; | ||
2176 | } | ||
2177 | |||
2106 | static int rt5645_probe(struct snd_soc_codec *codec) | 2178 | static int rt5645_probe(struct snd_soc_codec *codec) |
2107 | { | 2179 | { |
2108 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2180 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
@@ -2250,6 +2322,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2250 | if (rt5645 == NULL) | 2322 | if (rt5645 == NULL) |
2251 | return -ENOMEM; | 2323 | return -ENOMEM; |
2252 | 2324 | ||
2325 | rt5645->i2c = i2c; | ||
2253 | i2c_set_clientdata(i2c, rt5645); | 2326 | i2c_set_clientdata(i2c, rt5645); |
2254 | 2327 | ||
2255 | if (pdata) | 2328 | if (pdata) |
@@ -2345,12 +2418,38 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2345 | 2418 | ||
2346 | } | 2419 | } |
2347 | 2420 | ||
2421 | if (rt5645->i2c->irq) { | ||
2422 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | ||
2423 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | ||
2424 | | IRQF_ONESHOT, "rt5645", rt5645); | ||
2425 | if (ret) | ||
2426 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); | ||
2427 | } | ||
2428 | |||
2429 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) { | ||
2430 | ret = gpio_request(rt5645->pdata.hp_det_gpio, "rt5645"); | ||
2431 | if (ret) | ||
2432 | dev_err(&i2c->dev, "Fail gpio_request hp_det_gpio\n"); | ||
2433 | |||
2434 | ret = gpio_direction_input(rt5645->pdata.hp_det_gpio); | ||
2435 | if (ret) | ||
2436 | dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); | ||
2437 | } | ||
2438 | |||
2348 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 2439 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 2440 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2350 | } | 2441 | } |
2351 | 2442 | ||
2352 | static int rt5645_i2c_remove(struct i2c_client *i2c) | 2443 | static int rt5645_i2c_remove(struct i2c_client *i2c) |
2353 | { | 2444 | { |
2445 | struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c); | ||
2446 | |||
2447 | if (i2c->irq) | ||
2448 | free_irq(i2c->irq, rt5645); | ||
2449 | |||
2450 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) | ||
2451 | gpio_free(rt5645->pdata.hp_det_gpio); | ||
2452 | |||
2354 | snd_soc_unregister_codec(&i2c->dev); | 2453 | snd_soc_unregister_codec(&i2c->dev); |
2355 | 2454 | ||
2356 | return 0; | 2455 | return 0; |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 355b7e9eefab..50c62c5668ea 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -2166,6 +2166,8 @@ struct rt5645_priv { | |||
2166 | struct snd_soc_codec *codec; | 2166 | struct snd_soc_codec *codec; |
2167 | struct rt5645_platform_data pdata; | 2167 | struct rt5645_platform_data pdata; |
2168 | struct regmap *regmap; | 2168 | struct regmap *regmap; |
2169 | struct i2c_client *i2c; | ||
2170 | struct snd_soc_jack *jack; | ||
2169 | 2171 | ||
2170 | int sysclk; | 2172 | int sysclk; |
2171 | int sysclk_src; | 2173 | int sysclk_src; |
@@ -2178,4 +2180,7 @@ struct rt5645_priv { | |||
2178 | int pll_out; | 2180 | int pll_out; |
2179 | }; | 2181 | }; |
2180 | 2182 | ||
2183 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | ||
2184 | struct snd_soc_jack *jack); | ||
2185 | |||
2181 | #endif /* __RT5645_H__ */ | 2186 | #endif /* __RT5645_H__ */ |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 5337c448b5e3..16aa4d99a713 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -15,10 +15,12 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/of_gpio.h> | ||
18 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/gpio.h> | ||
22 | #include <sound/core.h> | 24 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -540,6 +542,7 @@ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | |||
540 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | 542 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); |
541 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | 543 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); |
542 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 544 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
545 | static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); | ||
543 | 546 | ||
544 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | 547 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ |
545 | static unsigned int bst_tlv[] = { | 548 | static unsigned int bst_tlv[] = { |
@@ -604,6 +607,10 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
604 | RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 127, 0, | 607 | RT5677_MONO_ADC_L_VOL_SFT, RT5677_MONO_ADC_R_VOL_SFT, 127, 0, |
605 | adc_vol_tlv), | 608 | adc_vol_tlv), |
606 | 609 | ||
610 | /* Sidetone Control */ | ||
611 | SOC_SINGLE_TLV("Sidetone Volume", RT5677_SIDETONE_CTRL, | ||
612 | RT5677_ST_VOL_SFT, 31, 0, st_vol_tlv), | ||
613 | |||
607 | /* ADC Boost Volume Control */ | 614 | /* ADC Boost Volume Control */ |
608 | SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST, | 615 | SOC_DOUBLE_TLV("STO1 ADC Boost Volume", RT5677_STO1_2_ADC_BST, |
609 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, | 616 | RT5677_STO1_ADC_L_BST_SFT, RT5677_STO1_ADC_R_BST_SFT, 3, 0, |
@@ -1700,14 +1707,19 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1700 | 1707 | ||
1701 | SND_SOC_DAPM_INPUT("Haptic Generator"), | 1708 | SND_SOC_DAPM_INPUT("Haptic Generator"), |
1702 | 1709 | ||
1703 | SND_SOC_DAPM_PGA("DMIC1", RT5677_DMIC_CTRL1, RT5677_DMIC_1_EN_SFT, 0, | 1710 | SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), |
1704 | NULL, 0), | 1711 | SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), |
1705 | SND_SOC_DAPM_PGA("DMIC2", RT5677_DMIC_CTRL1, RT5677_DMIC_2_EN_SFT, 0, | 1712 | SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0), |
1706 | NULL, 0), | 1713 | SND_SOC_DAPM_PGA("DMIC4", SND_SOC_NOPM, 0, 0, NULL, 0), |
1707 | SND_SOC_DAPM_PGA("DMIC3", RT5677_DMIC_CTRL1, RT5677_DMIC_3_EN_SFT, 0, | 1714 | |
1708 | NULL, 0), | 1715 | SND_SOC_DAPM_SUPPLY("DMIC1 power", RT5677_DMIC_CTRL1, |
1709 | SND_SOC_DAPM_PGA("DMIC4", RT5677_DMIC_CTRL2, RT5677_DMIC_4_EN_SFT, 0, | 1716 | RT5677_DMIC_1_EN_SFT, 0, NULL, 0), |
1710 | NULL, 0), | 1717 | SND_SOC_DAPM_SUPPLY("DMIC2 power", RT5677_DMIC_CTRL1, |
1718 | RT5677_DMIC_2_EN_SFT, 0, NULL, 0), | ||
1719 | SND_SOC_DAPM_SUPPLY("DMIC3 power", RT5677_DMIC_CTRL1, | ||
1720 | RT5677_DMIC_3_EN_SFT, 0, NULL, 0), | ||
1721 | SND_SOC_DAPM_SUPPLY("DMIC4 power", RT5677_DMIC_CTRL2, | ||
1722 | RT5677_DMIC_4_EN_SFT, 0, NULL, 0), | ||
1711 | 1723 | ||
1712 | SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, | 1724 | SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, |
1713 | set_dmic_clk, SND_SOC_DAPM_PRE_PMU), | 1725 | set_dmic_clk, SND_SOC_DAPM_PRE_PMU), |
@@ -1987,6 +1999,9 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
1987 | /* Sidetone Mux */ | 1999 | /* Sidetone Mux */ |
1988 | SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0, | 2000 | SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0, |
1989 | &rt5677_sidetone_mux), | 2001 | &rt5677_sidetone_mux), |
2002 | SND_SOC_DAPM_SUPPLY("Sidetone Power", RT5677_SIDETONE_CTRL, | ||
2003 | RT5677_ST_EN_SFT, 0, NULL, 0), | ||
2004 | |||
1990 | /* VAD Mux*/ | 2005 | /* VAD Mux*/ |
1991 | SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0, | 2006 | SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM, 0, 0, |
1992 | &rt5677_vad_src_mux), | 2007 | &rt5677_vad_src_mux), |
@@ -2130,6 +2145,13 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2130 | { "DMIC L4", NULL, "DMIC CLK" }, | 2145 | { "DMIC L4", NULL, "DMIC CLK" }, |
2131 | { "DMIC R4", NULL, "DMIC CLK" }, | 2146 | { "DMIC R4", NULL, "DMIC CLK" }, |
2132 | 2147 | ||
2148 | { "DMIC L1", NULL, "DMIC1 power" }, | ||
2149 | { "DMIC R1", NULL, "DMIC1 power" }, | ||
2150 | { "DMIC L3", NULL, "DMIC3 power" }, | ||
2151 | { "DMIC R3", NULL, "DMIC3 power" }, | ||
2152 | { "DMIC L4", NULL, "DMIC4 power" }, | ||
2153 | { "DMIC R4", NULL, "DMIC4 power" }, | ||
2154 | |||
2133 | { "BST1", NULL, "IN1P" }, | 2155 | { "BST1", NULL, "IN1P" }, |
2134 | { "BST1", NULL, "IN1N" }, | 2156 | { "BST1", NULL, "IN1N" }, |
2135 | { "BST2", NULL, "IN2P" }, | 2157 | { "BST2", NULL, "IN2P" }, |
@@ -2691,6 +2713,7 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2691 | { "Sidetone Mux", "DMIC4 L", "DMIC L4" }, | 2713 | { "Sidetone Mux", "DMIC4 L", "DMIC L4" }, |
2692 | { "Sidetone Mux", "ADC1", "ADC 1" }, | 2714 | { "Sidetone Mux", "ADC1", "ADC 1" }, |
2693 | { "Sidetone Mux", "ADC2", "ADC 2" }, | 2715 | { "Sidetone Mux", "ADC2", "ADC 2" }, |
2716 | { "Sidetone Mux", NULL, "Sidetone Power" }, | ||
2694 | 2717 | ||
2695 | { "Stereo DAC MIXL", "ST L Switch", "Sidetone Mux" }, | 2718 | { "Stereo DAC MIXL", "ST L Switch", "Sidetone Mux" }, |
2696 | { "Stereo DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" }, | 2719 | { "Stereo DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" }, |
@@ -2793,6 +2816,16 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2793 | { "PDM2R", NULL, "PDM2 R Mux" }, | 2816 | { "PDM2R", NULL, "PDM2 R Mux" }, |
2794 | }; | 2817 | }; |
2795 | 2818 | ||
2819 | static const struct snd_soc_dapm_route rt5677_dmic2_clk_1[] = { | ||
2820 | { "DMIC L2", NULL, "DMIC1 power" }, | ||
2821 | { "DMIC R2", NULL, "DMIC1 power" }, | ||
2822 | }; | ||
2823 | |||
2824 | static const struct snd_soc_dapm_route rt5677_dmic2_clk_2[] = { | ||
2825 | { "DMIC L2", NULL, "DMIC2 power" }, | ||
2826 | { "DMIC R2", NULL, "DMIC2 power" }, | ||
2827 | }; | ||
2828 | |||
2796 | static int rt5677_hw_params(struct snd_pcm_substream *substream, | 2829 | static int rt5677_hw_params(struct snd_pcm_substream *substream, |
2797 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2830 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2798 | { | 2831 | { |
@@ -3084,6 +3117,59 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
3084 | return 0; | 3117 | return 0; |
3085 | } | 3118 | } |
3086 | 3119 | ||
3120 | static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
3121 | unsigned int rx_mask, int slots, int slot_width) | ||
3122 | { | ||
3123 | struct snd_soc_codec *codec = dai->codec; | ||
3124 | unsigned int val = 0; | ||
3125 | |||
3126 | if (rx_mask || tx_mask) | ||
3127 | val |= (1 << 12); | ||
3128 | |||
3129 | switch (slots) { | ||
3130 | case 4: | ||
3131 | val |= (1 << 10); | ||
3132 | break; | ||
3133 | case 6: | ||
3134 | val |= (2 << 10); | ||
3135 | break; | ||
3136 | case 8: | ||
3137 | val |= (3 << 10); | ||
3138 | break; | ||
3139 | case 2: | ||
3140 | default: | ||
3141 | break; | ||
3142 | } | ||
3143 | |||
3144 | switch (slot_width) { | ||
3145 | case 20: | ||
3146 | val |= (1 << 8); | ||
3147 | break; | ||
3148 | case 24: | ||
3149 | val |= (2 << 8); | ||
3150 | break; | ||
3151 | case 32: | ||
3152 | val |= (3 << 8); | ||
3153 | break; | ||
3154 | case 16: | ||
3155 | default: | ||
3156 | break; | ||
3157 | } | ||
3158 | |||
3159 | switch (dai->id) { | ||
3160 | case RT5677_AIF1: | ||
3161 | snd_soc_update_bits(codec, RT5677_TDM1_CTRL1, 0x1f00, val); | ||
3162 | break; | ||
3163 | case RT5677_AIF2: | ||
3164 | snd_soc_update_bits(codec, RT5677_TDM2_CTRL1, 0x1f00, val); | ||
3165 | break; | ||
3166 | default: | ||
3167 | break; | ||
3168 | } | ||
3169 | |||
3170 | return 0; | ||
3171 | } | ||
3172 | |||
3087 | static int rt5677_set_bias_level(struct snd_soc_codec *codec, | 3173 | static int rt5677_set_bias_level(struct snd_soc_codec *codec, |
3088 | enum snd_soc_bias_level level) | 3174 | enum snd_soc_bias_level level) |
3089 | { | 3175 | { |
@@ -3138,12 +3224,148 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, | |||
3138 | return 0; | 3224 | return 0; |
3139 | } | 3225 | } |
3140 | 3226 | ||
3227 | #ifdef CONFIG_GPIOLIB | ||
3228 | static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip) | ||
3229 | { | ||
3230 | return container_of(chip, struct rt5677_priv, gpio_chip); | ||
3231 | } | ||
3232 | |||
3233 | static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
3234 | { | ||
3235 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
3236 | |||
3237 | switch (offset) { | ||
3238 | case RT5677_GPIO1 ... RT5677_GPIO5: | ||
3239 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2, | ||
3240 | 0x1 << (offset * 3 + 1), !!value << (offset * 3 + 1)); | ||
3241 | break; | ||
3242 | |||
3243 | case RT5677_GPIO6: | ||
3244 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3, | ||
3245 | RT5677_GPIO6_OUT_MASK, !!value << RT5677_GPIO6_OUT_SFT); | ||
3246 | break; | ||
3247 | |||
3248 | default: | ||
3249 | break; | ||
3250 | } | ||
3251 | } | ||
3252 | |||
3253 | static int rt5677_gpio_direction_out(struct gpio_chip *chip, | ||
3254 | unsigned offset, int value) | ||
3255 | { | ||
3256 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
3257 | |||
3258 | switch (offset) { | ||
3259 | case RT5677_GPIO1 ... RT5677_GPIO5: | ||
3260 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2, | ||
3261 | 0x3 << (offset * 3 + 1), | ||
3262 | (0x2 | !!value) << (offset * 3 + 1)); | ||
3263 | break; | ||
3264 | |||
3265 | case RT5677_GPIO6: | ||
3266 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3, | ||
3267 | RT5677_GPIO6_DIR_MASK | RT5677_GPIO6_OUT_MASK, | ||
3268 | RT5677_GPIO6_DIR_OUT | !!value << RT5677_GPIO6_OUT_SFT); | ||
3269 | break; | ||
3270 | |||
3271 | default: | ||
3272 | break; | ||
3273 | } | ||
3274 | |||
3275 | return 0; | ||
3276 | } | ||
3277 | |||
3278 | static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
3279 | { | ||
3280 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
3281 | int value, ret; | ||
3282 | |||
3283 | ret = regmap_read(rt5677->regmap, RT5677_GPIO_ST, &value); | ||
3284 | if (ret < 0) | ||
3285 | return ret; | ||
3286 | |||
3287 | return (value & (0x1 << offset)) >> offset; | ||
3288 | } | ||
3289 | |||
3290 | static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
3291 | { | ||
3292 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
3293 | |||
3294 | switch (offset) { | ||
3295 | case RT5677_GPIO1 ... RT5677_GPIO5: | ||
3296 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2, | ||
3297 | 0x1 << (offset * 3 + 2), 0x0); | ||
3298 | break; | ||
3299 | |||
3300 | case RT5677_GPIO6: | ||
3301 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3, | ||
3302 | RT5677_GPIO6_DIR_MASK, RT5677_GPIO6_DIR_IN); | ||
3303 | break; | ||
3304 | |||
3305 | default: | ||
3306 | break; | ||
3307 | } | ||
3308 | |||
3309 | return 0; | ||
3310 | } | ||
3311 | |||
3312 | static struct gpio_chip rt5677_template_chip = { | ||
3313 | .label = "rt5677", | ||
3314 | .owner = THIS_MODULE, | ||
3315 | .direction_output = rt5677_gpio_direction_out, | ||
3316 | .set = rt5677_gpio_set, | ||
3317 | .direction_input = rt5677_gpio_direction_in, | ||
3318 | .get = rt5677_gpio_get, | ||
3319 | .can_sleep = 1, | ||
3320 | }; | ||
3321 | |||
3322 | static void rt5677_init_gpio(struct i2c_client *i2c) | ||
3323 | { | ||
3324 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
3325 | int ret; | ||
3326 | |||
3327 | rt5677->gpio_chip = rt5677_template_chip; | ||
3328 | rt5677->gpio_chip.ngpio = RT5677_GPIO_NUM; | ||
3329 | rt5677->gpio_chip.dev = &i2c->dev; | ||
3330 | rt5677->gpio_chip.base = -1; | ||
3331 | |||
3332 | ret = gpiochip_add(&rt5677->gpio_chip); | ||
3333 | if (ret != 0) | ||
3334 | dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); | ||
3335 | } | ||
3336 | |||
3337 | static void rt5677_free_gpio(struct i2c_client *i2c) | ||
3338 | { | ||
3339 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
3340 | |||
3341 | gpiochip_remove(&rt5677->gpio_chip); | ||
3342 | } | ||
3343 | #else | ||
3344 | static void rt5677_init_gpio(struct i2c_client *i2c) | ||
3345 | { | ||
3346 | } | ||
3347 | |||
3348 | static void rt5677_free_gpio(struct i2c_client *i2c) | ||
3349 | { | ||
3350 | } | ||
3351 | #endif | ||
3352 | |||
3141 | static int rt5677_probe(struct snd_soc_codec *codec) | 3353 | static int rt5677_probe(struct snd_soc_codec *codec) |
3142 | { | 3354 | { |
3143 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 3355 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3144 | 3356 | ||
3145 | rt5677->codec = codec; | 3357 | rt5677->codec = codec; |
3146 | 3358 | ||
3359 | if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) { | ||
3360 | snd_soc_dapm_add_routes(&codec->dapm, | ||
3361 | rt5677_dmic2_clk_2, | ||
3362 | ARRAY_SIZE(rt5677_dmic2_clk_2)); | ||
3363 | } else { /*use dmic1 clock by default*/ | ||
3364 | snd_soc_dapm_add_routes(&codec->dapm, | ||
3365 | rt5677_dmic2_clk_1, | ||
3366 | ARRAY_SIZE(rt5677_dmic2_clk_1)); | ||
3367 | } | ||
3368 | |||
3147 | rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF); | 3369 | rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF); |
3148 | 3370 | ||
3149 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); | 3371 | regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); |
@@ -3157,6 +3379,8 @@ static int rt5677_remove(struct snd_soc_codec *codec) | |||
3157 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 3379 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3158 | 3380 | ||
3159 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); | 3381 | regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); |
3382 | if (gpio_is_valid(rt5677->pow_ldo2)) | ||
3383 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | ||
3160 | 3384 | ||
3161 | return 0; | 3385 | return 0; |
3162 | } | 3386 | } |
@@ -3168,6 +3392,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec) | |||
3168 | 3392 | ||
3169 | regcache_cache_only(rt5677->regmap, true); | 3393 | regcache_cache_only(rt5677->regmap, true); |
3170 | regcache_mark_dirty(rt5677->regmap); | 3394 | regcache_mark_dirty(rt5677->regmap); |
3395 | if (gpio_is_valid(rt5677->pow_ldo2)) | ||
3396 | gpio_set_value_cansleep(rt5677->pow_ldo2, 0); | ||
3171 | 3397 | ||
3172 | return 0; | 3398 | return 0; |
3173 | } | 3399 | } |
@@ -3176,6 +3402,10 @@ static int rt5677_resume(struct snd_soc_codec *codec) | |||
3176 | { | 3402 | { |
3177 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 3403 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
3178 | 3404 | ||
3405 | if (gpio_is_valid(rt5677->pow_ldo2)) { | ||
3406 | gpio_set_value_cansleep(rt5677->pow_ldo2, 1); | ||
3407 | msleep(10); | ||
3408 | } | ||
3179 | regcache_cache_only(rt5677->regmap, false); | 3409 | regcache_cache_only(rt5677->regmap, false); |
3180 | regcache_sync(rt5677->regmap); | 3410 | regcache_sync(rt5677->regmap); |
3181 | 3411 | ||
@@ -3195,6 +3425,7 @@ static struct snd_soc_dai_ops rt5677_aif_dai_ops = { | |||
3195 | .set_fmt = rt5677_set_dai_fmt, | 3425 | .set_fmt = rt5677_set_dai_fmt, |
3196 | .set_sysclk = rt5677_set_dai_sysclk, | 3426 | .set_sysclk = rt5677_set_dai_sysclk, |
3197 | .set_pll = rt5677_set_dai_pll, | 3427 | .set_pll = rt5677_set_dai_pll, |
3428 | .set_tdm_slot = rt5677_set_tdm_slot, | ||
3198 | }; | 3429 | }; |
3199 | 3430 | ||
3200 | static struct snd_soc_dai_driver rt5677_dai[] = { | 3431 | static struct snd_soc_dai_driver rt5677_dai[] = { |
@@ -3333,6 +3564,35 @@ static const struct i2c_device_id rt5677_i2c_id[] = { | |||
3333 | }; | 3564 | }; |
3334 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); | 3565 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); |
3335 | 3566 | ||
3567 | static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | ||
3568 | { | ||
3569 | rt5677->pdata.in1_diff = of_property_read_bool(np, | ||
3570 | "realtek,in1-differential"); | ||
3571 | rt5677->pdata.in2_diff = of_property_read_bool(np, | ||
3572 | "realtek,in2-differential"); | ||
3573 | rt5677->pdata.lout1_diff = of_property_read_bool(np, | ||
3574 | "realtek,lout1-differential"); | ||
3575 | rt5677->pdata.lout2_diff = of_property_read_bool(np, | ||
3576 | "realtek,lout2-differential"); | ||
3577 | rt5677->pdata.lout3_diff = of_property_read_bool(np, | ||
3578 | "realtek,lout3-differential"); | ||
3579 | |||
3580 | rt5677->pow_ldo2 = of_get_named_gpio(np, | ||
3581 | "realtek,pow-ldo2-gpio", 0); | ||
3582 | |||
3583 | /* | ||
3584 | * POW_LDO2 is optional (it may be statically tied on the board). | ||
3585 | * -ENOENT means that the property doesn't exist, i.e. there is no | ||
3586 | * GPIO, so is not an error. Any other error code means the property | ||
3587 | * exists, but could not be parsed. | ||
3588 | */ | ||
3589 | if (!gpio_is_valid(rt5677->pow_ldo2) && | ||
3590 | (rt5677->pow_ldo2 != -ENOENT)) | ||
3591 | return rt5677->pow_ldo2; | ||
3592 | |||
3593 | return 0; | ||
3594 | } | ||
3595 | |||
3336 | static int rt5677_i2c_probe(struct i2c_client *i2c, | 3596 | static int rt5677_i2c_probe(struct i2c_client *i2c, |
3337 | const struct i2c_device_id *id) | 3597 | const struct i2c_device_id *id) |
3338 | { | 3598 | { |
@@ -3351,6 +3611,33 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3351 | if (pdata) | 3611 | if (pdata) |
3352 | rt5677->pdata = *pdata; | 3612 | rt5677->pdata = *pdata; |
3353 | 3613 | ||
3614 | if (i2c->dev.of_node) { | ||
3615 | ret = rt5677_parse_dt(rt5677, i2c->dev.of_node); | ||
3616 | if (ret) { | ||
3617 | dev_err(&i2c->dev, "Failed to parse device tree: %d\n", | ||
3618 | ret); | ||
3619 | return ret; | ||
3620 | } | ||
3621 | } else { | ||
3622 | rt5677->pow_ldo2 = -EINVAL; | ||
3623 | } | ||
3624 | |||
3625 | if (gpio_is_valid(rt5677->pow_ldo2)) { | ||
3626 | ret = devm_gpio_request_one(&i2c->dev, rt5677->pow_ldo2, | ||
3627 | GPIOF_OUT_INIT_HIGH, | ||
3628 | "RT5677 POW_LDO2"); | ||
3629 | if (ret < 0) { | ||
3630 | dev_err(&i2c->dev, "Failed to request POW_LDO2 %d: %d\n", | ||
3631 | rt5677->pow_ldo2, ret); | ||
3632 | return ret; | ||
3633 | } | ||
3634 | /* Wait a while until I2C bus becomes available. The datasheet | ||
3635 | * does not specify the exact we should wait but startup | ||
3636 | * sequence mentiones at least a few milliseconds. | ||
3637 | */ | ||
3638 | msleep(10); | ||
3639 | } | ||
3640 | |||
3354 | rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap); | 3641 | rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap); |
3355 | if (IS_ERR(rt5677->regmap)) { | 3642 | if (IS_ERR(rt5677->regmap)) { |
3356 | ret = PTR_ERR(rt5677->regmap); | 3643 | ret = PTR_ERR(rt5677->regmap); |
@@ -3381,6 +3668,29 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3381 | regmap_update_bits(rt5677->regmap, RT5677_IN1, | 3668 | regmap_update_bits(rt5677->regmap, RT5677_IN1, |
3382 | RT5677_IN_DF2, RT5677_IN_DF2); | 3669 | RT5677_IN_DF2, RT5677_IN_DF2); |
3383 | 3670 | ||
3671 | if (rt5677->pdata.lout1_diff) | ||
3672 | regmap_update_bits(rt5677->regmap, RT5677_LOUT1, | ||
3673 | RT5677_LOUT1_L_DF, RT5677_LOUT1_L_DF); | ||
3674 | |||
3675 | if (rt5677->pdata.lout2_diff) | ||
3676 | regmap_update_bits(rt5677->regmap, RT5677_LOUT1, | ||
3677 | RT5677_LOUT2_L_DF, RT5677_LOUT2_L_DF); | ||
3678 | |||
3679 | if (rt5677->pdata.lout3_diff) | ||
3680 | regmap_update_bits(rt5677->regmap, RT5677_LOUT1, | ||
3681 | RT5677_LOUT3_L_DF, RT5677_LOUT3_L_DF); | ||
3682 | |||
3683 | if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) { | ||
3684 | regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL2, | ||
3685 | RT5677_GPIO5_FUNC_MASK, | ||
3686 | RT5677_GPIO5_FUNC_DMIC); | ||
3687 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2, | ||
3688 | RT5677_GPIO5_DIR_MASK, | ||
3689 | RT5677_GPIO5_DIR_OUT); | ||
3690 | } | ||
3691 | |||
3692 | rt5677_init_gpio(i2c); | ||
3693 | |||
3384 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, | 3694 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, |
3385 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); | 3695 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); |
3386 | } | 3696 | } |
@@ -3388,6 +3698,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
3388 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 3698 | static int rt5677_i2c_remove(struct i2c_client *i2c) |
3389 | { | 3699 | { |
3390 | snd_soc_unregister_codec(&i2c->dev); | 3700 | snd_soc_unregister_codec(&i2c->dev); |
3701 | rt5677_free_gpio(i2c); | ||
3391 | 3702 | ||
3392 | return 0; | 3703 | return 0; |
3393 | } | 3704 | } |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 863393e62096..d4eb6d5e6746 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -382,6 +382,10 @@ | |||
382 | #define RT5677_ST_SEL_SFT 9 | 382 | #define RT5677_ST_SEL_SFT 9 |
383 | #define RT5677_ST_EN (0x1 << 6) | 383 | #define RT5677_ST_EN (0x1 << 6) |
384 | #define RT5677_ST_EN_SFT 6 | 384 | #define RT5677_ST_EN_SFT 6 |
385 | #define RT5677_ST_GAIN (0x1 << 5) | ||
386 | #define RT5677_ST_GAIN_SFT 5 | ||
387 | #define RT5677_ST_VOL_MASK (0x1f << 0) | ||
388 | #define RT5677_ST_VOL_SFT 0 | ||
385 | 389 | ||
386 | /* Analog DAC1/2/3 Source Control (0x15) */ | 390 | /* Analog DAC1/2/3 Source Control (0x15) */ |
387 | #define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4) | 391 | #define RT5677_ANA_DAC3_SRC_SEL_MASK (0x3 << 4) |
@@ -1287,16 +1291,16 @@ | |||
1287 | #define RT5677_PLL1_PD_SFT 8 | 1291 | #define RT5677_PLL1_PD_SFT 8 |
1288 | #define RT5677_PLL1_PD_1 (0x0 << 8) | 1292 | #define RT5677_PLL1_PD_1 (0x0 << 8) |
1289 | #define RT5677_PLL1_PD_2 (0x1 << 8) | 1293 | #define RT5677_PLL1_PD_2 (0x1 << 8) |
1290 | #define RT5671_DAC_OSR_MASK (0x3 << 6) | 1294 | #define RT5677_DAC_OSR_MASK (0x3 << 6) |
1291 | #define RT5671_DAC_OSR_SFT 6 | 1295 | #define RT5677_DAC_OSR_SFT 6 |
1292 | #define RT5671_DAC_OSR_128 (0x0 << 6) | 1296 | #define RT5677_DAC_OSR_128 (0x0 << 6) |
1293 | #define RT5671_DAC_OSR_64 (0x1 << 6) | 1297 | #define RT5677_DAC_OSR_64 (0x1 << 6) |
1294 | #define RT5671_DAC_OSR_32 (0x2 << 6) | 1298 | #define RT5677_DAC_OSR_32 (0x2 << 6) |
1295 | #define RT5671_ADC_OSR_MASK (0x3 << 4) | 1299 | #define RT5677_ADC_OSR_MASK (0x3 << 4) |
1296 | #define RT5671_ADC_OSR_SFT 4 | 1300 | #define RT5677_ADC_OSR_SFT 4 |
1297 | #define RT5671_ADC_OSR_128 (0x0 << 4) | 1301 | #define RT5677_ADC_OSR_128 (0x0 << 4) |
1298 | #define RT5671_ADC_OSR_64 (0x1 << 4) | 1302 | #define RT5677_ADC_OSR_64 (0x1 << 4) |
1299 | #define RT5671_ADC_OSR_32 (0x2 << 4) | 1303 | #define RT5677_ADC_OSR_32 (0x2 << 4) |
1300 | 1304 | ||
1301 | /* Global Clock Control 2 (0x81) */ | 1305 | /* Global Clock Control 2 (0x81) */ |
1302 | #define RT5677_PLL2_PR_SRC_MASK (0x1 << 15) | 1306 | #define RT5677_PLL2_PR_SRC_MASK (0x1 << 15) |
@@ -1312,18 +1316,18 @@ | |||
1312 | #define RT5677_PLL2_SRC_BCLK4 (0x4 << 12) | 1316 | #define RT5677_PLL2_SRC_BCLK4 (0x4 << 12) |
1313 | #define RT5677_PLL2_SRC_RCCLK (0x5 << 12) | 1317 | #define RT5677_PLL2_SRC_RCCLK (0x5 << 12) |
1314 | #define RT5677_PLL2_SRC_SLIM (0x6 << 12) | 1318 | #define RT5677_PLL2_SRC_SLIM (0x6 << 12) |
1315 | #define RT5671_DSP_ASRC_O_SRC (0x3 << 10) | 1319 | #define RT5677_DSP_ASRC_O_SRC (0x3 << 10) |
1316 | #define RT5671_DSP_ASRC_O_SRC_SFT 10 | 1320 | #define RT5677_DSP_ASRC_O_SRC_SFT 10 |
1317 | #define RT5671_DSP_ASRC_O_MCLK (0x0 << 10) | 1321 | #define RT5677_DSP_ASRC_O_MCLK (0x0 << 10) |
1318 | #define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10) | 1322 | #define RT5677_DSP_ASRC_O_PLL1 (0x1 << 10) |
1319 | #define RT5671_DSP_ASRC_O_SLIM (0x2 << 10) | 1323 | #define RT5677_DSP_ASRC_O_SLIM (0x2 << 10) |
1320 | #define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10) | 1324 | #define RT5677_DSP_ASRC_O_RCCLK (0x3 << 10) |
1321 | #define RT5671_DSP_ASRC_I_SRC (0x3 << 8) | 1325 | #define RT5677_DSP_ASRC_I_SRC (0x3 << 8) |
1322 | #define RT5671_DSP_ASRC_I_SRC_SFT 8 | 1326 | #define RT5677_DSP_ASRC_I_SRC_SFT 8 |
1323 | #define RT5671_DSP_ASRC_I_MCLK (0x0 << 8) | 1327 | #define RT5677_DSP_ASRC_I_MCLK (0x0 << 8) |
1324 | #define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8) | 1328 | #define RT5677_DSP_ASRC_I_PLL1 (0x1 << 8) |
1325 | #define RT5671_DSP_ASRC_I_SLIM (0x2 << 8) | 1329 | #define RT5677_DSP_ASRC_I_SLIM (0x2 << 8) |
1326 | #define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8) | 1330 | #define RT5677_DSP_ASRC_I_RCCLK (0x3 << 8) |
1327 | #define RT5677_DSP_CLK_SRC_MASK (0x1 << 7) | 1331 | #define RT5677_DSP_CLK_SRC_MASK (0x1 << 7) |
1328 | #define RT5677_DSP_CLK_SRC_SFT 7 | 1332 | #define RT5677_DSP_CLK_SRC_SFT 7 |
1329 | #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) | 1333 | #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) |
@@ -1363,6 +1367,110 @@ | |||
1363 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) | 1367 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) |
1364 | #define RT5677_SEL_SRC_IB01_SFT 0 | 1368 | #define RT5677_SEL_SRC_IB01_SFT 0 |
1365 | 1369 | ||
1370 | /* GPIO status (0xbf) */ | ||
1371 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) | ||
1372 | #define RT5677_GPIO6_STATUS_SFT 5 | ||
1373 | #define RT5677_GPIO5_STATUS_MASK (0x1 << 4) | ||
1374 | #define RT5677_GPIO5_STATUS_SFT 4 | ||
1375 | #define RT5677_GPIO4_STATUS_MASK (0x1 << 3) | ||
1376 | #define RT5677_GPIO4_STATUS_SFT 3 | ||
1377 | #define RT5677_GPIO3_STATUS_MASK (0x1 << 2) | ||
1378 | #define RT5677_GPIO3_STATUS_SFT 2 | ||
1379 | #define RT5677_GPIO2_STATUS_MASK (0x1 << 1) | ||
1380 | #define RT5677_GPIO2_STATUS_SFT 1 | ||
1381 | #define RT5677_GPIO1_STATUS_MASK (0x1 << 0) | ||
1382 | #define RT5677_GPIO1_STATUS_SFT 0 | ||
1383 | |||
1384 | /* GPIO Control 1 (0xc0) */ | ||
1385 | #define RT5677_GPIO1_PIN_MASK (0x1 << 15) | ||
1386 | #define RT5677_GPIO1_PIN_SFT 15 | ||
1387 | #define RT5677_GPIO1_PIN_GPIO1 (0x0 << 15) | ||
1388 | #define RT5677_GPIO1_PIN_IRQ (0x1 << 15) | ||
1389 | #define RT5677_IPTV_MODE_MASK (0x1 << 14) | ||
1390 | #define RT5677_IPTV_MODE_SFT 14 | ||
1391 | #define RT5677_IPTV_MODE_GPIO (0x0 << 14) | ||
1392 | #define RT5677_IPTV_MODE_IPTV (0x1 << 14) | ||
1393 | #define RT5677_FUNC_MODE_MASK (0x1 << 13) | ||
1394 | #define RT5677_FUNC_MODE_SFT 13 | ||
1395 | #define RT5677_FUNC_MODE_DMIC_GPIO (0x0 << 13) | ||
1396 | #define RT5677_FUNC_MODE_JTAG (0x1 << 13) | ||
1397 | |||
1398 | /* GPIO Control 2 (0xc1) */ | ||
1399 | #define RT5677_GPIO5_DIR_MASK (0x1 << 14) | ||
1400 | #define RT5677_GPIO5_DIR_SFT 14 | ||
1401 | #define RT5677_GPIO5_DIR_IN (0x0 << 14) | ||
1402 | #define RT5677_GPIO5_DIR_OUT (0x1 << 14) | ||
1403 | #define RT5677_GPIO5_OUT_MASK (0x1 << 13) | ||
1404 | #define RT5677_GPIO5_OUT_SFT 13 | ||
1405 | #define RT5677_GPIO5_OUT_LO (0x0 << 13) | ||
1406 | #define RT5677_GPIO5_OUT_HI (0x1 << 13) | ||
1407 | #define RT5677_GPIO5_P_MASK (0x1 << 12) | ||
1408 | #define RT5677_GPIO5_P_SFT 12 | ||
1409 | #define RT5677_GPIO5_P_NOR (0x0 << 12) | ||
1410 | #define RT5677_GPIO5_P_INV (0x1 << 12) | ||
1411 | #define RT5677_GPIO4_DIR_MASK (0x1 << 11) | ||
1412 | #define RT5677_GPIO4_DIR_SFT 11 | ||
1413 | #define RT5677_GPIO4_DIR_IN (0x0 << 11) | ||
1414 | #define RT5677_GPIO4_DIR_OUT (0x1 << 11) | ||
1415 | #define RT5677_GPIO4_OUT_MASK (0x1 << 10) | ||
1416 | #define RT5677_GPIO4_OUT_SFT 10 | ||
1417 | #define RT5677_GPIO4_OUT_LO (0x0 << 10) | ||
1418 | #define RT5677_GPIO4_OUT_HI (0x1 << 10) | ||
1419 | #define RT5677_GPIO4_P_MASK (0x1 << 9) | ||
1420 | #define RT5677_GPIO4_P_SFT 9 | ||
1421 | #define RT5677_GPIO4_P_NOR (0x0 << 9) | ||
1422 | #define RT5677_GPIO4_P_INV (0x1 << 9) | ||
1423 | #define RT5677_GPIO3_DIR_MASK (0x1 << 8) | ||
1424 | #define RT5677_GPIO3_DIR_SFT 8 | ||
1425 | #define RT5677_GPIO3_DIR_IN (0x0 << 8) | ||
1426 | #define RT5677_GPIO3_DIR_OUT (0x1 << 8) | ||
1427 | #define RT5677_GPIO3_OUT_MASK (0x1 << 7) | ||
1428 | #define RT5677_GPIO3_OUT_SFT 7 | ||
1429 | #define RT5677_GPIO3_OUT_LO (0x0 << 7) | ||
1430 | #define RT5677_GPIO3_OUT_HI (0x1 << 7) | ||
1431 | #define RT5677_GPIO3_P_MASK (0x1 << 6) | ||
1432 | #define RT5677_GPIO3_P_SFT 6 | ||
1433 | #define RT5677_GPIO3_P_NOR (0x0 << 6) | ||
1434 | #define RT5677_GPIO3_P_INV (0x1 << 6) | ||
1435 | #define RT5677_GPIO2_DIR_MASK (0x1 << 5) | ||
1436 | #define RT5677_GPIO2_DIR_SFT 5 | ||
1437 | #define RT5677_GPIO2_DIR_IN (0x0 << 5) | ||
1438 | #define RT5677_GPIO2_DIR_OUT (0x1 << 5) | ||
1439 | #define RT5677_GPIO2_OUT_MASK (0x1 << 4) | ||
1440 | #define RT5677_GPIO2_OUT_SFT 4 | ||
1441 | #define RT5677_GPIO2_OUT_LO (0x0 << 4) | ||
1442 | #define RT5677_GPIO2_OUT_HI (0x1 << 4) | ||
1443 | #define RT5677_GPIO2_P_MASK (0x1 << 3) | ||
1444 | #define RT5677_GPIO2_P_SFT 3 | ||
1445 | #define RT5677_GPIO2_P_NOR (0x0 << 3) | ||
1446 | #define RT5677_GPIO2_P_INV (0x1 << 3) | ||
1447 | #define RT5677_GPIO1_DIR_MASK (0x1 << 2) | ||
1448 | #define RT5677_GPIO1_DIR_SFT 2 | ||
1449 | #define RT5677_GPIO1_DIR_IN (0x0 << 2) | ||
1450 | #define RT5677_GPIO1_DIR_OUT (0x1 << 2) | ||
1451 | #define RT5677_GPIO1_OUT_MASK (0x1 << 1) | ||
1452 | #define RT5677_GPIO1_OUT_SFT 1 | ||
1453 | #define RT5677_GPIO1_OUT_LO (0x0 << 1) | ||
1454 | #define RT5677_GPIO1_OUT_HI (0x1 << 1) | ||
1455 | #define RT5677_GPIO1_P_MASK (0x1 << 0) | ||
1456 | #define RT5677_GPIO1_P_SFT 0 | ||
1457 | #define RT5677_GPIO1_P_NOR (0x0 << 0) | ||
1458 | #define RT5677_GPIO1_P_INV (0x1 << 0) | ||
1459 | |||
1460 | /* GPIO Control 3 (0xc2) */ | ||
1461 | #define RT5677_GPIO6_DIR_MASK (0x1 << 2) | ||
1462 | #define RT5677_GPIO6_DIR_SFT 2 | ||
1463 | #define RT5677_GPIO6_DIR_IN (0x0 << 2) | ||
1464 | #define RT5677_GPIO6_DIR_OUT (0x1 << 2) | ||
1465 | #define RT5677_GPIO6_OUT_MASK (0x1 << 1) | ||
1466 | #define RT5677_GPIO6_OUT_SFT 1 | ||
1467 | #define RT5677_GPIO6_OUT_LO (0x0 << 1) | ||
1468 | #define RT5677_GPIO6_OUT_HI (0x1 << 1) | ||
1469 | #define RT5677_GPIO6_P_MASK (0x1 << 0) | ||
1470 | #define RT5677_GPIO6_P_SFT 0 | ||
1471 | #define RT5677_GPIO6_P_NOR (0x0 << 0) | ||
1472 | #define RT5677_GPIO6_P_INV (0x1 << 0) | ||
1473 | |||
1366 | /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ | 1474 | /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ |
1367 | #define RT5677_DSP_IB_01_H (0x1 << 15) | 1475 | #define RT5677_DSP_IB_01_H (0x1 << 15) |
1368 | #define RT5677_DSP_IB_01_H_SFT 15 | 1476 | #define RT5677_DSP_IB_01_H_SFT 15 |
@@ -1393,6 +1501,11 @@ | |||
1393 | #define RT5677_DSP_IB_9_L (0x1 << 1) | 1501 | #define RT5677_DSP_IB_9_L (0x1 << 1) |
1394 | #define RT5677_DSP_IB_9_L_SFT 1 | 1502 | #define RT5677_DSP_IB_9_L_SFT 1 |
1395 | 1503 | ||
1504 | /* General Control2 (0xfc)*/ | ||
1505 | #define RT5677_GPIO5_FUNC_MASK (0x1 << 9) | ||
1506 | #define RT5677_GPIO5_FUNC_GPIO (0x0 << 9) | ||
1507 | #define RT5677_GPIO5_FUNC_DMIC (0x1 << 9) | ||
1508 | |||
1396 | /* System Clock Source */ | 1509 | /* System Clock Source */ |
1397 | enum { | 1510 | enum { |
1398 | RT5677_SCLK_S_MCLK, | 1511 | RT5677_SCLK_S_MCLK, |
@@ -1418,6 +1531,16 @@ enum { | |||
1418 | RT5677_AIFS, | 1531 | RT5677_AIFS, |
1419 | }; | 1532 | }; |
1420 | 1533 | ||
1534 | enum { | ||
1535 | RT5677_GPIO1, | ||
1536 | RT5677_GPIO2, | ||
1537 | RT5677_GPIO3, | ||
1538 | RT5677_GPIO4, | ||
1539 | RT5677_GPIO5, | ||
1540 | RT5677_GPIO6, | ||
1541 | RT5677_GPIO_NUM, | ||
1542 | }; | ||
1543 | |||
1421 | struct rt5677_priv { | 1544 | struct rt5677_priv { |
1422 | struct snd_soc_codec *codec; | 1545 | struct snd_soc_codec *codec; |
1423 | struct rt5677_platform_data pdata; | 1546 | struct rt5677_platform_data pdata; |
@@ -1431,6 +1554,10 @@ struct rt5677_priv { | |||
1431 | int pll_src; | 1554 | int pll_src; |
1432 | int pll_in; | 1555 | int pll_in; |
1433 | int pll_out; | 1556 | int pll_out; |
1557 | int pow_ldo2; /* POW_LDO2 pin */ | ||
1558 | #ifdef CONFIG_GPIOLIB | ||
1559 | struct gpio_chip gpio_chip; | ||
1560 | #endif | ||
1434 | }; | 1561 | }; |
1435 | 1562 | ||
1436 | #endif /* __RT5677_H__ */ | 1563 | #endif /* __RT5677_H__ */ |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index e997d271728d..6bb77d76561b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -626,6 +626,9 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | |||
626 | } else { | 626 | } else { |
627 | dev_err(codec->dev, | 627 | dev_err(codec->dev, |
628 | "PLL not supported in slave mode\n"); | 628 | "PLL not supported in slave mode\n"); |
629 | dev_err(codec->dev, "%d ratio is not supported. " | ||
630 | "SYS_MCLK needs to be 256, 384 or 512 * fs\n", | ||
631 | sgtl5000->sysclk / sys_fs); | ||
629 | return -EINVAL; | 632 | return -EINVAL; |
630 | } | 633 | } |
631 | } | 634 | } |
@@ -1073,26 +1076,6 @@ static bool sgtl5000_readable(struct device *dev, unsigned int reg) | |||
1073 | } | 1076 | } |
1074 | } | 1077 | } |
1075 | 1078 | ||
1076 | #ifdef CONFIG_SUSPEND | ||
1077 | static int sgtl5000_suspend(struct snd_soc_codec *codec) | ||
1078 | { | ||
1079 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1080 | |||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | static int sgtl5000_resume(struct snd_soc_codec *codec) | ||
1085 | { | ||
1086 | /* Bring the codec back up to standby to enable regulators */ | ||
1087 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | #else | ||
1092 | #define sgtl5000_suspend NULL | ||
1093 | #define sgtl5000_resume NULL | ||
1094 | #endif /* CONFIG_SUSPEND */ | ||
1095 | |||
1096 | /* | 1079 | /* |
1097 | * sgtl5000 has 3 internal power supplies: | 1080 | * sgtl5000 has 3 internal power supplies: |
1098 | * 1. VAG, normally set to vdda/2 | 1081 | * 1. VAG, normally set to vdda/2 |
@@ -1352,11 +1335,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1352 | */ | 1335 | */ |
1353 | snd_soc_write(codec, SGTL5000_DAP_CTRL, 0); | 1336 | snd_soc_write(codec, SGTL5000_DAP_CTRL, 0); |
1354 | 1337 | ||
1355 | /* leading to standby state */ | ||
1356 | ret = sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1357 | if (ret) | ||
1358 | goto err; | ||
1359 | |||
1360 | return 0; | 1338 | return 0; |
1361 | 1339 | ||
1362 | err: | 1340 | err: |
@@ -1373,8 +1351,6 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) | |||
1373 | { | 1351 | { |
1374 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1352 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1375 | 1353 | ||
1376 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1377 | |||
1378 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1354 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1379 | sgtl5000->supplies); | 1355 | sgtl5000->supplies); |
1380 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | 1356 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), |
@@ -1387,9 +1363,8 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) | |||
1387 | static struct snd_soc_codec_driver sgtl5000_driver = { | 1363 | static struct snd_soc_codec_driver sgtl5000_driver = { |
1388 | .probe = sgtl5000_probe, | 1364 | .probe = sgtl5000_probe, |
1389 | .remove = sgtl5000_remove, | 1365 | .remove = sgtl5000_remove, |
1390 | .suspend = sgtl5000_suspend, | ||
1391 | .resume = sgtl5000_resume, | ||
1392 | .set_bias_level = sgtl5000_set_bias_level, | 1366 | .set_bias_level = sgtl5000_set_bias_level, |
1367 | .suspend_bias_off = true, | ||
1393 | .controls = sgtl5000_snd_controls, | 1368 | .controls = sgtl5000_snd_controls, |
1394 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), | 1369 | .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), |
1395 | .dapm_widgets = sgtl5000_dapm_widgets, | 1370 | .dapm_widgets = sgtl5000_dapm_widgets, |
@@ -1442,6 +1417,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1442 | { | 1417 | { |
1443 | struct sgtl5000_priv *sgtl5000; | 1418 | struct sgtl5000_priv *sgtl5000; |
1444 | int ret, reg, rev; | 1419 | int ret, reg, rev; |
1420 | unsigned int mclk; | ||
1445 | 1421 | ||
1446 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), | 1422 | sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), |
1447 | GFP_KERNEL); | 1423 | GFP_KERNEL); |
@@ -1465,6 +1441,14 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, | |||
1465 | return ret; | 1441 | return ret; |
1466 | } | 1442 | } |
1467 | 1443 | ||
1444 | /* SGTL5000 SYS_MCLK should be between 8 and 27 MHz */ | ||
1445 | mclk = clk_get_rate(sgtl5000->mclk); | ||
1446 | if (mclk < 8000000 || mclk > 27000000) { | ||
1447 | dev_err(&client->dev, "Invalid SYS_CLK frequency: %u.%03uMHz\n", | ||
1448 | mclk / 1000000, mclk / 1000 % 1000); | ||
1449 | return -EINVAL; | ||
1450 | } | ||
1451 | |||
1468 | ret = clk_prepare_enable(sgtl5000->mclk); | 1452 | ret = clk_prepare_enable(sgtl5000->mclk); |
1469 | if (ret) | 1453 | if (ret) |
1470 | return ret; | 1454 | return ret; |
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index e8680bea5f86..67ea55adb307 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -646,17 +646,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { | |||
646 | .ops = &ssm2518_dai_ops, | 646 | .ops = &ssm2518_dai_ops, |
647 | }; | 647 | }; |
648 | 648 | ||
649 | static int ssm2518_probe(struct snd_soc_codec *codec) | ||
650 | { | ||
651 | return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
652 | } | ||
653 | |||
654 | static int ssm2518_remove(struct snd_soc_codec *codec) | ||
655 | { | ||
656 | ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 649 | static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
661 | int source, unsigned int freq, int dir) | 650 | int source, unsigned int freq, int dir) |
662 | { | 651 | { |
@@ -727,8 +716,6 @@ static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
727 | } | 716 | } |
728 | 717 | ||
729 | static struct snd_soc_codec_driver ssm2518_codec_driver = { | 718 | static struct snd_soc_codec_driver ssm2518_codec_driver = { |
730 | .probe = ssm2518_probe, | ||
731 | .remove = ssm2518_remove, | ||
732 | .set_bias_level = ssm2518_set_bias_level, | 719 | .set_bias_level = ssm2518_set_bias_level, |
733 | .set_sysclk = ssm2518_set_sysclk, | 720 | .set_sysclk = ssm2518_set_sysclk, |
734 | .idle_bias_off = true, | 721 | .idle_bias_off = true, |
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c index abd63d537173..0d9779d6bfda 100644 --- a/sound/soc/codecs/ssm2602-i2c.c +++ b/sound/soc/codecs/ssm2602-i2c.c | |||
@@ -41,10 +41,19 @@ static const struct i2c_device_id ssm2602_i2c_id[] = { | |||
41 | }; | 41 | }; |
42 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | 42 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); |
43 | 43 | ||
44 | static const struct of_device_id ssm2602_of_match[] = { | ||
45 | { .compatible = "adi,ssm2602", }, | ||
46 | { .compatible = "adi,ssm2603", }, | ||
47 | { .compatible = "adi,ssm2604", }, | ||
48 | { } | ||
49 | }; | ||
50 | MODULE_DEVICE_TABLE(of, ssm2602_of_match); | ||
51 | |||
44 | static struct i2c_driver ssm2602_i2c_driver = { | 52 | static struct i2c_driver ssm2602_i2c_driver = { |
45 | .driver = { | 53 | .driver = { |
46 | .name = "ssm2602", | 54 | .name = "ssm2602", |
47 | .owner = THIS_MODULE, | 55 | .owner = THIS_MODULE, |
56 | .of_match_table = ssm2602_of_match, | ||
48 | }, | 57 | }, |
49 | .probe = ssm2602_i2c_probe, | 58 | .probe = ssm2602_i2c_probe, |
50 | .remove = ssm2602_i2c_remove, | 59 | .remove = ssm2602_i2c_remove, |
diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c index 2bf55e24a7bb..b5df14fbe3ad 100644 --- a/sound/soc/codecs/ssm2602-spi.c +++ b/sound/soc/codecs/ssm2602-spi.c | |||
@@ -26,10 +26,17 @@ static int ssm2602_spi_remove(struct spi_device *spi) | |||
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | 28 | ||
29 | static const struct of_device_id ssm2602_of_match[] = { | ||
30 | { .compatible = "adi,ssm2602", }, | ||
31 | { } | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE(of, ssm2602_of_match); | ||
34 | |||
29 | static struct spi_driver ssm2602_spi_driver = { | 35 | static struct spi_driver ssm2602_spi_driver = { |
30 | .driver = { | 36 | .driver = { |
31 | .name = "ssm2602", | 37 | .name = "ssm2602", |
32 | .owner = THIS_MODULE, | 38 | .owner = THIS_MODULE, |
39 | .of_match_table = ssm2602_of_match, | ||
33 | }, | 40 | }, |
34 | .probe = ssm2602_spi_probe, | 41 | .probe = ssm2602_spi_probe, |
35 | .remove = ssm2602_spi_remove, | 42 | .remove = ssm2602_spi_remove, |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 4021cd435740..314eaece1b7d 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -192,7 +192,7 @@ static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { | |||
192 | }; | 192 | }; |
193 | 193 | ||
194 | static const unsigned int ssm2602_rates_11289600[] = { | 194 | static const unsigned int ssm2602_rates_11289600[] = { |
195 | 8000, 44100, 88200, | 195 | 8000, 11025, 22050, 44100, 88200, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { | 198 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { |
@@ -237,6 +237,16 @@ static const struct ssm2602_coeff ssm2602_coeff_table[] = { | |||
237 | {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, | 237 | {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, |
238 | {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, | 238 | {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, |
239 | 239 | ||
240 | /* 11.025k */ | ||
241 | {11289600, 11025, SSM2602_COEFF_SRATE(0xc, 0x0, 0x0)}, | ||
242 | {16934400, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x0)}, | ||
243 | {12000000, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x1)}, | ||
244 | |||
245 | /* 22.05k */ | ||
246 | {11289600, 22050, SSM2602_COEFF_SRATE(0xd, 0x0, 0x0)}, | ||
247 | {16934400, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x0)}, | ||
248 | {12000000, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x1)}, | ||
249 | |||
240 | /* 44.1k */ | 250 | /* 44.1k */ |
241 | {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, | 251 | {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, |
242 | {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, | 252 | {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, |
@@ -467,7 +477,8 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
467 | return 0; | 477 | return 0; |
468 | } | 478 | } |
469 | 479 | ||
470 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | 480 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
481 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
471 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | 482 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ |
472 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | 483 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ |
473 | SNDRV_PCM_RATE_96000) | 484 | SNDRV_PCM_RATE_96000) |
@@ -502,18 +513,11 @@ static struct snd_soc_dai_driver ssm2602_dai = { | |||
502 | .symmetric_samplebits = 1, | 513 | .symmetric_samplebits = 1, |
503 | }; | 514 | }; |
504 | 515 | ||
505 | static int ssm2602_suspend(struct snd_soc_codec *codec) | ||
506 | { | ||
507 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static int ssm2602_resume(struct snd_soc_codec *codec) | 516 | static int ssm2602_resume(struct snd_soc_codec *codec) |
512 | { | 517 | { |
513 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 518 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
514 | 519 | ||
515 | regcache_sync(ssm2602->regmap); | 520 | regcache_sync(ssm2602->regmap); |
516 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
517 | 521 | ||
518 | return 0; | 522 | return 0; |
519 | } | 523 | } |
@@ -586,27 +590,14 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec) | |||
586 | break; | 590 | break; |
587 | } | 591 | } |
588 | 592 | ||
589 | if (ret) | 593 | return ret; |
590 | return ret; | ||
591 | |||
592 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | /* remove everything here */ | ||
598 | static int ssm2602_remove(struct snd_soc_codec *codec) | ||
599 | { | ||
600 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
601 | return 0; | ||
602 | } | 594 | } |
603 | 595 | ||
604 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { | 596 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { |
605 | .probe = ssm260x_codec_probe, | 597 | .probe = ssm260x_codec_probe, |
606 | .remove = ssm2602_remove, | ||
607 | .suspend = ssm2602_suspend, | ||
608 | .resume = ssm2602_resume, | 598 | .resume = ssm2602_resume, |
609 | .set_bias_level = ssm2602_set_bias_level, | 599 | .set_bias_level = ssm2602_set_bias_level, |
600 | .suspend_bias_off = true, | ||
610 | 601 | ||
611 | .controls = ssm260x_snd_controls, | 602 | .controls = ssm260x_snd_controls, |
612 | .num_controls = ARRAY_SIZE(ssm260x_snd_controls), | 603 | .num_controls = ARRAY_SIZE(ssm260x_snd_controls), |
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c new file mode 100644 index 000000000000..4b5c17f8507e --- /dev/null +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * SSM4567 amplifier audio driver | ||
3 | * | ||
4 | * Copyright 2014 Google Chromium project. | ||
5 | * Author: Anatol Pomozov <anatol@chromium.org> | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * Copyright 2013 Analog Devices Inc. | ||
9 | * | ||
10 | * Licensed under the GPL-2. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/tlv.h> | ||
24 | |||
25 | #define SSM4567_REG_POWER_CTRL 0x00 | ||
26 | #define SSM4567_REG_AMP_SNS_CTRL 0x01 | ||
27 | #define SSM4567_REG_DAC_CTRL 0x02 | ||
28 | #define SSM4567_REG_DAC_VOLUME 0x03 | ||
29 | #define SSM4567_REG_SAI_CTRL_1 0x04 | ||
30 | #define SSM4567_REG_SAI_CTRL_2 0x05 | ||
31 | #define SSM4567_REG_SAI_PLACEMENT_1 0x06 | ||
32 | #define SSM4567_REG_SAI_PLACEMENT_2 0x07 | ||
33 | #define SSM4567_REG_SAI_PLACEMENT_3 0x08 | ||
34 | #define SSM4567_REG_SAI_PLACEMENT_4 0x09 | ||
35 | #define SSM4567_REG_SAI_PLACEMENT_5 0x0a | ||
36 | #define SSM4567_REG_SAI_PLACEMENT_6 0x0b | ||
37 | #define SSM4567_REG_BATTERY_V_OUT 0x0c | ||
38 | #define SSM4567_REG_LIMITER_CTRL_1 0x0d | ||
39 | #define SSM4567_REG_LIMITER_CTRL_2 0x0e | ||
40 | #define SSM4567_REG_LIMITER_CTRL_3 0x0f | ||
41 | #define SSM4567_REG_STATUS_1 0x10 | ||
42 | #define SSM4567_REG_STATUS_2 0x11 | ||
43 | #define SSM4567_REG_FAULT_CTRL 0x12 | ||
44 | #define SSM4567_REG_PDM_CTRL 0x13 | ||
45 | #define SSM4567_REG_MCLK_RATIO 0x14 | ||
46 | #define SSM4567_REG_BOOST_CTRL_1 0x15 | ||
47 | #define SSM4567_REG_BOOST_CTRL_2 0x16 | ||
48 | #define SSM4567_REG_SOFT_RESET 0xff | ||
49 | |||
50 | /* POWER_CTRL */ | ||
51 | #define SSM4567_POWER_APWDN_EN BIT(7) | ||
52 | #define SSM4567_POWER_BSNS_PWDN BIT(6) | ||
53 | #define SSM4567_POWER_VSNS_PWDN BIT(5) | ||
54 | #define SSM4567_POWER_ISNS_PWDN BIT(4) | ||
55 | #define SSM4567_POWER_BOOST_PWDN BIT(3) | ||
56 | #define SSM4567_POWER_AMP_PWDN BIT(2) | ||
57 | #define SSM4567_POWER_VBAT_ONLY BIT(1) | ||
58 | #define SSM4567_POWER_SPWDN BIT(0) | ||
59 | |||
60 | /* DAC_CTRL */ | ||
61 | #define SSM4567_DAC_HV BIT(7) | ||
62 | #define SSM4567_DAC_MUTE BIT(6) | ||
63 | #define SSM4567_DAC_HPF BIT(5) | ||
64 | #define SSM4567_DAC_LPM BIT(4) | ||
65 | #define SSM4567_DAC_FS_MASK 0x7 | ||
66 | #define SSM4567_DAC_FS_8000_12000 0x0 | ||
67 | #define SSM4567_DAC_FS_16000_24000 0x1 | ||
68 | #define SSM4567_DAC_FS_32000_48000 0x2 | ||
69 | #define SSM4567_DAC_FS_64000_96000 0x3 | ||
70 | #define SSM4567_DAC_FS_128000_192000 0x4 | ||
71 | |||
72 | struct ssm4567 { | ||
73 | struct regmap *regmap; | ||
74 | }; | ||
75 | |||
76 | static const struct reg_default ssm4567_reg_defaults[] = { | ||
77 | { SSM4567_REG_POWER_CTRL, 0x81 }, | ||
78 | { SSM4567_REG_AMP_SNS_CTRL, 0x09 }, | ||
79 | { SSM4567_REG_DAC_CTRL, 0x32 }, | ||
80 | { SSM4567_REG_DAC_VOLUME, 0x40 }, | ||
81 | { SSM4567_REG_SAI_CTRL_1, 0x00 }, | ||
82 | { SSM4567_REG_SAI_CTRL_2, 0x08 }, | ||
83 | { SSM4567_REG_SAI_PLACEMENT_1, 0x01 }, | ||
84 | { SSM4567_REG_SAI_PLACEMENT_2, 0x20 }, | ||
85 | { SSM4567_REG_SAI_PLACEMENT_3, 0x32 }, | ||
86 | { SSM4567_REG_SAI_PLACEMENT_4, 0x07 }, | ||
87 | { SSM4567_REG_SAI_PLACEMENT_5, 0x07 }, | ||
88 | { SSM4567_REG_SAI_PLACEMENT_6, 0x07 }, | ||
89 | { SSM4567_REG_BATTERY_V_OUT, 0x00 }, | ||
90 | { SSM4567_REG_LIMITER_CTRL_1, 0xa4 }, | ||
91 | { SSM4567_REG_LIMITER_CTRL_2, 0x73 }, | ||
92 | { SSM4567_REG_LIMITER_CTRL_3, 0x00 }, | ||
93 | { SSM4567_REG_STATUS_1, 0x00 }, | ||
94 | { SSM4567_REG_STATUS_2, 0x00 }, | ||
95 | { SSM4567_REG_FAULT_CTRL, 0x30 }, | ||
96 | { SSM4567_REG_PDM_CTRL, 0x40 }, | ||
97 | { SSM4567_REG_MCLK_RATIO, 0x11 }, | ||
98 | { SSM4567_REG_BOOST_CTRL_1, 0x03 }, | ||
99 | { SSM4567_REG_BOOST_CTRL_2, 0x00 }, | ||
100 | { SSM4567_REG_SOFT_RESET, 0x00 }, | ||
101 | }; | ||
102 | |||
103 | |||
104 | static bool ssm4567_readable_reg(struct device *dev, unsigned int reg) | ||
105 | { | ||
106 | switch (reg) { | ||
107 | case SSM4567_REG_POWER_CTRL ... SSM4567_REG_BOOST_CTRL_2: | ||
108 | return true; | ||
109 | default: | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | } | ||
114 | |||
115 | static bool ssm4567_writeable_reg(struct device *dev, unsigned int reg) | ||
116 | { | ||
117 | switch (reg) { | ||
118 | case SSM4567_REG_POWER_CTRL ... SSM4567_REG_SAI_PLACEMENT_6: | ||
119 | case SSM4567_REG_LIMITER_CTRL_1 ... SSM4567_REG_LIMITER_CTRL_3: | ||
120 | case SSM4567_REG_FAULT_CTRL ... SSM4567_REG_BOOST_CTRL_2: | ||
121 | /* The datasheet states that soft reset register is read-only, | ||
122 | * but logically it is write-only. */ | ||
123 | case SSM4567_REG_SOFT_RESET: | ||
124 | return true; | ||
125 | default: | ||
126 | return false; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static bool ssm4567_volatile_reg(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case SSM4567_REG_BATTERY_V_OUT: | ||
134 | case SSM4567_REG_STATUS_1 ... SSM4567_REG_STATUS_2: | ||
135 | case SSM4567_REG_SOFT_RESET: | ||
136 | return true; | ||
137 | default: | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static const DECLARE_TLV_DB_MINMAX_MUTE(ssm4567_vol_tlv, -7125, 2400); | ||
143 | |||
144 | static const struct snd_kcontrol_new ssm4567_snd_controls[] = { | ||
145 | SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0, | ||
146 | 0xff, 1, ssm4567_vol_tlv), | ||
147 | SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0), | ||
148 | }; | ||
149 | |||
150 | static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = { | ||
151 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1), | ||
152 | |||
153 | SND_SOC_DAPM_OUTPUT("OUT"), | ||
154 | }; | ||
155 | |||
156 | static const struct snd_soc_dapm_route ssm4567_routes[] = { | ||
157 | { "OUT", NULL, "DAC" }, | ||
158 | }; | ||
159 | |||
160 | static int ssm4567_hw_params(struct snd_pcm_substream *substream, | ||
161 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
162 | { | ||
163 | struct snd_soc_codec *codec = dai->codec; | ||
164 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(codec); | ||
165 | unsigned int rate = params_rate(params); | ||
166 | unsigned int dacfs; | ||
167 | |||
168 | if (rate >= 8000 && rate <= 12000) | ||
169 | dacfs = SSM4567_DAC_FS_8000_12000; | ||
170 | else if (rate >= 16000 && rate <= 24000) | ||
171 | dacfs = SSM4567_DAC_FS_16000_24000; | ||
172 | else if (rate >= 32000 && rate <= 48000) | ||
173 | dacfs = SSM4567_DAC_FS_32000_48000; | ||
174 | else if (rate >= 64000 && rate <= 96000) | ||
175 | dacfs = SSM4567_DAC_FS_64000_96000; | ||
176 | else if (rate >= 128000 && rate <= 192000) | ||
177 | dacfs = SSM4567_DAC_FS_128000_192000; | ||
178 | else | ||
179 | return -EINVAL; | ||
180 | |||
181 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL, | ||
182 | SSM4567_DAC_FS_MASK, dacfs); | ||
183 | } | ||
184 | |||
185 | static int ssm4567_mute(struct snd_soc_dai *dai, int mute) | ||
186 | { | ||
187 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(dai->codec); | ||
188 | unsigned int val; | ||
189 | |||
190 | val = mute ? SSM4567_DAC_MUTE : 0; | ||
191 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL, | ||
192 | SSM4567_DAC_MUTE, val); | ||
193 | } | ||
194 | |||
195 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) | ||
196 | { | ||
197 | int ret = 0; | ||
198 | |||
199 | if (!enable) { | ||
200 | ret = regmap_update_bits(ssm4567->regmap, | ||
201 | SSM4567_REG_POWER_CTRL, | ||
202 | SSM4567_POWER_SPWDN, SSM4567_POWER_SPWDN); | ||
203 | regcache_mark_dirty(ssm4567->regmap); | ||
204 | } | ||
205 | |||
206 | regcache_cache_only(ssm4567->regmap, !enable); | ||
207 | |||
208 | if (enable) { | ||
209 | ret = regmap_update_bits(ssm4567->regmap, | ||
210 | SSM4567_REG_POWER_CTRL, | ||
211 | SSM4567_POWER_SPWDN, 0x00); | ||
212 | regcache_sync(ssm4567->regmap); | ||
213 | } | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | ||
219 | enum snd_soc_bias_level level) | ||
220 | { | ||
221 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(codec); | ||
222 | int ret = 0; | ||
223 | |||
224 | switch (level) { | ||
225 | case SND_SOC_BIAS_ON: | ||
226 | break; | ||
227 | case SND_SOC_BIAS_PREPARE: | ||
228 | break; | ||
229 | case SND_SOC_BIAS_STANDBY: | ||
230 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
231 | ret = ssm4567_set_power(ssm4567, true); | ||
232 | break; | ||
233 | case SND_SOC_BIAS_OFF: | ||
234 | ret = ssm4567_set_power(ssm4567, false); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | if (ret) | ||
239 | return ret; | ||
240 | |||
241 | codec->dapm.bias_level = level; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { | ||
247 | .hw_params = ssm4567_hw_params, | ||
248 | .digital_mute = ssm4567_mute, | ||
249 | }; | ||
250 | |||
251 | static struct snd_soc_dai_driver ssm4567_dai = { | ||
252 | .name = "ssm4567-hifi", | ||
253 | .playback = { | ||
254 | .stream_name = "Playback", | ||
255 | .channels_min = 1, | ||
256 | .channels_max = 1, | ||
257 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
258 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
259 | SNDRV_PCM_FMTBIT_S32, | ||
260 | }, | ||
261 | .ops = &ssm4567_dai_ops, | ||
262 | }; | ||
263 | |||
264 | static struct snd_soc_codec_driver ssm4567_codec_driver = { | ||
265 | .set_bias_level = ssm4567_set_bias_level, | ||
266 | .idle_bias_off = true, | ||
267 | |||
268 | .controls = ssm4567_snd_controls, | ||
269 | .num_controls = ARRAY_SIZE(ssm4567_snd_controls), | ||
270 | .dapm_widgets = ssm4567_dapm_widgets, | ||
271 | .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), | ||
272 | .dapm_routes = ssm4567_routes, | ||
273 | .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), | ||
274 | }; | ||
275 | |||
276 | static const struct regmap_config ssm4567_regmap_config = { | ||
277 | .val_bits = 8, | ||
278 | .reg_bits = 8, | ||
279 | |||
280 | .max_register = SSM4567_REG_SOFT_RESET, | ||
281 | .readable_reg = ssm4567_readable_reg, | ||
282 | .writeable_reg = ssm4567_writeable_reg, | ||
283 | .volatile_reg = ssm4567_volatile_reg, | ||
284 | |||
285 | .cache_type = REGCACHE_RBTREE, | ||
286 | .reg_defaults = ssm4567_reg_defaults, | ||
287 | .num_reg_defaults = ARRAY_SIZE(ssm4567_reg_defaults), | ||
288 | }; | ||
289 | |||
290 | static int ssm4567_i2c_probe(struct i2c_client *i2c, | ||
291 | const struct i2c_device_id *id) | ||
292 | { | ||
293 | struct ssm4567 *ssm4567; | ||
294 | int ret; | ||
295 | |||
296 | ssm4567 = devm_kzalloc(&i2c->dev, sizeof(*ssm4567), GFP_KERNEL); | ||
297 | if (ssm4567 == NULL) | ||
298 | return -ENOMEM; | ||
299 | |||
300 | i2c_set_clientdata(i2c, ssm4567); | ||
301 | |||
302 | ssm4567->regmap = devm_regmap_init_i2c(i2c, &ssm4567_regmap_config); | ||
303 | if (IS_ERR(ssm4567->regmap)) | ||
304 | return PTR_ERR(ssm4567->regmap); | ||
305 | |||
306 | ret = regmap_write(ssm4567->regmap, SSM4567_REG_SOFT_RESET, 0x00); | ||
307 | if (ret) | ||
308 | return ret; | ||
309 | |||
310 | ret = ssm4567_set_power(ssm4567, false); | ||
311 | if (ret) | ||
312 | return ret; | ||
313 | |||
314 | return snd_soc_register_codec(&i2c->dev, &ssm4567_codec_driver, | ||
315 | &ssm4567_dai, 1); | ||
316 | } | ||
317 | |||
318 | static int ssm4567_i2c_remove(struct i2c_client *client) | ||
319 | { | ||
320 | snd_soc_unregister_codec(&client->dev); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static const struct i2c_device_id ssm4567_i2c_ids[] = { | ||
325 | { "ssm4567", 0 }, | ||
326 | { } | ||
327 | }; | ||
328 | MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); | ||
329 | |||
330 | static struct i2c_driver ssm4567_driver = { | ||
331 | .driver = { | ||
332 | .name = "ssm4567", | ||
333 | .owner = THIS_MODULE, | ||
334 | }, | ||
335 | .probe = ssm4567_i2c_probe, | ||
336 | .remove = ssm4567_i2c_remove, | ||
337 | .id_table = ssm4567_i2c_ids, | ||
338 | }; | ||
339 | module_i2c_driver(ssm4567_driver); | ||
340 | |||
341 | MODULE_DESCRIPTION("ASoC SSM4567 driver"); | ||
342 | MODULE_AUTHOR("Anatol Pomozov <anatol@chromium.org>"); | ||
343 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 23b32960ff1d..f039dc825971 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c | |||
@@ -78,6 +78,44 @@ struct tas2552_data { | |||
78 | unsigned int mclk; | 78 | unsigned int mclk; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* Input mux controls */ | ||
82 | static const char *tas2552_input_texts[] = { | ||
83 | "Digital", "Analog" | ||
84 | }; | ||
85 | |||
86 | static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, | ||
87 | tas2552_input_texts); | ||
88 | |||
89 | static const struct snd_kcontrol_new tas2552_input_mux_control[] = { | ||
90 | SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum) | ||
91 | }; | ||
92 | |||
93 | static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = | ||
94 | { | ||
95 | SND_SOC_DAPM_INPUT("IN"), | ||
96 | |||
97 | /* MUX Controls */ | ||
98 | SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, | ||
99 | tas2552_input_mux_control), | ||
100 | |||
101 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), | ||
102 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | ||
103 | SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), | ||
104 | SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), | ||
105 | |||
106 | SND_SOC_DAPM_OUTPUT("OUT") | ||
107 | }; | ||
108 | |||
109 | static const struct snd_soc_dapm_route tas2552_audio_map[] = { | ||
110 | {"DAC", NULL, "DAC IN"}, | ||
111 | {"Input selection", "Digital", "DAC"}, | ||
112 | {"Input selection", "Analog", "IN"}, | ||
113 | {"ClassD", NULL, "Input selection"}, | ||
114 | {"OUT", NULL, "ClassD"}, | ||
115 | {"ClassD", NULL, "PLL"}, | ||
116 | }; | ||
117 | |||
118 | #ifdef CONFIG_PM_RUNTIME | ||
81 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | 119 | static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) |
82 | { | 120 | { |
83 | u8 cfg1_reg; | 121 | u8 cfg1_reg; |
@@ -90,6 +128,7 @@ static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) | |||
90 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, | 128 | snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, |
91 | TAS2552_SWS_MASK, cfg1_reg); | 129 | TAS2552_SWS_MASK, cfg1_reg); |
92 | } | 130 | } |
131 | #endif | ||
93 | 132 | ||
94 | static int tas2552_hw_params(struct snd_pcm_substream *substream, | 133 | static int tas2552_hw_params(struct snd_pcm_substream *substream, |
95 | struct snd_pcm_hw_params *params, | 134 | struct snd_pcm_hw_params *params, |
@@ -101,10 +140,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream, | |||
101 | int d; | 140 | int d; |
102 | u8 p, j; | 141 | u8 p, j; |
103 | 142 | ||
104 | /* Turn on Class D amplifier */ | ||
105 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN_MASK, | ||
106 | TAS2552_CLASSD_EN); | ||
107 | |||
108 | if (!tas2552->mclk) | 143 | if (!tas2552->mclk) |
109 | return -EINVAL; | 144 | return -EINVAL; |
110 | 145 | ||
@@ -147,9 +182,6 @@ static int tas2552_hw_params(struct snd_pcm_substream *substream, | |||
147 | 182 | ||
148 | } | 183 | } |
149 | 184 | ||
150 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, | ||
151 | TAS2552_PLL_ENABLE); | ||
152 | |||
153 | return 0; | 185 | return 0; |
154 | } | 186 | } |
155 | 187 | ||
@@ -269,19 +301,10 @@ static const struct dev_pm_ops tas2552_pm = { | |||
269 | NULL) | 301 | NULL) |
270 | }; | 302 | }; |
271 | 303 | ||
272 | static void tas2552_shutdown(struct snd_pcm_substream *substream, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | struct snd_soc_codec *codec = dai->codec; | ||
276 | |||
277 | snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); | ||
278 | } | ||
279 | |||
280 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { | 304 | static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { |
281 | .hw_params = tas2552_hw_params, | 305 | .hw_params = tas2552_hw_params, |
282 | .set_sysclk = tas2552_set_dai_sysclk, | 306 | .set_sysclk = tas2552_set_dai_sysclk, |
283 | .set_fmt = tas2552_set_dai_fmt, | 307 | .set_fmt = tas2552_set_dai_fmt, |
284 | .shutdown = tas2552_shutdown, | ||
285 | .digital_mute = tas2552_mute, | 308 | .digital_mute = tas2552_mute, |
286 | }; | 309 | }; |
287 | 310 | ||
@@ -294,7 +317,7 @@ static struct snd_soc_dai_driver tas2552_dai[] = { | |||
294 | { | 317 | { |
295 | .name = "tas2552-amplifier", | 318 | .name = "tas2552-amplifier", |
296 | .playback = { | 319 | .playback = { |
297 | .stream_name = "Speaker", | 320 | .stream_name = "Playback", |
298 | .channels_min = 2, | 321 | .channels_min = 2, |
299 | .channels_max = 2, | 322 | .channels_max = 2, |
300 | .rates = SNDRV_PCM_RATE_8000_192000, | 323 | .rates = SNDRV_PCM_RATE_8000_192000, |
@@ -312,6 +335,7 @@ static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); | |||
312 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { | 335 | static const struct snd_kcontrol_new tas2552_snd_controls[] = { |
313 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", | 336 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", |
314 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), | 337 | TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), |
338 | SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0), | ||
315 | }; | 339 | }; |
316 | 340 | ||
317 | static const struct reg_default tas2552_init_regs[] = { | 341 | static const struct reg_default tas2552_init_regs[] = { |
@@ -321,6 +345,7 @@ static const struct reg_default tas2552_init_regs[] = { | |||
321 | static int tas2552_codec_probe(struct snd_soc_codec *codec) | 345 | static int tas2552_codec_probe(struct snd_soc_codec *codec) |
322 | { | 346 | { |
323 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); | 347 | struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); |
348 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
324 | int ret; | 349 | int ret; |
325 | 350 | ||
326 | tas2552->codec = codec; | 351 | tas2552->codec = codec; |
@@ -362,9 +387,14 @@ static int tas2552_codec_probe(struct snd_soc_codec *codec) | |||
362 | goto patch_fail; | 387 | goto patch_fail; |
363 | } | 388 | } |
364 | 389 | ||
365 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_CLASSD_EN | | 390 | snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | |
366 | TAS2552_BOOST_EN | TAS2552_APT_EN | | 391 | TAS2552_APT_EN | TAS2552_LIM_EN); |
367 | TAS2552_LIM_EN); | 392 | |
393 | snd_soc_dapm_new_controls(dapm, tas2552_dapm_widgets, | ||
394 | ARRAY_SIZE(tas2552_dapm_widgets)); | ||
395 | snd_soc_dapm_add_routes(dapm, tas2552_audio_map, | ||
396 | ARRAY_SIZE(tas2552_audio_map)); | ||
397 | |||
368 | return 0; | 398 | return 0; |
369 | 399 | ||
370 | patch_fail: | 400 | patch_fail: |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index aea9e1ff9126..145fe5b253d4 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -167,13 +167,13 @@ struct aic31xx_priv { | |||
167 | struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; | 167 | struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; |
168 | struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; | 168 | struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; |
169 | unsigned int sysclk; | 169 | unsigned int sysclk; |
170 | u8 p_div; | ||
170 | int rate_div_line; | 171 | int rate_div_line; |
171 | }; | 172 | }; |
172 | 173 | ||
173 | struct aic31xx_rate_divs { | 174 | struct aic31xx_rate_divs { |
174 | u32 mclk; | 175 | u32 mclk_p; |
175 | u32 rate; | 176 | u32 rate; |
176 | u8 p_val; | ||
177 | u8 pll_j; | 177 | u8 pll_j; |
178 | u16 pll_d; | 178 | u16 pll_d; |
179 | u16 dosr; | 179 | u16 dosr; |
@@ -186,62 +186,51 @@ struct aic31xx_rate_divs { | |||
186 | 186 | ||
187 | /* ADC dividers can be disabled by cofiguring them to 0 */ | 187 | /* ADC dividers can be disabled by cofiguring them to 0 */ |
188 | static const struct aic31xx_rate_divs aic31xx_divs[] = { | 188 | static const struct aic31xx_rate_divs aic31xx_divs[] = { |
189 | /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */ | 189 | /* mclk/p rate pll: j d dosr ndac mdac aors nadc madc */ |
190 | /* 8k rate */ | 190 | /* 8k rate */ |
191 | {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2}, | 191 | {12000000, 8000, 8, 1920, 128, 48, 2, 128, 48, 2}, |
192 | {12000000, 8000, 1, 8, 1920, 128, 32, 3, 128, 32, 3}, | 192 | {12000000, 8000, 8, 1920, 128, 32, 3, 128, 32, 3}, |
193 | {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2}, | 193 | {12500000, 8000, 7, 8643, 128, 48, 2, 128, 48, 2}, |
194 | {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2}, | ||
195 | /* 11.025k rate */ | 194 | /* 11.025k rate */ |
196 | {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2}, | 195 | {12000000, 11025, 7, 5264, 128, 32, 2, 128, 32, 2}, |
197 | {12000000, 11025, 1, 8, 4672, 128, 24, 3, 128, 24, 3}, | 196 | {12000000, 11025, 8, 4672, 128, 24, 3, 128, 24, 3}, |
198 | {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2}, | 197 | {12500000, 11025, 7, 2253, 128, 32, 2, 128, 32, 2}, |
199 | {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2}, | ||
200 | /* 16k rate */ | 198 | /* 16k rate */ |
201 | {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2}, | 199 | {12000000, 16000, 8, 1920, 128, 24, 2, 128, 24, 2}, |
202 | {12000000, 16000, 1, 8, 1920, 128, 16, 3, 128, 16, 3}, | 200 | {12000000, 16000, 8, 1920, 128, 16, 3, 128, 16, 3}, |
203 | {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2}, | 201 | {12500000, 16000, 7, 8643, 128, 24, 2, 128, 24, 2}, |
204 | {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2}, | ||
205 | /* 22.05k rate */ | 202 | /* 22.05k rate */ |
206 | {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2}, | 203 | {12000000, 22050, 7, 5264, 128, 16, 2, 128, 16, 2}, |
207 | {12000000, 22050, 1, 8, 4672, 128, 12, 3, 128, 12, 3}, | 204 | {12000000, 22050, 8, 4672, 128, 12, 3, 128, 12, 3}, |
208 | {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2}, | 205 | {12500000, 22050, 7, 2253, 128, 16, 2, 128, 16, 2}, |
209 | {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2}, | ||
210 | /* 32k rate */ | 206 | /* 32k rate */ |
211 | {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2}, | 207 | {12000000, 32000, 8, 1920, 128, 12, 2, 128, 12, 2}, |
212 | {12000000, 32000, 1, 8, 1920, 128, 8, 3, 128, 8, 3}, | 208 | {12000000, 32000, 8, 1920, 128, 8, 3, 128, 8, 3}, |
213 | {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2}, | 209 | {12500000, 32000, 7, 8643, 128, 12, 2, 128, 12, 2}, |
214 | {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2}, | ||
215 | /* 44.1k rate */ | 210 | /* 44.1k rate */ |
216 | {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2}, | 211 | {12000000, 44100, 7, 5264, 128, 8, 2, 128, 8, 2}, |
217 | {12000000, 44100, 1, 8, 4672, 128, 6, 3, 128, 6, 3}, | 212 | {12000000, 44100, 8, 4672, 128, 6, 3, 128, 6, 3}, |
218 | {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2}, | 213 | {12500000, 44100, 7, 2253, 128, 8, 2, 128, 8, 2}, |
219 | {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2}, | ||
220 | /* 48k rate */ | 214 | /* 48k rate */ |
221 | {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2}, | 215 | {12000000, 48000, 8, 1920, 128, 8, 2, 128, 8, 2}, |
222 | {12000000, 48000, 1, 7, 6800, 96, 5, 4, 96, 5, 4}, | 216 | {12000000, 48000, 7, 6800, 96, 5, 4, 96, 5, 4}, |
223 | {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2}, | 217 | {12500000, 48000, 7, 8643, 128, 8, 2, 128, 8, 2}, |
224 | {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2}, | ||
225 | /* 88.2k rate */ | 218 | /* 88.2k rate */ |
226 | {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2}, | 219 | {12000000, 88200, 7, 5264, 64, 8, 2, 64, 8, 2}, |
227 | {12000000, 88200, 1, 8, 4672, 64, 6, 3, 64, 6, 3}, | 220 | {12000000, 88200, 8, 4672, 64, 6, 3, 64, 6, 3}, |
228 | {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2}, | 221 | {12500000, 88200, 7, 2253, 64, 8, 2, 64, 8, 2}, |
229 | {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2}, | ||
230 | /* 96k rate */ | 222 | /* 96k rate */ |
231 | {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2}, | 223 | {12000000, 96000, 8, 1920, 64, 8, 2, 64, 8, 2}, |
232 | {12000000, 96000, 1, 7, 6800, 48, 5, 4, 48, 5, 4}, | 224 | {12000000, 96000, 7, 6800, 48, 5, 4, 48, 5, 4}, |
233 | {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2}, | 225 | {12500000, 96000, 7, 8643, 64, 8, 2, 64, 8, 2}, |
234 | {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2}, | ||
235 | /* 176.4k rate */ | 226 | /* 176.4k rate */ |
236 | {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2}, | 227 | {12000000, 176400, 7, 5264, 32, 8, 2, 32, 8, 2}, |
237 | {12000000, 176400, 1, 8, 4672, 32, 6, 3, 32, 6, 3}, | 228 | {12000000, 176400, 8, 4672, 32, 6, 3, 32, 6, 3}, |
238 | {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2}, | 229 | {12500000, 176400, 7, 2253, 32, 8, 2, 32, 8, 2}, |
239 | {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2}, | ||
240 | /* 192k rate */ | 230 | /* 192k rate */ |
241 | {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2}, | 231 | {12000000, 192000, 8, 1920, 32, 8, 2, 32, 8, 2}, |
242 | {12000000, 192000, 1, 7, 6800, 24, 5, 4, 24, 5, 4}, | 232 | {12000000, 192000, 7, 6800, 24, 5, 4, 24, 5, 4}, |
243 | {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2}, | 233 | {12500000, 192000, 7, 8643, 32, 8, 2, 32, 8, 2}, |
244 | {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2}, | ||
245 | }; | 234 | }; |
246 | 235 | ||
247 | static const char * const ldac_in_text[] = { | 236 | static const char * const ldac_in_text[] = { |
@@ -692,6 +681,7 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec, | |||
692 | { | 681 | { |
693 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 682 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
694 | int bclk_score = snd_soc_params_to_frame_size(params); | 683 | int bclk_score = snd_soc_params_to_frame_size(params); |
684 | int mclk_p = aic31xx->sysclk / aic31xx->p_div; | ||
695 | int bclk_n = 0; | 685 | int bclk_n = 0; |
696 | int match = -1; | 686 | int match = -1; |
697 | int i; | 687 | int i; |
@@ -704,7 +694,7 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec, | |||
704 | 694 | ||
705 | for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { | 695 | for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { |
706 | if (aic31xx_divs[i].rate == params_rate(params) && | 696 | if (aic31xx_divs[i].rate == params_rate(params) && |
707 | aic31xx_divs[i].mclk == aic31xx->sysclk) { | 697 | aic31xx_divs[i].mclk_p == mclk_p) { |
708 | int s = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) % | 698 | int s = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) % |
709 | snd_soc_params_to_frame_size(params); | 699 | snd_soc_params_to_frame_size(params); |
710 | int bn = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) / | 700 | int bn = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) / |
@@ -738,7 +728,7 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec, | |||
738 | 728 | ||
739 | /* PLL configuration */ | 729 | /* PLL configuration */ |
740 | snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, | 730 | snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, |
741 | (aic31xx_divs[i].p_val << 4) | 0x01); | 731 | (aic31xx->p_div << 4) | 0x01); |
742 | snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); | 732 | snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); |
743 | 733 | ||
744 | snd_soc_write(codec, AIC31XX_PLLDMSB, | 734 | snd_soc_write(codec, AIC31XX_PLLDMSB, |
@@ -772,7 +762,7 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec, | |||
772 | dev_dbg(codec->dev, | 762 | dev_dbg(codec->dev, |
773 | "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", | 763 | "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", |
774 | aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, | 764 | aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, |
775 | aic31xx_divs[i].p_val, aic31xx_divs[i].dosr, | 765 | aic31xx->p_div, aic31xx_divs[i].dosr, |
776 | aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, | 766 | aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, |
777 | aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, | 767 | aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, |
778 | aic31xx_divs[i].madc, bclk_n); | 768 | aic31xx_divs[i].madc, bclk_n); |
@@ -840,7 +830,7 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
840 | { | 830 | { |
841 | struct snd_soc_codec *codec = codec_dai->codec; | 831 | struct snd_soc_codec *codec = codec_dai->codec; |
842 | u8 iface_reg1 = 0; | 832 | u8 iface_reg1 = 0; |
843 | u8 iface_reg3 = 0; | 833 | u8 iface_reg2 = 0; |
844 | u8 dsp_a_val = 0; | 834 | u8 dsp_a_val = 0; |
845 | 835 | ||
846 | dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); | 836 | dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); |
@@ -865,7 +855,7 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
865 | /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ | 855 | /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ |
866 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 856 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
867 | case SND_SOC_DAIFMT_NB_NF: | 857 | case SND_SOC_DAIFMT_NB_NF: |
868 | iface_reg3 |= AIC31XX_BCLKINV_MASK; | 858 | iface_reg2 |= AIC31XX_BCLKINV_MASK; |
869 | break; | 859 | break; |
870 | case SND_SOC_DAIFMT_IB_NF: | 860 | case SND_SOC_DAIFMT_IB_NF: |
871 | break; | 861 | break; |
@@ -897,7 +887,7 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
897 | dsp_a_val); | 887 | dsp_a_val); |
898 | snd_soc_update_bits(codec, AIC31XX_IFACE2, | 888 | snd_soc_update_bits(codec, AIC31XX_IFACE2, |
899 | AIC31XX_BCLKINV_MASK, | 889 | AIC31XX_BCLKINV_MASK, |
900 | iface_reg3); | 890 | iface_reg2); |
901 | 891 | ||
902 | return 0; | 892 | return 0; |
903 | } | 893 | } |
@@ -912,7 +902,16 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
912 | dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", | 902 | dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", |
913 | __func__, clk_id, freq, dir); | 903 | __func__, clk_id, freq, dir); |
914 | 904 | ||
915 | for (i = 0; aic31xx_divs[i].mclk != freq; i++) { | 905 | for (i = 1; freq/i > 20000000 && i < 8; i++) |
906 | ; | ||
907 | if (freq/i > 20000000) { | ||
908 | dev_err(aic31xx->dev, "%s: Too high mclk frequency %u\n", | ||
909 | __func__, freq); | ||
910 | return -EINVAL; | ||
911 | } | ||
912 | aic31xx->p_div = i; | ||
913 | |||
914 | for (i = 0; aic31xx_divs[i].mclk_p != freq/aic31xx->p_div; i++) { | ||
916 | if (i == ARRAY_SIZE(aic31xx_divs)) { | 915 | if (i == ARRAY_SIZE(aic31xx_divs)) { |
917 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", | 916 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", |
918 | __func__, freq); | 917 | __func__, freq); |
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index 52ed57c69dfa..fe16c34607bb 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h | |||
@@ -18,7 +18,8 @@ | |||
18 | #define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 | 18 | #define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 |
19 | 19 | ||
20 | #define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | 20 | #define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ |
21 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | 21 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE \ |
22 | | SNDRV_PCM_FMTBIT_S32_LE) | ||
22 | 23 | ||
23 | 24 | ||
24 | #define AIC31XX_STEREO_CLASS_D_BIT 0x1 | 25 | #define AIC31XX_STEREO_CLASS_D_BIT 0x1 |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 64f179ee9834..f7c2a575a892 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -1121,6 +1121,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, | |||
1121 | static int aic3x_set_power(struct snd_soc_codec *codec, int power) | 1121 | static int aic3x_set_power(struct snd_soc_codec *codec, int power) |
1122 | { | 1122 | { |
1123 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1123 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1124 | unsigned int pll_c, pll_d; | ||
1124 | int ret; | 1125 | int ret; |
1125 | 1126 | ||
1126 | if (power) { | 1127 | if (power) { |
@@ -1138,6 +1139,18 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1138 | /* Sync reg_cache with the hardware */ | 1139 | /* Sync reg_cache with the hardware */ |
1139 | regcache_cache_only(aic3x->regmap, false); | 1140 | regcache_cache_only(aic3x->regmap, false); |
1140 | regcache_sync(aic3x->regmap); | 1141 | regcache_sync(aic3x->regmap); |
1142 | |||
1143 | /* Rewrite paired PLL D registers in case cached sync skipped | ||
1144 | * writing one of them and thus caused other one also not | ||
1145 | * being written | ||
1146 | */ | ||
1147 | pll_c = snd_soc_read(codec, AIC3X_PLL_PROGC_REG); | ||
1148 | pll_d = snd_soc_read(codec, AIC3X_PLL_PROGD_REG); | ||
1149 | if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || | ||
1150 | pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { | ||
1151 | snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c); | ||
1152 | snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d); | ||
1153 | } | ||
1141 | } else { | 1154 | } else { |
1142 | /* | 1155 | /* |
1143 | * Do soft reset to this codec instance in order to clear | 1156 | * Do soft reset to this codec instance in order to clear |
@@ -1222,20 +1235,6 @@ static struct snd_soc_dai_driver aic3x_dai = { | |||
1222 | .symmetric_rates = 1, | 1235 | .symmetric_rates = 1, |
1223 | }; | 1236 | }; |
1224 | 1237 | ||
1225 | static int aic3x_suspend(struct snd_soc_codec *codec) | ||
1226 | { | ||
1227 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1228 | |||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | static int aic3x_resume(struct snd_soc_codec *codec) | ||
1233 | { | ||
1234 | aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1235 | |||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | static void aic3x_mono_init(struct snd_soc_codec *codec) | 1238 | static void aic3x_mono_init(struct snd_soc_codec *codec) |
1240 | { | 1239 | { |
1241 | /* DAC to Mono Line Out default volume and route to Output mixer */ | 1240 | /* DAC to Mono Line Out default volume and route to Output mixer */ |
@@ -1429,8 +1428,6 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { | |||
1429 | .idle_bias_off = true, | 1428 | .idle_bias_off = true, |
1430 | .probe = aic3x_probe, | 1429 | .probe = aic3x_probe, |
1431 | .remove = aic3x_remove, | 1430 | .remove = aic3x_remove, |
1432 | .suspend = aic3x_suspend, | ||
1433 | .resume = aic3x_resume, | ||
1434 | .controls = aic3x_snd_controls, | 1431 | .controls = aic3x_snd_controls, |
1435 | .num_controls = ARRAY_SIZE(aic3x_snd_controls), | 1432 | .num_controls = ARRAY_SIZE(aic3x_snd_controls), |
1436 | .dapm_widgets = aic3x_dapm_widgets, | 1433 | .dapm_widgets = aic3x_dapm_widgets, |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 3dfdcc4197fa..628ec774cf22 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -212,7 +212,7 @@ static void wm8350_pga_work(struct work_struct *work) | |||
212 | { | 212 | { |
213 | struct snd_soc_dapm_context *dapm = | 213 | struct snd_soc_dapm_context *dapm = |
214 | container_of(work, struct snd_soc_dapm_context, delayed_work.work); | 214 | container_of(work, struct snd_soc_dapm_context, delayed_work.work); |
215 | struct snd_soc_codec *codec = dapm->codec; | 215 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
216 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | 216 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); |
217 | struct wm8350_output *out1 = &wm8350_data->out1, | 217 | struct wm8350_output *out1 = &wm8350_data->out1, |
218 | *out2 = &wm8350_data->out2; | 218 | *out2 = &wm8350_data->out2; |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index a237f1627f61..31bb4801a005 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -413,7 +413,6 @@ static int wm8741_resume(struct snd_soc_codec *codec) | |||
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | #else | 415 | #else |
416 | #define wm8741_suspend NULL | ||
417 | #define wm8741_resume NULL | 416 | #define wm8741_resume NULL |
418 | #endif | 417 | #endif |
419 | 418 | ||
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index e54e097f4fcb..21ca3a94fc96 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -1433,7 +1433,7 @@ static void wm8753_work(struct work_struct *work) | |||
1433 | struct snd_soc_dapm_context *dapm = | 1433 | struct snd_soc_dapm_context *dapm = |
1434 | container_of(work, struct snd_soc_dapm_context, | 1434 | container_of(work, struct snd_soc_dapm_context, |
1435 | delayed_work.work); | 1435 | delayed_work.work); |
1436 | struct snd_soc_codec *codec = dapm->codec; | 1436 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
1437 | wm8753_set_bias_level(codec, dapm->bias_level); | 1437 | wm8753_set_bias_level(codec, dapm->bias_level); |
1438 | } | 1438 | } |
1439 | 1439 | ||
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 0ea01dfcb6e1..3addc5fe5cb2 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -518,23 +518,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec, | |||
518 | return 0; | 518 | return 0; |
519 | } | 519 | } |
520 | 520 | ||
521 | #ifdef CONFIG_PM | ||
522 | static int wm8804_suspend(struct snd_soc_codec *codec) | ||
523 | { | ||
524 | wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int wm8804_resume(struct snd_soc_codec *codec) | ||
529 | { | ||
530 | wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
531 | return 0; | ||
532 | } | ||
533 | #else | ||
534 | #define wm8804_suspend NULL | ||
535 | #define wm8804_resume NULL | ||
536 | #endif | ||
537 | |||
538 | static int wm8804_remove(struct snd_soc_codec *codec) | 521 | static int wm8804_remove(struct snd_soc_codec *codec) |
539 | { | 522 | { |
540 | struct wm8804_priv *wm8804; | 523 | struct wm8804_priv *wm8804; |
@@ -671,8 +654,6 @@ static struct snd_soc_dai_driver wm8804_dai = { | |||
671 | static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { | 654 | static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { |
672 | .probe = wm8804_probe, | 655 | .probe = wm8804_probe, |
673 | .remove = wm8804_remove, | 656 | .remove = wm8804_remove, |
674 | .suspend = wm8804_suspend, | ||
675 | .resume = wm8804_resume, | ||
676 | .set_bias_level = wm8804_set_bias_level, | 657 | .set_bias_level = wm8804_set_bias_level, |
677 | .idle_bias_off = true, | 658 | .idle_bias_off = true, |
678 | 659 | ||
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 0499cd4cfb71..39ddb9b8834c 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -615,7 +615,7 @@ static void wm8971_work(struct work_struct *work) | |||
615 | struct snd_soc_dapm_context *dapm = | 615 | struct snd_soc_dapm_context *dapm = |
616 | container_of(work, struct snd_soc_dapm_context, | 616 | container_of(work, struct snd_soc_dapm_context, |
617 | delayed_work.work); | 617 | delayed_work.work); |
618 | struct snd_soc_codec *codec = dapm->codec; | 618 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); |
619 | wm8971_set_bias_level(codec, codec->dapm.bias_level); | 619 | wm8971_set_bias_level(codec, codec->dapm.bias_level); |
620 | } | 620 | } |
621 | 621 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6cc0566dc29a..1fcb9f3f3097 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -4082,17 +4082,23 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
4082 | 4082 | ||
4083 | switch (control->type) { | 4083 | switch (control->type) { |
4084 | case WM8994: | 4084 | case WM8994: |
4085 | if (wm8994->micdet_irq) { | 4085 | if (wm8994->micdet_irq) |
4086 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, | 4086 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
4087 | wm8994_mic_irq, | 4087 | wm8994_mic_irq, |
4088 | IRQF_TRIGGER_RISING, | 4088 | IRQF_TRIGGER_RISING, |
4089 | "Mic1 detect", | 4089 | "Mic1 detect", |
4090 | wm8994); | 4090 | wm8994); |
4091 | if (ret != 0) | 4091 | else |
4092 | dev_warn(codec->dev, | 4092 | ret = wm8994_request_irq(wm8994->wm8994, |
4093 | "Failed to request Mic1 detect IRQ: %d\n", | 4093 | WM8994_IRQ_MIC1_DET, |
4094 | ret); | 4094 | wm8994_mic_irq, "Mic 1 detect", |
4095 | } | 4095 | wm8994); |
4096 | |||
4097 | if (ret != 0) | ||
4098 | dev_warn(codec->dev, | ||
4099 | "Failed to request Mic1 detect IRQ: %d\n", | ||
4100 | ret); | ||
4101 | |||
4096 | 4102 | ||
4097 | ret = wm8994_request_irq(wm8994->wm8994, | 4103 | ret = wm8994_request_irq(wm8994->wm8994, |
4098 | WM8994_IRQ_MIC1_SHRT, | 4104 | WM8994_IRQ_MIC1_SHRT, |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index cae4ac5a5730..1288edeb8c7d 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -1998,23 +1998,6 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, | |||
1998 | return 0; | 1998 | return 0; |
1999 | } | 1999 | } |
2000 | 2000 | ||
2001 | #ifdef CONFIG_PM | ||
2002 | static int wm8995_suspend(struct snd_soc_codec *codec) | ||
2003 | { | ||
2004 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2005 | return 0; | ||
2006 | } | ||
2007 | |||
2008 | static int wm8995_resume(struct snd_soc_codec *codec) | ||
2009 | { | ||
2010 | wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2011 | return 0; | ||
2012 | } | ||
2013 | #else | ||
2014 | #define wm8995_suspend NULL | ||
2015 | #define wm8995_resume NULL | ||
2016 | #endif | ||
2017 | |||
2018 | static int wm8995_remove(struct snd_soc_codec *codec) | 2001 | static int wm8995_remove(struct snd_soc_codec *codec) |
2019 | { | 2002 | { |
2020 | struct wm8995_priv *wm8995; | 2003 | struct wm8995_priv *wm8995; |
@@ -2220,8 +2203,6 @@ static struct snd_soc_dai_driver wm8995_dai[] = { | |||
2220 | static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { | 2203 | static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { |
2221 | .probe = wm8995_probe, | 2204 | .probe = wm8995_probe, |
2222 | .remove = wm8995_remove, | 2205 | .remove = wm8995_remove, |
2223 | .suspend = wm8995_suspend, | ||
2224 | .resume = wm8995_resume, | ||
2225 | .set_bias_level = wm8995_set_bias_level, | 2206 | .set_bias_level = wm8995_set_bias_level, |
2226 | .idle_bias_off = true, | 2207 | .idle_bias_off = true, |
2227 | }; | 2208 | }; |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index d69510c53239..8e948c63f3d9 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -63,7 +63,8 @@ config SND_DM365_AIC3X_CODEC | |||
63 | Say Y if you want to add support for AIC3101 audio codec | 63 | Say Y if you want to add support for AIC3101 audio codec |
64 | 64 | ||
65 | config SND_DM365_VOICE_CODEC | 65 | config SND_DM365_VOICE_CODEC |
66 | bool "Voice Codec - CQ93VC" | 66 | tristate "Voice Codec - CQ93VC" |
67 | depends on SND_DAVINCI_SOC | ||
67 | select MFD_DAVINCI_VOICECODEC | 68 | select MFD_DAVINCI_VOICECODEC |
68 | select SND_DAVINCI_SOC_VCIF | 69 | select SND_DAVINCI_SOC_VCIF |
69 | select SND_SOC_CQ0093VC | 70 | select SND_SOC_CQ0093VC |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 68347b55f6e1..0eed9b1b24e1 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -42,14 +42,26 @@ | |||
42 | 42 | ||
43 | #define MCASP_MAX_AFIFO_DEPTH 64 | 43 | #define MCASP_MAX_AFIFO_DEPTH 64 |
44 | 44 | ||
45 | static u32 context_regs[] = { | ||
46 | DAVINCI_MCASP_TXFMCTL_REG, | ||
47 | DAVINCI_MCASP_RXFMCTL_REG, | ||
48 | DAVINCI_MCASP_TXFMT_REG, | ||
49 | DAVINCI_MCASP_RXFMT_REG, | ||
50 | DAVINCI_MCASP_ACLKXCTL_REG, | ||
51 | DAVINCI_MCASP_ACLKRCTL_REG, | ||
52 | DAVINCI_MCASP_AHCLKXCTL_REG, | ||
53 | DAVINCI_MCASP_AHCLKRCTL_REG, | ||
54 | DAVINCI_MCASP_PDIR_REG, | ||
55 | DAVINCI_MCASP_RXMASK_REG, | ||
56 | DAVINCI_MCASP_TXMASK_REG, | ||
57 | DAVINCI_MCASP_RXTDM_REG, | ||
58 | DAVINCI_MCASP_TXTDM_REG, | ||
59 | }; | ||
60 | |||
45 | struct davinci_mcasp_context { | 61 | struct davinci_mcasp_context { |
46 | u32 txfmtctl; | 62 | u32 config_regs[ARRAY_SIZE(context_regs)]; |
47 | u32 rxfmtctl; | 63 | u32 afifo_regs[2]; /* for read/write fifo control registers */ |
48 | u32 txfmt; | 64 | u32 *xrsr_regs; /* for serializer configuration */ |
49 | u32 rxfmt; | ||
50 | u32 aclkxctl; | ||
51 | u32 aclkrctl; | ||
52 | u32 pdir; | ||
53 | }; | 65 | }; |
54 | 66 | ||
55 | struct davinci_mcasp { | 67 | struct davinci_mcasp { |
@@ -874,14 +886,24 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai) | |||
874 | { | 886 | { |
875 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | 887 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
876 | struct davinci_mcasp_context *context = &mcasp->context; | 888 | struct davinci_mcasp_context *context = &mcasp->context; |
889 | u32 reg; | ||
890 | int i; | ||
891 | |||
892 | for (i = 0; i < ARRAY_SIZE(context_regs); i++) | ||
893 | context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); | ||
894 | |||
895 | if (mcasp->txnumevt) { | ||
896 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; | ||
897 | context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); | ||
898 | } | ||
899 | if (mcasp->rxnumevt) { | ||
900 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; | ||
901 | context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); | ||
902 | } | ||
877 | 903 | ||
878 | context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); | 904 | for (i = 0; i < mcasp->num_serializer; i++) |
879 | context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); | 905 | context->xrsr_regs[i] = mcasp_get_reg(mcasp, |
880 | context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); | 906 | DAVINCI_MCASP_XRSRCTL_REG(i)); |
881 | context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); | ||
882 | context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); | ||
883 | context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); | ||
884 | context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); | ||
885 | 907 | ||
886 | return 0; | 908 | return 0; |
887 | } | 909 | } |
@@ -890,14 +912,24 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai) | |||
890 | { | 912 | { |
891 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | 913 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
892 | struct davinci_mcasp_context *context = &mcasp->context; | 914 | struct davinci_mcasp_context *context = &mcasp->context; |
915 | u32 reg; | ||
916 | int i; | ||
917 | |||
918 | for (i = 0; i < ARRAY_SIZE(context_regs); i++) | ||
919 | mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); | ||
920 | |||
921 | if (mcasp->txnumevt) { | ||
922 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; | ||
923 | mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); | ||
924 | } | ||
925 | if (mcasp->rxnumevt) { | ||
926 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; | ||
927 | mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); | ||
928 | } | ||
893 | 929 | ||
894 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); | 930 | for (i = 0; i < mcasp->num_serializer; i++) |
895 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); | 931 | mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), |
896 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); | 932 | context->xrsr_regs[i]); |
897 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt); | ||
898 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl); | ||
899 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl); | ||
900 | mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir); | ||
901 | 933 | ||
902 | return 0; | 934 | return 0; |
903 | } | 935 | } |
@@ -1216,6 +1248,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1216 | mcasp->op_mode = pdata->op_mode; | 1248 | mcasp->op_mode = pdata->op_mode; |
1217 | mcasp->tdm_slots = pdata->tdm_slots; | 1249 | mcasp->tdm_slots = pdata->tdm_slots; |
1218 | mcasp->num_serializer = pdata->num_serializer; | 1250 | mcasp->num_serializer = pdata->num_serializer; |
1251 | #ifdef CONFIG_PM_SLEEP | ||
1252 | mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev, | ||
1253 | sizeof(u32) * mcasp->num_serializer, | ||
1254 | GFP_KERNEL); | ||
1255 | #endif | ||
1219 | mcasp->serial_dir = pdata->serial_dir; | 1256 | mcasp->serial_dir = pdata->serial_dir; |
1220 | mcasp->version = pdata->version; | 1257 | mcasp->version = pdata->version; |
1221 | mcasp->txnumevt = pdata->txnumevt; | 1258 | mcasp->txnumevt = pdata->txnumevt; |
diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c index 605e643133db..59e588abe54b 100644 --- a/sound/soc/davinci/edma-pcm.c +++ b/sound/soc/davinci/edma-pcm.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <sound/dmaengine_pcm.h> | 25 | #include <sound/dmaengine_pcm.h> |
26 | #include <linux/edma.h> | 26 | #include <linux/edma.h> |
27 | 27 | ||
28 | #include "edma-pcm.h" | ||
29 | |||
28 | static const struct snd_pcm_hardware edma_pcm_hardware = { | 30 | static const struct snd_pcm_hardware edma_pcm_hardware = { |
29 | .info = SNDRV_PCM_INFO_MMAP | | 31 | .info = SNDRV_PCM_INFO_MMAP | |
30 | SNDRV_PCM_INFO_MMAP_VALID | | 32 | SNDRV_PCM_INFO_MMAP_VALID | |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index f3012b645b51..081e406b3713 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -240,6 +240,18 @@ config SND_SOC_IMX_WM8962 | |||
240 | Say Y if you want to add support for SoC audio on an i.MX board with | 240 | Say Y if you want to add support for SoC audio on an i.MX board with |
241 | a wm8962 codec. | 241 | a wm8962 codec. |
242 | 242 | ||
243 | config SND_SOC_IMX_ES8328 | ||
244 | tristate "SoC Audio support for i.MX boards with the ES8328 codec" | ||
245 | depends on OF && (I2C || SPI) | ||
246 | select SND_SOC_ES8328_I2C if I2C | ||
247 | select SND_SOC_ES8328_SPI if SPI_MASTER | ||
248 | select SND_SOC_IMX_PCM_DMA | ||
249 | select SND_SOC_IMX_AUDMUX | ||
250 | select SND_SOC_FSL_SSI | ||
251 | help | ||
252 | Say Y if you want to add support for the ES8328 audio codec connected | ||
253 | via SSI/I2S over either SPI or I2C. | ||
254 | |||
243 | config SND_SOC_IMX_SGTL5000 | 255 | config SND_SOC_IMX_SGTL5000 |
244 | tristate "SoC Audio support for i.MX boards with sgtl5000" | 256 | tristate "SoC Audio support for i.MX boards with sgtl5000" |
245 | depends on OF && I2C | 257 | depends on OF && I2C |
@@ -268,6 +280,20 @@ config SND_SOC_IMX_MC13783 | |||
268 | select SND_SOC_MC13783 | 280 | select SND_SOC_MC13783 |
269 | select SND_SOC_IMX_PCM_DMA | 281 | select SND_SOC_IMX_PCM_DMA |
270 | 282 | ||
283 | config SND_SOC_FSL_ASOC_CARD | ||
284 | tristate "Generic ASoC Sound Card with ASRC support" | ||
285 | depends on OF && I2C | ||
286 | select SND_SOC_IMX_AUDMUX | ||
287 | select SND_SOC_IMX_PCM_DMA | ||
288 | select SND_SOC_FSL_ESAI | ||
289 | select SND_SOC_FSL_SAI | ||
290 | select SND_SOC_FSL_SSI | ||
291 | help | ||
292 | ALSA SoC Audio support with ASRC feature for Freescale SoCs that have | ||
293 | ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888 | ||
294 | and SGTL5000. | ||
295 | Say Y if you want to add support for Freescale Generic ASoC Sound Card. | ||
296 | |||
271 | endif # SND_IMX_SOC | 297 | endif # SND_IMX_SOC |
272 | 298 | ||
273 | endmenu | 299 | endmenu |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 9ff59267eac9..d28dc25c9375 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o | |||
11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o | 11 | obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o |
12 | 12 | ||
13 | # Freescale SSI/DMA/SAI/SPDIF Support | 13 | # Freescale SSI/DMA/SAI/SPDIF Support |
14 | snd-soc-fsl-asoc-card-objs := fsl-asoc-card.o | ||
14 | snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o | 15 | snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o |
15 | snd-soc-fsl-sai-objs := fsl_sai.o | 16 | snd-soc-fsl-sai-objs := fsl_sai.o |
16 | snd-soc-fsl-ssi-y := fsl_ssi.o | 17 | snd-soc-fsl-ssi-y := fsl_ssi.o |
@@ -19,6 +20,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o | |||
19 | snd-soc-fsl-esai-objs := fsl_esai.o | 20 | snd-soc-fsl-esai-objs := fsl_esai.o |
20 | snd-soc-fsl-utils-objs := fsl_utils.o | 21 | snd-soc-fsl-utils-objs := fsl_utils.o |
21 | snd-soc-fsl-dma-objs := fsl_dma.o | 22 | snd-soc-fsl-dma-objs := fsl_dma.o |
23 | obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o | ||
22 | obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o | 24 | obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o |
23 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o | 25 | obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o |
24 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o | 26 | obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o |
@@ -50,6 +52,7 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | |||
50 | snd-soc-phycore-ac97-objs := phycore-ac97.o | 52 | snd-soc-phycore-ac97-objs := phycore-ac97.o |
51 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | 53 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o |
52 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 54 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
55 | snd-soc-imx-es8328-objs := imx-es8328.o | ||
53 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o | 56 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o |
54 | snd-soc-imx-wm8962-objs := imx-wm8962.o | 57 | snd-soc-imx-wm8962-objs := imx-wm8962.o |
55 | snd-soc-imx-spdif-objs := imx-spdif.o | 58 | snd-soc-imx-spdif-objs := imx-spdif.o |
@@ -59,6 +62,7 @@ obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | |||
59 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o | 62 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o |
60 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | 63 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o |
61 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 64 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
65 | obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o | ||
62 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o | 66 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o |
63 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o | 67 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o |
64 | obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o | 68 | obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o |
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c new file mode 100644 index 000000000000..007c772f3cef --- /dev/null +++ b/sound/soc/fsl/fsl-asoc-card.c | |||
@@ -0,0 +1,574 @@ | |||
1 | /* | ||
2 | * Freescale Generic ASoC Sound Card driver with ASRC | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <nicoleotsuka@gmail.com> | ||
7 | * | ||
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 | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #include "fsl_esai.h" | ||
21 | #include "fsl_sai.h" | ||
22 | #include "imx-audmux.h" | ||
23 | |||
24 | #include "../codecs/sgtl5000.h" | ||
25 | #include "../codecs/wm8962.h" | ||
26 | |||
27 | #define RX 0 | ||
28 | #define TX 1 | ||
29 | |||
30 | /* Default DAI format without Master and Slave flag */ | ||
31 | #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF) | ||
32 | |||
33 | /** | ||
34 | * CODEC private data | ||
35 | * | ||
36 | * @mclk_freq: Clock rate of MCLK | ||
37 | * @mclk_id: MCLK (or main clock) id for set_sysclk() | ||
38 | * @fll_id: FLL (or secordary clock) id for set_sysclk() | ||
39 | * @pll_id: PLL id for set_pll() | ||
40 | */ | ||
41 | struct codec_priv { | ||
42 | unsigned long mclk_freq; | ||
43 | u32 mclk_id; | ||
44 | u32 fll_id; | ||
45 | u32 pll_id; | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * CPU private data | ||
50 | * | ||
51 | * @sysclk_freq[2]: SYSCLK rates for set_sysclk() | ||
52 | * @sysclk_dir[2]: SYSCLK directions for set_sysclk() | ||
53 | * @sysclk_id[2]: SYSCLK ids for set_sysclk() | ||
54 | * | ||
55 | * Note: [1] for tx and [0] for rx | ||
56 | */ | ||
57 | struct cpu_priv { | ||
58 | unsigned long sysclk_freq[2]; | ||
59 | u32 sysclk_dir[2]; | ||
60 | u32 sysclk_id[2]; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * Freescale Generic ASOC card private data | ||
65 | * | ||
66 | * @dai_link[3]: DAI link structure including normal one and DPCM link | ||
67 | * @pdev: platform device pointer | ||
68 | * @codec_priv: CODEC private data | ||
69 | * @cpu_priv: CPU private data | ||
70 | * @card: ASoC card structure | ||
71 | * @sample_rate: Current sample rate | ||
72 | * @sample_format: Current sample format | ||
73 | * @asrc_rate: ASRC sample rate used by Back-Ends | ||
74 | * @asrc_format: ASRC sample format used by Back-Ends | ||
75 | * @dai_fmt: DAI format between CPU and CODEC | ||
76 | * @name: Card name | ||
77 | */ | ||
78 | |||
79 | struct fsl_asoc_card_priv { | ||
80 | struct snd_soc_dai_link dai_link[3]; | ||
81 | struct platform_device *pdev; | ||
82 | struct codec_priv codec_priv; | ||
83 | struct cpu_priv cpu_priv; | ||
84 | struct snd_soc_card card; | ||
85 | u32 sample_rate; | ||
86 | u32 sample_format; | ||
87 | u32 asrc_rate; | ||
88 | u32 asrc_format; | ||
89 | u32 dai_fmt; | ||
90 | char name[32]; | ||
91 | }; | ||
92 | |||
93 | /** | ||
94 | * This dapm route map exsits for DPCM link only. | ||
95 | * The other routes shall go through Device Tree. | ||
96 | */ | ||
97 | static const struct snd_soc_dapm_route audio_map[] = { | ||
98 | {"CPU-Playback", NULL, "ASRC-Playback"}, | ||
99 | {"Playback", NULL, "CPU-Playback"}, | ||
100 | {"ASRC-Capture", NULL, "CPU-Capture"}, | ||
101 | {"CPU-Capture", NULL, "Capture"}, | ||
102 | }; | ||
103 | |||
104 | /* Add all possible widgets into here without being redundant */ | ||
105 | static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { | ||
106 | SND_SOC_DAPM_LINE("Line Out Jack", NULL), | ||
107 | SND_SOC_DAPM_LINE("Line In Jack", NULL), | ||
108 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
109 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
110 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
111 | SND_SOC_DAPM_MIC("AMIC", NULL), | ||
112 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
113 | }; | ||
114 | |||
115 | static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, | ||
116 | struct snd_pcm_hw_params *params) | ||
117 | { | ||
118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
119 | struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
120 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
121 | struct cpu_priv *cpu_priv = &priv->cpu_priv; | ||
122 | struct device *dev = rtd->card->dev; | ||
123 | int ret; | ||
124 | |||
125 | priv->sample_rate = params_rate(params); | ||
126 | priv->sample_format = params_format(params); | ||
127 | |||
128 | if (priv->card.set_bias_level) | ||
129 | return 0; | ||
130 | |||
131 | /* Specific configurations of DAIs starts from here */ | ||
132 | ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, cpu_priv->sysclk_id[tx], | ||
133 | cpu_priv->sysclk_freq[tx], | ||
134 | cpu_priv->sysclk_dir[tx]); | ||
135 | if (ret) { | ||
136 | dev_err(dev, "failed to set sysclk for cpu dai\n"); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static struct snd_soc_ops fsl_asoc_card_ops = { | ||
144 | .hw_params = fsl_asoc_card_hw_params, | ||
145 | }; | ||
146 | |||
147 | static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | ||
148 | struct snd_pcm_hw_params *params) | ||
149 | { | ||
150 | struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
151 | struct snd_interval *rate; | ||
152 | struct snd_mask *mask; | ||
153 | |||
154 | rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
155 | rate->max = rate->min = priv->asrc_rate; | ||
156 | |||
157 | mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
158 | snd_mask_none(mask); | ||
159 | snd_mask_set(mask, priv->asrc_format); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static struct snd_soc_dai_link fsl_asoc_card_dai[] = { | ||
165 | /* Default ASoC DAI Link*/ | ||
166 | { | ||
167 | .name = "HiFi", | ||
168 | .stream_name = "HiFi", | ||
169 | .ops = &fsl_asoc_card_ops, | ||
170 | }, | ||
171 | /* DPCM Link between Front-End and Back-End (Optional) */ | ||
172 | { | ||
173 | .name = "HiFi-ASRC-FE", | ||
174 | .stream_name = "HiFi-ASRC-FE", | ||
175 | .codec_name = "snd-soc-dummy", | ||
176 | .codec_dai_name = "snd-soc-dummy-dai", | ||
177 | .dpcm_playback = 1, | ||
178 | .dpcm_capture = 1, | ||
179 | .dynamic = 1, | ||
180 | }, | ||
181 | { | ||
182 | .name = "HiFi-ASRC-BE", | ||
183 | .stream_name = "HiFi-ASRC-BE", | ||
184 | .platform_name = "snd-soc-dummy", | ||
185 | .be_hw_params_fixup = be_hw_params_fixup, | ||
186 | .ops = &fsl_asoc_card_ops, | ||
187 | .dpcm_playback = 1, | ||
188 | .dpcm_capture = 1, | ||
189 | .no_pcm = 1, | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | static int fsl_asoc_card_set_bias_level(struct snd_soc_card *card, | ||
194 | struct snd_soc_dapm_context *dapm, | ||
195 | enum snd_soc_bias_level level) | ||
196 | { | ||
197 | struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); | ||
198 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
199 | struct codec_priv *codec_priv = &priv->codec_priv; | ||
200 | struct device *dev = card->dev; | ||
201 | unsigned int pll_out; | ||
202 | int ret; | ||
203 | |||
204 | if (dapm->dev != codec_dai->dev) | ||
205 | return 0; | ||
206 | |||
207 | switch (level) { | ||
208 | case SND_SOC_BIAS_PREPARE: | ||
209 | if (dapm->bias_level != SND_SOC_BIAS_STANDBY) | ||
210 | break; | ||
211 | |||
212 | if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) | ||
213 | pll_out = priv->sample_rate * 384; | ||
214 | else | ||
215 | pll_out = priv->sample_rate * 256; | ||
216 | |||
217 | ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id, | ||
218 | codec_priv->mclk_id, | ||
219 | codec_priv->mclk_freq, pll_out); | ||
220 | if (ret) { | ||
221 | dev_err(dev, "failed to start FLL: %d\n", ret); | ||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->fll_id, | ||
226 | pll_out, SND_SOC_CLOCK_IN); | ||
227 | if (ret) { | ||
228 | dev_err(dev, "failed to set SYSCLK: %d\n", ret); | ||
229 | return ret; | ||
230 | } | ||
231 | break; | ||
232 | |||
233 | case SND_SOC_BIAS_STANDBY: | ||
234 | if (dapm->bias_level != SND_SOC_BIAS_PREPARE) | ||
235 | break; | ||
236 | |||
237 | ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, | ||
238 | codec_priv->mclk_freq, | ||
239 | SND_SOC_CLOCK_IN); | ||
240 | if (ret) { | ||
241 | dev_err(dev, "failed to switch away from FLL: %d\n", ret); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id, 0, 0, 0); | ||
246 | if (ret) { | ||
247 | dev_err(dev, "failed to stop FLL: %d\n", ret); | ||
248 | return ret; | ||
249 | } | ||
250 | break; | ||
251 | |||
252 | default: | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int fsl_asoc_card_audmux_init(struct device_node *np, | ||
260 | struct fsl_asoc_card_priv *priv) | ||
261 | { | ||
262 | struct device *dev = &priv->pdev->dev; | ||
263 | u32 int_ptcr = 0, ext_ptcr = 0; | ||
264 | int int_port, ext_port; | ||
265 | int ret; | ||
266 | |||
267 | ret = of_property_read_u32(np, "mux-int-port", &int_port); | ||
268 | if (ret) { | ||
269 | dev_err(dev, "mux-int-port missing or invalid\n"); | ||
270 | return ret; | ||
271 | } | ||
272 | ret = of_property_read_u32(np, "mux-ext-port", &ext_port); | ||
273 | if (ret) { | ||
274 | dev_err(dev, "mux-ext-port missing or invalid\n"); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * The port numbering in the hardware manual starts at 1, while | ||
280 | * the AUDMUX API expects it starts at 0. | ||
281 | */ | ||
282 | int_port--; | ||
283 | ext_port--; | ||
284 | |||
285 | /* | ||
286 | * Use asynchronous mode (6 wires) for all cases. | ||
287 | * If only 4 wires are needed, just set SSI into | ||
288 | * synchronous mode and enable 4 PADs in IOMUX. | ||
289 | */ | ||
290 | switch (priv->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
291 | case SND_SOC_DAIFMT_CBM_CFM: | ||
292 | int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) | | ||
293 | IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) | | ||
294 | IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | | ||
295 | IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | | ||
296 | IMX_AUDMUX_V2_PTCR_RFSDIR | | ||
297 | IMX_AUDMUX_V2_PTCR_RCLKDIR | | ||
298 | IMX_AUDMUX_V2_PTCR_TFSDIR | | ||
299 | IMX_AUDMUX_V2_PTCR_TCLKDIR; | ||
300 | break; | ||
301 | case SND_SOC_DAIFMT_CBM_CFS: | ||
302 | int_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) | | ||
303 | IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | | ||
304 | IMX_AUDMUX_V2_PTCR_RCLKDIR | | ||
305 | IMX_AUDMUX_V2_PTCR_TCLKDIR; | ||
306 | ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) | | ||
307 | IMX_AUDMUX_V2_PTCR_TFSEL(int_port) | | ||
308 | IMX_AUDMUX_V2_PTCR_RFSDIR | | ||
309 | IMX_AUDMUX_V2_PTCR_TFSDIR; | ||
310 | break; | ||
311 | case SND_SOC_DAIFMT_CBS_CFM: | ||
312 | int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) | | ||
313 | IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | | ||
314 | IMX_AUDMUX_V2_PTCR_RFSDIR | | ||
315 | IMX_AUDMUX_V2_PTCR_TFSDIR; | ||
316 | ext_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) | | ||
317 | IMX_AUDMUX_V2_PTCR_TCSEL(int_port) | | ||
318 | IMX_AUDMUX_V2_PTCR_RCLKDIR | | ||
319 | IMX_AUDMUX_V2_PTCR_TCLKDIR; | ||
320 | break; | ||
321 | case SND_SOC_DAIFMT_CBS_CFS: | ||
322 | ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) | | ||
323 | IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) | | ||
324 | IMX_AUDMUX_V2_PTCR_TFSEL(int_port) | | ||
325 | IMX_AUDMUX_V2_PTCR_TCSEL(int_port) | | ||
326 | IMX_AUDMUX_V2_PTCR_RFSDIR | | ||
327 | IMX_AUDMUX_V2_PTCR_RCLKDIR | | ||
328 | IMX_AUDMUX_V2_PTCR_TFSDIR | | ||
329 | IMX_AUDMUX_V2_PTCR_TCLKDIR; | ||
330 | break; | ||
331 | default: | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | |||
335 | /* Asynchronous mode can not be set along with RCLKDIR */ | ||
336 | ret = imx_audmux_v2_configure_port(int_port, 0, | ||
337 | IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); | ||
338 | if (ret) { | ||
339 | dev_err(dev, "audmux internal port setup failed\n"); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | ret = imx_audmux_v2_configure_port(int_port, int_ptcr, | ||
344 | IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); | ||
345 | if (ret) { | ||
346 | dev_err(dev, "audmux internal port setup failed\n"); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | ret = imx_audmux_v2_configure_port(ext_port, 0, | ||
351 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | ||
352 | if (ret) { | ||
353 | dev_err(dev, "audmux external port setup failed\n"); | ||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | ret = imx_audmux_v2_configure_port(ext_port, ext_ptcr, | ||
358 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | ||
359 | if (ret) { | ||
360 | dev_err(dev, "audmux external port setup failed\n"); | ||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int fsl_asoc_card_late_probe(struct snd_soc_card *card) | ||
368 | { | ||
369 | struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); | ||
370 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
371 | struct codec_priv *codec_priv = &priv->codec_priv; | ||
372 | struct device *dev = card->dev; | ||
373 | int ret; | ||
374 | |||
375 | ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, | ||
376 | codec_priv->mclk_freq, SND_SOC_CLOCK_IN); | ||
377 | if (ret) { | ||
378 | dev_err(dev, "failed to set sysclk in %s\n", __func__); | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int fsl_asoc_card_probe(struct platform_device *pdev) | ||
386 | { | ||
387 | struct device_node *cpu_np, *codec_np, *asrc_np; | ||
388 | struct device_node *np = pdev->dev.of_node; | ||
389 | struct platform_device *asrc_pdev = NULL; | ||
390 | struct platform_device *cpu_pdev; | ||
391 | struct fsl_asoc_card_priv *priv; | ||
392 | struct i2c_client *codec_dev; | ||
393 | struct clk *codec_clk; | ||
394 | u32 width; | ||
395 | int ret; | ||
396 | |||
397 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
398 | if (!priv) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | cpu_np = of_parse_phandle(np, "audio-cpu", 0); | ||
402 | /* Give a chance to old DT binding */ | ||
403 | if (!cpu_np) | ||
404 | cpu_np = of_parse_phandle(np, "ssi-controller", 0); | ||
405 | codec_np = of_parse_phandle(np, "audio-codec", 0); | ||
406 | if (!cpu_np || !codec_np) { | ||
407 | dev_err(&pdev->dev, "phandle missing or invalid\n"); | ||
408 | ret = -EINVAL; | ||
409 | goto fail; | ||
410 | } | ||
411 | |||
412 | cpu_pdev = of_find_device_by_node(cpu_np); | ||
413 | if (!cpu_pdev) { | ||
414 | dev_err(&pdev->dev, "failed to find CPU DAI device\n"); | ||
415 | ret = -EINVAL; | ||
416 | goto fail; | ||
417 | } | ||
418 | |||
419 | codec_dev = of_find_i2c_device_by_node(codec_np); | ||
420 | if (!codec_dev) { | ||
421 | dev_err(&pdev->dev, "failed to find codec platform device\n"); | ||
422 | ret = -EINVAL; | ||
423 | goto fail; | ||
424 | } | ||
425 | |||
426 | asrc_np = of_parse_phandle(np, "audio-asrc", 0); | ||
427 | if (asrc_np) | ||
428 | asrc_pdev = of_find_device_by_node(asrc_np); | ||
429 | |||
430 | /* Get the MCLK rate only, and leave it controlled by CODEC drivers */ | ||
431 | codec_clk = clk_get(&codec_dev->dev, NULL); | ||
432 | if (!IS_ERR(codec_clk)) { | ||
433 | priv->codec_priv.mclk_freq = clk_get_rate(codec_clk); | ||
434 | clk_put(codec_clk); | ||
435 | } | ||
436 | |||
437 | /* Default sample rate and format, will be updated in hw_params() */ | ||
438 | priv->sample_rate = 44100; | ||
439 | priv->sample_format = SNDRV_PCM_FORMAT_S16_LE; | ||
440 | |||
441 | /* Assign a default DAI format, and allow each card to overwrite it */ | ||
442 | priv->dai_fmt = DAI_FMT_BASE; | ||
443 | |||
444 | /* Diversify the card configurations */ | ||
445 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { | ||
446 | priv->card.set_bias_level = NULL; | ||
447 | priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq; | ||
448 | priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq; | ||
449 | priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT; | ||
450 | priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT; | ||
451 | priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; | ||
452 | } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { | ||
453 | priv->codec_priv.mclk_id = SGTL5000_SYSCLK; | ||
454 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
455 | } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { | ||
456 | priv->card.set_bias_level = fsl_asoc_card_set_bias_level; | ||
457 | priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; | ||
458 | priv->codec_priv.fll_id = WM8962_SYSCLK_FLL; | ||
459 | priv->codec_priv.pll_id = WM8962_FLL; | ||
460 | priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
461 | } else { | ||
462 | dev_err(&pdev->dev, "unknown Device Tree compatible\n"); | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | |||
466 | /* Common settings for corresponding Freescale CPU DAI driver */ | ||
467 | if (strstr(cpu_np->name, "ssi")) { | ||
468 | /* Only SSI needs to configure AUDMUX */ | ||
469 | ret = fsl_asoc_card_audmux_init(np, priv); | ||
470 | if (ret) { | ||
471 | dev_err(&pdev->dev, "failed to init audmux\n"); | ||
472 | goto asrc_fail; | ||
473 | } | ||
474 | } else if (strstr(cpu_np->name, "esai")) { | ||
475 | priv->cpu_priv.sysclk_id[1] = ESAI_HCKT_EXTAL; | ||
476 | priv->cpu_priv.sysclk_id[0] = ESAI_HCKR_EXTAL; | ||
477 | } else if (strstr(cpu_np->name, "sai")) { | ||
478 | priv->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1; | ||
479 | priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; | ||
480 | } | ||
481 | |||
482 | sprintf(priv->name, "%s-audio", codec_dev->name); | ||
483 | |||
484 | /* Initialize sound card */ | ||
485 | priv->pdev = pdev; | ||
486 | priv->card.dev = &pdev->dev; | ||
487 | priv->card.name = priv->name; | ||
488 | priv->card.dai_link = priv->dai_link; | ||
489 | priv->card.dapm_routes = audio_map; | ||
490 | priv->card.late_probe = fsl_asoc_card_late_probe; | ||
491 | priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); | ||
492 | priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; | ||
493 | priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets); | ||
494 | |||
495 | memcpy(priv->dai_link, fsl_asoc_card_dai, | ||
496 | sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); | ||
497 | |||
498 | /* Normal DAI Link */ | ||
499 | priv->dai_link[0].cpu_of_node = cpu_np; | ||
500 | priv->dai_link[0].codec_of_node = codec_np; | ||
501 | priv->dai_link[0].codec_dai_name = codec_dev->name; | ||
502 | priv->dai_link[0].platform_of_node = cpu_np; | ||
503 | priv->dai_link[0].dai_fmt = priv->dai_fmt; | ||
504 | priv->card.num_links = 1; | ||
505 | |||
506 | if (asrc_pdev) { | ||
507 | /* DPCM DAI Links only if ASRC exsits */ | ||
508 | priv->dai_link[1].cpu_of_node = asrc_np; | ||
509 | priv->dai_link[1].platform_of_node = asrc_np; | ||
510 | priv->dai_link[2].codec_dai_name = codec_dev->name; | ||
511 | priv->dai_link[2].codec_of_node = codec_np; | ||
512 | priv->dai_link[2].cpu_of_node = cpu_np; | ||
513 | priv->dai_link[2].dai_fmt = priv->dai_fmt; | ||
514 | priv->card.num_links = 3; | ||
515 | |||
516 | ret = of_property_read_u32(asrc_np, "fsl,asrc-rate", | ||
517 | &priv->asrc_rate); | ||
518 | if (ret) { | ||
519 | dev_err(&pdev->dev, "failed to get output rate\n"); | ||
520 | ret = -EINVAL; | ||
521 | goto asrc_fail; | ||
522 | } | ||
523 | |||
524 | ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width); | ||
525 | if (ret) { | ||
526 | dev_err(&pdev->dev, "failed to get output rate\n"); | ||
527 | ret = -EINVAL; | ||
528 | goto asrc_fail; | ||
529 | } | ||
530 | |||
531 | if (width == 24) | ||
532 | priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE; | ||
533 | else | ||
534 | priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE; | ||
535 | } | ||
536 | |||
537 | /* Finish card registering */ | ||
538 | platform_set_drvdata(pdev, priv); | ||
539 | snd_soc_card_set_drvdata(&priv->card, priv); | ||
540 | |||
541 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); | ||
542 | if (ret) | ||
543 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | ||
544 | |||
545 | asrc_fail: | ||
546 | of_node_put(asrc_np); | ||
547 | fail: | ||
548 | of_node_put(codec_np); | ||
549 | of_node_put(cpu_np); | ||
550 | |||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | static const struct of_device_id fsl_asoc_card_dt_ids[] = { | ||
555 | { .compatible = "fsl,imx-audio-cs42888", }, | ||
556 | { .compatible = "fsl,imx-audio-sgtl5000", }, | ||
557 | { .compatible = "fsl,imx-audio-wm8962", }, | ||
558 | {} | ||
559 | }; | ||
560 | |||
561 | static struct platform_driver fsl_asoc_card_driver = { | ||
562 | .probe = fsl_asoc_card_probe, | ||
563 | .driver = { | ||
564 | .name = "fsl-asoc-card", | ||
565 | .pm = &snd_soc_pm_ops, | ||
566 | .of_match_table = fsl_asoc_card_dt_ids, | ||
567 | }, | ||
568 | }; | ||
569 | module_platform_driver(fsl_asoc_card_driver); | ||
570 | |||
571 | MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC"); | ||
572 | MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>"); | ||
573 | MODULE_ALIAS("platform:fsl-asoc-card"); | ||
574 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 822110420b71..3b145313f93e 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -684,7 +684,7 @@ static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg) | |||
684 | } | 684 | } |
685 | } | 685 | } |
686 | 686 | ||
687 | static struct regmap_config fsl_asrc_regmap_config = { | 687 | static const struct regmap_config fsl_asrc_regmap_config = { |
688 | .reg_bits = 32, | 688 | .reg_bits = 32, |
689 | .reg_stride = 4, | 689 | .reg_stride = 4, |
690 | .val_bits = 32, | 690 | .val_bits = 32, |
@@ -802,10 +802,6 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
802 | 802 | ||
803 | asrc_priv->paddr = res->start; | 803 | asrc_priv->paddr = res->start; |
804 | 804 | ||
805 | /* Register regmap and let it prepare core clock */ | ||
806 | if (of_property_read_bool(np, "big-endian")) | ||
807 | fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
808 | |||
809 | asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, | 805 | asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, |
810 | &fsl_asrc_regmap_config); | 806 | &fsl_asrc_regmap_config); |
811 | if (IS_ERR(asrc_priv->regmap)) { | 807 | if (IS_ERR(asrc_priv->regmap)) { |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index a3b29ed84963..8bcdfda09d7a 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -37,6 +37,7 @@ | |||
37 | * @fsysclk: system clock source to derive HCK, SCK and FS | 37 | * @fsysclk: system clock source to derive HCK, SCK and FS |
38 | * @fifo_depth: depth of tx/rx FIFO | 38 | * @fifo_depth: depth of tx/rx FIFO |
39 | * @slot_width: width of each DAI slot | 39 | * @slot_width: width of each DAI slot |
40 | * @slots: number of slots | ||
40 | * @hck_rate: clock rate of desired HCKx clock | 41 | * @hck_rate: clock rate of desired HCKx clock |
41 | * @sck_rate: clock rate of desired SCKx clock | 42 | * @sck_rate: clock rate of desired SCKx clock |
42 | * @hck_dir: the direction of HCKx pads | 43 | * @hck_dir: the direction of HCKx pads |
@@ -55,6 +56,7 @@ struct fsl_esai { | |||
55 | struct clk *fsysclk; | 56 | struct clk *fsysclk; |
56 | u32 fifo_depth; | 57 | u32 fifo_depth; |
57 | u32 slot_width; | 58 | u32 slot_width; |
59 | u32 slots; | ||
58 | u32 hck_rate[2]; | 60 | u32 hck_rate[2]; |
59 | u32 sck_rate[2]; | 61 | u32 sck_rate[2]; |
60 | bool hck_dir[2]; | 62 | bool hck_dir[2]; |
@@ -362,6 +364,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, | |||
362 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask)); | 364 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask)); |
363 | 365 | ||
364 | esai_priv->slot_width = slot_width; | 366 | esai_priv->slot_width = slot_width; |
367 | esai_priv->slots = slots; | ||
365 | 368 | ||
366 | return 0; | 369 | return 0; |
367 | } | 370 | } |
@@ -509,10 +512,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | |||
509 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 512 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
510 | u32 width = snd_pcm_format_width(params_format(params)); | 513 | u32 width = snd_pcm_format_width(params_format(params)); |
511 | u32 channels = params_channels(params); | 514 | u32 channels = params_channels(params); |
515 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); | ||
512 | u32 bclk, mask, val; | 516 | u32 bclk, mask, val; |
513 | int ret; | 517 | int ret; |
514 | 518 | ||
515 | bclk = params_rate(params) * esai_priv->slot_width * 2; | 519 | bclk = params_rate(params) * esai_priv->slot_width * esai_priv->slots; |
516 | 520 | ||
517 | ret = fsl_esai_set_bclk(dai, tx, bclk); | 521 | ret = fsl_esai_set_bclk(dai, tx, bclk); |
518 | if (ret) | 522 | if (ret) |
@@ -529,7 +533,7 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | |||
529 | mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK | | 533 | mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK | |
530 | (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK); | 534 | (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK); |
531 | val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) | | 535 | val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) | |
532 | (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels)); | 536 | (tx ? ESAI_xFCR_TE(pins) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(pins)); |
533 | 537 | ||
534 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); | 538 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); |
535 | 539 | ||
@@ -564,6 +568,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
564 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | 568 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); |
565 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 569 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
566 | u8 i, channels = substream->runtime->channels; | 570 | u8 i, channels = substream->runtime->channels; |
571 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); | ||
567 | 572 | ||
568 | switch (cmd) { | 573 | switch (cmd) { |
569 | case SNDRV_PCM_TRIGGER_START: | 574 | case SNDRV_PCM_TRIGGER_START: |
@@ -578,7 +583,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
578 | 583 | ||
579 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | 584 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), |
580 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, | 585 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, |
581 | tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels)); | 586 | tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); |
582 | break; | 587 | break; |
583 | case SNDRV_PCM_TRIGGER_SUSPEND: | 588 | case SNDRV_PCM_TRIGGER_SUSPEND: |
584 | case SNDRV_PCM_TRIGGER_STOP: | 589 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -705,7 +710,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) | |||
705 | } | 710 | } |
706 | } | 711 | } |
707 | 712 | ||
708 | static struct regmap_config fsl_esai_regmap_config = { | 713 | static const struct regmap_config fsl_esai_regmap_config = { |
709 | .reg_bits = 32, | 714 | .reg_bits = 32, |
710 | .reg_stride = 4, | 715 | .reg_stride = 4, |
711 | .val_bits = 32, | 716 | .val_bits = 32, |
@@ -731,9 +736,6 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
731 | esai_priv->pdev = pdev; | 736 | esai_priv->pdev = pdev; |
732 | strcpy(esai_priv->name, np->name); | 737 | strcpy(esai_priv->name, np->name); |
733 | 738 | ||
734 | if (of_property_read_bool(np, "big-endian")) | ||
735 | fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
736 | |||
737 | /* Get the addresses and IRQ */ | 739 | /* Get the addresses and IRQ */ |
738 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 740 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
739 | regs = devm_ioremap_resource(&pdev->dev, res); | 741 | regs = devm_ioremap_resource(&pdev->dev, res); |
@@ -781,6 +783,9 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
781 | /* Set a default slot size */ | 783 | /* Set a default slot size */ |
782 | esai_priv->slot_width = 32; | 784 | esai_priv->slot_width = 32; |
783 | 785 | ||
786 | /* Set a default slot number */ | ||
787 | esai_priv->slots = 2; | ||
788 | |||
784 | /* Set a default master/slave state */ | 789 | /* Set a default master/slave state */ |
785 | esai_priv->slave_mode = true; | 790 | esai_priv->slave_mode = true; |
786 | 791 | ||
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h index 75e14033e8d8..91a550f4a10d 100644 --- a/sound/soc/fsl/fsl_esai.h +++ b/sound/soc/fsl/fsl_esai.h | |||
@@ -130,8 +130,8 @@ | |||
130 | #define ESAI_xFCR_RE_WIDTH 4 | 130 | #define ESAI_xFCR_RE_WIDTH 4 |
131 | #define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) | 131 | #define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) |
132 | #define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) | 132 | #define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) |
133 | #define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_TE_MASK) | 133 | #define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - x)) & ESAI_xFCR_TE_MASK) |
134 | #define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_RE_MASK) | 134 | #define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - x)) & ESAI_xFCR_RE_MASK) |
135 | #define ESAI_xFCR_xFR_SHIFT 1 | 135 | #define ESAI_xFCR_xFR_SHIFT 1 |
136 | #define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT) | 136 | #define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT) |
137 | #define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT) | 137 | #define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT) |
@@ -272,8 +272,8 @@ | |||
272 | #define ESAI_xCR_RE_WIDTH 4 | 272 | #define ESAI_xCR_RE_WIDTH 4 |
273 | #define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) | 273 | #define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) |
274 | #define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) | 274 | #define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) |
275 | #define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_TE_MASK) | 275 | #define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - x)) & ESAI_xCR_TE_MASK) |
276 | #define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_RE_MASK) | 276 | #define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - x)) & ESAI_xCR_RE_MASK) |
277 | 277 | ||
278 | /* | 278 | /* |
279 | * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8 | 279 | * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8 |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index faa049797897..7eeb1dd8ce27 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -175,7 +175,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
175 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; | 175 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; |
176 | u32 val_cr2 = 0, val_cr4 = 0; | 176 | u32 val_cr2 = 0, val_cr4 = 0; |
177 | 177 | ||
178 | if (!sai->big_endian_data) | 178 | if (!sai->is_lsb_first) |
179 | val_cr4 |= FSL_SAI_CR4_MF; | 179 | val_cr4 |= FSL_SAI_CR4_MF; |
180 | 180 | ||
181 | /* DAI mode */ | 181 | /* DAI mode */ |
@@ -304,7 +304,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
304 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); | 304 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); |
305 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); | 305 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); |
306 | 306 | ||
307 | if (sai->big_endian_data) | 307 | if (sai->is_lsb_first) |
308 | val_cr5 |= FSL_SAI_CR5_FBT(0); | 308 | val_cr5 |= FSL_SAI_CR5_FBT(0); |
309 | else | 309 | else |
310 | val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); | 310 | val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); |
@@ -330,13 +330,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
330 | u32 xcsr, count = 100; | 330 | u32 xcsr, count = 100; |
331 | 331 | ||
332 | /* | 332 | /* |
333 | * The transmitter bit clock and frame sync are to be | 333 | * Asynchronous mode: Clear SYNC for both Tx and Rx. |
334 | * used by both the transmitter and receiver. | 334 | * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx. |
335 | * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx. | ||
335 | */ | 336 | */ |
336 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, | 337 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, 0); |
337 | ~FSL_SAI_CR2_SYNC); | ||
338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, | 338 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, |
339 | FSL_SAI_CR2_SYNC); | 339 | sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0); |
340 | 340 | ||
341 | /* | 341 | /* |
342 | * It is recommended that the transmitter is the last enabled | 342 | * It is recommended that the transmitter is the last enabled |
@@ -437,8 +437,13 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | |||
437 | { | 437 | { |
438 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); | 438 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); |
439 | 439 | ||
440 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0); | 440 | /* Software Reset for both Tx and Rx */ |
441 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0); | 441 | regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); |
442 | regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); | ||
443 | /* Clear SR bit to finish the reset */ | ||
444 | regmap_write(sai->regmap, FSL_SAI_TCSR, 0); | ||
445 | regmap_write(sai->regmap, FSL_SAI_RCSR, 0); | ||
446 | |||
442 | regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, | 447 | regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, |
443 | FSL_SAI_MAXBURST_TX * 2); | 448 | FSL_SAI_MAXBURST_TX * 2); |
444 | regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, | 449 | regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, |
@@ -539,7 +544,7 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) | |||
539 | } | 544 | } |
540 | } | 545 | } |
541 | 546 | ||
542 | static struct regmap_config fsl_sai_regmap_config = { | 547 | static const struct regmap_config fsl_sai_regmap_config = { |
543 | .reg_bits = 32, | 548 | .reg_bits = 32, |
544 | .reg_stride = 4, | 549 | .reg_stride = 4, |
545 | .val_bits = 32, | 550 | .val_bits = 32, |
@@ -568,11 +573,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
568 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx6sx-sai")) | 573 | if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx6sx-sai")) |
569 | sai->sai_on_imx = true; | 574 | sai->sai_on_imx = true; |
570 | 575 | ||
571 | sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); | 576 | sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); |
572 | if (sai->big_endian_regs) | ||
573 | fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
574 | |||
575 | sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); | ||
576 | 577 | ||
577 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 578 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
578 | base = devm_ioremap_resource(&pdev->dev, res); | 579 | base = devm_ioremap_resource(&pdev->dev, res); |
@@ -621,6 +622,33 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
621 | return ret; | 622 | return ret; |
622 | } | 623 | } |
623 | 624 | ||
625 | /* Sync Tx with Rx as default by following old DT binding */ | ||
626 | sai->synchronous[RX] = true; | ||
627 | sai->synchronous[TX] = false; | ||
628 | fsl_sai_dai.symmetric_rates = 1; | ||
629 | fsl_sai_dai.symmetric_channels = 1; | ||
630 | fsl_sai_dai.symmetric_samplebits = 1; | ||
631 | |||
632 | if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && | ||
633 | of_find_property(np, "fsl,sai-asynchronous", NULL)) { | ||
634 | /* error out if both synchronous and asynchronous are present */ | ||
635 | dev_err(&pdev->dev, "invalid binding for synchronous mode\n"); | ||
636 | return -EINVAL; | ||
637 | } | ||
638 | |||
639 | if (of_find_property(np, "fsl,sai-synchronous-rx", NULL)) { | ||
640 | /* Sync Rx with Tx */ | ||
641 | sai->synchronous[RX] = false; | ||
642 | sai->synchronous[TX] = true; | ||
643 | } else if (of_find_property(np, "fsl,sai-asynchronous", NULL)) { | ||
644 | /* Discard all settings for asynchronous mode */ | ||
645 | sai->synchronous[RX] = false; | ||
646 | sai->synchronous[TX] = false; | ||
647 | fsl_sai_dai.symmetric_rates = 0; | ||
648 | fsl_sai_dai.symmetric_channels = 0; | ||
649 | fsl_sai_dai.symmetric_samplebits = 0; | ||
650 | } | ||
651 | |||
624 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; | 652 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; |
625 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; | 653 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; |
626 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; | 654 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 0e6c9f595d75..34667209b607 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -48,6 +48,7 @@ | |||
48 | /* SAI Transmit/Recieve Control Register */ | 48 | /* SAI Transmit/Recieve Control Register */ |
49 | #define FSL_SAI_CSR_TERE BIT(31) | 49 | #define FSL_SAI_CSR_TERE BIT(31) |
50 | #define FSL_SAI_CSR_FR BIT(25) | 50 | #define FSL_SAI_CSR_FR BIT(25) |
51 | #define FSL_SAI_CSR_SR BIT(24) | ||
51 | #define FSL_SAI_CSR_xF_SHIFT 16 | 52 | #define FSL_SAI_CSR_xF_SHIFT 16 |
52 | #define FSL_SAI_CSR_xF_W_SHIFT 18 | 53 | #define FSL_SAI_CSR_xF_W_SHIFT 18 |
53 | #define FSL_SAI_CSR_xF_MASK (0x1f << FSL_SAI_CSR_xF_SHIFT) | 54 | #define FSL_SAI_CSR_xF_MASK (0x1f << FSL_SAI_CSR_xF_SHIFT) |
@@ -131,13 +132,16 @@ struct fsl_sai { | |||
131 | struct clk *bus_clk; | 132 | struct clk *bus_clk; |
132 | struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; | 133 | struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; |
133 | 134 | ||
134 | bool big_endian_regs; | 135 | bool is_lsb_first; |
135 | bool big_endian_data; | ||
136 | bool is_dsp_mode; | 136 | bool is_dsp_mode; |
137 | bool sai_on_imx; | 137 | bool sai_on_imx; |
138 | bool synchronous[2]; | ||
138 | 139 | ||
139 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 140 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
140 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 141 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
141 | }; | 142 | }; |
142 | 143 | ||
144 | #define TX 1 | ||
145 | #define RX 0 | ||
146 | |||
143 | #endif /* __FSL_SAI_H */ | 147 | #endif /* __FSL_SAI_H */ |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 70acfe4a9bd5..9b791621294c 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/bitrev.h> | 16 | #include <linux/bitrev.h> |
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clk-private.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
21 | #include <linux/of_device.h> | 20 | #include <linux/of_device.h> |
@@ -1040,7 +1039,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) | |||
1040 | } | 1039 | } |
1041 | } | 1040 | } |
1042 | 1041 | ||
1043 | static struct regmap_config fsl_spdif_regmap_config = { | 1042 | static const struct regmap_config fsl_spdif_regmap_config = { |
1044 | .reg_bits = 32, | 1043 | .reg_bits = 32, |
1045 | .reg_stride = 4, | 1044 | .reg_stride = 4, |
1046 | .val_bits = 32, | 1045 | .val_bits = 32, |
@@ -1184,9 +1183,6 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1184 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | 1183 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); |
1185 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; | 1184 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; |
1186 | 1185 | ||
1187 | if (of_property_read_bool(np, "big-endian")) | ||
1188 | fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
1189 | |||
1190 | /* Get the addresses and IRQ */ | 1186 | /* Get the addresses and IRQ */ |
1191 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1187 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1192 | regs = devm_ioremap_resource(&pdev->dev, res); | 1188 | regs = devm_ioremap_resource(&pdev->dev, res); |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index de6ab06f58a5..e6955170dc42 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -169,6 +169,7 @@ struct fsl_ssi_private { | |||
169 | u8 i2s_mode; | 169 | u8 i2s_mode; |
170 | bool use_dma; | 170 | bool use_dma; |
171 | bool use_dual_fifo; | 171 | bool use_dual_fifo; |
172 | bool has_ipg_clk_name; | ||
172 | unsigned int fifo_depth; | 173 | unsigned int fifo_depth; |
173 | struct fsl_ssi_rxtx_reg_val rxtx_reg_val; | 174 | struct fsl_ssi_rxtx_reg_val rxtx_reg_val; |
174 | 175 | ||
@@ -259,6 +260,11 @@ static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private) | |||
259 | SND_SOC_DAIFMT_CBS_CFS; | 260 | SND_SOC_DAIFMT_CBS_CFS; |
260 | } | 261 | } |
261 | 262 | ||
263 | static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private *ssi_private) | ||
264 | { | ||
265 | return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == | ||
266 | SND_SOC_DAIFMT_CBM_CFS; | ||
267 | } | ||
262 | /** | 268 | /** |
263 | * fsl_ssi_isr: SSI interrupt handler | 269 | * fsl_ssi_isr: SSI interrupt handler |
264 | * | 270 | * |
@@ -525,6 +531,11 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
525 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 531 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
526 | struct fsl_ssi_private *ssi_private = | 532 | struct fsl_ssi_private *ssi_private = |
527 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | 533 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
534 | int ret; | ||
535 | |||
536 | ret = clk_prepare_enable(ssi_private->clk); | ||
537 | if (ret) | ||
538 | return ret; | ||
528 | 539 | ||
529 | /* When using dual fifo mode, it is safer to ensure an even period | 540 | /* When using dual fifo mode, it is safer to ensure an even period |
530 | * size. If appearing to an odd number while DMA always starts its | 541 | * size. If appearing to an odd number while DMA always starts its |
@@ -539,6 +550,21 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
539 | } | 550 | } |
540 | 551 | ||
541 | /** | 552 | /** |
553 | * fsl_ssi_shutdown: shutdown the SSI | ||
554 | * | ||
555 | */ | ||
556 | static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | ||
557 | struct snd_soc_dai *dai) | ||
558 | { | ||
559 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
560 | struct fsl_ssi_private *ssi_private = | ||
561 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
562 | |||
563 | clk_disable_unprepare(ssi_private->clk); | ||
564 | |||
565 | } | ||
566 | |||
567 | /** | ||
542 | * fsl_ssi_set_bclk - configure Digital Audio Interface bit clock | 568 | * fsl_ssi_set_bclk - configure Digital Audio Interface bit clock |
543 | * | 569 | * |
544 | * Note: This function can be only called when using SSI as DAI master | 570 | * Note: This function can be only called when using SSI as DAI master |
@@ -705,6 +731,23 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
705 | } | 731 | } |
706 | } | 732 | } |
707 | 733 | ||
734 | if (!fsl_ssi_is_ac97(ssi_private)) { | ||
735 | u8 i2smode; | ||
736 | /* | ||
737 | * Switch to normal net mode in order to have a frame sync | ||
738 | * signal every 32 bits instead of 16 bits | ||
739 | */ | ||
740 | if (fsl_ssi_is_i2s_cbm_cfs(ssi_private) && sample_size == 16) | ||
741 | i2smode = CCSR_SSI_SCR_I2S_MODE_NORMAL | | ||
742 | CCSR_SSI_SCR_NET; | ||
743 | else | ||
744 | i2smode = ssi_private->i2s_mode; | ||
745 | |||
746 | regmap_update_bits(regs, CCSR_SSI_SCR, | ||
747 | CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, | ||
748 | channels == 1 ? 0 : i2smode); | ||
749 | } | ||
750 | |||
708 | /* | 751 | /* |
709 | * FIXME: The documentation says that SxCCR[WL] should not be | 752 | * FIXME: The documentation says that SxCCR[WL] should not be |
710 | * modified while the SSI is enabled. The only time this can | 753 | * modified while the SSI is enabled. The only time this can |
@@ -724,11 +767,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
724 | regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK, | 767 | regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK, |
725 | wl); | 768 | wl); |
726 | 769 | ||
727 | if (!fsl_ssi_is_ac97(ssi_private)) | ||
728 | regmap_update_bits(regs, CCSR_SSI_SCR, | ||
729 | CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, | ||
730 | channels == 1 ? 0 : ssi_private->i2s_mode); | ||
731 | |||
732 | return 0; | 770 | return 0; |
733 | } | 771 | } |
734 | 772 | ||
@@ -781,6 +819,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, | |||
781 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 819 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
782 | case SND_SOC_DAIFMT_I2S: | 820 | case SND_SOC_DAIFMT_I2S: |
783 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 821 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
822 | case SND_SOC_DAIFMT_CBM_CFS: | ||
784 | case SND_SOC_DAIFMT_CBS_CFS: | 823 | case SND_SOC_DAIFMT_CBS_CFS: |
785 | ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER; | 824 | ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER; |
786 | regmap_update_bits(regs, CCSR_SSI_STCCR, | 825 | regmap_update_bits(regs, CCSR_SSI_STCCR, |
@@ -854,6 +893,11 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, | |||
854 | case SND_SOC_DAIFMT_CBM_CFM: | 893 | case SND_SOC_DAIFMT_CBM_CFM: |
855 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; | 894 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; |
856 | break; | 895 | break; |
896 | case SND_SOC_DAIFMT_CBM_CFS: | ||
897 | strcr &= ~CCSR_SSI_STCR_TXDIR; | ||
898 | strcr |= CCSR_SSI_STCR_TFDIR; | ||
899 | scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; | ||
900 | break; | ||
857 | default: | 901 | default: |
858 | return -EINVAL; | 902 | return -EINVAL; |
859 | } | 903 | } |
@@ -1021,6 +1065,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | |||
1021 | 1065 | ||
1022 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 1066 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
1023 | .startup = fsl_ssi_startup, | 1067 | .startup = fsl_ssi_startup, |
1068 | .shutdown = fsl_ssi_shutdown, | ||
1024 | .hw_params = fsl_ssi_hw_params, | 1069 | .hw_params = fsl_ssi_hw_params, |
1025 | .hw_free = fsl_ssi_hw_free, | 1070 | .hw_free = fsl_ssi_hw_free, |
1026 | .set_fmt = fsl_ssi_set_dai_fmt, | 1071 | .set_fmt = fsl_ssi_set_dai_fmt, |
@@ -1146,17 +1191,22 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, | |||
1146 | u32 dmas[4]; | 1191 | u32 dmas[4]; |
1147 | int ret; | 1192 | int ret; |
1148 | 1193 | ||
1149 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); | 1194 | if (ssi_private->has_ipg_clk_name) |
1195 | ssi_private->clk = devm_clk_get(&pdev->dev, "ipg"); | ||
1196 | else | ||
1197 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); | ||
1150 | if (IS_ERR(ssi_private->clk)) { | 1198 | if (IS_ERR(ssi_private->clk)) { |
1151 | ret = PTR_ERR(ssi_private->clk); | 1199 | ret = PTR_ERR(ssi_private->clk); |
1152 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); | 1200 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); |
1153 | return ret; | 1201 | return ret; |
1154 | } | 1202 | } |
1155 | 1203 | ||
1156 | ret = clk_prepare_enable(ssi_private->clk); | 1204 | if (!ssi_private->has_ipg_clk_name) { |
1157 | if (ret) { | 1205 | ret = clk_prepare_enable(ssi_private->clk); |
1158 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); | 1206 | if (ret) { |
1159 | return ret; | 1207 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); |
1208 | return ret; | ||
1209 | } | ||
1160 | } | 1210 | } |
1161 | 1211 | ||
1162 | /* For those SLAVE implementations, we ingore non-baudclk cases | 1212 | /* For those SLAVE implementations, we ingore non-baudclk cases |
@@ -1214,8 +1264,9 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, | |||
1214 | return 0; | 1264 | return 0; |
1215 | 1265 | ||
1216 | error_pcm: | 1266 | error_pcm: |
1217 | clk_disable_unprepare(ssi_private->clk); | ||
1218 | 1267 | ||
1268 | if (!ssi_private->has_ipg_clk_name) | ||
1269 | clk_disable_unprepare(ssi_private->clk); | ||
1219 | return ret; | 1270 | return ret; |
1220 | } | 1271 | } |
1221 | 1272 | ||
@@ -1224,7 +1275,8 @@ static void fsl_ssi_imx_clean(struct platform_device *pdev, | |||
1224 | { | 1275 | { |
1225 | if (!ssi_private->use_dma) | 1276 | if (!ssi_private->use_dma) |
1226 | imx_pcm_fiq_exit(pdev); | 1277 | imx_pcm_fiq_exit(pdev); |
1227 | clk_disable_unprepare(ssi_private->clk); | 1278 | if (!ssi_private->has_ipg_clk_name) |
1279 | clk_disable_unprepare(ssi_private->clk); | ||
1228 | } | 1280 | } |
1229 | 1281 | ||
1230 | static int fsl_ssi_probe(struct platform_device *pdev) | 1282 | static int fsl_ssi_probe(struct platform_device *pdev) |
@@ -1263,9 +1315,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1263 | if (sprop) { | 1315 | if (sprop) { |
1264 | if (!strcmp(sprop, "ac97-slave")) | 1316 | if (!strcmp(sprop, "ac97-slave")) |
1265 | ssi_private->dai_fmt = SND_SOC_DAIFMT_AC97; | 1317 | ssi_private->dai_fmt = SND_SOC_DAIFMT_AC97; |
1266 | else if (!strcmp(sprop, "i2s-slave")) | ||
1267 | ssi_private->dai_fmt = SND_SOC_DAIFMT_I2S | | ||
1268 | SND_SOC_DAIFMT_CBM_CFM; | ||
1269 | } | 1318 | } |
1270 | 1319 | ||
1271 | ssi_private->use_dma = !of_property_read_bool(np, | 1320 | ssi_private->use_dma = !of_property_read_bool(np, |
@@ -1299,8 +1348,16 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1299 | return -ENOMEM; | 1348 | return -ENOMEM; |
1300 | } | 1349 | } |
1301 | 1350 | ||
1302 | ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, | 1351 | ret = of_property_match_string(np, "clock-names", "ipg"); |
1352 | if (ret < 0) { | ||
1353 | ssi_private->has_ipg_clk_name = false; | ||
1354 | ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, | ||
1303 | &fsl_ssi_regconfig); | 1355 | &fsl_ssi_regconfig); |
1356 | } else { | ||
1357 | ssi_private->has_ipg_clk_name = true; | ||
1358 | ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev, | ||
1359 | "ipg", iomem, &fsl_ssi_regconfig); | ||
1360 | } | ||
1304 | if (IS_ERR(ssi_private->regs)) { | 1361 | if (IS_ERR(ssi_private->regs)) { |
1305 | dev_err(&pdev->dev, "Failed to init register map\n"); | 1362 | dev_err(&pdev->dev, "Failed to init register map\n"); |
1306 | return PTR_ERR(ssi_private->regs); | 1363 | return PTR_ERR(ssi_private->regs); |
diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c new file mode 100644 index 000000000000..f8cf10e16ce9 --- /dev/null +++ b/sound/soc/fsl/imx-es8328.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 Linaro Ltd. | ||
4 | * | ||
5 | * The code contained herein is licensed under the GNU General Public | ||
6 | * License. You may obtain a copy of the GNU General Public License | ||
7 | * Version 2 or later at the following locations: | ||
8 | * | ||
9 | * http://www.opensource.org/licenses/gpl-license.html | ||
10 | * http://www.gnu.org/copyleft/gpl.html | ||
11 | */ | ||
12 | |||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/of_gpio.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include <sound/jack.h> | ||
21 | |||
22 | #include "imx-audmux.h" | ||
23 | |||
24 | #define DAI_NAME_SIZE 32 | ||
25 | #define MUX_PORT_MAX 7 | ||
26 | |||
27 | struct imx_es8328_data { | ||
28 | struct device *dev; | ||
29 | struct snd_soc_dai_link dai; | ||
30 | struct snd_soc_card card; | ||
31 | char codec_dai_name[DAI_NAME_SIZE]; | ||
32 | char platform_name[DAI_NAME_SIZE]; | ||
33 | int jack_gpio; | ||
34 | }; | ||
35 | |||
36 | static struct snd_soc_jack_gpio headset_jack_gpios[] = { | ||
37 | { | ||
38 | .gpio = -1, | ||
39 | .name = "headset-gpio", | ||
40 | .report = SND_JACK_HEADSET, | ||
41 | .invert = 0, | ||
42 | .debounce_time = 200, | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static struct snd_soc_jack headset_jack; | ||
47 | |||
48 | static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
49 | { | ||
50 | struct imx_es8328_data *data = container_of(rtd->card, | ||
51 | struct imx_es8328_data, card); | ||
52 | int ret = 0; | ||
53 | |||
54 | /* Headphone jack detection */ | ||
55 | if (gpio_is_valid(data->jack_gpio)) { | ||
56 | ret = snd_soc_jack_new(rtd->codec, "Headphone", | ||
57 | SND_JACK_HEADPHONE | SND_JACK_BTN_0, | ||
58 | &headset_jack); | ||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | headset_jack_gpios[0].gpio = data->jack_gpio; | ||
63 | ret = snd_soc_jack_add_gpios(&headset_jack, | ||
64 | ARRAY_SIZE(headset_jack_gpios), | ||
65 | headset_jack_gpios); | ||
66 | } | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static const struct snd_soc_dapm_widget imx_es8328_dapm_widgets[] = { | ||
72 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
73 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
74 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
75 | SND_SOC_DAPM_REGULATOR_SUPPLY("audio-amp", 1, 0), | ||
76 | }; | ||
77 | |||
78 | static int imx_es8328_probe(struct platform_device *pdev) | ||
79 | { | ||
80 | struct device_node *np = pdev->dev.of_node; | ||
81 | struct device_node *ssi_np = NULL, *codec_np = NULL; | ||
82 | struct platform_device *ssi_pdev; | ||
83 | struct imx_es8328_data *data; | ||
84 | u32 int_port, ext_port; | ||
85 | int ret; | ||
86 | struct device *dev = &pdev->dev; | ||
87 | |||
88 | ret = of_property_read_u32(np, "mux-int-port", &int_port); | ||
89 | if (ret) { | ||
90 | dev_err(dev, "mux-int-port missing or invalid\n"); | ||
91 | goto fail; | ||
92 | } | ||
93 | if (int_port > MUX_PORT_MAX || int_port == 0) { | ||
94 | dev_err(dev, "mux-int-port: hardware only has %d mux ports\n", | ||
95 | MUX_PORT_MAX); | ||
96 | goto fail; | ||
97 | } | ||
98 | |||
99 | ret = of_property_read_u32(np, "mux-ext-port", &ext_port); | ||
100 | if (ret) { | ||
101 | dev_err(dev, "mux-ext-port missing or invalid\n"); | ||
102 | goto fail; | ||
103 | } | ||
104 | if (ext_port > MUX_PORT_MAX || ext_port == 0) { | ||
105 | dev_err(dev, "mux-ext-port: hardware only has %d mux ports\n", | ||
106 | MUX_PORT_MAX); | ||
107 | ret = -EINVAL; | ||
108 | goto fail; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * The port numbering in the hardware manual starts at 1, while | ||
113 | * the audmux API expects it starts at 0. | ||
114 | */ | ||
115 | int_port--; | ||
116 | ext_port--; | ||
117 | ret = imx_audmux_v2_configure_port(int_port, | ||
118 | IMX_AUDMUX_V2_PTCR_SYN | | ||
119 | IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | | ||
120 | IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | | ||
121 | IMX_AUDMUX_V2_PTCR_TFSDIR | | ||
122 | IMX_AUDMUX_V2_PTCR_TCLKDIR, | ||
123 | IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); | ||
124 | if (ret) { | ||
125 | dev_err(dev, "audmux internal port setup failed\n"); | ||
126 | return ret; | ||
127 | } | ||
128 | ret = imx_audmux_v2_configure_port(ext_port, | ||
129 | IMX_AUDMUX_V2_PTCR_SYN, | ||
130 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | ||
131 | if (ret) { | ||
132 | dev_err(dev, "audmux external port setup failed\n"); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0); | ||
137 | codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); | ||
138 | if (!ssi_np || !codec_np) { | ||
139 | dev_err(dev, "phandle missing or invalid\n"); | ||
140 | ret = -EINVAL; | ||
141 | goto fail; | ||
142 | } | ||
143 | |||
144 | ssi_pdev = of_find_device_by_node(ssi_np); | ||
145 | if (!ssi_pdev) { | ||
146 | dev_err(dev, "failed to find SSI platform device\n"); | ||
147 | ret = -EINVAL; | ||
148 | goto fail; | ||
149 | } | ||
150 | |||
151 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
152 | if (!data) { | ||
153 | ret = -ENOMEM; | ||
154 | goto fail; | ||
155 | } | ||
156 | |||
157 | data->dev = dev; | ||
158 | |||
159 | data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); | ||
160 | |||
161 | data->dai.name = "hifi"; | ||
162 | data->dai.stream_name = "hifi"; | ||
163 | data->dai.codec_dai_name = "es8328-hifi-analog"; | ||
164 | data->dai.codec_of_node = codec_np; | ||
165 | data->dai.cpu_of_node = ssi_np; | ||
166 | data->dai.platform_of_node = ssi_np; | ||
167 | data->dai.init = &imx_es8328_dai_init; | ||
168 | data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
169 | SND_SOC_DAIFMT_CBM_CFM; | ||
170 | |||
171 | data->card.dev = dev; | ||
172 | data->card.dapm_widgets = imx_es8328_dapm_widgets; | ||
173 | data->card.num_dapm_widgets = ARRAY_SIZE(imx_es8328_dapm_widgets); | ||
174 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | ||
175 | if (ret) { | ||
176 | dev_err(dev, "Unable to parse card name\n"); | ||
177 | goto fail; | ||
178 | } | ||
179 | ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); | ||
180 | if (ret) { | ||
181 | dev_err(dev, "Unable to parse routing: %d\n", ret); | ||
182 | goto fail; | ||
183 | } | ||
184 | data->card.num_links = 1; | ||
185 | data->card.owner = THIS_MODULE; | ||
186 | data->card.dai_link = &data->dai; | ||
187 | |||
188 | ret = snd_soc_register_card(&data->card); | ||
189 | if (ret) { | ||
190 | dev_err(dev, "Unable to register: %d\n", ret); | ||
191 | goto fail; | ||
192 | } | ||
193 | |||
194 | platform_set_drvdata(pdev, data); | ||
195 | fail: | ||
196 | of_node_put(ssi_np); | ||
197 | of_node_put(codec_np); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int imx_es8328_remove(struct platform_device *pdev) | ||
203 | { | ||
204 | struct imx_es8328_data *data = platform_get_drvdata(pdev); | ||
205 | |||
206 | snd_soc_jack_free_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios), | ||
207 | headset_jack_gpios); | ||
208 | |||
209 | snd_soc_unregister_card(&data->card); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static const struct of_device_id imx_es8328_dt_ids[] = { | ||
215 | { .compatible = "fsl,imx-audio-es8328", }, | ||
216 | { /* sentinel */ } | ||
217 | }; | ||
218 | MODULE_DEVICE_TABLE(of, imx_es8328_dt_ids); | ||
219 | |||
220 | static struct platform_driver imx_es8328_driver = { | ||
221 | .driver = { | ||
222 | .name = "imx-es8328", | ||
223 | .of_match_table = imx_es8328_dt_ids, | ||
224 | }, | ||
225 | .probe = imx_es8328_probe, | ||
226 | .remove = imx_es8328_remove, | ||
227 | }; | ||
228 | module_platform_driver(imx_es8328_driver); | ||
229 | |||
230 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
231 | MODULE_DESCRIPTION("Kosagi i.MX6 ES8328 ASoC machine driver"); | ||
232 | MODULE_LICENSE("GPL v2"); | ||
233 | MODULE_ALIAS("platform:imx-audio-es8328"); | ||
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index cef7776b712c..d1b7293c133e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -10,10 +10,13 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/gpio.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_gpio.h> | ||
15 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
16 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <sound/jack.h> | ||
17 | #include <sound/simple_card.h> | 20 | #include <sound/simple_card.h> |
18 | #include <sound/soc-dai.h> | 21 | #include <sound/soc-dai.h> |
19 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
@@ -25,9 +28,15 @@ struct simple_card_data { | |||
25 | struct asoc_simple_dai codec_dai; | 28 | struct asoc_simple_dai codec_dai; |
26 | } *dai_props; | 29 | } *dai_props; |
27 | unsigned int mclk_fs; | 30 | unsigned int mclk_fs; |
31 | int gpio_hp_det; | ||
32 | int gpio_mic_det; | ||
28 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ | 33 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ |
29 | }; | 34 | }; |
30 | 35 | ||
36 | #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) | ||
37 | #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) | ||
38 | #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) | ||
39 | |||
31 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | 40 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, |
32 | struct snd_pcm_hw_params *params) | 41 | struct snd_pcm_hw_params *params) |
33 | { | 42 | { |
@@ -50,6 +59,32 @@ static struct snd_soc_ops asoc_simple_card_ops = { | |||
50 | .hw_params = asoc_simple_card_hw_params, | 59 | .hw_params = asoc_simple_card_hw_params, |
51 | }; | 60 | }; |
52 | 61 | ||
62 | static struct snd_soc_jack simple_card_hp_jack; | ||
63 | static struct snd_soc_jack_pin simple_card_hp_jack_pins[] = { | ||
64 | { | ||
65 | .pin = "Headphones", | ||
66 | .mask = SND_JACK_HEADPHONE, | ||
67 | }, | ||
68 | }; | ||
69 | static struct snd_soc_jack_gpio simple_card_hp_jack_gpio = { | ||
70 | .name = "Headphone detection", | ||
71 | .report = SND_JACK_HEADPHONE, | ||
72 | .debounce_time = 150, | ||
73 | }; | ||
74 | |||
75 | static struct snd_soc_jack simple_card_mic_jack; | ||
76 | static struct snd_soc_jack_pin simple_card_mic_jack_pins[] = { | ||
77 | { | ||
78 | .pin = "Mic Jack", | ||
79 | .mask = SND_JACK_MICROPHONE, | ||
80 | }, | ||
81 | }; | ||
82 | static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = { | ||
83 | .name = "Mic detection", | ||
84 | .report = SND_JACK_MICROPHONE, | ||
85 | .debounce_time = 150, | ||
86 | }; | ||
87 | |||
53 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | 88 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, |
54 | struct asoc_simple_dai *set) | 89 | struct asoc_simple_dai *set) |
55 | { | 90 | { |
@@ -105,42 +140,70 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
105 | if (ret < 0) | 140 | if (ret < 0) |
106 | return ret; | 141 | return ret; |
107 | 142 | ||
143 | if (gpio_is_valid(priv->gpio_hp_det)) { | ||
144 | snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE, | ||
145 | &simple_card_hp_jack); | ||
146 | snd_soc_jack_add_pins(&simple_card_hp_jack, | ||
147 | ARRAY_SIZE(simple_card_hp_jack_pins), | ||
148 | simple_card_hp_jack_pins); | ||
149 | |||
150 | simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det; | ||
151 | snd_soc_jack_add_gpios(&simple_card_hp_jack, 1, | ||
152 | &simple_card_hp_jack_gpio); | ||
153 | } | ||
154 | |||
155 | if (gpio_is_valid(priv->gpio_mic_det)) { | ||
156 | snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
157 | &simple_card_mic_jack); | ||
158 | snd_soc_jack_add_pins(&simple_card_mic_jack, | ||
159 | ARRAY_SIZE(simple_card_mic_jack_pins), | ||
160 | simple_card_mic_jack_pins); | ||
161 | simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det; | ||
162 | snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, | ||
163 | &simple_card_mic_jack_gpio); | ||
164 | } | ||
108 | return 0; | 165 | return 0; |
109 | } | 166 | } |
110 | 167 | ||
111 | static int | 168 | static int |
112 | asoc_simple_card_sub_parse_of(struct device_node *np, | 169 | asoc_simple_card_sub_parse_of(struct device_node *np, |
113 | struct asoc_simple_dai *dai, | 170 | struct asoc_simple_dai *dai, |
114 | const struct device_node **p_node, | 171 | struct device_node **p_node, |
115 | const char **name) | 172 | const char **name, |
173 | int *args_count) | ||
116 | { | 174 | { |
117 | struct device_node *node; | 175 | struct of_phandle_args args; |
118 | struct clk *clk; | 176 | struct clk *clk; |
119 | u32 val; | 177 | u32 val; |
120 | int ret; | 178 | int ret; |
121 | 179 | ||
122 | /* | 180 | /* |
123 | * get node via "sound-dai = <&phandle port>" | 181 | * Get node via "sound-dai = <&phandle port>" |
124 | * it will be used as xxx_of_node on soc_bind_dai_link() | 182 | * it will be used as xxx_of_node on soc_bind_dai_link() |
125 | */ | 183 | */ |
126 | node = of_parse_phandle(np, "sound-dai", 0); | 184 | ret = of_parse_phandle_with_args(np, "sound-dai", |
127 | if (!node) | 185 | "#sound-dai-cells", 0, &args); |
128 | return -ENODEV; | 186 | if (ret) |
129 | *p_node = node; | 187 | return ret; |
188 | |||
189 | *p_node = args.np; | ||
190 | |||
191 | if (args_count) | ||
192 | *args_count = args.args_count; | ||
130 | 193 | ||
131 | /* get dai->name */ | 194 | /* Get dai->name */ |
132 | ret = snd_soc_of_get_dai_name(np, name); | 195 | ret = snd_soc_of_get_dai_name(np, name); |
133 | if (ret < 0) | 196 | if (ret < 0) |
134 | return ret; | 197 | return ret; |
135 | 198 | ||
136 | /* parse TDM slot */ | 199 | /* Parse TDM slot */ |
137 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | 200 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); |
138 | if (ret) | 201 | if (ret) |
139 | return ret; | 202 | return ret; |
140 | 203 | ||
141 | /* | 204 | /* |
142 | * dai->sysclk come from | 205 | * Parse dai->sysclk come from "clocks = <&xxx>" |
143 | * "clocks = <&xxx>" (if system has common clock) | 206 | * (if system has common clock) |
144 | * or "system-clock-frequency = <xxx>" | 207 | * or "system-clock-frequency = <xxx>" |
145 | * or device's module clock. | 208 | * or device's module clock. |
146 | */ | 209 | */ |
@@ -155,7 +218,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
155 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { | 218 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
156 | dai->sysclk = val; | 219 | dai->sysclk = val; |
157 | } else { | 220 | } else { |
158 | clk = of_clk_get(node, 0); | 221 | clk = of_clk_get(args.np, 0); |
159 | if (!IS_ERR(clk)) | 222 | if (!IS_ERR(clk)) |
160 | dai->sysclk = clk_get_rate(clk); | 223 | dai->sysclk = clk_get_rate(clk); |
161 | } | 224 | } |
@@ -163,12 +226,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
163 | return 0; | 226 | return 0; |
164 | } | 227 | } |
165 | 228 | ||
166 | static int simple_card_dai_link_of(struct device_node *node, | 229 | static int asoc_simple_card_dai_link_of(struct device_node *node, |
167 | struct device *dev, | 230 | struct simple_card_data *priv, |
168 | struct snd_soc_dai_link *dai_link, | 231 | int idx, |
169 | struct simple_dai_props *dai_props, | 232 | bool is_top_level_node) |
170 | bool is_top_level_node) | ||
171 | { | 233 | { |
234 | struct device *dev = simple_priv_to_dev(priv); | ||
235 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); | ||
236 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); | ||
172 | struct device_node *np = NULL; | 237 | struct device_node *np = NULL; |
173 | struct device_node *bitclkmaster = NULL; | 238 | struct device_node *bitclkmaster = NULL; |
174 | struct device_node *framemaster = NULL; | 239 | struct device_node *framemaster = NULL; |
@@ -176,8 +241,9 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
176 | char *name; | 241 | char *name; |
177 | char prop[128]; | 242 | char prop[128]; |
178 | char *prefix = ""; | 243 | char *prefix = ""; |
179 | int ret; | 244 | int ret, cpu_args; |
180 | 245 | ||
246 | /* For single DAI link & old style of DT node */ | ||
181 | if (is_top_level_node) | 247 | if (is_top_level_node) |
182 | prefix = "simple-audio-card,"; | 248 | prefix = "simple-audio-card,"; |
183 | 249 | ||
@@ -195,7 +261,8 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
195 | 261 | ||
196 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, | 262 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, |
197 | &dai_link->cpu_of_node, | 263 | &dai_link->cpu_of_node, |
198 | &dai_link->cpu_dai_name); | 264 | &dai_link->cpu_dai_name, |
265 | &cpu_args); | ||
199 | if (ret < 0) | 266 | if (ret < 0) |
200 | goto dai_link_of_err; | 267 | goto dai_link_of_err; |
201 | 268 | ||
@@ -226,14 +293,16 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
226 | 293 | ||
227 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, | 294 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, |
228 | &dai_link->codec_of_node, | 295 | &dai_link->codec_of_node, |
229 | &dai_link->codec_dai_name); | 296 | &dai_link->codec_dai_name, NULL); |
230 | if (ret < 0) | 297 | if (ret < 0) |
231 | goto dai_link_of_err; | 298 | goto dai_link_of_err; |
232 | 299 | ||
233 | if (strlen(prefix) && !bitclkmaster && !framemaster) { | 300 | if (strlen(prefix) && !bitclkmaster && !framemaster) { |
234 | /* No dai-link level and master setting was not found from | 301 | /* |
235 | sound node level, revert back to legacy DT parsing and | 302 | * No DAI link level and master setting was found |
236 | take the settings from codec node. */ | 303 | * from sound node level, revert back to legacy DT |
304 | * parsing and take the settings from codec node. | ||
305 | */ | ||
237 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", | 306 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", |
238 | __func__); | 307 | __func__); |
239 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = | 308 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = |
@@ -262,10 +331,10 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
262 | goto dai_link_of_err; | 331 | goto dai_link_of_err; |
263 | } | 332 | } |
264 | 333 | ||
265 | /* simple-card assumes platform == cpu */ | 334 | /* Simple Card assumes platform == cpu */ |
266 | dai_link->platform_of_node = dai_link->cpu_of_node; | 335 | dai_link->platform_of_node = dai_link->cpu_of_node; |
267 | 336 | ||
268 | /* Link name is created from CPU/CODEC dai name */ | 337 | /* DAI link name is created from CPU/CODEC dai name */ |
269 | name = devm_kzalloc(dev, | 338 | name = devm_kzalloc(dev, |
270 | strlen(dai_link->cpu_dai_name) + | 339 | strlen(dai_link->cpu_dai_name) + |
271 | strlen(dai_link->codec_dai_name) + 2, | 340 | strlen(dai_link->codec_dai_name) + 2, |
@@ -274,6 +343,7 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
274 | dai_link->codec_dai_name); | 343 | dai_link->codec_dai_name); |
275 | dai_link->name = dai_link->stream_name = name; | 344 | dai_link->name = dai_link->stream_name = name; |
276 | dai_link->ops = &asoc_simple_card_ops; | 345 | dai_link->ops = &asoc_simple_card_ops; |
346 | dai_link->init = asoc_simple_card_dai_init; | ||
277 | 347 | ||
278 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); | 348 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); |
279 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", | 349 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", |
@@ -285,6 +355,18 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
285 | dai_props->codec_dai.fmt, | 355 | dai_props->codec_dai.fmt, |
286 | dai_props->codec_dai.sysclk); | 356 | dai_props->codec_dai.sysclk); |
287 | 357 | ||
358 | /* | ||
359 | * In soc_bind_dai_link() will check cpu name after | ||
360 | * of_node matching if dai_link has cpu_dai_name. | ||
361 | * but, it will never match if name was created by | ||
362 | * fmt_single_name() remove cpu_dai_name if cpu_args | ||
363 | * was 0. See: | ||
364 | * fmt_single_name() | ||
365 | * fmt_multiple_name() | ||
366 | */ | ||
367 | if (!cpu_args) | ||
368 | dai_link->cpu_dai_name = NULL; | ||
369 | |||
288 | dai_link_of_err: | 370 | dai_link_of_err: |
289 | if (np) | 371 | if (np) |
290 | of_node_put(np); | 372 | of_node_put(np); |
@@ -296,19 +378,19 @@ dai_link_of_err: | |||
296 | } | 378 | } |
297 | 379 | ||
298 | static int asoc_simple_card_parse_of(struct device_node *node, | 380 | static int asoc_simple_card_parse_of(struct device_node *node, |
299 | struct simple_card_data *priv, | 381 | struct simple_card_data *priv) |
300 | struct device *dev, | ||
301 | int multi) | ||
302 | { | 382 | { |
303 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 383 | struct device *dev = simple_priv_to_dev(priv); |
304 | struct simple_dai_props *dai_props = priv->dai_props; | ||
305 | u32 val; | 384 | u32 val; |
306 | int ret; | 385 | int ret; |
307 | 386 | ||
308 | /* parsing the card name from DT */ | 387 | if (!node) |
388 | return -EINVAL; | ||
389 | |||
390 | /* Parse the card name from DT */ | ||
309 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); | 391 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); |
310 | 392 | ||
311 | /* off-codec widgets */ | 393 | /* The off-codec widgets */ |
312 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { | 394 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { |
313 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, | 395 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, |
314 | "simple-audio-card,widgets"); | 396 | "simple-audio-card,widgets"); |
@@ -332,32 +414,45 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
332 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? | 414 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? |
333 | priv->snd_card.name : ""); | 415 | priv->snd_card.name : ""); |
334 | 416 | ||
335 | if (multi) { | 417 | /* Single/Muti DAI link(s) & New style of DT node */ |
418 | if (of_get_child_by_name(node, "simple-audio-card,dai-link")) { | ||
336 | struct device_node *np = NULL; | 419 | struct device_node *np = NULL; |
337 | int i; | 420 | int i = 0; |
338 | for (i = 0; (np = of_get_next_child(node, np)); i++) { | 421 | |
422 | for_each_child_of_node(node, np) { | ||
339 | dev_dbg(dev, "\tlink %d:\n", i); | 423 | dev_dbg(dev, "\tlink %d:\n", i); |
340 | ret = simple_card_dai_link_of(np, dev, dai_link + i, | 424 | ret = asoc_simple_card_dai_link_of(np, priv, |
341 | dai_props + i, false); | 425 | i, false); |
342 | if (ret < 0) { | 426 | if (ret < 0) { |
343 | of_node_put(np); | 427 | of_node_put(np); |
344 | return ret; | 428 | return ret; |
345 | } | 429 | } |
430 | i++; | ||
346 | } | 431 | } |
347 | } else { | 432 | } else { |
348 | ret = simple_card_dai_link_of(node, dev, dai_link, dai_props, | 433 | /* For single DAI link & old style of DT node */ |
349 | true); | 434 | ret = asoc_simple_card_dai_link_of(node, priv, 0, true); |
350 | if (ret < 0) | 435 | if (ret < 0) |
351 | return ret; | 436 | return ret; |
352 | } | 437 | } |
353 | 438 | ||
439 | priv->gpio_hp_det = of_get_named_gpio(node, | ||
440 | "simple-audio-card,hp-det-gpio", 0); | ||
441 | if (priv->gpio_hp_det == -EPROBE_DEFER) | ||
442 | return -EPROBE_DEFER; | ||
443 | |||
444 | priv->gpio_mic_det = of_get_named_gpio(node, | ||
445 | "simple-audio-card,mic-det-gpio", 0); | ||
446 | if (priv->gpio_mic_det == -EPROBE_DEFER) | ||
447 | return -EPROBE_DEFER; | ||
448 | |||
354 | if (!priv->snd_card.name) | 449 | if (!priv->snd_card.name) |
355 | priv->snd_card.name = priv->snd_card.dai_link->name; | 450 | priv->snd_card.name = priv->snd_card.dai_link->name; |
356 | 451 | ||
357 | return 0; | 452 | return 0; |
358 | } | 453 | } |
359 | 454 | ||
360 | /* update the reference count of the devices nodes at end of probe */ | 455 | /* Decrease the reference count of the device nodes */ |
361 | static int asoc_simple_card_unref(struct platform_device *pdev) | 456 | static int asoc_simple_card_unref(struct platform_device *pdev) |
362 | { | 457 | { |
363 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 458 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
@@ -384,34 +479,32 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
384 | struct snd_soc_dai_link *dai_link; | 479 | struct snd_soc_dai_link *dai_link; |
385 | struct device_node *np = pdev->dev.of_node; | 480 | struct device_node *np = pdev->dev.of_node; |
386 | struct device *dev = &pdev->dev; | 481 | struct device *dev = &pdev->dev; |
387 | int num_links, multi, ret; | 482 | int num_links, ret; |
388 | 483 | ||
389 | /* get the number of DAI links */ | 484 | /* Get the number of DAI links */ |
390 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) { | 485 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) |
391 | num_links = of_get_child_count(np); | 486 | num_links = of_get_child_count(np); |
392 | multi = 1; | 487 | else |
393 | } else { | ||
394 | num_links = 1; | 488 | num_links = 1; |
395 | multi = 0; | ||
396 | } | ||
397 | 489 | ||
398 | /* allocate the private data and the DAI link array */ | 490 | /* Allocate the private data and the DAI link array */ |
399 | priv = devm_kzalloc(dev, | 491 | priv = devm_kzalloc(dev, |
400 | sizeof(*priv) + sizeof(*dai_link) * num_links, | 492 | sizeof(*priv) + sizeof(*dai_link) * num_links, |
401 | GFP_KERNEL); | 493 | GFP_KERNEL); |
402 | if (!priv) | 494 | if (!priv) |
403 | return -ENOMEM; | 495 | return -ENOMEM; |
404 | 496 | ||
405 | /* | 497 | /* Init snd_soc_card */ |
406 | * init snd_soc_card | ||
407 | */ | ||
408 | priv->snd_card.owner = THIS_MODULE; | 498 | priv->snd_card.owner = THIS_MODULE; |
409 | priv->snd_card.dev = dev; | 499 | priv->snd_card.dev = dev; |
410 | dai_link = priv->dai_link; | 500 | dai_link = priv->dai_link; |
411 | priv->snd_card.dai_link = dai_link; | 501 | priv->snd_card.dai_link = dai_link; |
412 | priv->snd_card.num_links = num_links; | 502 | priv->snd_card.num_links = num_links; |
413 | 503 | ||
414 | /* get room for the other properties */ | 504 | priv->gpio_hp_det = -ENOENT; |
505 | priv->gpio_mic_det = -ENOENT; | ||
506 | |||
507 | /* Get room for the other properties */ | ||
415 | priv->dai_props = devm_kzalloc(dev, | 508 | priv->dai_props = devm_kzalloc(dev, |
416 | sizeof(*priv->dai_props) * num_links, | 509 | sizeof(*priv->dai_props) * num_links, |
417 | GFP_KERNEL); | 510 | GFP_KERNEL); |
@@ -420,25 +513,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
420 | 513 | ||
421 | if (np && of_device_is_available(np)) { | 514 | if (np && of_device_is_available(np)) { |
422 | 515 | ||
423 | ret = asoc_simple_card_parse_of(np, priv, dev, multi); | 516 | ret = asoc_simple_card_parse_of(np, priv); |
424 | if (ret < 0) { | 517 | if (ret < 0) { |
425 | if (ret != -EPROBE_DEFER) | 518 | if (ret != -EPROBE_DEFER) |
426 | dev_err(dev, "parse error %d\n", ret); | 519 | dev_err(dev, "parse error %d\n", ret); |
427 | goto err; | 520 | goto err; |
428 | } | 521 | } |
429 | 522 | ||
430 | /* | ||
431 | * soc_bind_dai_link() will check cpu name | ||
432 | * after of_node matching if dai_link has cpu_dai_name. | ||
433 | * but, it will never match if name was created by fmt_single_name() | ||
434 | * remove cpu_dai_name to escape name matching. | ||
435 | * see | ||
436 | * fmt_single_name() | ||
437 | * fmt_multiple_name() | ||
438 | */ | ||
439 | if (num_links == 1) | ||
440 | dai_link->cpu_dai_name = NULL; | ||
441 | |||
442 | } else { | 523 | } else { |
443 | struct asoc_simple_card_info *cinfo; | 524 | struct asoc_simple_card_info *cinfo; |
444 | 525 | ||
@@ -464,6 +545,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
464 | dai_link->codec_name = cinfo->codec; | 545 | dai_link->codec_name = cinfo->codec; |
465 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; | 546 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; |
466 | dai_link->codec_dai_name = cinfo->codec_dai.name; | 547 | dai_link->codec_dai_name = cinfo->codec_dai.name; |
548 | dai_link->init = asoc_simple_card_dai_init; | ||
467 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, | 549 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, |
468 | sizeof(priv->dai_props->cpu_dai)); | 550 | sizeof(priv->dai_props->cpu_dai)); |
469 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, | 551 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, |
@@ -473,11 +555,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
473 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; | 555 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; |
474 | } | 556 | } |
475 | 557 | ||
476 | /* | ||
477 | * init snd_soc_dai_link | ||
478 | */ | ||
479 | dai_link->init = asoc_simple_card_dai_init; | ||
480 | |||
481 | snd_soc_card_set_drvdata(&priv->snd_card, priv); | 558 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
482 | 559 | ||
483 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); | 560 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
@@ -491,6 +568,16 @@ err: | |||
491 | 568 | ||
492 | static int asoc_simple_card_remove(struct platform_device *pdev) | 569 | static int asoc_simple_card_remove(struct platform_device *pdev) |
493 | { | 570 | { |
571 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
572 | struct simple_card_data *priv = snd_soc_card_get_drvdata(card); | ||
573 | |||
574 | if (gpio_is_valid(priv->gpio_hp_det)) | ||
575 | snd_soc_jack_free_gpios(&simple_card_hp_jack, 1, | ||
576 | &simple_card_hp_jack_gpio); | ||
577 | if (gpio_is_valid(priv->gpio_mic_det)) | ||
578 | snd_soc_jack_free_gpios(&simple_card_mic_jack, 1, | ||
579 | &simple_card_mic_jack_gpio); | ||
580 | |||
494 | return asoc_simple_card_unref(pdev); | 581 | return asoc_simple_card_unref(pdev); |
495 | } | 582 | } |
496 | 583 | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 7acbfc43a0c6..f841786dad15 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o | 2 | snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o |
3 | snd-soc-sst-acpi-objs := sst-acpi.o | 3 | snd-soc-sst-acpi-objs := sst-acpi.o |
4 | 4 | ||
5 | snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o sst-mfld-platform-compress.o | 5 | snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \ |
6 | sst-mfld-platform-compress.o sst-atom-controls.o | ||
6 | snd-soc-mfld-machine-objs := mfld_machine.o | 7 | snd-soc-mfld-machine-objs := mfld_machine.o |
7 | 8 | ||
8 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o | 9 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o |
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index b8b8af571ef1..d52681e7225e 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c | |||
@@ -139,6 +139,7 @@ static struct snd_soc_card byt_max98090_card = { | |||
139 | .num_dapm_routes = ARRAY_SIZE(byt_max98090_audio_map), | 139 | .num_dapm_routes = ARRAY_SIZE(byt_max98090_audio_map), |
140 | .controls = byt_max98090_controls, | 140 | .controls = byt_max98090_controls, |
141 | .num_controls = ARRAY_SIZE(byt_max98090_controls), | 141 | .num_controls = ARRAY_SIZE(byt_max98090_controls), |
142 | .fully_routed = true, | ||
142 | }; | 143 | }; |
143 | 144 | ||
144 | static int byt_max98090_probe(struct platform_device *pdev) | 145 | static int byt_max98090_probe(struct platform_device *pdev) |
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 234a58de3c53..e03abdf21c1b 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/acpi.h> | 18 | #include <linux/acpi.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/dmi.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
@@ -36,8 +37,6 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { | |||
36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | 37 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { |
37 | {"Headset Mic", NULL, "MICBIAS1"}, | 38 | {"Headset Mic", NULL, "MICBIAS1"}, |
38 | {"IN2P", NULL, "Headset Mic"}, | 39 | {"IN2P", NULL, "Headset Mic"}, |
39 | {"IN2N", NULL, "Headset Mic"}, | ||
40 | {"DMIC1", NULL, "Internal Mic"}, | ||
41 | {"Headphone", NULL, "HPOL"}, | 40 | {"Headphone", NULL, "HPOL"}, |
42 | {"Headphone", NULL, "HPOR"}, | 41 | {"Headphone", NULL, "HPOR"}, |
43 | {"Speaker", NULL, "SPOLP"}, | 42 | {"Speaker", NULL, "SPOLP"}, |
@@ -46,6 +45,31 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | |||
46 | {"Speaker", NULL, "SPORN"}, | 45 | {"Speaker", NULL, "SPORN"}, |
47 | }; | 46 | }; |
48 | 47 | ||
48 | static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { | ||
49 | {"DMIC1", NULL, "Internal Mic"}, | ||
50 | }; | ||
51 | |||
52 | static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { | ||
53 | {"DMIC2", NULL, "Internal Mic"}, | ||
54 | }; | ||
55 | |||
56 | static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { | ||
57 | {"Internal Mic", NULL, "MICBIAS1"}, | ||
58 | {"IN1P", NULL, "Internal Mic"}, | ||
59 | }; | ||
60 | |||
61 | enum { | ||
62 | BYT_RT5640_DMIC1_MAP, | ||
63 | BYT_RT5640_DMIC2_MAP, | ||
64 | BYT_RT5640_IN1_MAP, | ||
65 | }; | ||
66 | |||
67 | #define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) | ||
68 | #define BYT_RT5640_DMIC_EN BIT(16) | ||
69 | |||
70 | static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | | ||
71 | BYT_RT5640_DMIC_EN; | ||
72 | |||
49 | static const struct snd_kcontrol_new byt_rt5640_controls[] = { | 73 | static const struct snd_kcontrol_new byt_rt5640_controls[] = { |
50 | SOC_DAPM_PIN_SWITCH("Headphone"), | 74 | SOC_DAPM_PIN_SWITCH("Headphone"), |
51 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | 75 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
@@ -77,12 +101,41 @@ static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, | |||
77 | return 0; | 101 | return 0; |
78 | } | 102 | } |
79 | 103 | ||
104 | static int byt_rt5640_quirk_cb(const struct dmi_system_id *id) | ||
105 | { | ||
106 | byt_rt5640_quirk = (unsigned long)id->driver_data; | ||
107 | return 1; | ||
108 | } | ||
109 | |||
110 | static const struct dmi_system_id byt_rt5640_quirk_table[] = { | ||
111 | { | ||
112 | .callback = byt_rt5640_quirk_cb, | ||
113 | .matches = { | ||
114 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
115 | DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"), | ||
116 | }, | ||
117 | .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, | ||
118 | }, | ||
119 | { | ||
120 | .callback = byt_rt5640_quirk_cb, | ||
121 | .matches = { | ||
122 | DMI_MATCH(DMI_SYS_VENDOR, "DellInc."), | ||
123 | DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), | ||
124 | }, | ||
125 | .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP | | ||
126 | BYT_RT5640_DMIC_EN), | ||
127 | }, | ||
128 | {} | ||
129 | }; | ||
130 | |||
80 | static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | 131 | static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) |
81 | { | 132 | { |
82 | int ret; | 133 | int ret; |
83 | struct snd_soc_codec *codec = runtime->codec; | 134 | struct snd_soc_codec *codec = runtime->codec; |
84 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 135 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
85 | struct snd_soc_card *card = runtime->card; | 136 | struct snd_soc_card *card = runtime->card; |
137 | const struct snd_soc_dapm_route *custom_map; | ||
138 | int num_routes; | ||
86 | 139 | ||
87 | card->dapm.idle_bias_off = true; | 140 | card->dapm.idle_bias_off = true; |
88 | 141 | ||
@@ -93,6 +146,31 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
93 | return ret; | 146 | return ret; |
94 | } | 147 | } |
95 | 148 | ||
149 | dmi_check_system(byt_rt5640_quirk_table); | ||
150 | switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { | ||
151 | case BYT_RT5640_IN1_MAP: | ||
152 | custom_map = byt_rt5640_intmic_in1_map; | ||
153 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); | ||
154 | break; | ||
155 | case BYT_RT5640_DMIC2_MAP: | ||
156 | custom_map = byt_rt5640_intmic_dmic2_map; | ||
157 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); | ||
158 | break; | ||
159 | default: | ||
160 | custom_map = byt_rt5640_intmic_dmic1_map; | ||
161 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); | ||
162 | } | ||
163 | |||
164 | ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes); | ||
165 | if (ret) | ||
166 | return ret; | ||
167 | |||
168 | if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) { | ||
169 | ret = rt5640_dmic_enable(codec, 0, 0); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | } | ||
173 | |||
96 | snd_soc_dapm_ignore_suspend(dapm, "HPOL"); | 174 | snd_soc_dapm_ignore_suspend(dapm, "HPOL"); |
97 | snd_soc_dapm_ignore_suspend(dapm, "HPOR"); | 175 | snd_soc_dapm_ignore_suspend(dapm, "HPOR"); |
98 | 176 | ||
@@ -131,6 +209,7 @@ static struct snd_soc_card byt_rt5640_card = { | |||
131 | .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), | 209 | .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), |
132 | .dapm_routes = byt_rt5640_audio_map, | 210 | .dapm_routes = byt_rt5640_audio_map, |
133 | .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), | 211 | .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), |
212 | .fully_routed = true, | ||
134 | }; | 213 | }; |
135 | 214 | ||
136 | static int byt_rt5640_probe(struct platform_device *pdev) | 215 | static int byt_rt5640_probe(struct platform_device *pdev) |
diff --git a/sound/soc/intel/sst-atom-controls.c b/sound/soc/intel/sst-atom-controls.c new file mode 100644 index 000000000000..7104a34181a9 --- /dev/null +++ b/sound/soc/intel/sst-atom-controls.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld | ||
3 | * | ||
4 | * Copyright (C) 2013-14 Intel Corp | ||
5 | * Author: Omair Mohammed Abdullah <omair.m.abdullah@intel.com> | ||
6 | * Vinod Koul <vinod.koul@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
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 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
21 | |||
22 | #include <linux/slab.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/tlv.h> | ||
25 | #include "sst-mfld-platform.h" | ||
26 | #include "sst-atom-controls.h" | ||
27 | |||
28 | static int sst_fill_byte_control(struct sst_data *drv, | ||
29 | u8 ipc_msg, u8 block, | ||
30 | u8 task_id, u8 pipe_id, | ||
31 | u16 len, void *cmd_data) | ||
32 | { | ||
33 | struct snd_sst_bytes_v2 *byte_data = drv->byte_stream; | ||
34 | |||
35 | byte_data->type = SST_CMD_BYTES_SET; | ||
36 | byte_data->ipc_msg = ipc_msg; | ||
37 | byte_data->block = block; | ||
38 | byte_data->task_id = task_id; | ||
39 | byte_data->pipe_id = pipe_id; | ||
40 | |||
41 | if (len > SST_MAX_BIN_BYTES - sizeof(*byte_data)) { | ||
42 | dev_err(&drv->pdev->dev, "command length too big (%u)", len); | ||
43 | return -EINVAL; | ||
44 | } | ||
45 | byte_data->len = len; | ||
46 | memcpy(byte_data->bytes, cmd_data, len); | ||
47 | print_hex_dump_bytes("writing to lpe: ", DUMP_PREFIX_OFFSET, | ||
48 | byte_data, len + sizeof(*byte_data)); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv, | ||
53 | u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id, | ||
54 | void *cmd_data, u16 len) | ||
55 | { | ||
56 | int ret = 0; | ||
57 | |||
58 | ret = sst_fill_byte_control(drv, ipc_msg, | ||
59 | block, task_id, pipe_id, len, cmd_data); | ||
60 | if (ret < 0) | ||
61 | return ret; | ||
62 | return sst->ops->send_byte_stream(sst->dev, drv->byte_stream); | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * sst_fill_and_send_cmd - generate the IPC message and send it to the FW | ||
67 | * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS) | ||
68 | * @cmd_data: the IPC payload | ||
69 | */ | ||
70 | static int sst_fill_and_send_cmd(struct sst_data *drv, | ||
71 | u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id, | ||
72 | void *cmd_data, u16 len) | ||
73 | { | ||
74 | int ret; | ||
75 | |||
76 | mutex_lock(&drv->lock); | ||
77 | ret = sst_fill_and_send_cmd_unlocked(drv, ipc_msg, block, | ||
78 | task_id, pipe_id, cmd_data, len); | ||
79 | mutex_unlock(&drv->lock); | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static int sst_send_algo_cmd(struct sst_data *drv, | ||
85 | struct sst_algo_control *bc) | ||
86 | { | ||
87 | int len, ret = 0; | ||
88 | struct sst_cmd_set_params *cmd; | ||
89 | |||
90 | /*bc->max includes sizeof algos + length field*/ | ||
91 | len = sizeof(cmd->dst) + sizeof(cmd->command_id) + bc->max; | ||
92 | |||
93 | cmd = kzalloc(len, GFP_KERNEL); | ||
94 | if (cmd == NULL) | ||
95 | return -ENOMEM; | ||
96 | |||
97 | SST_FILL_DESTINATION(2, cmd->dst, bc->pipe_id, bc->module_id); | ||
98 | cmd->command_id = bc->cmd_id; | ||
99 | memcpy(cmd->params, bc->params, bc->max); | ||
100 | |||
101 | ret = sst_fill_and_send_cmd_unlocked(drv, SST_IPC_IA_SET_PARAMS, | ||
102 | SST_FLAG_BLOCKED, bc->task_id, 0, cmd, len); | ||
103 | kfree(cmd); | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static int sst_algo_bytes_ctl_info(struct snd_kcontrol *kcontrol, | ||
108 | struct snd_ctl_elem_info *uinfo) | ||
109 | { | ||
110 | struct sst_algo_control *bc = (void *)kcontrol->private_value; | ||
111 | |||
112 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
113 | uinfo->count = bc->max; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int sst_algo_control_get(struct snd_kcontrol *kcontrol, | ||
119 | struct snd_ctl_elem_value *ucontrol) | ||
120 | { | ||
121 | struct sst_algo_control *bc = (void *)kcontrol->private_value; | ||
122 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
123 | |||
124 | switch (bc->type) { | ||
125 | case SST_ALGO_PARAMS: | ||
126 | memcpy(ucontrol->value.bytes.data, bc->params, bc->max); | ||
127 | break; | ||
128 | default: | ||
129 | dev_err(component->dev, "Invalid Input- algo type:%d\n", | ||
130 | bc->type); | ||
131 | return -EINVAL; | ||
132 | |||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int sst_algo_control_set(struct snd_kcontrol *kcontrol, | ||
138 | struct snd_ctl_elem_value *ucontrol) | ||
139 | { | ||
140 | int ret = 0; | ||
141 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | ||
142 | struct sst_data *drv = snd_soc_component_get_drvdata(cmpnt); | ||
143 | struct sst_algo_control *bc = (void *)kcontrol->private_value; | ||
144 | |||
145 | dev_dbg(cmpnt->dev, "control_name=%s\n", kcontrol->id.name); | ||
146 | mutex_lock(&drv->lock); | ||
147 | switch (bc->type) { | ||
148 | case SST_ALGO_PARAMS: | ||
149 | memcpy(bc->params, ucontrol->value.bytes.data, bc->max); | ||
150 | break; | ||
151 | default: | ||
152 | mutex_unlock(&drv->lock); | ||
153 | dev_err(cmpnt->dev, "Invalid Input- algo type:%d\n", | ||
154 | bc->type); | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | /*if pipe is enabled, need to send the algo params from here*/ | ||
158 | if (bc->w && bc->w->power) | ||
159 | ret = sst_send_algo_cmd(drv, bc); | ||
160 | mutex_unlock(&drv->lock); | ||
161 | |||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static const struct snd_kcontrol_new sst_algo_controls[] = { | ||
166 | SST_ALGO_KCONTROL_BYTES("media_loop1_out", "fir", 272, SST_MODULE_ID_FIR_24, | ||
167 | SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR), | ||
168 | SST_ALGO_KCONTROL_BYTES("media_loop1_out", "iir", 300, SST_MODULE_ID_IIR_24, | ||
169 | SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR), | ||
170 | SST_ALGO_KCONTROL_BYTES("media_loop1_out", "mdrp", 286, SST_MODULE_ID_MDRP, | ||
171 | SST_PATH_INDEX_MEDIA_LOOP1_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP), | ||
172 | SST_ALGO_KCONTROL_BYTES("media_loop2_out", "fir", 272, SST_MODULE_ID_FIR_24, | ||
173 | SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_FIR), | ||
174 | SST_ALGO_KCONTROL_BYTES("media_loop2_out", "iir", 300, SST_MODULE_ID_IIR_24, | ||
175 | SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_VB_SET_IIR), | ||
176 | SST_ALGO_KCONTROL_BYTES("media_loop2_out", "mdrp", 286, SST_MODULE_ID_MDRP, | ||
177 | SST_PATH_INDEX_MEDIA_LOOP2_OUT, 0, SST_TASK_SBA, SBA_SET_MDRP), | ||
178 | SST_ALGO_KCONTROL_BYTES("sprot_loop_out", "lpro", 192, SST_MODULE_ID_SPROT, | ||
179 | SST_PATH_INDEX_SPROT_LOOP_OUT, 0, SST_TASK_SBA, SBA_VB_LPRO), | ||
180 | SST_ALGO_KCONTROL_BYTES("codec_in0", "dcr", 52, SST_MODULE_ID_FILT_DCR, | ||
181 | SST_PATH_INDEX_CODEC_IN0, 0, SST_TASK_SBA, SBA_VB_SET_IIR), | ||
182 | SST_ALGO_KCONTROL_BYTES("codec_in1", "dcr", 52, SST_MODULE_ID_FILT_DCR, | ||
183 | SST_PATH_INDEX_CODEC_IN1, 0, SST_TASK_SBA, SBA_VB_SET_IIR), | ||
184 | |||
185 | }; | ||
186 | |||
187 | static int sst_algo_control_init(struct device *dev) | ||
188 | { | ||
189 | int i = 0; | ||
190 | struct sst_algo_control *bc; | ||
191 | /*allocate space to cache the algo parameters in the driver*/ | ||
192 | for (i = 0; i < ARRAY_SIZE(sst_algo_controls); i++) { | ||
193 | bc = (struct sst_algo_control *)sst_algo_controls[i].private_value; | ||
194 | bc->params = devm_kzalloc(dev, bc->max, GFP_KERNEL); | ||
195 | if (bc->params == NULL) | ||
196 | return -ENOMEM; | ||
197 | } | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform) | ||
202 | { | ||
203 | int ret = 0; | ||
204 | struct sst_data *drv = snd_soc_platform_get_drvdata(platform); | ||
205 | |||
206 | drv->byte_stream = devm_kzalloc(platform->dev, | ||
207 | SST_MAX_BIN_BYTES, GFP_KERNEL); | ||
208 | if (!drv->byte_stream) | ||
209 | return -ENOMEM; | ||
210 | |||
211 | /*Initialize algo control params*/ | ||
212 | ret = sst_algo_control_init(platform->dev); | ||
213 | if (ret) | ||
214 | return ret; | ||
215 | ret = snd_soc_add_platform_controls(platform, sst_algo_controls, | ||
216 | ARRAY_SIZE(sst_algo_controls)); | ||
217 | return ret; | ||
218 | } | ||
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h index 14063ab8c7c5..a73e894b175c 100644 --- a/sound/soc/intel/sst-atom-controls.h +++ b/sound/soc/intel/sst-atom-controls.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * sst-atom-controls.h - Intel MID Platform driver header file | ||
3 | * | ||
2 | * Copyright (C) 2013-14 Intel Corp | 4 | * Copyright (C) 2013-14 Intel Corp |
3 | * Author: Ramesh Babu <ramesh.babu.koul@intel.com> | 5 | * Author: Ramesh Babu <ramesh.babu.koul@intel.com> |
4 | * Omair M Abdullah <omair.m.abdullah@intel.com> | 6 | * Omair M Abdullah <omair.m.abdullah@intel.com> |
@@ -18,13 +20,423 @@ | |||
18 | * | 20 | * |
19 | */ | 21 | */ |
20 | 22 | ||
21 | #ifndef __SST_CONTROLS_V2_H__ | 23 | #ifndef __SST_ATOM_CONTROLS_H__ |
22 | #define __SST_CONTROLS_V2_H__ | 24 | #define __SST_ATOM_CONTROLS_H__ |
23 | 25 | ||
24 | enum { | 26 | enum { |
25 | MERR_DPCM_AUDIO = 0, | 27 | MERR_DPCM_AUDIO = 0, |
26 | MERR_DPCM_COMPR, | 28 | MERR_DPCM_COMPR, |
27 | }; | 29 | }; |
28 | 30 | ||
31 | /* define a bit for each mixer input */ | ||
32 | #define SST_MIX_IP(x) (x) | ||
33 | |||
34 | #define SST_IP_CODEC0 SST_MIX_IP(2) | ||
35 | #define SST_IP_CODEC1 SST_MIX_IP(3) | ||
36 | #define SST_IP_LOOP0 SST_MIX_IP(4) | ||
37 | #define SST_IP_LOOP1 SST_MIX_IP(5) | ||
38 | #define SST_IP_LOOP2 SST_MIX_IP(6) | ||
39 | #define SST_IP_PROBE SST_MIX_IP(7) | ||
40 | #define SST_IP_VOIP SST_MIX_IP(12) | ||
41 | #define SST_IP_PCM0 SST_MIX_IP(13) | ||
42 | #define SST_IP_PCM1 SST_MIX_IP(14) | ||
43 | #define SST_IP_MEDIA0 SST_MIX_IP(17) | ||
44 | #define SST_IP_MEDIA1 SST_MIX_IP(18) | ||
45 | #define SST_IP_MEDIA2 SST_MIX_IP(19) | ||
46 | #define SST_IP_MEDIA3 SST_MIX_IP(20) | ||
47 | |||
48 | #define SST_IP_LAST SST_IP_MEDIA3 | ||
49 | |||
50 | #define SST_SWM_INPUT_COUNT (SST_IP_LAST + 1) | ||
51 | #define SST_CMD_SWM_MAX_INPUTS 6 | ||
52 | |||
53 | #define SST_PATH_ID_SHIFT 8 | ||
54 | #define SST_DEFAULT_LOCATION_ID 0xFFFF | ||
55 | #define SST_DEFAULT_CELL_NBR 0xFF | ||
56 | #define SST_DEFAULT_MODULE_ID 0xFFFF | ||
57 | |||
58 | /* | ||
59 | * Audio DSP Path Ids. Specified by the audio DSP FW | ||
60 | */ | ||
61 | enum sst_path_index { | ||
62 | SST_PATH_INDEX_CODEC_OUT0 = (0x02 << SST_PATH_ID_SHIFT), | ||
63 | SST_PATH_INDEX_CODEC_OUT1 = (0x03 << SST_PATH_ID_SHIFT), | ||
64 | |||
65 | SST_PATH_INDEX_SPROT_LOOP_OUT = (0x04 << SST_PATH_ID_SHIFT), | ||
66 | SST_PATH_INDEX_MEDIA_LOOP1_OUT = (0x05 << SST_PATH_ID_SHIFT), | ||
67 | SST_PATH_INDEX_MEDIA_LOOP2_OUT = (0x06 << SST_PATH_ID_SHIFT), | ||
68 | |||
69 | SST_PATH_INDEX_VOIP_OUT = (0x0C << SST_PATH_ID_SHIFT), | ||
70 | SST_PATH_INDEX_PCM0_OUT = (0x0D << SST_PATH_ID_SHIFT), | ||
71 | SST_PATH_INDEX_PCM1_OUT = (0x0E << SST_PATH_ID_SHIFT), | ||
72 | SST_PATH_INDEX_PCM2_OUT = (0x0F << SST_PATH_ID_SHIFT), | ||
73 | |||
74 | SST_PATH_INDEX_MEDIA0_OUT = (0x12 << SST_PATH_ID_SHIFT), | ||
75 | SST_PATH_INDEX_MEDIA1_OUT = (0x13 << SST_PATH_ID_SHIFT), | ||
76 | |||
77 | |||
78 | /* Start of input paths */ | ||
79 | SST_PATH_INDEX_CODEC_IN0 = (0x82 << SST_PATH_ID_SHIFT), | ||
80 | SST_PATH_INDEX_CODEC_IN1 = (0x83 << SST_PATH_ID_SHIFT), | ||
81 | |||
82 | SST_PATH_INDEX_SPROT_LOOP_IN = (0x84 << SST_PATH_ID_SHIFT), | ||
83 | SST_PATH_INDEX_MEDIA_LOOP1_IN = (0x85 << SST_PATH_ID_SHIFT), | ||
84 | SST_PATH_INDEX_MEDIA_LOOP2_IN = (0x86 << SST_PATH_ID_SHIFT), | ||
85 | |||
86 | SST_PATH_INDEX_VOIP_IN = (0x8C << SST_PATH_ID_SHIFT), | ||
87 | |||
88 | SST_PATH_INDEX_PCM0_IN = (0x8D << SST_PATH_ID_SHIFT), | ||
89 | SST_PATH_INDEX_PCM1_IN = (0x8E << SST_PATH_ID_SHIFT), | ||
90 | |||
91 | SST_PATH_INDEX_MEDIA0_IN = (0x8F << SST_PATH_ID_SHIFT), | ||
92 | SST_PATH_INDEX_MEDIA1_IN = (0x90 << SST_PATH_ID_SHIFT), | ||
93 | SST_PATH_INDEX_MEDIA2_IN = (0x91 << SST_PATH_ID_SHIFT), | ||
94 | |||
95 | SST_PATH_INDEX_MEDIA3_IN = (0x9C << SST_PATH_ID_SHIFT), | ||
96 | |||
97 | SST_PATH_INDEX_RESERVED = (0xFF << SST_PATH_ID_SHIFT), | ||
98 | }; | ||
99 | |||
100 | /* | ||
101 | * path IDs | ||
102 | */ | ||
103 | enum sst_swm_inputs { | ||
104 | SST_SWM_IN_CODEC0 = (SST_PATH_INDEX_CODEC_IN0 | SST_DEFAULT_CELL_NBR), | ||
105 | SST_SWM_IN_CODEC1 = (SST_PATH_INDEX_CODEC_IN1 | SST_DEFAULT_CELL_NBR), | ||
106 | SST_SWM_IN_SPROT_LOOP = (SST_PATH_INDEX_SPROT_LOOP_IN | SST_DEFAULT_CELL_NBR), | ||
107 | SST_SWM_IN_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_IN | SST_DEFAULT_CELL_NBR), | ||
108 | SST_SWM_IN_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_IN | SST_DEFAULT_CELL_NBR), | ||
109 | SST_SWM_IN_VOIP = (SST_PATH_INDEX_VOIP_IN | SST_DEFAULT_CELL_NBR), | ||
110 | SST_SWM_IN_PCM0 = (SST_PATH_INDEX_PCM0_IN | SST_DEFAULT_CELL_NBR), | ||
111 | SST_SWM_IN_PCM1 = (SST_PATH_INDEX_PCM1_IN | SST_DEFAULT_CELL_NBR), | ||
112 | SST_SWM_IN_MEDIA0 = (SST_PATH_INDEX_MEDIA0_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
113 | SST_SWM_IN_MEDIA1 = (SST_PATH_INDEX_MEDIA1_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
114 | SST_SWM_IN_MEDIA2 = (SST_PATH_INDEX_MEDIA2_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
115 | SST_SWM_IN_MEDIA3 = (SST_PATH_INDEX_MEDIA3_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
116 | SST_SWM_IN_END = (SST_PATH_INDEX_RESERVED | SST_DEFAULT_CELL_NBR) | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * path IDs | ||
121 | */ | ||
122 | enum sst_swm_outputs { | ||
123 | SST_SWM_OUT_CODEC0 = (SST_PATH_INDEX_CODEC_OUT0 | SST_DEFAULT_CELL_NBR), | ||
124 | SST_SWM_OUT_CODEC1 = (SST_PATH_INDEX_CODEC_OUT1 | SST_DEFAULT_CELL_NBR), | ||
125 | SST_SWM_OUT_SPROT_LOOP = (SST_PATH_INDEX_SPROT_LOOP_OUT | SST_DEFAULT_CELL_NBR), | ||
126 | SST_SWM_OUT_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR), | ||
127 | SST_SWM_OUT_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR), | ||
128 | SST_SWM_OUT_VOIP = (SST_PATH_INDEX_VOIP_OUT | SST_DEFAULT_CELL_NBR), | ||
129 | SST_SWM_OUT_PCM0 = (SST_PATH_INDEX_PCM0_OUT | SST_DEFAULT_CELL_NBR), | ||
130 | SST_SWM_OUT_PCM1 = (SST_PATH_INDEX_PCM1_OUT | SST_DEFAULT_CELL_NBR), | ||
131 | SST_SWM_OUT_PCM2 = (SST_PATH_INDEX_PCM2_OUT | SST_DEFAULT_CELL_NBR), | ||
132 | SST_SWM_OUT_MEDIA0 = (SST_PATH_INDEX_MEDIA0_OUT | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
133 | SST_SWM_OUT_MEDIA1 = (SST_PATH_INDEX_MEDIA1_OUT | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ | ||
134 | SST_SWM_OUT_END = (SST_PATH_INDEX_RESERVED | SST_DEFAULT_CELL_NBR), | ||
135 | }; | ||
136 | |||
137 | enum sst_ipc_msg { | ||
138 | SST_IPC_IA_CMD = 1, | ||
139 | SST_IPC_IA_SET_PARAMS, | ||
140 | SST_IPC_IA_GET_PARAMS, | ||
141 | }; | ||
142 | |||
143 | enum sst_cmd_type { | ||
144 | SST_CMD_BYTES_SET = 1, | ||
145 | SST_CMD_BYTES_GET = 2, | ||
146 | }; | ||
147 | |||
148 | enum sst_task { | ||
149 | SST_TASK_SBA = 1, | ||
150 | SST_TASK_MMX, | ||
151 | }; | ||
152 | |||
153 | enum sst_type { | ||
154 | SST_TYPE_CMD = 1, | ||
155 | SST_TYPE_PARAMS, | ||
156 | }; | ||
157 | |||
158 | enum sst_flag { | ||
159 | SST_FLAG_BLOCKED = 1, | ||
160 | SST_FLAG_NONBLOCK, | ||
161 | }; | ||
162 | |||
163 | /* | ||
164 | * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command | ||
165 | */ | ||
166 | enum sst_gain_index { | ||
167 | /* GAIN IDs for SB task start here */ | ||
168 | SST_GAIN_INDEX_CODEC_OUT0, | ||
169 | SST_GAIN_INDEX_CODEC_OUT1, | ||
170 | SST_GAIN_INDEX_CODEC_IN0, | ||
171 | SST_GAIN_INDEX_CODEC_IN1, | ||
172 | |||
173 | SST_GAIN_INDEX_SPROT_LOOP_OUT, | ||
174 | SST_GAIN_INDEX_MEDIA_LOOP1_OUT, | ||
175 | SST_GAIN_INDEX_MEDIA_LOOP2_OUT, | ||
176 | |||
177 | SST_GAIN_INDEX_PCM0_IN_LEFT, | ||
178 | SST_GAIN_INDEX_PCM0_IN_RIGHT, | ||
179 | |||
180 | SST_GAIN_INDEX_PCM1_OUT_LEFT, | ||
181 | SST_GAIN_INDEX_PCM1_OUT_RIGHT, | ||
182 | SST_GAIN_INDEX_PCM1_IN_LEFT, | ||
183 | SST_GAIN_INDEX_PCM1_IN_RIGHT, | ||
184 | SST_GAIN_INDEX_PCM2_OUT_LEFT, | ||
185 | |||
186 | SST_GAIN_INDEX_PCM2_OUT_RIGHT, | ||
187 | SST_GAIN_INDEX_VOIP_OUT, | ||
188 | SST_GAIN_INDEX_VOIP_IN, | ||
189 | |||
190 | /* Gain IDs for MMX task start here */ | ||
191 | SST_GAIN_INDEX_MEDIA0_IN_LEFT, | ||
192 | SST_GAIN_INDEX_MEDIA0_IN_RIGHT, | ||
193 | SST_GAIN_INDEX_MEDIA1_IN_LEFT, | ||
194 | SST_GAIN_INDEX_MEDIA1_IN_RIGHT, | ||
195 | |||
196 | SST_GAIN_INDEX_MEDIA2_IN_LEFT, | ||
197 | SST_GAIN_INDEX_MEDIA2_IN_RIGHT, | ||
198 | |||
199 | SST_GAIN_INDEX_GAIN_END | ||
200 | }; | ||
201 | |||
202 | /* | ||
203 | * Audio DSP module IDs specified by FW spec | ||
204 | * TODO: Update with all modules | ||
205 | */ | ||
206 | enum sst_module_id { | ||
207 | SST_MODULE_ID_PCM = 0x0001, | ||
208 | SST_MODULE_ID_MP3 = 0x0002, | ||
209 | SST_MODULE_ID_MP24 = 0x0003, | ||
210 | SST_MODULE_ID_AAC = 0x0004, | ||
211 | SST_MODULE_ID_AACP = 0x0005, | ||
212 | SST_MODULE_ID_EAACP = 0x0006, | ||
213 | SST_MODULE_ID_WMA9 = 0x0007, | ||
214 | SST_MODULE_ID_WMA10 = 0x0008, | ||
215 | SST_MODULE_ID_WMA10P = 0x0009, | ||
216 | SST_MODULE_ID_RA = 0x000A, | ||
217 | SST_MODULE_ID_DDAC3 = 0x000B, | ||
218 | SST_MODULE_ID_TRUE_HD = 0x000C, | ||
219 | SST_MODULE_ID_HD_PLUS = 0x000D, | ||
220 | |||
221 | SST_MODULE_ID_SRC = 0x0064, | ||
222 | SST_MODULE_ID_DOWNMIX = 0x0066, | ||
223 | SST_MODULE_ID_GAIN_CELL = 0x0067, | ||
224 | SST_MODULE_ID_SPROT = 0x006D, | ||
225 | SST_MODULE_ID_BASS_BOOST = 0x006E, | ||
226 | SST_MODULE_ID_STEREO_WDNG = 0x006F, | ||
227 | SST_MODULE_ID_AV_REMOVAL = 0x0070, | ||
228 | SST_MODULE_ID_MIC_EQ = 0x0071, | ||
229 | SST_MODULE_ID_SPL = 0x0072, | ||
230 | SST_MODULE_ID_ALGO_VTSV = 0x0073, | ||
231 | SST_MODULE_ID_NR = 0x0076, | ||
232 | SST_MODULE_ID_BWX = 0x0077, | ||
233 | SST_MODULE_ID_DRP = 0x0078, | ||
234 | SST_MODULE_ID_MDRP = 0x0079, | ||
235 | |||
236 | SST_MODULE_ID_ANA = 0x007A, | ||
237 | SST_MODULE_ID_AEC = 0x007B, | ||
238 | SST_MODULE_ID_NR_SNS = 0x007C, | ||
239 | SST_MODULE_ID_SER = 0x007D, | ||
240 | SST_MODULE_ID_AGC = 0x007E, | ||
241 | |||
242 | SST_MODULE_ID_CNI = 0x007F, | ||
243 | SST_MODULE_ID_CONTEXT_ALGO_AWARE = 0x0080, | ||
244 | SST_MODULE_ID_FIR_24 = 0x0081, | ||
245 | SST_MODULE_ID_IIR_24 = 0x0082, | ||
246 | |||
247 | SST_MODULE_ID_ASRC = 0x0083, | ||
248 | SST_MODULE_ID_TONE_GEN = 0x0084, | ||
249 | SST_MODULE_ID_BMF = 0x0086, | ||
250 | SST_MODULE_ID_EDL = 0x0087, | ||
251 | SST_MODULE_ID_GLC = 0x0088, | ||
252 | |||
253 | SST_MODULE_ID_FIR_16 = 0x0089, | ||
254 | SST_MODULE_ID_IIR_16 = 0x008A, | ||
255 | SST_MODULE_ID_DNR = 0x008B, | ||
256 | |||
257 | SST_MODULE_ID_VIRTUALIZER = 0x008C, | ||
258 | SST_MODULE_ID_VISUALIZATION = 0x008D, | ||
259 | SST_MODULE_ID_LOUDNESS_OPTIMIZER = 0x008E, | ||
260 | SST_MODULE_ID_REVERBERATION = 0x008F, | ||
261 | |||
262 | SST_MODULE_ID_CNI_TX = 0x0090, | ||
263 | SST_MODULE_ID_REF_LINE = 0x0091, | ||
264 | SST_MODULE_ID_VOLUME = 0x0092, | ||
265 | SST_MODULE_ID_FILT_DCR = 0x0094, | ||
266 | SST_MODULE_ID_SLV = 0x009A, | ||
267 | SST_MODULE_ID_NLF = 0x009B, | ||
268 | SST_MODULE_ID_TNR = 0x009C, | ||
269 | SST_MODULE_ID_WNR = 0x009D, | ||
270 | |||
271 | SST_MODULE_ID_LOG = 0xFF00, | ||
272 | |||
273 | SST_MODULE_ID_TASK = 0xFFFF, | ||
274 | }; | ||
275 | |||
276 | enum sst_cmd { | ||
277 | SBA_IDLE = 14, | ||
278 | SBA_VB_SET_SPEECH_PATH = 26, | ||
279 | MMX_SET_GAIN = 33, | ||
280 | SBA_VB_SET_GAIN = 33, | ||
281 | FBA_VB_RX_CNI = 35, | ||
282 | MMX_SET_GAIN_TIMECONST = 36, | ||
283 | SBA_VB_SET_TIMECONST = 36, | ||
284 | SBA_VB_START = 85, | ||
285 | SBA_SET_SWM = 114, | ||
286 | SBA_SET_MDRP = 116, | ||
287 | SBA_HW_SET_SSP = 117, | ||
288 | SBA_SET_MEDIA_LOOP_MAP = 118, | ||
289 | SBA_SET_MEDIA_PATH = 119, | ||
290 | MMX_SET_MEDIA_PATH = 119, | ||
291 | SBA_VB_LPRO = 126, | ||
292 | SBA_VB_SET_FIR = 128, | ||
293 | SBA_VB_SET_IIR = 129, | ||
294 | SBA_SET_SSP_SLOT_MAP = 130, | ||
295 | }; | ||
296 | |||
297 | enum sst_dsp_switch { | ||
298 | SST_SWITCH_OFF = 0, | ||
299 | SST_SWITCH_ON = 3, | ||
300 | }; | ||
301 | |||
302 | enum sst_path_switch { | ||
303 | SST_PATH_OFF = 0, | ||
304 | SST_PATH_ON = 1, | ||
305 | }; | ||
306 | |||
307 | enum sst_swm_state { | ||
308 | SST_SWM_OFF = 0, | ||
309 | SST_SWM_ON = 3, | ||
310 | }; | ||
311 | |||
312 | #define SST_FILL_LOCATION_IDS(dst, cell_idx, pipe_id) do { \ | ||
313 | dst.location_id.p.cell_nbr_idx = (cell_idx); \ | ||
314 | dst.location_id.p.path_id = (pipe_id); \ | ||
315 | } while (0) | ||
316 | #define SST_FILL_LOCATION_ID(dst, loc_id) (\ | ||
317 | dst.location_id.f = (loc_id)) | ||
318 | #define SST_FILL_MODULE_ID(dst, mod_id) (\ | ||
319 | dst.module_id = (mod_id)) | ||
320 | |||
321 | #define SST_FILL_DESTINATION1(dst, id) do { \ | ||
322 | SST_FILL_LOCATION_ID(dst, (id) & 0xFFFF); \ | ||
323 | SST_FILL_MODULE_ID(dst, ((id) & 0xFFFF0000) >> 16); \ | ||
324 | } while (0) | ||
325 | #define SST_FILL_DESTINATION2(dst, loc_id, mod_id) do { \ | ||
326 | SST_FILL_LOCATION_ID(dst, loc_id); \ | ||
327 | SST_FILL_MODULE_ID(dst, mod_id); \ | ||
328 | } while (0) | ||
329 | #define SST_FILL_DESTINATION3(dst, cell_idx, path_id, mod_id) do { \ | ||
330 | SST_FILL_LOCATION_IDS(dst, cell_idx, path_id); \ | ||
331 | SST_FILL_MODULE_ID(dst, mod_id); \ | ||
332 | } while (0) | ||
333 | |||
334 | #define SST_FILL_DESTINATION(level, dst, ...) \ | ||
335 | SST_FILL_DESTINATION##level(dst, __VA_ARGS__) | ||
336 | #define SST_FILL_DEFAULT_DESTINATION(dst) \ | ||
337 | SST_FILL_DESTINATION(2, dst, SST_DEFAULT_LOCATION_ID, SST_DEFAULT_MODULE_ID) | ||
338 | |||
339 | struct sst_destination_id { | ||
340 | union sst_location_id { | ||
341 | struct { | ||
342 | u8 cell_nbr_idx; /* module index */ | ||
343 | u8 path_id; /* pipe_id */ | ||
344 | } __packed p; /* part */ | ||
345 | u16 f; /* full */ | ||
346 | } __packed location_id; | ||
347 | u16 module_id; | ||
348 | } __packed; | ||
349 | struct sst_dsp_header { | ||
350 | struct sst_destination_id dst; | ||
351 | u16 command_id; | ||
352 | u16 length; | ||
353 | } __packed; | ||
354 | |||
355 | /* | ||
356 | * | ||
357 | * Common Commands | ||
358 | * | ||
359 | */ | ||
360 | struct sst_cmd_generic { | ||
361 | struct sst_dsp_header header; | ||
362 | } __packed; | ||
363 | struct sst_cmd_set_params { | ||
364 | struct sst_destination_id dst; | ||
365 | u16 command_id; | ||
366 | char params[0]; | ||
367 | } __packed; | ||
368 | #define SST_CONTROL_NAME(xpname, xmname, xinstance, xtype) \ | ||
369 | xpname " " xmname " " #xinstance " " xtype | ||
370 | |||
371 | #define SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, xtype, xsubmodule) \ | ||
372 | xpname " " xmname " " #xinstance " " xtype " " xsubmodule | ||
373 | enum sst_algo_kcontrol_type { | ||
374 | SST_ALGO_PARAMS, | ||
375 | SST_ALGO_BYPASS, | ||
376 | }; | ||
377 | |||
378 | struct sst_algo_control { | ||
379 | enum sst_algo_kcontrol_type type; | ||
380 | int max; | ||
381 | u16 module_id; | ||
382 | u16 pipe_id; | ||
383 | u16 task_id; | ||
384 | u16 cmd_id; | ||
385 | bool bypass; | ||
386 | unsigned char *params; | ||
387 | struct snd_soc_dapm_widget *w; | ||
388 | }; | ||
389 | |||
390 | /* size of the control = size of params + size of length field */ | ||
391 | #define SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, xmod, xtask, xcmd) \ | ||
392 | (struct sst_algo_control){ \ | ||
393 | .max = xcount + sizeof(u16), .type = xtype, .module_id = xmod, \ | ||
394 | .pipe_id = xpipe, .task_id = xtask, .cmd_id = xcmd, \ | ||
395 | } | ||
396 | |||
397 | #define SST_ALGO_KCONTROL(xname, xcount, xmod, xpipe, \ | ||
398 | xtask, xcmd, xtype, xinfo, xget, xput) \ | ||
399 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
400 | .name = xname, \ | ||
401 | .info = xinfo, .get = xget, .put = xput, \ | ||
402 | .private_value = (unsigned long)& \ | ||
403 | SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, \ | ||
404 | xmod, xtask, xcmd), \ | ||
405 | } | ||
406 | |||
407 | #define SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, \ | ||
408 | xpipe, xinstance, xtask, xcmd) \ | ||
409 | SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "params"), \ | ||
410 | xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS, \ | ||
411 | sst_algo_bytes_ctl_info, \ | ||
412 | sst_algo_control_get, sst_algo_control_set) | ||
413 | |||
414 | #define SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask) \ | ||
415 | SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "bypass"), \ | ||
416 | 0, xmod, xpipe, xtask, 0, SST_ALGO_BYPASS, \ | ||
417 | snd_soc_info_bool_ext, \ | ||
418 | sst_algo_control_get, sst_algo_control_set) | ||
419 | |||
420 | #define SST_ALGO_BYPASS_PARAMS(xpname, xmname, xcount, xmod, xpipe, \ | ||
421 | xinstance, xtask, xcmd) \ | ||
422 | SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask), \ | ||
423 | SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, xpipe, xinstance, xtask, xcmd) | ||
424 | |||
425 | #define SST_COMBO_ALGO_KCONTROL_BYTES(xpname, xmname, xsubmod, xcount, xmod, \ | ||
426 | xpipe, xinstance, xtask, xcmd) \ | ||
427 | SST_ALGO_KCONTROL(SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, "params", \ | ||
428 | xsubmod), \ | ||
429 | xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS, \ | ||
430 | sst_algo_bytes_ctl_info, \ | ||
431 | sst_algo_control_get, sst_algo_control_set) | ||
432 | |||
433 | |||
434 | struct sst_enum { | ||
435 | bool tx; | ||
436 | unsigned short reg; | ||
437 | unsigned int max; | ||
438 | const char * const *texts; | ||
439 | struct snd_soc_dapm_widget *w; | ||
440 | }; | ||
29 | 441 | ||
30 | #endif | 442 | #endif |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 61bf6da4bb02..33fc5c3abf55 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -138,11 +138,10 @@ static inline unsigned int hsw_ipc_to_mixer(u32 value) | |||
138 | static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, | 138 | static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, |
139 | struct snd_ctl_elem_value *ucontrol) | 139 | struct snd_ctl_elem_value *ucontrol) |
140 | { | 140 | { |
141 | struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol); | 141 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
142 | struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(cmpnt); | ||
142 | struct soc_mixer_control *mc = | 143 | struct soc_mixer_control *mc = |
143 | (struct soc_mixer_control *)kcontrol->private_value; | 144 | (struct soc_mixer_control *)kcontrol->private_value; |
144 | struct hsw_priv_data *pdata = | ||
145 | snd_soc_platform_get_drvdata(platform); | ||
146 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 145 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; |
147 | struct sst_hsw *hsw = pdata->hsw; | 146 | struct sst_hsw *hsw = pdata->hsw; |
148 | u32 volume; | 147 | u32 volume; |
@@ -176,11 +175,10 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, | |||
176 | static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, | 175 | static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, |
177 | struct snd_ctl_elem_value *ucontrol) | 176 | struct snd_ctl_elem_value *ucontrol) |
178 | { | 177 | { |
179 | struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol); | 178 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
179 | struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(cmpnt); | ||
180 | struct soc_mixer_control *mc = | 180 | struct soc_mixer_control *mc = |
181 | (struct soc_mixer_control *)kcontrol->private_value; | 181 | (struct soc_mixer_control *)kcontrol->private_value; |
182 | struct hsw_priv_data *pdata = | ||
183 | snd_soc_platform_get_drvdata(platform); | ||
184 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 182 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; |
185 | struct sst_hsw *hsw = pdata->hsw; | 183 | struct sst_hsw *hsw = pdata->hsw; |
186 | u32 volume; | 184 | u32 volume; |
@@ -208,8 +206,8 @@ static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, | |||
208 | static int hsw_volume_put(struct snd_kcontrol *kcontrol, | 206 | static int hsw_volume_put(struct snd_kcontrol *kcontrol, |
209 | struct snd_ctl_elem_value *ucontrol) | 207 | struct snd_ctl_elem_value *ucontrol) |
210 | { | 208 | { |
211 | struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol); | 209 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
212 | struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); | 210 | struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(cmpnt); |
213 | struct sst_hsw *hsw = pdata->hsw; | 211 | struct sst_hsw *hsw = pdata->hsw; |
214 | u32 volume; | 212 | u32 volume; |
215 | 213 | ||
@@ -233,8 +231,8 @@ static int hsw_volume_put(struct snd_kcontrol *kcontrol, | |||
233 | static int hsw_volume_get(struct snd_kcontrol *kcontrol, | 231 | static int hsw_volume_get(struct snd_kcontrol *kcontrol, |
234 | struct snd_ctl_elem_value *ucontrol) | 232 | struct snd_ctl_elem_value *ucontrol) |
235 | { | 233 | { |
236 | struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol); | 234 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
237 | struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); | 235 | struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(cmpnt); |
238 | struct sst_hsw *hsw = pdata->hsw; | 236 | struct sst_hsw *hsw = pdata->hsw; |
239 | unsigned int volume = 0; | 237 | unsigned int volume = 0; |
240 | 238 | ||
@@ -778,20 +776,11 @@ static const struct snd_soc_dapm_route graph[] = { | |||
778 | 776 | ||
779 | static int hsw_pcm_probe(struct snd_soc_platform *platform) | 777 | static int hsw_pcm_probe(struct snd_soc_platform *platform) |
780 | { | 778 | { |
779 | struct hsw_priv_data *priv_data = snd_soc_platform_get_drvdata(platform); | ||
781 | struct sst_pdata *pdata = dev_get_platdata(platform->dev); | 780 | struct sst_pdata *pdata = dev_get_platdata(platform->dev); |
782 | struct hsw_priv_data *priv_data; | 781 | struct device *dma_dev = pdata->dma_dev; |
783 | struct device *dma_dev; | ||
784 | int i, ret = 0; | 782 | int i, ret = 0; |
785 | 783 | ||
786 | if (!pdata) | ||
787 | return -ENODEV; | ||
788 | |||
789 | dma_dev = pdata->dma_dev; | ||
790 | |||
791 | priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); | ||
792 | priv_data->hsw = pdata->dsp; | ||
793 | snd_soc_platform_set_drvdata(platform, priv_data); | ||
794 | |||
795 | /* allocate DSP buffer page tables */ | 784 | /* allocate DSP buffer page tables */ |
796 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { | 785 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { |
797 | 786 | ||
@@ -848,27 +837,38 @@ static struct snd_soc_platform_driver hsw_soc_platform = { | |||
848 | .ops = &hsw_pcm_ops, | 837 | .ops = &hsw_pcm_ops, |
849 | .pcm_new = hsw_pcm_new, | 838 | .pcm_new = hsw_pcm_new, |
850 | .pcm_free = hsw_pcm_free, | 839 | .pcm_free = hsw_pcm_free, |
851 | .controls = hsw_volume_controls, | ||
852 | .num_controls = ARRAY_SIZE(hsw_volume_controls), | ||
853 | .dapm_widgets = widgets, | ||
854 | .num_dapm_widgets = ARRAY_SIZE(widgets), | ||
855 | .dapm_routes = graph, | ||
856 | .num_dapm_routes = ARRAY_SIZE(graph), | ||
857 | }; | 840 | }; |
858 | 841 | ||
859 | static const struct snd_soc_component_driver hsw_dai_component = { | 842 | static const struct snd_soc_component_driver hsw_dai_component = { |
860 | .name = "haswell-dai", | 843 | .name = "haswell-dai", |
844 | .controls = hsw_volume_controls, | ||
845 | .num_controls = ARRAY_SIZE(hsw_volume_controls), | ||
846 | .dapm_widgets = widgets, | ||
847 | .num_dapm_widgets = ARRAY_SIZE(widgets), | ||
848 | .dapm_routes = graph, | ||
849 | .num_dapm_routes = ARRAY_SIZE(graph), | ||
861 | }; | 850 | }; |
862 | 851 | ||
863 | static int hsw_pcm_dev_probe(struct platform_device *pdev) | 852 | static int hsw_pcm_dev_probe(struct platform_device *pdev) |
864 | { | 853 | { |
865 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); | 854 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); |
855 | struct hsw_priv_data *priv_data; | ||
866 | int ret; | 856 | int ret; |
867 | 857 | ||
858 | if (!sst_pdata) | ||
859 | return -EINVAL; | ||
860 | |||
861 | priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv_data), GFP_KERNEL); | ||
862 | if (!priv_data) | ||
863 | return -ENOMEM; | ||
864 | |||
868 | ret = sst_hsw_dsp_init(&pdev->dev, sst_pdata); | 865 | ret = sst_hsw_dsp_init(&pdev->dev, sst_pdata); |
869 | if (ret < 0) | 866 | if (ret < 0) |
870 | return -ENODEV; | 867 | return -ENODEV; |
871 | 868 | ||
869 | priv_data->hsw = sst_pdata->dsp; | ||
870 | platform_set_drvdata(pdev, priv_data); | ||
871 | |||
872 | ret = snd_soc_register_platform(&pdev->dev, &hsw_soc_platform); | 872 | ret = snd_soc_register_platform(&pdev->dev, &hsw_soc_platform); |
873 | if (ret < 0) | 873 | if (ret < 0) |
874 | goto err_plat; | 874 | goto err_plat; |
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c index 29c059ca19e8..59467775c9b8 100644 --- a/sound/soc/intel/sst-mfld-platform-compress.c +++ b/sound/soc/intel/sst-mfld-platform-compress.c | |||
@@ -86,7 +86,7 @@ static int sst_platform_compr_free(struct snd_compr_stream *cstream) | |||
86 | /*need to check*/ | 86 | /*need to check*/ |
87 | str_id = stream->id; | 87 | str_id = stream->id; |
88 | if (str_id) | 88 | if (str_id) |
89 | ret_val = stream->compr_ops->close(str_id); | 89 | ret_val = stream->compr_ops->close(sst->dev, str_id); |
90 | module_put(sst->dev->driver->owner); | 90 | module_put(sst->dev->driver->owner); |
91 | kfree(stream); | 91 | kfree(stream); |
92 | pr_debug("%s: %d\n", __func__, ret_val); | 92 | pr_debug("%s: %d\n", __func__, ret_val); |
@@ -158,7 +158,7 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | |||
158 | cb.drain_cb_param = cstream; | 158 | cb.drain_cb_param = cstream; |
159 | cb.drain_notify = sst_drain_notify; | 159 | cb.drain_notify = sst_drain_notify; |
160 | 160 | ||
161 | retval = stream->compr_ops->open(&str_params, &cb); | 161 | retval = stream->compr_ops->open(sst->dev, &str_params, &cb); |
162 | if (retval < 0) { | 162 | if (retval < 0) { |
163 | pr_err("stream allocation failed %d\n", retval); | 163 | pr_err("stream allocation failed %d\n", retval); |
164 | return retval; | 164 | return retval; |
@@ -170,10 +170,30 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | |||
170 | 170 | ||
171 | static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) | 171 | static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) |
172 | { | 172 | { |
173 | struct sst_runtime_stream *stream = | 173 | struct sst_runtime_stream *stream = cstream->runtime->private_data; |
174 | cstream->runtime->private_data; | 174 | |
175 | 175 | switch (cmd) { | |
176 | return stream->compr_ops->control(cmd, stream->id); | 176 | case SNDRV_PCM_TRIGGER_START: |
177 | if (stream->compr_ops->stream_start) | ||
178 | return stream->compr_ops->stream_start(sst->dev, stream->id); | ||
179 | case SNDRV_PCM_TRIGGER_STOP: | ||
180 | if (stream->compr_ops->stream_drop) | ||
181 | return stream->compr_ops->stream_drop(sst->dev, stream->id); | ||
182 | case SND_COMPR_TRIGGER_DRAIN: | ||
183 | if (stream->compr_ops->stream_drain) | ||
184 | return stream->compr_ops->stream_drain(sst->dev, stream->id); | ||
185 | case SND_COMPR_TRIGGER_PARTIAL_DRAIN: | ||
186 | if (stream->compr_ops->stream_partial_drain) | ||
187 | return stream->compr_ops->stream_partial_drain(sst->dev, stream->id); | ||
188 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
189 | if (stream->compr_ops->stream_pause) | ||
190 | return stream->compr_ops->stream_pause(sst->dev, stream->id); | ||
191 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
192 | if (stream->compr_ops->stream_pause_release) | ||
193 | return stream->compr_ops->stream_pause_release(sst->dev, stream->id); | ||
194 | default: | ||
195 | return -EINVAL; | ||
196 | } | ||
177 | } | 197 | } |
178 | 198 | ||
179 | static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, | 199 | static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, |
@@ -182,7 +202,7 @@ static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, | |||
182 | struct sst_runtime_stream *stream; | 202 | struct sst_runtime_stream *stream; |
183 | 203 | ||
184 | stream = cstream->runtime->private_data; | 204 | stream = cstream->runtime->private_data; |
185 | stream->compr_ops->tstamp(stream->id, tstamp); | 205 | stream->compr_ops->tstamp(sst->dev, stream->id, tstamp); |
186 | tstamp->byte_offset = tstamp->copied_total % | 206 | tstamp->byte_offset = tstamp->copied_total % |
187 | (u32)cstream->runtime->buffer_size; | 207 | (u32)cstream->runtime->buffer_size; |
188 | pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); | 208 | pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); |
@@ -195,7 +215,7 @@ static int sst_platform_compr_ack(struct snd_compr_stream *cstream, | |||
195 | struct sst_runtime_stream *stream; | 215 | struct sst_runtime_stream *stream; |
196 | 216 | ||
197 | stream = cstream->runtime->private_data; | 217 | stream = cstream->runtime->private_data; |
198 | stream->compr_ops->ack(stream->id, (unsigned long)bytes); | 218 | stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes); |
199 | stream->bytes_written += bytes; | 219 | stream->bytes_written += bytes; |
200 | 220 | ||
201 | return 0; | 221 | return 0; |
@@ -225,7 +245,7 @@ static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream, | |||
225 | struct sst_runtime_stream *stream = | 245 | struct sst_runtime_stream *stream = |
226 | cstream->runtime->private_data; | 246 | cstream->runtime->private_data; |
227 | 247 | ||
228 | return stream->compr_ops->set_metadata(stream->id, metadata); | 248 | return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata); |
229 | } | 249 | } |
230 | 250 | ||
231 | struct snd_compr_ops sst_platform_compr_ops = { | 251 | struct snd_compr_ops sst_platform_compr_ops = { |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 706212a6a68c..aa9b600dfc9b 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -43,12 +43,12 @@ int sst_register_dsp(struct sst_device *dev) | |||
43 | return -ENODEV; | 43 | return -ENODEV; |
44 | mutex_lock(&sst_lock); | 44 | mutex_lock(&sst_lock); |
45 | if (sst) { | 45 | if (sst) { |
46 | pr_err("we already have a device %s\n", sst->name); | 46 | dev_err(dev->dev, "we already have a device %s\n", sst->name); |
47 | module_put(dev->dev->driver->owner); | 47 | module_put(dev->dev->driver->owner); |
48 | mutex_unlock(&sst_lock); | 48 | mutex_unlock(&sst_lock); |
49 | return -EEXIST; | 49 | return -EEXIST; |
50 | } | 50 | } |
51 | pr_debug("registering device %s\n", dev->name); | 51 | dev_dbg(dev->dev, "registering device %s\n", dev->name); |
52 | sst = dev; | 52 | sst = dev; |
53 | mutex_unlock(&sst_lock); | 53 | mutex_unlock(&sst_lock); |
54 | return 0; | 54 | return 0; |
@@ -70,7 +70,7 @@ int sst_unregister_dsp(struct sst_device *dev) | |||
70 | } | 70 | } |
71 | 71 | ||
72 | module_put(sst->dev->driver->owner); | 72 | module_put(sst->dev->driver->owner); |
73 | pr_debug("unreg %s\n", sst->name); | 73 | dev_dbg(dev->dev, "unreg %s\n", sst->name); |
74 | sst = NULL; | 74 | sst = NULL; |
75 | mutex_unlock(&sst_lock); | 75 | mutex_unlock(&sst_lock); |
76 | return 0; | 76 | return 0; |
@@ -252,7 +252,7 @@ int sst_fill_stream_params(void *substream, | |||
252 | } | 252 | } |
253 | 253 | ||
254 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | 254 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, |
255 | struct snd_soc_platform *platform) | 255 | struct snd_soc_dai *dai) |
256 | { | 256 | { |
257 | struct sst_runtime_stream *stream = | 257 | struct sst_runtime_stream *stream = |
258 | substream->runtime->private_data; | 258 | substream->runtime->private_data; |
@@ -260,7 +260,7 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | |||
260 | struct snd_sst_params str_params = {0}; | 260 | struct snd_sst_params str_params = {0}; |
261 | struct snd_sst_alloc_params_ext alloc_params = {0}; | 261 | struct snd_sst_alloc_params_ext alloc_params = {0}; |
262 | int ret_val = 0; | 262 | int ret_val = 0; |
263 | struct sst_data *ctx = snd_soc_platform_get_drvdata(platform); | 263 | struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); |
264 | 264 | ||
265 | /* set codec params and inform SST driver the same */ | 265 | /* set codec params and inform SST driver the same */ |
266 | sst_fill_pcm_params(substream, ¶m); | 266 | sst_fill_pcm_params(substream, ¶m); |
@@ -277,7 +277,7 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, | |||
277 | 277 | ||
278 | stream->stream_info.str_id = str_params.stream_id; | 278 | stream->stream_info.str_id = str_params.stream_id; |
279 | 279 | ||
280 | ret_val = stream->ops->open(&str_params); | 280 | ret_val = stream->ops->open(sst->dev, &str_params); |
281 | if (ret_val <= 0) | 281 | if (ret_val <= 0) |
282 | return ret_val; | 282 | return ret_val; |
283 | 283 | ||
@@ -306,22 +306,31 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
306 | { | 306 | { |
307 | struct sst_runtime_stream *stream = | 307 | struct sst_runtime_stream *stream = |
308 | substream->runtime->private_data; | 308 | substream->runtime->private_data; |
309 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
309 | int ret_val; | 310 | int ret_val; |
310 | 311 | ||
311 | pr_debug("setting buffer ptr param\n"); | 312 | dev_dbg(rtd->dev, "setting buffer ptr param\n"); |
312 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | 313 | sst_set_stream_status(stream, SST_PLATFORM_INIT); |
313 | stream->stream_info.period_elapsed = sst_period_elapsed; | 314 | stream->stream_info.period_elapsed = sst_period_elapsed; |
314 | stream->stream_info.arg = substream; | 315 | stream->stream_info.arg = substream; |
315 | stream->stream_info.buffer_ptr = 0; | 316 | stream->stream_info.buffer_ptr = 0; |
316 | stream->stream_info.sfreq = substream->runtime->rate; | 317 | stream->stream_info.sfreq = substream->runtime->rate; |
317 | ret_val = stream->ops->device_control( | 318 | ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info); |
318 | SST_SND_STREAM_INIT, &stream->stream_info); | ||
319 | if (ret_val) | 319 | if (ret_val) |
320 | pr_err("control_set ret error %d\n", ret_val); | 320 | dev_err(rtd->dev, "control_set ret error %d\n", ret_val); |
321 | return ret_val; | 321 | return ret_val; |
322 | 322 | ||
323 | } | 323 | } |
324 | /* end -- helper functions */ | 324 | |
325 | static int power_up_sst(struct sst_runtime_stream *stream) | ||
326 | { | ||
327 | return stream->ops->power(sst->dev, true); | ||
328 | } | ||
329 | |||
330 | static void power_down_sst(struct sst_runtime_stream *stream) | ||
331 | { | ||
332 | stream->ops->power(sst->dev, false); | ||
333 | } | ||
325 | 334 | ||
326 | static int sst_media_open(struct snd_pcm_substream *substream, | 335 | static int sst_media_open(struct snd_pcm_substream *substream, |
327 | struct snd_soc_dai *dai) | 336 | struct snd_soc_dai *dai) |
@@ -339,7 +348,7 @@ static int sst_media_open(struct snd_pcm_substream *substream, | |||
339 | mutex_lock(&sst_lock); | 348 | mutex_lock(&sst_lock); |
340 | if (!sst || | 349 | if (!sst || |
341 | !try_module_get(sst->dev->driver->owner)) { | 350 | !try_module_get(sst->dev->driver->owner)) { |
342 | pr_err("no device available to run\n"); | 351 | dev_err(dai->dev, "no device available to run\n"); |
343 | ret_val = -ENODEV; | 352 | ret_val = -ENODEV; |
344 | goto out_ops; | 353 | goto out_ops; |
345 | } | 354 | } |
@@ -352,6 +361,10 @@ static int sst_media_open(struct snd_pcm_substream *substream, | |||
352 | /* allocate memory for SST API set */ | 361 | /* allocate memory for SST API set */ |
353 | runtime->private_data = stream; | 362 | runtime->private_data = stream; |
354 | 363 | ||
364 | ret_val = power_up_sst(stream); | ||
365 | if (ret_val < 0) | ||
366 | return ret_val; | ||
367 | |||
355 | /* Make sure, that the period size is always even */ | 368 | /* Make sure, that the period size is always even */ |
356 | snd_pcm_hw_constraint_step(substream->runtime, 0, | 369 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
357 | SNDRV_PCM_HW_PARAM_PERIODS, 2); | 370 | SNDRV_PCM_HW_PARAM_PERIODS, 2); |
@@ -371,26 +384,29 @@ static void sst_media_close(struct snd_pcm_substream *substream, | |||
371 | int ret_val = 0, str_id; | 384 | int ret_val = 0, str_id; |
372 | 385 | ||
373 | stream = substream->runtime->private_data; | 386 | stream = substream->runtime->private_data; |
387 | power_down_sst(stream); | ||
388 | |||
374 | str_id = stream->stream_info.str_id; | 389 | str_id = stream->stream_info.str_id; |
375 | if (str_id) | 390 | if (str_id) |
376 | ret_val = stream->ops->close(str_id); | 391 | ret_val = stream->ops->close(sst->dev, str_id); |
377 | module_put(sst->dev->driver->owner); | 392 | module_put(sst->dev->driver->owner); |
378 | kfree(stream); | 393 | kfree(stream); |
379 | } | 394 | } |
380 | 395 | ||
381 | static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform, | 396 | static inline unsigned int get_current_pipe_id(struct snd_soc_dai *dai, |
382 | struct snd_pcm_substream *substream) | 397 | struct snd_pcm_substream *substream) |
383 | { | 398 | { |
384 | struct sst_data *sst = snd_soc_platform_get_drvdata(platform); | 399 | struct sst_data *sst = snd_soc_dai_get_drvdata(dai); |
385 | struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map; | 400 | struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map; |
386 | struct sst_runtime_stream *stream = | 401 | struct sst_runtime_stream *stream = |
387 | substream->runtime->private_data; | 402 | substream->runtime->private_data; |
388 | u32 str_id = stream->stream_info.str_id; | 403 | u32 str_id = stream->stream_info.str_id; |
389 | unsigned int pipe_id; | 404 | unsigned int pipe_id; |
405 | |||
390 | pipe_id = map[str_id].device_id; | 406 | pipe_id = map[str_id].device_id; |
391 | 407 | ||
392 | pr_debug("%s: got pipe_id = %#x for str_id = %d\n", | 408 | dev_dbg(dai->dev, "got pipe_id = %#x for str_id = %d\n", |
393 | __func__, pipe_id, str_id); | 409 | pipe_id, str_id); |
394 | return pipe_id; | 410 | return pipe_id; |
395 | } | 411 | } |
396 | 412 | ||
@@ -403,12 +419,11 @@ static int sst_media_prepare(struct snd_pcm_substream *substream, | |||
403 | stream = substream->runtime->private_data; | 419 | stream = substream->runtime->private_data; |
404 | str_id = stream->stream_info.str_id; | 420 | str_id = stream->stream_info.str_id; |
405 | if (stream->stream_info.str_id) { | 421 | if (stream->stream_info.str_id) { |
406 | ret_val = stream->ops->device_control( | 422 | ret_val = stream->ops->stream_drop(sst->dev, str_id); |
407 | SST_SND_DROP, &str_id); | ||
408 | return ret_val; | 423 | return ret_val; |
409 | } | 424 | } |
410 | 425 | ||
411 | ret_val = sst_platform_alloc_stream(substream, dai->platform); | 426 | ret_val = sst_platform_alloc_stream(substream, dai); |
412 | if (ret_val <= 0) | 427 | if (ret_val <= 0) |
413 | return ret_val; | 428 | return ret_val; |
414 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), | 429 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), |
@@ -461,37 +476,40 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | |||
461 | { | 476 | { |
462 | int ret_val = 0, str_id; | 477 | int ret_val = 0, str_id; |
463 | struct sst_runtime_stream *stream; | 478 | struct sst_runtime_stream *stream; |
464 | int str_cmd, status; | 479 | int status; |
480 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
465 | 481 | ||
466 | pr_debug("sst_platform_pcm_trigger called\n"); | 482 | dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n"); |
483 | if (substream->pcm->internal) | ||
484 | return 0; | ||
467 | stream = substream->runtime->private_data; | 485 | stream = substream->runtime->private_data; |
468 | str_id = stream->stream_info.str_id; | 486 | str_id = stream->stream_info.str_id; |
469 | switch (cmd) { | 487 | switch (cmd) { |
470 | case SNDRV_PCM_TRIGGER_START: | 488 | case SNDRV_PCM_TRIGGER_START: |
471 | pr_debug("sst: Trigger Start\n"); | 489 | dev_dbg(rtd->dev, "sst: Trigger Start\n"); |
472 | str_cmd = SST_SND_START; | ||
473 | status = SST_PLATFORM_RUNNING; | 490 | status = SST_PLATFORM_RUNNING; |
474 | stream->stream_info.arg = substream; | 491 | stream->stream_info.arg = substream; |
492 | ret_val = stream->ops->stream_start(sst->dev, str_id); | ||
475 | break; | 493 | break; |
476 | case SNDRV_PCM_TRIGGER_STOP: | 494 | case SNDRV_PCM_TRIGGER_STOP: |
477 | pr_debug("sst: in stop\n"); | 495 | dev_dbg(rtd->dev, "sst: in stop\n"); |
478 | str_cmd = SST_SND_DROP; | ||
479 | status = SST_PLATFORM_DROPPED; | 496 | status = SST_PLATFORM_DROPPED; |
497 | ret_val = stream->ops->stream_drop(sst->dev, str_id); | ||
480 | break; | 498 | break; |
481 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 499 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
482 | pr_debug("sst: in pause\n"); | 500 | dev_dbg(rtd->dev, "sst: in pause\n"); |
483 | str_cmd = SST_SND_PAUSE; | ||
484 | status = SST_PLATFORM_PAUSED; | 501 | status = SST_PLATFORM_PAUSED; |
502 | ret_val = stream->ops->stream_pause(sst->dev, str_id); | ||
485 | break; | 503 | break; |
486 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 504 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
487 | pr_debug("sst: in pause release\n"); | 505 | dev_dbg(rtd->dev, "sst: in pause release\n"); |
488 | str_cmd = SST_SND_RESUME; | ||
489 | status = SST_PLATFORM_RUNNING; | 506 | status = SST_PLATFORM_RUNNING; |
507 | ret_val = stream->ops->stream_pause_release(sst->dev, str_id); | ||
490 | break; | 508 | break; |
491 | default: | 509 | default: |
492 | return -EINVAL; | 510 | return -EINVAL; |
493 | } | 511 | } |
494 | ret_val = stream->ops->device_control(str_cmd, &str_id); | 512 | |
495 | if (!ret_val) | 513 | if (!ret_val) |
496 | sst_set_stream_status(stream, status); | 514 | sst_set_stream_status(stream, status); |
497 | 515 | ||
@@ -505,16 +523,16 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer | |||
505 | struct sst_runtime_stream *stream; | 523 | struct sst_runtime_stream *stream; |
506 | int ret_val, status; | 524 | int ret_val, status; |
507 | struct pcm_stream_info *str_info; | 525 | struct pcm_stream_info *str_info; |
526 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
508 | 527 | ||
509 | stream = substream->runtime->private_data; | 528 | stream = substream->runtime->private_data; |
510 | status = sst_get_stream_status(stream); | 529 | status = sst_get_stream_status(stream); |
511 | if (status == SST_PLATFORM_INIT) | 530 | if (status == SST_PLATFORM_INIT) |
512 | return 0; | 531 | return 0; |
513 | str_info = &stream->stream_info; | 532 | str_info = &stream->stream_info; |
514 | ret_val = stream->ops->device_control( | 533 | ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info); |
515 | SST_SND_BUFFER_POINTER, str_info); | ||
516 | if (ret_val) { | 534 | if (ret_val) { |
517 | pr_err("sst: error code = %d\n", ret_val); | 535 | dev_err(rtd->dev, "sst: error code = %d\n", ret_val); |
518 | return ret_val; | 536 | return ret_val; |
519 | } | 537 | } |
520 | substream->runtime->delay = str_info->pcm_delay; | 538 | substream->runtime->delay = str_info->pcm_delay; |
@@ -530,7 +548,7 @@ static struct snd_pcm_ops sst_platform_ops = { | |||
530 | 548 | ||
531 | static void sst_pcm_free(struct snd_pcm *pcm) | 549 | static void sst_pcm_free(struct snd_pcm *pcm) |
532 | { | 550 | { |
533 | pr_debug("sst_pcm_free called\n"); | 551 | dev_dbg(pcm->dev, "sst_pcm_free called\n"); |
534 | snd_pcm_lib_preallocate_free_for_all(pcm); | 552 | snd_pcm_lib_preallocate_free_for_all(pcm); |
535 | } | 553 | } |
536 | 554 | ||
@@ -547,14 +565,20 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
547 | snd_dma_continuous_data(GFP_DMA), | 565 | snd_dma_continuous_data(GFP_DMA), |
548 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 566 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
549 | if (retval) { | 567 | if (retval) { |
550 | pr_err("dma buffer allocationf fail\n"); | 568 | dev_err(rtd->dev, "dma buffer allocationf fail\n"); |
551 | return retval; | 569 | return retval; |
552 | } | 570 | } |
553 | } | 571 | } |
554 | return retval; | 572 | return retval; |
555 | } | 573 | } |
556 | 574 | ||
557 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | 575 | static int sst_soc_probe(struct snd_soc_platform *platform) |
576 | { | ||
577 | return sst_dsp_init_v2_dpcm(platform); | ||
578 | } | ||
579 | |||
580 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | ||
581 | .probe = sst_soc_probe, | ||
558 | .ops = &sst_platform_ops, | 582 | .ops = &sst_platform_ops, |
559 | .compr_ops = &sst_platform_compr_ops, | 583 | .compr_ops = &sst_platform_compr_ops, |
560 | .pcm_new = sst_pcm_new, | 584 | .pcm_new = sst_pcm_new, |
@@ -574,13 +598,11 @@ static int sst_platform_probe(struct platform_device *pdev) | |||
574 | 598 | ||
575 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); | 599 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); |
576 | if (drv == NULL) { | 600 | if (drv == NULL) { |
577 | pr_err("kzalloc failed\n"); | ||
578 | return -ENOMEM; | 601 | return -ENOMEM; |
579 | } | 602 | } |
580 | 603 | ||
581 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 604 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
582 | if (pdata == NULL) { | 605 | if (pdata == NULL) { |
583 | pr_err("kzalloc failed for pdata\n"); | ||
584 | return -ENOMEM; | 606 | return -ENOMEM; |
585 | } | 607 | } |
586 | 608 | ||
@@ -592,14 +614,14 @@ static int sst_platform_probe(struct platform_device *pdev) | |||
592 | 614 | ||
593 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); | 615 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); |
594 | if (ret) { | 616 | if (ret) { |
595 | pr_err("registering soc platform failed\n"); | 617 | dev_err(&pdev->dev, "registering soc platform failed\n"); |
596 | return ret; | 618 | return ret; |
597 | } | 619 | } |
598 | 620 | ||
599 | ret = snd_soc_register_component(&pdev->dev, &sst_component, | 621 | ret = snd_soc_register_component(&pdev->dev, &sst_component, |
600 | sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); | 622 | sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); |
601 | if (ret) { | 623 | if (ret) { |
602 | pr_err("registering cpu dais failed\n"); | 624 | dev_err(&pdev->dev, "registering cpu dais failed\n"); |
603 | snd_soc_unregister_platform(&pdev->dev); | 625 | snd_soc_unregister_platform(&pdev->dev); |
604 | } | 626 | } |
605 | return ret; | 627 | return ret; |
@@ -610,7 +632,7 @@ static int sst_platform_remove(struct platform_device *pdev) | |||
610 | 632 | ||
611 | snd_soc_unregister_component(&pdev->dev); | 633 | snd_soc_unregister_component(&pdev->dev); |
612 | snd_soc_unregister_platform(&pdev->dev); | 634 | snd_soc_unregister_platform(&pdev->dev); |
613 | pr_debug("sst_platform_remove success\n"); | 635 | dev_dbg(&pdev->dev, "sst_platform_remove success\n"); |
614 | return 0; | 636 | return 0; |
615 | } | 637 | } |
616 | 638 | ||
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 6c6a42c08e24..19f83ec51613 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h | |||
@@ -54,20 +54,6 @@ enum sst_drv_status { | |||
54 | SST_PLATFORM_DROPPED, | 54 | SST_PLATFORM_DROPPED, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | enum sst_controls { | ||
58 | SST_SND_ALLOC = 0x00, | ||
59 | SST_SND_PAUSE = 0x01, | ||
60 | SST_SND_RESUME = 0x02, | ||
61 | SST_SND_DROP = 0x03, | ||
62 | SST_SND_FREE = 0x04, | ||
63 | SST_SND_BUFFER_POINTER = 0x05, | ||
64 | SST_SND_STREAM_INIT = 0x06, | ||
65 | SST_SND_START = 0x07, | ||
66 | SST_SET_BYTE_STREAM = 0x100A, | ||
67 | SST_GET_BYTE_STREAM = 0x100B, | ||
68 | SST_MAX_CONTROLS = SST_GET_BYTE_STREAM, | ||
69 | }; | ||
70 | |||
71 | enum sst_stream_ops { | 57 | enum sst_stream_ops { |
72 | STREAM_OPS_PLAYBACK = 0, | 58 | STREAM_OPS_PLAYBACK = 0, |
73 | STREAM_OPS_CAPTURE, | 59 | STREAM_OPS_CAPTURE, |
@@ -113,24 +99,37 @@ struct sst_compress_cb { | |||
113 | 99 | ||
114 | struct compress_sst_ops { | 100 | struct compress_sst_ops { |
115 | const char *name; | 101 | const char *name; |
116 | int (*open) (struct snd_sst_params *str_params, | 102 | int (*open)(struct device *dev, |
117 | struct sst_compress_cb *cb); | 103 | struct snd_sst_params *str_params, struct sst_compress_cb *cb); |
118 | int (*control) (unsigned int cmd, unsigned int str_id); | 104 | int (*stream_start)(struct device *dev, unsigned int str_id); |
119 | int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); | 105 | int (*stream_drop)(struct device *dev, unsigned int str_id); |
120 | int (*ack) (unsigned int str_id, unsigned long bytes); | 106 | int (*stream_drain)(struct device *dev, unsigned int str_id); |
121 | int (*close) (unsigned int str_id); | 107 | int (*stream_partial_drain)(struct device *dev, unsigned int str_id); |
122 | int (*get_caps) (struct snd_compr_caps *caps); | 108 | int (*stream_pause)(struct device *dev, unsigned int str_id); |
123 | int (*get_codec_caps) (struct snd_compr_codec_caps *codec); | 109 | int (*stream_pause_release)(struct device *dev, unsigned int str_id); |
124 | int (*set_metadata) (unsigned int str_id, | 110 | |
111 | int (*tstamp)(struct device *dev, unsigned int str_id, | ||
112 | struct snd_compr_tstamp *tstamp); | ||
113 | int (*ack)(struct device *dev, unsigned int str_id, | ||
114 | unsigned long bytes); | ||
115 | int (*close)(struct device *dev, unsigned int str_id); | ||
116 | int (*get_caps)(struct snd_compr_caps *caps); | ||
117 | int (*get_codec_caps)(struct snd_compr_codec_caps *codec); | ||
118 | int (*set_metadata)(struct device *dev, unsigned int str_id, | ||
125 | struct snd_compr_metadata *mdata); | 119 | struct snd_compr_metadata *mdata); |
126 | |||
127 | }; | 120 | }; |
128 | 121 | ||
129 | struct sst_ops { | 122 | struct sst_ops { |
130 | int (*open) (struct snd_sst_params *str_param); | 123 | int (*open)(struct device *dev, struct snd_sst_params *str_param); |
131 | int (*device_control) (int cmd, void *arg); | 124 | int (*stream_init)(struct device *dev, struct pcm_stream_info *str_info); |
132 | int (*set_generic_params)(enum sst_controls cmd, void *arg); | 125 | int (*stream_start)(struct device *dev, int str_id); |
133 | int (*close) (unsigned int str_id); | 126 | int (*stream_drop)(struct device *dev, int str_id); |
127 | int (*stream_pause)(struct device *dev, int str_id); | ||
128 | int (*stream_pause_release)(struct device *dev, int str_id); | ||
129 | int (*stream_read_tstamp)(struct device *dev, struct pcm_stream_info *str_info); | ||
130 | int (*send_byte_stream)(struct device *dev, struct snd_sst_bytes_v2 *bytes); | ||
131 | int (*close)(struct device *dev, unsigned int str_id); | ||
132 | int (*power)(struct device *dev, bool state); | ||
134 | }; | 133 | }; |
135 | 134 | ||
136 | struct sst_runtime_stream { | 135 | struct sst_runtime_stream { |
@@ -152,6 +151,8 @@ struct sst_device { | |||
152 | }; | 151 | }; |
153 | 152 | ||
154 | struct sst_data; | 153 | struct sst_data; |
154 | |||
155 | int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform); | ||
155 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); | 156 | void sst_set_stream_status(struct sst_runtime_stream *stream, int state); |
156 | int sst_fill_stream_params(void *substream, const struct sst_data *ctx, | 157 | int sst_fill_stream_params(void *substream, const struct sst_data *ctx, |
157 | struct snd_sst_params *str_params, bool is_compress); | 158 | struct snd_sst_params *str_params, bool is_compress); |
@@ -166,6 +167,7 @@ struct sst_algo_int_control_v2 { | |||
166 | struct sst_data { | 167 | struct sst_data { |
167 | struct platform_device *pdev; | 168 | struct platform_device *pdev; |
168 | struct sst_platform_data *pdata; | 169 | struct sst_platform_data *pdata; |
170 | struct snd_sst_bytes_v2 *byte_stream; | ||
169 | struct mutex lock; | 171 | struct mutex lock; |
170 | }; | 172 | }; |
171 | int sst_register_dsp(struct sst_device *sst); | 173 | int sst_register_dsp(struct sst_device *sst); |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 943922c79f78..b10ae8074461 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -168,7 +168,7 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, | |||
168 | static int rx51_hp_event(struct snd_soc_dapm_widget *w, | 168 | static int rx51_hp_event(struct snd_soc_dapm_widget *w, |
169 | struct snd_kcontrol *k, int event) | 169 | struct snd_kcontrol *k, int event) |
170 | { | 170 | { |
171 | struct snd_soc_codec *codec = w->dapm->codec; | 171 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
172 | 172 | ||
173 | if (SND_SOC_DAPM_EVENT_ON(event)) | 173 | if (SND_SOC_DAPM_EVENT_ON(event)) |
174 | tpa6130a2_stereo_enable(codec, 1); | 174 | tpa6130a2_stereo_enable(codec, 1); |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index c196a466eef6..78fc159559b0 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig | |||
@@ -2,11 +2,10 @@ config SND_SOC_ROCKCHIP | |||
2 | tristate "ASoC support for Rockchip" | 2 | tristate "ASoC support for Rockchip" |
3 | depends on COMPILE_TEST || ARCH_ROCKCHIP | 3 | depends on COMPILE_TEST || ARCH_ROCKCHIP |
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | 4 | select SND_SOC_GENERIC_DMAENGINE_PCM |
5 | select SND_ROCKCHIP_I2S | ||
6 | help | 5 | help |
7 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
8 | the Rockchip SoCs' Audio interfaces. You will also need to | 7 | the Rockchip SoCs' Audio interfaces. You will also need to |
9 | select the audio interfaces to support below. | 8 | select the audio interfaces to support below. |
10 | 9 | ||
11 | config SND_ROCKCHIP_I2S | 10 | config SND_SOC_ROCKCHIP_I2S |
12 | tristate | 11 | tristate |
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index 1006418e1394..b9219092b47f 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # ROCKCHIP Platform Support | 1 | # ROCKCHIP Platform Support |
2 | snd-soc-i2s-objs := rockchip_i2s.o | 2 | snd-soc-i2s-objs := rockchip_i2s.o |
3 | 3 | ||
4 | obj-$(CONFIG_SND_ROCKCHIP_I2S) += snd-soc-i2s.o | 4 | obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-i2s.o |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index fb9e05c9f471..f373e37f8305 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -108,8 +108,10 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) | |||
108 | while (val) { | 108 | while (val) { |
109 | regmap_read(i2s->regmap, I2S_CLR, &val); | 109 | regmap_read(i2s->regmap, I2S_CLR, &val); |
110 | retry--; | 110 | retry--; |
111 | if (!retry) | 111 | if (!retry) { |
112 | dev_warn(i2s->dev, "fail to clear\n"); | 112 | dev_warn(i2s->dev, "fail to clear\n"); |
113 | break; | ||
114 | } | ||
113 | } | 115 | } |
114 | } | 116 | } |
115 | } | 117 | } |
@@ -244,16 +246,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | |||
244 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); | 246 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); |
245 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); | 247 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); |
246 | 248 | ||
247 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
248 | dai->playback_dma_data = &i2s->playback_dma_data; | ||
249 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, | ||
250 | I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE); | ||
251 | } else { | ||
252 | dai->capture_dma_data = &i2s->capture_dma_data; | ||
253 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, | ||
254 | I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE); | ||
255 | } | ||
256 | |||
257 | return 0; | 249 | return 0; |
258 | } | 250 | } |
259 | 251 | ||
@@ -301,6 +293,16 @@ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | |||
301 | return ret; | 293 | return ret; |
302 | } | 294 | } |
303 | 295 | ||
296 | static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) | ||
297 | { | ||
298 | struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); | ||
299 | |||
300 | dai->capture_dma_data = &i2s->capture_dma_data; | ||
301 | dai->playback_dma_data = &i2s->playback_dma_data; | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
304 | static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { | 306 | static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { |
305 | .hw_params = rockchip_i2s_hw_params, | 307 | .hw_params = rockchip_i2s_hw_params, |
306 | .set_sysclk = rockchip_i2s_set_sysclk, | 308 | .set_sysclk = rockchip_i2s_set_sysclk, |
@@ -309,7 +311,9 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { | |||
309 | }; | 311 | }; |
310 | 312 | ||
311 | static struct snd_soc_dai_driver rockchip_i2s_dai = { | 313 | static struct snd_soc_dai_driver rockchip_i2s_dai = { |
314 | .probe = rockchip_i2s_dai_probe, | ||
312 | .playback = { | 315 | .playback = { |
316 | .stream_name = "Playback", | ||
313 | .channels_min = 2, | 317 | .channels_min = 2, |
314 | .channels_max = 8, | 318 | .channels_max = 8, |
315 | .rates = SNDRV_PCM_RATE_8000_192000, | 319 | .rates = SNDRV_PCM_RATE_8000_192000, |
@@ -319,6 +323,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = { | |||
319 | SNDRV_PCM_FMTBIT_S24_LE), | 323 | SNDRV_PCM_FMTBIT_S24_LE), |
320 | }, | 324 | }, |
321 | .capture = { | 325 | .capture = { |
326 | .stream_name = "Capture", | ||
322 | .channels_min = 2, | 327 | .channels_min = 2, |
323 | .channels_max = 2, | 328 | .channels_max = 2, |
324 | .rates = SNDRV_PCM_RATE_8000_192000, | 329 | .rates = SNDRV_PCM_RATE_8000_192000, |
@@ -420,6 +425,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
420 | dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n"); | 425 | dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n"); |
421 | return PTR_ERR(i2s->hclk); | 426 | return PTR_ERR(i2s->hclk); |
422 | } | 427 | } |
428 | ret = clk_prepare_enable(i2s->hclk); | ||
429 | if (ret) { | ||
430 | dev_err(i2s->dev, "hclock enable failed %d\n", ret); | ||
431 | return ret; | ||
432 | } | ||
423 | 433 | ||
424 | i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); | 434 | i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); |
425 | if (IS_ERR(i2s->mclk)) { | 435 | if (IS_ERR(i2s->mclk)) { |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index db6cefa18017..0e8dd985fcb3 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c | |||
@@ -351,7 +351,7 @@ static void idma_free(struct snd_pcm *pcm) | |||
351 | if (!buf->area) | 351 | if (!buf->area) |
352 | return; | 352 | return; |
353 | 353 | ||
354 | iounmap(buf->area); | 354 | iounmap((void __iomem *)buf->area); |
355 | 355 | ||
356 | buf->area = NULL; | 356 | buf->area = NULL; |
357 | buf->addr = 0; | 357 | buf->addr = 0; |
@@ -369,7 +369,7 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream) | |||
369 | buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; | 369 | buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; |
370 | buf->addr = idma.lp_tx_addr; | 370 | buf->addr = idma.lp_tx_addr; |
371 | buf->bytes = idma_hardware.buffer_bytes_max; | 371 | buf->bytes = idma_hardware.buffer_bytes_max; |
372 | buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes); | 372 | buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes); |
373 | 373 | ||
374 | return 0; | 374 | return 0; |
375 | } | 375 | } |
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c index 278edf9e2a87..3c8f60423e82 100644 --- a/sound/soc/samsung/odroidx2_max98090.c +++ b/sound/soc/samsung/odroidx2_max98090.c | |||
@@ -66,12 +66,12 @@ static struct snd_soc_card odroidx2 = { | |||
66 | .late_probe = odroidx2_late_probe, | 66 | .late_probe = odroidx2_late_probe, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct odroidx2_drv_data odroidx2_drvdata = { | 69 | static const struct odroidx2_drv_data odroidx2_drvdata = { |
70 | .dapm_widgets = odroidx2_dapm_widgets, | 70 | .dapm_widgets = odroidx2_dapm_widgets, |
71 | .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets), | 71 | .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets), |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct odroidx2_drv_data odroidu3_drvdata = { | 74 | static const struct odroidx2_drv_data odroidu3_drvdata = { |
75 | .dapm_widgets = odroidu3_dapm_widgets, | 75 | .dapm_widgets = odroidu3_dapm_widgets, |
76 | .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets), | 76 | .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets), |
77 | }; | 77 | }; |
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 9902efcb8ea1..a05482651aae 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -228,10 +228,12 @@ static struct snd_soc_dai_link speyside_dai[] = { | |||
228 | }, | 228 | }, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm) | 231 | static int speyside_wm9081_init(struct snd_soc_component *component) |
232 | { | 232 | { |
233 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
234 | |||
233 | /* At any time the WM9081 is active it will have this clock */ | 235 | /* At any time the WM9081 is active it will have this clock */ |
234 | return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0, | 236 | return snd_soc_codec_set_sysclk(codec, WM9081_SYSCLK_MCLK, 0, |
235 | MCLK_AUDIO_RATE, 0); | 237 | MCLK_AUDIO_RATE, 0); |
236 | } | 238 | } |
237 | 239 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index c76344350e44..66fddec9543d 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1297,9 +1297,14 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1297 | struct snd_pcm_substream *substream = io->substream; | 1297 | struct snd_pcm_substream *substream = io->substream; |
1298 | struct dma_async_tx_descriptor *desc; | 1298 | struct dma_async_tx_descriptor *desc; |
1299 | int is_play = fsi_stream_is_play(fsi, io); | 1299 | int is_play = fsi_stream_is_play(fsi, io); |
1300 | enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1300 | enum dma_transfer_direction dir; |
1301 | int ret = -EIO; | 1301 | int ret = -EIO; |
1302 | 1302 | ||
1303 | if (is_play) | ||
1304 | dir = DMA_MEM_TO_DEV; | ||
1305 | else | ||
1306 | dir = DMA_DEV_TO_MEM; | ||
1307 | |||
1303 | desc = dmaengine_prep_dma_cyclic(io->chan, | 1308 | desc = dmaengine_prep_dma_cyclic(io->chan, |
1304 | substream->runtime->dma_addr, | 1309 | substream->runtime->dma_addr, |
1305 | snd_pcm_lib_buffer_bytes(substream), | 1310 | snd_pcm_lib_buffer_bytes(substream), |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 19f78963e8b9..1922ec57d10a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -798,10 +798,8 @@ if (name##_node) { \ | |||
798 | mod_parse(src); | 798 | mod_parse(src); |
799 | mod_parse(dvc); | 799 | mod_parse(dvc); |
800 | 800 | ||
801 | if (playback) | 801 | of_node_put(playback); |
802 | of_node_put(playback); | 802 | of_node_put(capture); |
803 | if (capture) | ||
804 | of_node_put(capture); | ||
805 | } | 803 | } |
806 | 804 | ||
807 | dai_i++; | 805 | dai_i++; |
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 488f9becb44f..32eb6da2d2bd 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c | |||
@@ -139,7 +139,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, | |||
139 | 139 | ||
140 | desc->callback = siu_dma_tx_complete; | 140 | desc->callback = siu_dma_tx_complete; |
141 | desc->callback_param = siu_stream; | 141 | desc->callback_param = siu_stream; |
142 | cookie = desc->tx_submit(desc); | 142 | cookie = dmaengine_submit(desc); |
143 | if (cookie < 0) { | 143 | if (cookie < 0) { |
144 | dev_err(dev, "Failed to submit a dma transfer\n"); | 144 | dev_err(dev, "Failed to submit a dma transfer\n"); |
145 | return cookie; | 145 | return cookie; |
@@ -189,7 +189,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info, | |||
189 | 189 | ||
190 | desc->callback = siu_dma_tx_complete; | 190 | desc->callback = siu_dma_tx_complete; |
191 | desc->callback_param = siu_stream; | 191 | desc->callback_param = siu_stream; |
192 | cookie = desc->tx_submit(desc); | 192 | cookie = dmaengine_submit(desc); |
193 | if (cookie < 0) { | 193 | if (cookie < 0) { |
194 | dev_err(dev, "Failed to submit dma descriptor\n"); | 194 | dev_err(dev, "Failed to submit dma descriptor\n"); |
195 | return cookie; | 195 | return cookie; |
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 3a730374e259..186dc7f33a55 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c | |||
@@ -100,6 +100,16 @@ static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai, | |||
100 | return -EINVAL; | 100 | return -EINVAL; |
101 | } | 101 | } |
102 | 102 | ||
103 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
104 | case SND_SOC_DAIFMT_NB_NF: | ||
105 | break; | ||
106 | case SND_SOC_DAIFMT_IB_NF: | ||
107 | usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK); | ||
108 | break; | ||
109 | default: | ||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
103 | return 0; | 113 | return 0; |
104 | } | 114 | } |
105 | 115 | ||
@@ -177,7 +187,7 @@ static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
177 | 187 | ||
178 | shifter_len = data_len; | 188 | shifter_len = data_len; |
179 | 189 | ||
180 | switch (usp->daifmt_format) { | 190 | switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) { |
181 | case SND_SOC_DAIFMT_I2S: | 191 | case SND_SOC_DAIFMT_I2S: |
182 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | 192 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, |
183 | USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); | 193 | USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); |
@@ -193,6 +203,18 @@ static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
193 | return -EINVAL; | 203 | return -EINVAL; |
194 | } | 204 | } |
195 | 205 | ||
206 | switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) { | ||
207 | case SND_SOC_DAIFMT_NB_NF: | ||
208 | break; | ||
209 | case SND_SOC_DAIFMT_IB_NF: | ||
210 | regmap_update_bits(usp->regmap, USP_MODE1, | ||
211 | USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING, | ||
212 | USP_RXD_ACT_EDGE_FALLING); | ||
213 | break; | ||
214 | default: | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
196 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 218 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
197 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, | 219 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, |
198 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK | 220 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d074aa91b023..4c8f8a23a0e9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -270,79 +270,54 @@ static const struct file_operations codec_reg_fops = { | |||
270 | .llseek = default_llseek, | 270 | .llseek = default_llseek, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static struct dentry *soc_debugfs_create_dir(struct dentry *parent, | 273 | static void soc_init_component_debugfs(struct snd_soc_component *component) |
274 | const char *fmt, ...) | ||
275 | { | 274 | { |
276 | struct dentry *de; | 275 | if (component->debugfs_prefix) { |
277 | va_list ap; | 276 | char *name; |
278 | char *s; | ||
279 | 277 | ||
280 | va_start(ap, fmt); | 278 | name = kasprintf(GFP_KERNEL, "%s:%s", |
281 | s = kvasprintf(GFP_KERNEL, fmt, ap); | 279 | component->debugfs_prefix, component->name); |
282 | va_end(ap); | 280 | if (name) { |
281 | component->debugfs_root = debugfs_create_dir(name, | ||
282 | component->card->debugfs_card_root); | ||
283 | kfree(name); | ||
284 | } | ||
285 | } else { | ||
286 | component->debugfs_root = debugfs_create_dir(component->name, | ||
287 | component->card->debugfs_card_root); | ||
288 | } | ||
283 | 289 | ||
284 | if (!s) | 290 | if (!component->debugfs_root) { |
285 | return NULL; | 291 | dev_warn(component->dev, |
292 | "ASoC: Failed to create component debugfs directory\n"); | ||
293 | return; | ||
294 | } | ||
286 | 295 | ||
287 | de = debugfs_create_dir(s, parent); | 296 | snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component), |
288 | kfree(s); | 297 | component->debugfs_root); |
289 | 298 | ||
290 | return de; | 299 | if (component->init_debugfs) |
300 | component->init_debugfs(component); | ||
291 | } | 301 | } |
292 | 302 | ||
293 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 303 | static void soc_cleanup_component_debugfs(struct snd_soc_component *component) |
294 | { | 304 | { |
295 | struct dentry *debugfs_card_root = codec->component.card->debugfs_card_root; | 305 | debugfs_remove_recursive(component->debugfs_root); |
306 | } | ||
296 | 307 | ||
297 | codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root, | 308 | static void soc_init_codec_debugfs(struct snd_soc_component *component) |
298 | "codec:%s", | 309 | { |
299 | codec->component.name); | 310 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); |
300 | if (!codec->debugfs_codec_root) { | ||
301 | dev_warn(codec->dev, | ||
302 | "ASoC: Failed to create codec debugfs directory\n"); | ||
303 | return; | ||
304 | } | ||
305 | 311 | ||
306 | debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root, | 312 | debugfs_create_bool("cache_sync", 0444, codec->component.debugfs_root, |
307 | &codec->cache_sync); | 313 | &codec->cache_sync); |
308 | debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root, | ||
309 | &codec->cache_only); | ||
310 | 314 | ||
311 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 315 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
312 | codec->debugfs_codec_root, | 316 | codec->component.debugfs_root, |
313 | codec, &codec_reg_fops); | 317 | codec, &codec_reg_fops); |
314 | if (!codec->debugfs_reg) | 318 | if (!codec->debugfs_reg) |
315 | dev_warn(codec->dev, | 319 | dev_warn(codec->dev, |
316 | "ASoC: Failed to create codec register debugfs file\n"); | 320 | "ASoC: Failed to create codec register debugfs file\n"); |
317 | |||
318 | snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); | ||
319 | } | ||
320 | |||
321 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | ||
322 | { | ||
323 | debugfs_remove_recursive(codec->debugfs_codec_root); | ||
324 | } | ||
325 | |||
326 | static void soc_init_platform_debugfs(struct snd_soc_platform *platform) | ||
327 | { | ||
328 | struct dentry *debugfs_card_root = platform->component.card->debugfs_card_root; | ||
329 | |||
330 | platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root, | ||
331 | "platform:%s", | ||
332 | platform->component.name); | ||
333 | if (!platform->debugfs_platform_root) { | ||
334 | dev_warn(platform->dev, | ||
335 | "ASoC: Failed to create platform debugfs directory\n"); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | snd_soc_dapm_debugfs_init(&platform->component.dapm, | ||
340 | platform->debugfs_platform_root); | ||
341 | } | ||
342 | |||
343 | static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform) | ||
344 | { | ||
345 | debugfs_remove_recursive(platform->debugfs_platform_root); | ||
346 | } | 321 | } |
347 | 322 | ||
348 | static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, | 323 | static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, |
@@ -474,19 +449,15 @@ static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | |||
474 | 449 | ||
475 | #else | 450 | #else |
476 | 451 | ||
477 | static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 452 | #define soc_init_codec_debugfs NULL |
478 | { | ||
479 | } | ||
480 | 453 | ||
481 | static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 454 | static inline void soc_init_component_debugfs( |
455 | struct snd_soc_component *component) | ||
482 | { | 456 | { |
483 | } | 457 | } |
484 | 458 | ||
485 | static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform) | 459 | static inline void soc_cleanup_component_debugfs( |
486 | { | 460 | struct snd_soc_component *component) |
487 | } | ||
488 | |||
489 | static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform) | ||
490 | { | 461 | { |
491 | } | 462 | } |
492 | 463 | ||
@@ -579,10 +550,8 @@ int snd_soc_suspend(struct device *dev) | |||
579 | struct snd_soc_codec *codec; | 550 | struct snd_soc_codec *codec; |
580 | int i, j; | 551 | int i, j; |
581 | 552 | ||
582 | /* If the initialization of this soc device failed, there is no codec | 553 | /* If the card is not initialized yet there is nothing to do */ |
583 | * associated with it. Just bail out in this case. | 554 | if (!card->instantiated) |
584 | */ | ||
585 | if (list_empty(&card->codec_dev_list)) | ||
586 | return 0; | 555 | return 0; |
587 | 556 | ||
588 | /* Due to the resume being scheduled into a workqueue we could | 557 | /* Due to the resume being scheduled into a workqueue we could |
@@ -668,7 +637,7 @@ int snd_soc_suspend(struct device *dev) | |||
668 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 637 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
669 | /* If there are paths active then the CODEC will be held with | 638 | /* If there are paths active then the CODEC will be held with |
670 | * bias _ON and should not be suspended. */ | 639 | * bias _ON and should not be suspended. */ |
671 | if (!codec->suspended && codec->driver->suspend) { | 640 | if (!codec->suspended) { |
672 | switch (codec->dapm.bias_level) { | 641 | switch (codec->dapm.bias_level) { |
673 | case SND_SOC_BIAS_STANDBY: | 642 | case SND_SOC_BIAS_STANDBY: |
674 | /* | 643 | /* |
@@ -682,8 +651,10 @@ int snd_soc_suspend(struct device *dev) | |||
682 | "ASoC: idle_bias_off CODEC on over suspend\n"); | 651 | "ASoC: idle_bias_off CODEC on over suspend\n"); |
683 | break; | 652 | break; |
684 | } | 653 | } |
654 | |||
685 | case SND_SOC_BIAS_OFF: | 655 | case SND_SOC_BIAS_OFF: |
686 | codec->driver->suspend(codec); | 656 | if (codec->driver->suspend) |
657 | codec->driver->suspend(codec); | ||
687 | codec->suspended = 1; | 658 | codec->suspended = 1; |
688 | codec->cache_sync = 1; | 659 | codec->cache_sync = 1; |
689 | if (codec->component.regmap) | 660 | if (codec->component.regmap) |
@@ -757,11 +728,12 @@ static void soc_resume_deferred(struct work_struct *work) | |||
757 | * left with bias OFF or STANDBY and suspended so we must now | 728 | * left with bias OFF or STANDBY and suspended so we must now |
758 | * resume. Otherwise the suspend was suppressed. | 729 | * resume. Otherwise the suspend was suppressed. |
759 | */ | 730 | */ |
760 | if (codec->driver->resume && codec->suspended) { | 731 | if (codec->suspended) { |
761 | switch (codec->dapm.bias_level) { | 732 | switch (codec->dapm.bias_level) { |
762 | case SND_SOC_BIAS_STANDBY: | 733 | case SND_SOC_BIAS_STANDBY: |
763 | case SND_SOC_BIAS_OFF: | 734 | case SND_SOC_BIAS_OFF: |
764 | codec->driver->resume(codec); | 735 | if (codec->driver->resume) |
736 | codec->driver->resume(codec); | ||
765 | codec->suspended = 0; | 737 | codec->suspended = 0; |
766 | break; | 738 | break; |
767 | default: | 739 | default: |
@@ -835,10 +807,8 @@ int snd_soc_resume(struct device *dev) | |||
835 | struct snd_soc_card *card = dev_get_drvdata(dev); | 807 | struct snd_soc_card *card = dev_get_drvdata(dev); |
836 | int i, ac97_control = 0; | 808 | int i, ac97_control = 0; |
837 | 809 | ||
838 | /* If the initialization of this soc device failed, there is no codec | 810 | /* If the card is not initialized yet there is nothing to do */ |
839 | * associated with it. Just bail out in this case. | 811 | if (!card->instantiated) |
840 | */ | ||
841 | if (list_empty(&card->codec_dev_list)) | ||
842 | return 0; | 812 | return 0; |
843 | 813 | ||
844 | /* activate pins from sleep state */ | 814 | /* activate pins from sleep state */ |
@@ -887,35 +857,40 @@ EXPORT_SYMBOL_GPL(snd_soc_resume); | |||
887 | static const struct snd_soc_dai_ops null_dai_ops = { | 857 | static const struct snd_soc_dai_ops null_dai_ops = { |
888 | }; | 858 | }; |
889 | 859 | ||
890 | static struct snd_soc_codec *soc_find_codec( | 860 | static struct snd_soc_component *soc_find_component( |
891 | const struct device_node *codec_of_node, | 861 | const struct device_node *of_node, const char *name) |
892 | const char *codec_name) | ||
893 | { | 862 | { |
894 | struct snd_soc_codec *codec; | 863 | struct snd_soc_component *component; |
895 | 864 | ||
896 | list_for_each_entry(codec, &codec_list, list) { | 865 | list_for_each_entry(component, &component_list, list) { |
897 | if (codec_of_node) { | 866 | if (of_node) { |
898 | if (codec->dev->of_node != codec_of_node) | 867 | if (component->dev->of_node == of_node) |
899 | continue; | 868 | return component; |
900 | } else { | 869 | } else if (strcmp(component->name, name) == 0) { |
901 | if (strcmp(codec->component.name, codec_name)) | 870 | return component; |
902 | continue; | ||
903 | } | 871 | } |
904 | |||
905 | return codec; | ||
906 | } | 872 | } |
907 | 873 | ||
908 | return NULL; | 874 | return NULL; |
909 | } | 875 | } |
910 | 876 | ||
911 | static struct snd_soc_dai *soc_find_codec_dai(struct snd_soc_codec *codec, | 877 | static struct snd_soc_dai *snd_soc_find_dai( |
912 | const char *codec_dai_name) | 878 | const struct snd_soc_dai_link_component *dlc) |
913 | { | 879 | { |
914 | struct snd_soc_dai *codec_dai; | 880 | struct snd_soc_component *component; |
881 | struct snd_soc_dai *dai; | ||
915 | 882 | ||
916 | list_for_each_entry(codec_dai, &codec->component.dai_list, list) { | 883 | /* Find CPU DAI from registered DAIs*/ |
917 | if (!strcmp(codec_dai->name, codec_dai_name)) { | 884 | list_for_each_entry(component, &component_list, list) { |
918 | return codec_dai; | 885 | if (dlc->of_node && component->dev->of_node != dlc->of_node) |
886 | continue; | ||
887 | if (dlc->name && strcmp(dev_name(component->dev), dlc->name)) | ||
888 | continue; | ||
889 | list_for_each_entry(dai, &component->dai_list, list) { | ||
890 | if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)) | ||
891 | continue; | ||
892 | |||
893 | return dai; | ||
919 | } | 894 | } |
920 | } | 895 | } |
921 | 896 | ||
@@ -926,33 +901,19 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
926 | { | 901 | { |
927 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 902 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
928 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 903 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
929 | struct snd_soc_component *component; | ||
930 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; | 904 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; |
905 | struct snd_soc_dai_link_component cpu_dai_component; | ||
931 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | 906 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
932 | struct snd_soc_platform *platform; | 907 | struct snd_soc_platform *platform; |
933 | struct snd_soc_dai *cpu_dai; | ||
934 | const char *platform_name; | 908 | const char *platform_name; |
935 | int i; | 909 | int i; |
936 | 910 | ||
937 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 911 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); |
938 | 912 | ||
939 | /* Find CPU DAI from registered DAIs*/ | 913 | cpu_dai_component.name = dai_link->cpu_name; |
940 | list_for_each_entry(component, &component_list, list) { | 914 | cpu_dai_component.of_node = dai_link->cpu_of_node; |
941 | if (dai_link->cpu_of_node && | 915 | cpu_dai_component.dai_name = dai_link->cpu_dai_name; |
942 | component->dev->of_node != dai_link->cpu_of_node) | 916 | rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component); |
943 | continue; | ||
944 | if (dai_link->cpu_name && | ||
945 | strcmp(dev_name(component->dev), dai_link->cpu_name)) | ||
946 | continue; | ||
947 | list_for_each_entry(cpu_dai, &component->dai_list, list) { | ||
948 | if (dai_link->cpu_dai_name && | ||
949 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
950 | continue; | ||
951 | |||
952 | rtd->cpu_dai = cpu_dai; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | if (!rtd->cpu_dai) { | 917 | if (!rtd->cpu_dai) { |
957 | dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", | 918 | dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", |
958 | dai_link->cpu_dai_name); | 919 | dai_link->cpu_dai_name); |
@@ -963,15 +924,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
963 | 924 | ||
964 | /* Find CODEC from registered CODECs */ | 925 | /* Find CODEC from registered CODECs */ |
965 | for (i = 0; i < rtd->num_codecs; i++) { | 926 | for (i = 0; i < rtd->num_codecs; i++) { |
966 | struct snd_soc_codec *codec; | 927 | codec_dais[i] = snd_soc_find_dai(&codecs[i]); |
967 | codec = soc_find_codec(codecs[i].of_node, codecs[i].name); | ||
968 | if (!codec) { | ||
969 | dev_err(card->dev, "ASoC: CODEC %s not registered\n", | ||
970 | codecs[i].name); | ||
971 | return -EPROBE_DEFER; | ||
972 | } | ||
973 | |||
974 | codec_dais[i] = soc_find_codec_dai(codec, codecs[i].dai_name); | ||
975 | if (!codec_dais[i]) { | 928 | if (!codec_dais[i]) { |
976 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | 929 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", |
977 | codecs[i].dai_name); | 930 | codecs[i].dai_name); |
@@ -1012,68 +965,46 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
1012 | return 0; | 965 | return 0; |
1013 | } | 966 | } |
1014 | 967 | ||
1015 | static int soc_remove_platform(struct snd_soc_platform *platform) | 968 | static void soc_remove_component(struct snd_soc_component *component) |
1016 | { | 969 | { |
1017 | int ret; | 970 | if (!component->probed) |
1018 | 971 | return; | |
1019 | if (platform->driver->remove) { | ||
1020 | ret = platform->driver->remove(platform); | ||
1021 | if (ret < 0) | ||
1022 | dev_err(platform->dev, "ASoC: failed to remove %d\n", | ||
1023 | ret); | ||
1024 | } | ||
1025 | |||
1026 | /* Make sure all DAPM widgets are freed */ | ||
1027 | snd_soc_dapm_free(&platform->component.dapm); | ||
1028 | |||
1029 | soc_cleanup_platform_debugfs(platform); | ||
1030 | platform->probed = 0; | ||
1031 | module_put(platform->dev->driver->owner); | ||
1032 | |||
1033 | return 0; | ||
1034 | } | ||
1035 | 972 | ||
1036 | static void soc_remove_codec(struct snd_soc_codec *codec) | 973 | /* This is a HACK and will be removed soon */ |
1037 | { | 974 | if (component->codec) |
1038 | int err; | 975 | list_del(&component->codec->card_list); |
1039 | 976 | ||
1040 | if (codec->driver->remove) { | 977 | if (component->remove) |
1041 | err = codec->driver->remove(codec); | 978 | component->remove(component); |
1042 | if (err < 0) | ||
1043 | dev_err(codec->dev, "ASoC: failed to remove %d\n", err); | ||
1044 | } | ||
1045 | 979 | ||
1046 | /* Make sure all DAPM widgets are freed */ | 980 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); |
1047 | snd_soc_dapm_free(&codec->dapm); | ||
1048 | 981 | ||
1049 | soc_cleanup_codec_debugfs(codec); | 982 | soc_cleanup_component_debugfs(component); |
1050 | codec->probed = 0; | 983 | component->probed = 0; |
1051 | list_del(&codec->card_list); | 984 | module_put(component->dev->driver->owner); |
1052 | module_put(codec->dev->driver->owner); | ||
1053 | } | 985 | } |
1054 | 986 | ||
1055 | static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) | 987 | static void soc_remove_dai(struct snd_soc_dai *dai, int order) |
1056 | { | 988 | { |
1057 | int err; | 989 | int err; |
1058 | 990 | ||
1059 | if (codec_dai && codec_dai->probed && | 991 | if (dai && dai->probed && |
1060 | codec_dai->driver->remove_order == order) { | 992 | dai->driver->remove_order == order) { |
1061 | if (codec_dai->driver->remove) { | 993 | if (dai->driver->remove) { |
1062 | err = codec_dai->driver->remove(codec_dai); | 994 | err = dai->driver->remove(dai); |
1063 | if (err < 0) | 995 | if (err < 0) |
1064 | dev_err(codec_dai->dev, | 996 | dev_err(dai->dev, |
1065 | "ASoC: failed to remove %s: %d\n", | 997 | "ASoC: failed to remove %s: %d\n", |
1066 | codec_dai->name, err); | 998 | dai->name, err); |
1067 | } | 999 | } |
1068 | codec_dai->probed = 0; | 1000 | dai->probed = 0; |
1069 | } | 1001 | } |
1070 | } | 1002 | } |
1071 | 1003 | ||
1072 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | 1004 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) |
1073 | { | 1005 | { |
1074 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1006 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1075 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1007 | int i; |
1076 | int i, err; | ||
1077 | 1008 | ||
1078 | /* unregister the rtd device */ | 1009 | /* unregister the rtd device */ |
1079 | if (rtd->dev_registered) { | 1010 | if (rtd->dev_registered) { |
@@ -1085,22 +1016,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1085 | 1016 | ||
1086 | /* remove the CODEC DAI */ | 1017 | /* remove the CODEC DAI */ |
1087 | for (i = 0; i < rtd->num_codecs; i++) | 1018 | for (i = 0; i < rtd->num_codecs; i++) |
1088 | soc_remove_codec_dai(rtd->codec_dais[i], order); | 1019 | soc_remove_dai(rtd->codec_dais[i], order); |
1089 | 1020 | ||
1090 | /* remove the cpu_dai */ | 1021 | soc_remove_dai(rtd->cpu_dai, order); |
1091 | if (cpu_dai && cpu_dai->probed && | ||
1092 | cpu_dai->driver->remove_order == order) { | ||
1093 | if (cpu_dai->driver->remove) { | ||
1094 | err = cpu_dai->driver->remove(cpu_dai); | ||
1095 | if (err < 0) | ||
1096 | dev_err(cpu_dai->dev, | ||
1097 | "ASoC: failed to remove %s: %d\n", | ||
1098 | cpu_dai->name, err); | ||
1099 | } | ||
1100 | cpu_dai->probed = 0; | ||
1101 | if (!cpu_dai->codec) | ||
1102 | module_put(cpu_dai->dev->driver->owner); | ||
1103 | } | ||
1104 | } | 1022 | } |
1105 | 1023 | ||
1106 | static void soc_remove_link_components(struct snd_soc_card *card, int num, | 1024 | static void soc_remove_link_components(struct snd_soc_card *card, int num, |
@@ -1109,29 +1027,24 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1109 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1027 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1110 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1028 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1111 | struct snd_soc_platform *platform = rtd->platform; | 1029 | struct snd_soc_platform *platform = rtd->platform; |
1112 | struct snd_soc_codec *codec; | 1030 | struct snd_soc_component *component; |
1113 | int i; | 1031 | int i; |
1114 | 1032 | ||
1115 | /* remove the platform */ | 1033 | /* remove the platform */ |
1116 | if (platform && platform->probed && | 1034 | if (platform && platform->component.driver->remove_order == order) |
1117 | platform->driver->remove_order == order) { | 1035 | soc_remove_component(&platform->component); |
1118 | soc_remove_platform(platform); | ||
1119 | } | ||
1120 | 1036 | ||
1121 | /* remove the CODEC-side CODEC */ | 1037 | /* remove the CODEC-side CODEC */ |
1122 | for (i = 0; i < rtd->num_codecs; i++) { | 1038 | for (i = 0; i < rtd->num_codecs; i++) { |
1123 | codec = rtd->codec_dais[i]->codec; | 1039 | component = rtd->codec_dais[i]->component; |
1124 | if (codec && codec->probed && | 1040 | if (component->driver->remove_order == order) |
1125 | codec->driver->remove_order == order) | 1041 | soc_remove_component(component); |
1126 | soc_remove_codec(codec); | ||
1127 | } | 1042 | } |
1128 | 1043 | ||
1129 | /* remove any CPU-side CODEC */ | 1044 | /* remove any CPU-side CODEC */ |
1130 | if (cpu_dai) { | 1045 | if (cpu_dai) { |
1131 | codec = cpu_dai->codec; | 1046 | if (cpu_dai->component->driver->remove_order == order) |
1132 | if (codec && codec->probed && | 1047 | soc_remove_component(cpu_dai->component); |
1133 | codec->driver->remove_order == order) | ||
1134 | soc_remove_codec(codec); | ||
1135 | } | 1048 | } |
1136 | } | 1049 | } |
1137 | 1050 | ||
@@ -1173,137 +1086,78 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1173 | } | 1086 | } |
1174 | } | 1087 | } |
1175 | 1088 | ||
1176 | static int soc_probe_codec(struct snd_soc_card *card, | 1089 | static int soc_probe_component(struct snd_soc_card *card, |
1177 | struct snd_soc_codec *codec) | 1090 | struct snd_soc_component *component) |
1178 | { | 1091 | { |
1179 | int ret = 0; | 1092 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
1180 | const struct snd_soc_codec_driver *driver = codec->driver; | ||
1181 | struct snd_soc_dai *dai; | 1093 | struct snd_soc_dai *dai; |
1094 | int ret; | ||
1182 | 1095 | ||
1183 | codec->component.card = card; | 1096 | if (component->probed) |
1184 | codec->dapm.card = card; | 1097 | return 0; |
1185 | soc_set_name_prefix(card, &codec->component); | 1098 | |
1099 | component->card = card; | ||
1100 | dapm->card = card; | ||
1101 | soc_set_name_prefix(card, component); | ||
1186 | 1102 | ||
1187 | if (!try_module_get(codec->dev->driver->owner)) | 1103 | if (!try_module_get(component->dev->driver->owner)) |
1188 | return -ENODEV; | 1104 | return -ENODEV; |
1189 | 1105 | ||
1190 | soc_init_codec_debugfs(codec); | 1106 | soc_init_component_debugfs(component); |
1191 | 1107 | ||
1192 | if (driver->dapm_widgets) { | 1108 | if (component->dapm_widgets) { |
1193 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 1109 | ret = snd_soc_dapm_new_controls(dapm, component->dapm_widgets, |
1194 | driver->dapm_widgets, | 1110 | component->num_dapm_widgets); |
1195 | driver->num_dapm_widgets); | ||
1196 | 1111 | ||
1197 | if (ret != 0) { | 1112 | if (ret != 0) { |
1198 | dev_err(codec->dev, | 1113 | dev_err(component->dev, |
1199 | "Failed to create new controls %d\n", ret); | 1114 | "Failed to create new controls %d\n", ret); |
1200 | goto err_probe; | 1115 | goto err_probe; |
1201 | } | 1116 | } |
1202 | } | 1117 | } |
1203 | 1118 | ||
1204 | /* Create DAPM widgets for each DAI stream */ | 1119 | list_for_each_entry(dai, &component->dai_list, list) { |
1205 | list_for_each_entry(dai, &codec->component.dai_list, list) { | 1120 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); |
1206 | ret = snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); | ||
1207 | |||
1208 | if (ret != 0) { | 1121 | if (ret != 0) { |
1209 | dev_err(codec->dev, | 1122 | dev_err(component->dev, |
1210 | "Failed to create DAI widgets %d\n", ret); | 1123 | "Failed to create DAI widgets %d\n", ret); |
1211 | goto err_probe; | 1124 | goto err_probe; |
1212 | } | 1125 | } |
1213 | } | 1126 | } |
1214 | 1127 | ||
1215 | codec->dapm.idle_bias_off = driver->idle_bias_off; | 1128 | if (component->probe) { |
1216 | 1129 | ret = component->probe(component); | |
1217 | if (driver->probe) { | ||
1218 | ret = driver->probe(codec); | ||
1219 | if (ret < 0) { | 1130 | if (ret < 0) { |
1220 | dev_err(codec->dev, | 1131 | dev_err(component->dev, |
1221 | "ASoC: failed to probe CODEC %d\n", ret); | 1132 | "ASoC: failed to probe component %d\n", ret); |
1222 | goto err_probe; | 1133 | goto err_probe; |
1223 | } | 1134 | } |
1224 | WARN(codec->dapm.idle_bias_off && | 1135 | |
1225 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, | 1136 | WARN(dapm->idle_bias_off && |
1137 | dapm->bias_level != SND_SOC_BIAS_OFF, | ||
1226 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | 1138 | "codec %s can not start from non-off bias with idle_bias_off==1\n", |
1227 | codec->component.name); | 1139 | component->name); |
1228 | } | 1140 | } |
1229 | 1141 | ||
1230 | if (driver->controls) | 1142 | if (component->controls) |
1231 | snd_soc_add_codec_controls(codec, driver->controls, | 1143 | snd_soc_add_component_controls(component, component->controls, |
1232 | driver->num_controls); | 1144 | component->num_controls); |
1233 | if (driver->dapm_routes) | 1145 | if (component->dapm_routes) |
1234 | snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, | 1146 | snd_soc_dapm_add_routes(dapm, component->dapm_routes, |
1235 | driver->num_dapm_routes); | 1147 | component->num_dapm_routes); |
1236 | |||
1237 | /* mark codec as probed and add to card codec list */ | ||
1238 | codec->probed = 1; | ||
1239 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1240 | list_add(&codec->dapm.list, &card->dapm_list); | ||
1241 | |||
1242 | return 0; | ||
1243 | |||
1244 | err_probe: | ||
1245 | soc_cleanup_codec_debugfs(codec); | ||
1246 | module_put(codec->dev->driver->owner); | ||
1247 | |||
1248 | return ret; | ||
1249 | } | ||
1250 | |||
1251 | static int soc_probe_platform(struct snd_soc_card *card, | ||
1252 | struct snd_soc_platform *platform) | ||
1253 | { | ||
1254 | int ret = 0; | ||
1255 | const struct snd_soc_platform_driver *driver = platform->driver; | ||
1256 | struct snd_soc_component *component; | ||
1257 | struct snd_soc_dai *dai; | ||
1258 | |||
1259 | platform->component.card = card; | ||
1260 | platform->component.dapm.card = card; | ||
1261 | 1148 | ||
1262 | if (!try_module_get(platform->dev->driver->owner)) | 1149 | component->probed = 1; |
1263 | return -ENODEV; | 1150 | list_add(&dapm->list, &card->dapm_list); |
1264 | |||
1265 | soc_init_platform_debugfs(platform); | ||
1266 | 1151 | ||
1267 | if (driver->dapm_widgets) | 1152 | /* This is a HACK and will be removed soon */ |
1268 | snd_soc_dapm_new_controls(&platform->component.dapm, | 1153 | if (component->codec) |
1269 | driver->dapm_widgets, driver->num_dapm_widgets); | 1154 | list_add(&component->codec->card_list, &card->codec_dev_list); |
1270 | |||
1271 | /* Create DAPM widgets for each DAI stream */ | ||
1272 | list_for_each_entry(component, &component_list, list) { | ||
1273 | if (component->dev != platform->dev) | ||
1274 | continue; | ||
1275 | list_for_each_entry(dai, &component->dai_list, list) | ||
1276 | snd_soc_dapm_new_dai_widgets(&platform->component.dapm, | ||
1277 | dai); | ||
1278 | } | ||
1279 | |||
1280 | platform->component.dapm.idle_bias_off = 1; | ||
1281 | |||
1282 | if (driver->probe) { | ||
1283 | ret = driver->probe(platform); | ||
1284 | if (ret < 0) { | ||
1285 | dev_err(platform->dev, | ||
1286 | "ASoC: failed to probe platform %d\n", ret); | ||
1287 | goto err_probe; | ||
1288 | } | ||
1289 | } | ||
1290 | |||
1291 | if (driver->controls) | ||
1292 | snd_soc_add_platform_controls(platform, driver->controls, | ||
1293 | driver->num_controls); | ||
1294 | if (driver->dapm_routes) | ||
1295 | snd_soc_dapm_add_routes(&platform->component.dapm, | ||
1296 | driver->dapm_routes, driver->num_dapm_routes); | ||
1297 | |||
1298 | /* mark platform as probed and add to card platform list */ | ||
1299 | platform->probed = 1; | ||
1300 | list_add(&platform->component.dapm.list, &card->dapm_list); | ||
1301 | 1155 | ||
1302 | return 0; | 1156 | return 0; |
1303 | 1157 | ||
1304 | err_probe: | 1158 | err_probe: |
1305 | soc_cleanup_platform_debugfs(platform); | 1159 | soc_cleanup_component_debugfs(component); |
1306 | module_put(platform->dev->driver->owner); | 1160 | module_put(component->dev->driver->owner); |
1307 | 1161 | ||
1308 | return ret; | 1162 | return ret; |
1309 | } | 1163 | } |
@@ -1342,17 +1196,21 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1342 | } | 1196 | } |
1343 | rtd->dev_registered = 1; | 1197 | rtd->dev_registered = 1; |
1344 | 1198 | ||
1345 | /* add DAPM sysfs entries for this codec */ | 1199 | if (rtd->codec) { |
1346 | ret = snd_soc_dapm_sys_add(rtd->dev); | 1200 | /* add DAPM sysfs entries for this codec */ |
1347 | if (ret < 0) | 1201 | ret = snd_soc_dapm_sys_add(rtd->dev); |
1348 | dev_err(rtd->dev, | 1202 | if (ret < 0) |
1349 | "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); | 1203 | dev_err(rtd->dev, |
1204 | "ASoC: failed to add codec dapm sysfs entries: %d\n", | ||
1205 | ret); | ||
1350 | 1206 | ||
1351 | /* add codec sysfs entries */ | 1207 | /* add codec sysfs entries */ |
1352 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); | 1208 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); |
1353 | if (ret < 0) | 1209 | if (ret < 0) |
1354 | dev_err(rtd->dev, | 1210 | dev_err(rtd->dev, |
1355 | "ASoC: failed to add codec sysfs files: %d\n", ret); | 1211 | "ASoC: failed to add codec sysfs files: %d\n", |
1212 | ret); | ||
1213 | } | ||
1356 | 1214 | ||
1357 | return 0; | 1215 | return 0; |
1358 | } | 1216 | } |
@@ -1361,33 +1219,31 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1361 | int order) | 1219 | int order) |
1362 | { | 1220 | { |
1363 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1221 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1364 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1365 | struct snd_soc_platform *platform = rtd->platform; | 1222 | struct snd_soc_platform *platform = rtd->platform; |
1223 | struct snd_soc_component *component; | ||
1366 | int i, ret; | 1224 | int i, ret; |
1367 | 1225 | ||
1368 | /* probe the CPU-side component, if it is a CODEC */ | 1226 | /* probe the CPU-side component, if it is a CODEC */ |
1369 | if (cpu_dai->codec && | 1227 | component = rtd->cpu_dai->component; |
1370 | !cpu_dai->codec->probed && | 1228 | if (component->driver->probe_order == order) { |
1371 | cpu_dai->codec->driver->probe_order == order) { | 1229 | ret = soc_probe_component(card, component); |
1372 | ret = soc_probe_codec(card, cpu_dai->codec); | ||
1373 | if (ret < 0) | 1230 | if (ret < 0) |
1374 | return ret; | 1231 | return ret; |
1375 | } | 1232 | } |
1376 | 1233 | ||
1377 | /* probe the CODEC-side components */ | 1234 | /* probe the CODEC-side components */ |
1378 | for (i = 0; i < rtd->num_codecs; i++) { | 1235 | for (i = 0; i < rtd->num_codecs; i++) { |
1379 | if (!rtd->codec_dais[i]->codec->probed && | 1236 | component = rtd->codec_dais[i]->component; |
1380 | rtd->codec_dais[i]->codec->driver->probe_order == order) { | 1237 | if (component->driver->probe_order == order) { |
1381 | ret = soc_probe_codec(card, rtd->codec_dais[i]->codec); | 1238 | ret = soc_probe_component(card, component); |
1382 | if (ret < 0) | 1239 | if (ret < 0) |
1383 | return ret; | 1240 | return ret; |
1384 | } | 1241 | } |
1385 | } | 1242 | } |
1386 | 1243 | ||
1387 | /* probe the platform */ | 1244 | /* probe the platform */ |
1388 | if (!platform->probed && | 1245 | if (platform->component.driver->probe_order == order) { |
1389 | platform->driver->probe_order == order) { | 1246 | ret = soc_probe_component(card, &platform->component); |
1390 | ret = soc_probe_platform(card, platform); | ||
1391 | if (ret < 0) | 1247 | if (ret < 0) |
1392 | return ret; | 1248 | return ret; |
1393 | } | 1249 | } |
@@ -1482,18 +1338,12 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1482 | /* probe the cpu_dai */ | 1338 | /* probe the cpu_dai */ |
1483 | if (!cpu_dai->probed && | 1339 | if (!cpu_dai->probed && |
1484 | cpu_dai->driver->probe_order == order) { | 1340 | cpu_dai->driver->probe_order == order) { |
1485 | if (!cpu_dai->codec) { | ||
1486 | if (!try_module_get(cpu_dai->dev->driver->owner)) | ||
1487 | return -ENODEV; | ||
1488 | } | ||
1489 | |||
1490 | if (cpu_dai->driver->probe) { | 1341 | if (cpu_dai->driver->probe) { |
1491 | ret = cpu_dai->driver->probe(cpu_dai); | 1342 | ret = cpu_dai->driver->probe(cpu_dai); |
1492 | if (ret < 0) { | 1343 | if (ret < 0) { |
1493 | dev_err(cpu_dai->dev, | 1344 | dev_err(cpu_dai->dev, |
1494 | "ASoC: failed to probe CPU DAI %s: %d\n", | 1345 | "ASoC: failed to probe CPU DAI %s: %d\n", |
1495 | cpu_dai->name, ret); | 1346 | cpu_dai->name, ret); |
1496 | module_put(cpu_dai->dev->driver->owner); | ||
1497 | return ret; | 1347 | return ret; |
1498 | } | 1348 | } |
1499 | } | 1349 | } |
@@ -1654,17 +1504,24 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) | |||
1654 | { | 1504 | { |
1655 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1505 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
1656 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1506 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1657 | const char *codecname = aux_dev->codec_name; | 1507 | const char *name = aux_dev->codec_name; |
1658 | 1508 | ||
1659 | rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname); | 1509 | rtd->component = soc_find_component(aux_dev->codec_of_node, name); |
1660 | if (!rtd->codec) { | 1510 | if (!rtd->component) { |
1661 | if (aux_dev->codec_of_node) | 1511 | if (aux_dev->codec_of_node) |
1662 | codecname = of_node_full_name(aux_dev->codec_of_node); | 1512 | name = of_node_full_name(aux_dev->codec_of_node); |
1663 | 1513 | ||
1664 | dev_err(card->dev, "ASoC: %s not registered\n", codecname); | 1514 | dev_err(card->dev, "ASoC: %s not registered\n", name); |
1665 | return -EPROBE_DEFER; | 1515 | return -EPROBE_DEFER; |
1666 | } | 1516 | } |
1667 | 1517 | ||
1518 | /* | ||
1519 | * Some places still reference rtd->codec, so we have to keep that | ||
1520 | * initialized if the component is a CODEC. Once all those references | ||
1521 | * have been removed, this code can be removed as well. | ||
1522 | */ | ||
1523 | rtd->codec = rtd->component->codec; | ||
1524 | |||
1668 | return 0; | 1525 | return 0; |
1669 | } | 1526 | } |
1670 | 1527 | ||
@@ -1674,18 +1531,13 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | |||
1674 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1531 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1675 | int ret; | 1532 | int ret; |
1676 | 1533 | ||
1677 | if (rtd->codec->probed) { | 1534 | ret = soc_probe_component(card, rtd->component); |
1678 | dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); | ||
1679 | return -EBUSY; | ||
1680 | } | ||
1681 | |||
1682 | ret = soc_probe_codec(card, rtd->codec); | ||
1683 | if (ret < 0) | 1535 | if (ret < 0) |
1684 | return ret; | 1536 | return ret; |
1685 | 1537 | ||
1686 | /* do machine specific initialization */ | 1538 | /* do machine specific initialization */ |
1687 | if (aux_dev->init) { | 1539 | if (aux_dev->init) { |
1688 | ret = aux_dev->init(&rtd->codec->dapm); | 1540 | ret = aux_dev->init(rtd->component); |
1689 | if (ret < 0) { | 1541 | if (ret < 0) { |
1690 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", | 1542 | dev_err(card->dev, "ASoC: failed to init %s: %d\n", |
1691 | aux_dev->name, ret); | 1543 | aux_dev->name, ret); |
@@ -1699,7 +1551,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | |||
1699 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | 1551 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) |
1700 | { | 1552 | { |
1701 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1553 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
1702 | struct snd_soc_codec *codec = rtd->codec; | 1554 | struct snd_soc_component *component = rtd->component; |
1703 | 1555 | ||
1704 | /* unregister the rtd device */ | 1556 | /* unregister the rtd device */ |
1705 | if (rtd->dev_registered) { | 1557 | if (rtd->dev_registered) { |
@@ -1708,8 +1560,8 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | |||
1708 | rtd->dev_registered = 0; | 1560 | rtd->dev_registered = 0; |
1709 | } | 1561 | } |
1710 | 1562 | ||
1711 | if (codec && codec->probed) | 1563 | if (component && component->probed) |
1712 | soc_remove_codec(codec); | 1564 | soc_remove_component(component); |
1713 | } | 1565 | } |
1714 | 1566 | ||
1715 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) | 1567 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) |
@@ -2107,19 +1959,14 @@ static struct platform_driver soc_driver = { | |||
2107 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | 1959 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, |
2108 | struct snd_ac97_bus_ops *ops, int num) | 1960 | struct snd_ac97_bus_ops *ops, int num) |
2109 | { | 1961 | { |
2110 | mutex_lock(&codec->mutex); | ||
2111 | |||
2112 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | 1962 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); |
2113 | if (codec->ac97 == NULL) { | 1963 | if (codec->ac97 == NULL) |
2114 | mutex_unlock(&codec->mutex); | ||
2115 | return -ENOMEM; | 1964 | return -ENOMEM; |
2116 | } | ||
2117 | 1965 | ||
2118 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); | 1966 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); |
2119 | if (codec->ac97->bus == NULL) { | 1967 | if (codec->ac97->bus == NULL) { |
2120 | kfree(codec->ac97); | 1968 | kfree(codec->ac97); |
2121 | codec->ac97 = NULL; | 1969 | codec->ac97 = NULL; |
2122 | mutex_unlock(&codec->mutex); | ||
2123 | return -ENOMEM; | 1970 | return -ENOMEM; |
2124 | } | 1971 | } |
2125 | 1972 | ||
@@ -2132,7 +1979,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
2132 | */ | 1979 | */ |
2133 | codec->ac97_created = 1; | 1980 | codec->ac97_created = 1; |
2134 | 1981 | ||
2135 | mutex_unlock(&codec->mutex); | ||
2136 | return 0; | 1982 | return 0; |
2137 | } | 1983 | } |
2138 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 1984 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
@@ -2302,7 +2148,6 @@ EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | |||
2302 | */ | 2148 | */ |
2303 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | 2149 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) |
2304 | { | 2150 | { |
2305 | mutex_lock(&codec->mutex); | ||
2306 | #ifdef CONFIG_SND_SOC_AC97_BUS | 2151 | #ifdef CONFIG_SND_SOC_AC97_BUS |
2307 | soc_unregister_ac97_codec(codec); | 2152 | soc_unregister_ac97_codec(codec); |
2308 | #endif | 2153 | #endif |
@@ -2310,7 +2155,6 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | |||
2310 | kfree(codec->ac97); | 2155 | kfree(codec->ac97); |
2311 | codec->ac97 = NULL; | 2156 | codec->ac97 = NULL; |
2312 | codec->ac97_created = 0; | 2157 | codec->ac97_created = 0; |
2313 | mutex_unlock(&codec->mutex); | ||
2314 | } | 2158 | } |
2315 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | 2159 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); |
2316 | 2160 | ||
@@ -3027,9 +2871,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | |||
3027 | unsigned int val, val_mask; | 2871 | unsigned int val, val_mask; |
3028 | int ret; | 2872 | int ret; |
3029 | 2873 | ||
3030 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
3031 | if (invert) | 2874 | if (invert) |
3032 | val = max - val; | 2875 | val = (max - ucontrol->value.integer.value[0]) & mask; |
2876 | else | ||
2877 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
3033 | val_mask = mask << shift; | 2878 | val_mask = mask << shift; |
3034 | val = val << shift; | 2879 | val = val << shift; |
3035 | 2880 | ||
@@ -3038,9 +2883,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | |||
3038 | return ret; | 2883 | return ret; |
3039 | 2884 | ||
3040 | if (snd_soc_volsw_is_stereo(mc)) { | 2885 | if (snd_soc_volsw_is_stereo(mc)) { |
3041 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
3042 | if (invert) | 2886 | if (invert) |
3043 | val = max - val; | 2887 | val = (max - ucontrol->value.integer.value[1]) & mask; |
2888 | else | ||
2889 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
3044 | val_mask = mask << shift; | 2890 | val_mask = mask << shift; |
3045 | val = val << shift; | 2891 | val = val << shift; |
3046 | 2892 | ||
@@ -3085,8 +2931,9 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | |||
3085 | if (invert) | 2931 | if (invert) |
3086 | ucontrol->value.integer.value[0] = | 2932 | ucontrol->value.integer.value[0] = |
3087 | max - ucontrol->value.integer.value[0]; | 2933 | max - ucontrol->value.integer.value[0]; |
3088 | ucontrol->value.integer.value[0] = | 2934 | else |
3089 | ucontrol->value.integer.value[0] - min; | 2935 | ucontrol->value.integer.value[0] = |
2936 | ucontrol->value.integer.value[0] - min; | ||
3090 | 2937 | ||
3091 | if (snd_soc_volsw_is_stereo(mc)) { | 2938 | if (snd_soc_volsw_is_stereo(mc)) { |
3092 | ret = snd_soc_component_read(component, rreg, &val); | 2939 | ret = snd_soc_component_read(component, rreg, &val); |
@@ -3097,8 +2944,9 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | |||
3097 | if (invert) | 2944 | if (invert) |
3098 | ucontrol->value.integer.value[1] = | 2945 | ucontrol->value.integer.value[1] = |
3099 | max - ucontrol->value.integer.value[1]; | 2946 | max - ucontrol->value.integer.value[1]; |
3100 | ucontrol->value.integer.value[1] = | 2947 | else |
3101 | ucontrol->value.integer.value[1] - min; | 2948 | ucontrol->value.integer.value[1] = |
2949 | ucontrol->value.integer.value[1] - min; | ||
3102 | } | 2950 | } |
3103 | 2951 | ||
3104 | return 0; | 2952 | return 0; |
@@ -3928,8 +3776,11 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); | |||
3928 | */ | 3776 | */ |
3929 | int snd_soc_unregister_card(struct snd_soc_card *card) | 3777 | int snd_soc_unregister_card(struct snd_soc_card *card) |
3930 | { | 3778 | { |
3931 | if (card->instantiated) | 3779 | if (card->instantiated) { |
3780 | card->instantiated = false; | ||
3781 | snd_soc_dapm_shutdown(card); | ||
3932 | soc_cleanup_card_resources(card); | 3782 | soc_cleanup_card_resources(card); |
3783 | } | ||
3933 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); | 3784 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); |
3934 | 3785 | ||
3935 | return 0; | 3786 | return 0; |
@@ -4116,6 +3967,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
4116 | 3967 | ||
4117 | component->dev = dev; | 3968 | component->dev = dev; |
4118 | component->driver = driver; | 3969 | component->driver = driver; |
3970 | component->probe = component->driver->probe; | ||
3971 | component->remove = component->driver->remove; | ||
4119 | 3972 | ||
4120 | if (!component->dapm_ptr) | 3973 | if (!component->dapm_ptr) |
4121 | component->dapm_ptr = &component->dapm; | 3974 | component->dapm_ptr = &component->dapm; |
@@ -4124,19 +3977,42 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
4124 | dapm->dev = dev; | 3977 | dapm->dev = dev; |
4125 | dapm->component = component; | 3978 | dapm->component = component; |
4126 | dapm->bias_level = SND_SOC_BIAS_OFF; | 3979 | dapm->bias_level = SND_SOC_BIAS_OFF; |
3980 | dapm->idle_bias_off = true; | ||
4127 | if (driver->seq_notifier) | 3981 | if (driver->seq_notifier) |
4128 | dapm->seq_notifier = snd_soc_component_seq_notifier; | 3982 | dapm->seq_notifier = snd_soc_component_seq_notifier; |
4129 | if (driver->stream_event) | 3983 | if (driver->stream_event) |
4130 | dapm->stream_event = snd_soc_component_stream_event; | 3984 | dapm->stream_event = snd_soc_component_stream_event; |
4131 | 3985 | ||
3986 | component->controls = driver->controls; | ||
3987 | component->num_controls = driver->num_controls; | ||
3988 | component->dapm_widgets = driver->dapm_widgets; | ||
3989 | component->num_dapm_widgets = driver->num_dapm_widgets; | ||
3990 | component->dapm_routes = driver->dapm_routes; | ||
3991 | component->num_dapm_routes = driver->num_dapm_routes; | ||
3992 | |||
4132 | INIT_LIST_HEAD(&component->dai_list); | 3993 | INIT_LIST_HEAD(&component->dai_list); |
4133 | mutex_init(&component->io_mutex); | 3994 | mutex_init(&component->io_mutex); |
4134 | 3995 | ||
4135 | return 0; | 3996 | return 0; |
4136 | } | 3997 | } |
4137 | 3998 | ||
3999 | static void snd_soc_component_init_regmap(struct snd_soc_component *component) | ||
4000 | { | ||
4001 | if (!component->regmap) | ||
4002 | component->regmap = dev_get_regmap(component->dev, NULL); | ||
4003 | if (component->regmap) { | ||
4004 | int val_bytes = regmap_get_val_bytes(component->regmap); | ||
4005 | /* Errors are legitimate for non-integer byte multiples */ | ||
4006 | if (val_bytes > 0) | ||
4007 | component->val_bytes = val_bytes; | ||
4008 | } | ||
4009 | } | ||
4010 | |||
4138 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | 4011 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) |
4139 | { | 4012 | { |
4013 | if (!component->write && !component->read) | ||
4014 | snd_soc_component_init_regmap(component); | ||
4015 | |||
4140 | list_add(&component->list, &component_list); | 4016 | list_add(&component->list, &component_list); |
4141 | } | 4017 | } |
4142 | 4018 | ||
@@ -4225,22 +4101,18 @@ found: | |||
4225 | } | 4101 | } |
4226 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | 4102 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); |
4227 | 4103 | ||
4228 | static int snd_soc_platform_drv_write(struct snd_soc_component *component, | 4104 | static int snd_soc_platform_drv_probe(struct snd_soc_component *component) |
4229 | unsigned int reg, unsigned int val) | ||
4230 | { | 4105 | { |
4231 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); | 4106 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); |
4232 | 4107 | ||
4233 | return platform->driver->write(platform, reg, val); | 4108 | return platform->driver->probe(platform); |
4234 | } | 4109 | } |
4235 | 4110 | ||
4236 | static int snd_soc_platform_drv_read(struct snd_soc_component *component, | 4111 | static void snd_soc_platform_drv_remove(struct snd_soc_component *component) |
4237 | unsigned int reg, unsigned int *val) | ||
4238 | { | 4112 | { |
4239 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); | 4113 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); |
4240 | 4114 | ||
4241 | *val = platform->driver->read(platform, reg); | 4115 | platform->driver->remove(platform); |
4242 | |||
4243 | return 0; | ||
4244 | } | 4116 | } |
4245 | 4117 | ||
4246 | /** | 4118 | /** |
@@ -4261,10 +4133,15 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | |||
4261 | 4133 | ||
4262 | platform->dev = dev; | 4134 | platform->dev = dev; |
4263 | platform->driver = platform_drv; | 4135 | platform->driver = platform_drv; |
4264 | if (platform_drv->write) | 4136 | |
4265 | platform->component.write = snd_soc_platform_drv_write; | 4137 | if (platform_drv->probe) |
4266 | if (platform_drv->read) | 4138 | platform->component.probe = snd_soc_platform_drv_probe; |
4267 | platform->component.read = snd_soc_platform_drv_read; | 4139 | if (platform_drv->remove) |
4140 | platform->component.remove = snd_soc_platform_drv_remove; | ||
4141 | |||
4142 | #ifdef CONFIG_DEBUG_FS | ||
4143 | platform->component.debugfs_prefix = "platform"; | ||
4144 | #endif | ||
4268 | 4145 | ||
4269 | mutex_lock(&client_mutex); | 4146 | mutex_lock(&client_mutex); |
4270 | snd_soc_component_add_unlocked(&platform->component); | 4147 | snd_soc_component_add_unlocked(&platform->component); |
@@ -4315,10 +4192,10 @@ void snd_soc_remove_platform(struct snd_soc_platform *platform) | |||
4315 | snd_soc_component_del_unlocked(&platform->component); | 4192 | snd_soc_component_del_unlocked(&platform->component); |
4316 | mutex_unlock(&client_mutex); | 4193 | mutex_unlock(&client_mutex); |
4317 | 4194 | ||
4318 | snd_soc_component_cleanup(&platform->component); | ||
4319 | |||
4320 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", | 4195 | dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", |
4321 | platform->component.name); | 4196 | platform->component.name); |
4197 | |||
4198 | snd_soc_component_cleanup(&platform->component); | ||
4322 | } | 4199 | } |
4323 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); | 4200 | EXPORT_SYMBOL_GPL(snd_soc_remove_platform); |
4324 | 4201 | ||
@@ -4386,6 +4263,20 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) | |||
4386 | stream->formats |= codec_format_map[i]; | 4263 | stream->formats |= codec_format_map[i]; |
4387 | } | 4264 | } |
4388 | 4265 | ||
4266 | static int snd_soc_codec_drv_probe(struct snd_soc_component *component) | ||
4267 | { | ||
4268 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
4269 | |||
4270 | return codec->driver->probe(codec); | ||
4271 | } | ||
4272 | |||
4273 | static void snd_soc_codec_drv_remove(struct snd_soc_component *component) | ||
4274 | { | ||
4275 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
4276 | |||
4277 | codec->driver->remove(codec); | ||
4278 | } | ||
4279 | |||
4389 | static int snd_soc_codec_drv_write(struct snd_soc_component *component, | 4280 | static int snd_soc_codec_drv_write(struct snd_soc_component *component, |
4390 | unsigned int reg, unsigned int val) | 4281 | unsigned int reg, unsigned int val) |
4391 | { | 4282 | { |
@@ -4424,7 +4315,6 @@ int snd_soc_register_codec(struct device *dev, | |||
4424 | { | 4315 | { |
4425 | struct snd_soc_codec *codec; | 4316 | struct snd_soc_codec *codec; |
4426 | struct snd_soc_dai *dai; | 4317 | struct snd_soc_dai *dai; |
4427 | struct regmap *regmap; | ||
4428 | int ret, i; | 4318 | int ret, i; |
4429 | 4319 | ||
4430 | dev_dbg(dev, "codec register %s\n", dev_name(dev)); | 4320 | dev_dbg(dev, "codec register %s\n", dev_name(dev)); |
@@ -4434,18 +4324,37 @@ int snd_soc_register_codec(struct device *dev, | |||
4434 | return -ENOMEM; | 4324 | return -ENOMEM; |
4435 | 4325 | ||
4436 | codec->component.dapm_ptr = &codec->dapm; | 4326 | codec->component.dapm_ptr = &codec->dapm; |
4327 | codec->component.codec = codec; | ||
4437 | 4328 | ||
4438 | ret = snd_soc_component_initialize(&codec->component, | 4329 | ret = snd_soc_component_initialize(&codec->component, |
4439 | &codec_drv->component_driver, dev); | 4330 | &codec_drv->component_driver, dev); |
4440 | if (ret) | 4331 | if (ret) |
4441 | goto err_free; | 4332 | goto err_free; |
4442 | 4333 | ||
4334 | if (codec_drv->controls) { | ||
4335 | codec->component.controls = codec_drv->controls; | ||
4336 | codec->component.num_controls = codec_drv->num_controls; | ||
4337 | } | ||
4338 | if (codec_drv->dapm_widgets) { | ||
4339 | codec->component.dapm_widgets = codec_drv->dapm_widgets; | ||
4340 | codec->component.num_dapm_widgets = codec_drv->num_dapm_widgets; | ||
4341 | } | ||
4342 | if (codec_drv->dapm_routes) { | ||
4343 | codec->component.dapm_routes = codec_drv->dapm_routes; | ||
4344 | codec->component.num_dapm_routes = codec_drv->num_dapm_routes; | ||
4345 | } | ||
4346 | |||
4347 | if (codec_drv->probe) | ||
4348 | codec->component.probe = snd_soc_codec_drv_probe; | ||
4349 | if (codec_drv->remove) | ||
4350 | codec->component.remove = snd_soc_codec_drv_remove; | ||
4443 | if (codec_drv->write) | 4351 | if (codec_drv->write) |
4444 | codec->component.write = snd_soc_codec_drv_write; | 4352 | codec->component.write = snd_soc_codec_drv_write; |
4445 | if (codec_drv->read) | 4353 | if (codec_drv->read) |
4446 | codec->component.read = snd_soc_codec_drv_read; | 4354 | codec->component.read = snd_soc_codec_drv_read; |
4447 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4355 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4448 | codec->dapm.codec = codec; | 4356 | codec->dapm.idle_bias_off = codec_drv->idle_bias_off; |
4357 | codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off; | ||
4449 | if (codec_drv->seq_notifier) | 4358 | if (codec_drv->seq_notifier) |
4450 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 4359 | codec->dapm.seq_notifier = codec_drv->seq_notifier; |
4451 | if (codec_drv->set_bias_level) | 4360 | if (codec_drv->set_bias_level) |
@@ -4455,23 +4364,13 @@ int snd_soc_register_codec(struct device *dev, | |||
4455 | codec->component.val_bytes = codec_drv->reg_word_size; | 4364 | codec->component.val_bytes = codec_drv->reg_word_size; |
4456 | mutex_init(&codec->mutex); | 4365 | mutex_init(&codec->mutex); |
4457 | 4366 | ||
4458 | if (!codec->component.write) { | 4367 | #ifdef CONFIG_DEBUG_FS |
4459 | if (codec_drv->get_regmap) | 4368 | codec->component.init_debugfs = soc_init_codec_debugfs; |
4460 | regmap = codec_drv->get_regmap(dev); | 4369 | codec->component.debugfs_prefix = "codec"; |
4461 | else | 4370 | #endif |
4462 | regmap = dev_get_regmap(dev, NULL); | 4371 | |
4463 | 4372 | if (codec_drv->get_regmap) | |
4464 | if (regmap) { | 4373 | codec->component.regmap = codec_drv->get_regmap(dev); |
4465 | ret = snd_soc_component_init_io(&codec->component, | ||
4466 | regmap); | ||
4467 | if (ret) { | ||
4468 | dev_err(codec->dev, | ||
4469 | "Failed to set cache I/O:%d\n", | ||
4470 | ret); | ||
4471 | goto err_cleanup; | ||
4472 | } | ||
4473 | } | ||
4474 | } | ||
4475 | 4374 | ||
4476 | for (i = 0; i < num_dai; i++) { | 4375 | for (i = 0; i < num_dai; i++) { |
4477 | fixup_codec_formats(&dai_drv[i].playback); | 4376 | fixup_codec_formats(&dai_drv[i].playback); |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 177bd8639ef9..c61cb9cedbcd 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -326,12 +326,13 @@ static struct list_head *dapm_kcontrol_get_path_list( | |||
326 | list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \ | 326 | list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \ |
327 | list_kcontrol) | 327 | list_kcontrol) |
328 | 328 | ||
329 | static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) | 329 | unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) |
330 | { | 330 | { |
331 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); | 331 | struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); |
332 | 332 | ||
333 | return data->value; | 333 | return data->value; |
334 | } | 334 | } |
335 | EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value); | ||
335 | 336 | ||
336 | static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, | 337 | static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, |
337 | unsigned int value) | 338 | unsigned int value) |
@@ -591,9 +592,9 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
591 | int shared; | 592 | int shared; |
592 | struct snd_kcontrol *kcontrol; | 593 | struct snd_kcontrol *kcontrol; |
593 | bool wname_in_long_name, kcname_in_long_name; | 594 | bool wname_in_long_name, kcname_in_long_name; |
594 | char *long_name; | 595 | char *long_name = NULL; |
595 | const char *name; | 596 | const char *name; |
596 | int ret; | 597 | int ret = 0; |
597 | 598 | ||
598 | prefix = soc_dapm_prefix(dapm); | 599 | prefix = soc_dapm_prefix(dapm); |
599 | if (prefix) | 600 | if (prefix) |
@@ -652,15 +653,17 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
652 | 653 | ||
653 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, | 654 | kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, |
654 | prefix); | 655 | prefix); |
655 | kfree(long_name); | 656 | if (!kcontrol) { |
656 | if (!kcontrol) | 657 | ret = -ENOMEM; |
657 | return -ENOMEM; | 658 | goto exit_free; |
659 | } | ||
660 | |||
658 | kcontrol->private_free = dapm_kcontrol_free; | 661 | kcontrol->private_free = dapm_kcontrol_free; |
659 | 662 | ||
660 | ret = dapm_kcontrol_data_alloc(w, kcontrol); | 663 | ret = dapm_kcontrol_data_alloc(w, kcontrol); |
661 | if (ret) { | 664 | if (ret) { |
662 | snd_ctl_free_one(kcontrol); | 665 | snd_ctl_free_one(kcontrol); |
663 | return ret; | 666 | goto exit_free; |
664 | } | 667 | } |
665 | 668 | ||
666 | ret = snd_ctl_add(card, kcontrol); | 669 | ret = snd_ctl_add(card, kcontrol); |
@@ -668,17 +671,18 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
668 | dev_err(dapm->dev, | 671 | dev_err(dapm->dev, |
669 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", | 672 | "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", |
670 | w->name, name, ret); | 673 | w->name, name, ret); |
671 | return ret; | 674 | goto exit_free; |
672 | } | 675 | } |
673 | } | 676 | } |
674 | 677 | ||
675 | ret = dapm_kcontrol_add_widget(kcontrol, w); | 678 | ret = dapm_kcontrol_add_widget(kcontrol, w); |
676 | if (ret) | 679 | if (ret == 0) |
677 | return ret; | 680 | w->kcontrols[kci] = kcontrol; |
678 | 681 | ||
679 | w->kcontrols[kci] = kcontrol; | 682 | exit_free: |
683 | kfree(long_name); | ||
680 | 684 | ||
681 | return 0; | 685 | return ret; |
682 | } | 686 | } |
683 | 687 | ||
684 | /* create new dapm mixer control */ | 688 | /* create new dapm mixer control */ |
@@ -1683,6 +1687,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, | |||
1683 | } | 1687 | } |
1684 | } | 1688 | } |
1685 | 1689 | ||
1690 | static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) | ||
1691 | { | ||
1692 | if (dapm->idle_bias_off) | ||
1693 | return true; | ||
1694 | |||
1695 | switch (snd_power_get_state(dapm->card->snd_card)) { | ||
1696 | case SNDRV_CTL_POWER_D3hot: | ||
1697 | case SNDRV_CTL_POWER_D3cold: | ||
1698 | return dapm->suspend_bias_off; | ||
1699 | default: | ||
1700 | break; | ||
1701 | } | ||
1702 | |||
1703 | return false; | ||
1704 | } | ||
1705 | |||
1686 | /* | 1706 | /* |
1687 | * Scan each dapm widget for complete audio path. | 1707 | * Scan each dapm widget for complete audio path. |
1688 | * A complete path is a route that has valid endpoints i.e.:- | 1708 | * A complete path is a route that has valid endpoints i.e.:- |
@@ -1706,7 +1726,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1706 | trace_snd_soc_dapm_start(card); | 1726 | trace_snd_soc_dapm_start(card); |
1707 | 1727 | ||
1708 | list_for_each_entry(d, &card->dapm_list, list) { | 1728 | list_for_each_entry(d, &card->dapm_list, list) { |
1709 | if (d->idle_bias_off) | 1729 | if (dapm_idle_bias_off(d)) |
1710 | d->target_bias_level = SND_SOC_BIAS_OFF; | 1730 | d->target_bias_level = SND_SOC_BIAS_OFF; |
1711 | else | 1731 | else |
1712 | d->target_bias_level = SND_SOC_BIAS_STANDBY; | 1732 | d->target_bias_level = SND_SOC_BIAS_STANDBY; |
@@ -1772,7 +1792,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1772 | if (d->target_bias_level > bias) | 1792 | if (d->target_bias_level > bias) |
1773 | bias = d->target_bias_level; | 1793 | bias = d->target_bias_level; |
1774 | list_for_each_entry(d, &card->dapm_list, list) | 1794 | list_for_each_entry(d, &card->dapm_list, list) |
1775 | if (!d->idle_bias_off) | 1795 | if (!dapm_idle_bias_off(d)) |
1776 | d->target_bias_level = bias; | 1796 | d->target_bias_level = bias; |
1777 | 1797 | ||
1778 | trace_snd_soc_dapm_walk_done(card); | 1798 | trace_snd_soc_dapm_walk_done(card); |
@@ -3109,7 +3129,8 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3109 | } | 3129 | } |
3110 | 3130 | ||
3111 | w->dapm = dapm; | 3131 | w->dapm = dapm; |
3112 | w->codec = dapm->codec; | 3132 | if (dapm->component) |
3133 | w->codec = dapm->component->codec; | ||
3113 | INIT_LIST_HEAD(&w->sources); | 3134 | INIT_LIST_HEAD(&w->sources); |
3114 | INIT_LIST_HEAD(&w->sinks); | 3135 | INIT_LIST_HEAD(&w->sinks); |
3115 | INIT_LIST_HEAD(&w->list); | 3136 | INIT_LIST_HEAD(&w->list); |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6307f85e871b..b329b84bc5af 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -336,10 +336,12 @@ static const struct snd_pcm_ops dmaengine_pcm_ops = { | |||
336 | }; | 336 | }; |
337 | 337 | ||
338 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | 338 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { |
339 | .component_driver = { | ||
340 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
341 | }, | ||
339 | .ops = &dmaengine_pcm_ops, | 342 | .ops = &dmaengine_pcm_ops, |
340 | .pcm_new = dmaengine_pcm_new, | 343 | .pcm_new = dmaengine_pcm_new, |
341 | .pcm_free = dmaengine_pcm_free, | 344 | .pcm_free = dmaengine_pcm_free, |
342 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
343 | }; | 345 | }; |
344 | 346 | ||
345 | static const char * const dmaengine_pcm_dma_channel_names[] = { | 347 | static const char * const dmaengine_pcm_dma_channel_names[] = { |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 7767fbd73eb7..9b3939049cef 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -271,31 +271,3 @@ int snd_soc_platform_write(struct snd_soc_platform *platform, | |||
271 | return snd_soc_component_write(&platform->component, reg, val); | 271 | return snd_soc_component_write(&platform->component, reg, val); |
272 | } | 272 | } |
273 | EXPORT_SYMBOL_GPL(snd_soc_platform_write); | 273 | EXPORT_SYMBOL_GPL(snd_soc_platform_write); |
274 | |||
275 | /** | ||
276 | * snd_soc_component_init_io() - Initialize regmap IO | ||
277 | * | ||
278 | * @component: component to initialize | ||
279 | * @regmap: regmap instance to use for IO operations | ||
280 | * | ||
281 | * Return: 0 on success, a negative error code otherwise | ||
282 | */ | ||
283 | int snd_soc_component_init_io(struct snd_soc_component *component, | ||
284 | struct regmap *regmap) | ||
285 | { | ||
286 | int ret; | ||
287 | |||
288 | if (!regmap) | ||
289 | return -EINVAL; | ||
290 | |||
291 | ret = regmap_get_val_bytes(regmap); | ||
292 | /* Errors are legitimate for non-integer byte | ||
293 | * multiples */ | ||
294 | if (ret > 0) | ||
295 | component->val_bytes = ret; | ||
296 | |||
297 | component->regmap = regmap; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(snd_soc_component_init_io); | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 642c86240752..002311afdeaa 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -352,7 +352,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) | |||
352 | } else { | 352 | } else { |
353 | for (i = 0; i < rtd->num_codecs; i++) { | 353 | for (i = 0; i < rtd->num_codecs; i++) { |
354 | codec_dai = rtd->codec_dais[i]; | 354 | codec_dai = rtd->codec_dais[i]; |
355 | if (codec_dai->driver->playback.sig_bits == 0) { | 355 | if (codec_dai->driver->capture.sig_bits == 0) { |
356 | bits = 0; | 356 | bits = 0; |
357 | break; | 357 | break; |
358 | } | 358 | } |
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index b86cd9936ef1..01921d7e73fa 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c | |||
@@ -42,6 +42,7 @@ | |||
42 | struct tegra_max98090 { | 42 | struct tegra_max98090 { |
43 | struct tegra_asoc_utils_data util_data; | 43 | struct tegra_asoc_utils_data util_data; |
44 | int gpio_hp_det; | 44 | int gpio_hp_det; |
45 | int gpio_mic_det; | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, | 48 | static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, |
@@ -112,6 +113,22 @@ static struct snd_soc_jack_gpio tegra_max98090_hp_jack_gpio = { | |||
112 | .invert = 1, | 113 | .invert = 1, |
113 | }; | 114 | }; |
114 | 115 | ||
116 | static struct snd_soc_jack tegra_max98090_mic_jack; | ||
117 | |||
118 | static struct snd_soc_jack_pin tegra_max98090_mic_jack_pins[] = { | ||
119 | { | ||
120 | .pin = "Mic Jack", | ||
121 | .mask = SND_JACK_MICROPHONE, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static struct snd_soc_jack_gpio tegra_max98090_mic_jack_gpio = { | ||
126 | .name = "Mic detection", | ||
127 | .report = SND_JACK_MICROPHONE, | ||
128 | .debounce_time = 150, | ||
129 | .invert = 1, | ||
130 | }; | ||
131 | |||
115 | static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = { | 132 | static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = { |
116 | SND_SOC_DAPM_HP("Headphones", NULL), | 133 | SND_SOC_DAPM_HP("Headphones", NULL), |
117 | SND_SOC_DAPM_SPK("Speakers", NULL), | 134 | SND_SOC_DAPM_SPK("Speakers", NULL), |
@@ -141,6 +158,19 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
141 | &tegra_max98090_hp_jack_gpio); | 158 | &tegra_max98090_hp_jack_gpio); |
142 | } | 159 | } |
143 | 160 | ||
161 | if (gpio_is_valid(machine->gpio_mic_det)) { | ||
162 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
163 | &tegra_max98090_mic_jack); | ||
164 | snd_soc_jack_add_pins(&tegra_max98090_mic_jack, | ||
165 | ARRAY_SIZE(tegra_max98090_mic_jack_pins), | ||
166 | tegra_max98090_mic_jack_pins); | ||
167 | |||
168 | tegra_max98090_mic_jack_gpio.gpio = machine->gpio_mic_det; | ||
169 | snd_soc_jack_add_gpios(&tegra_max98090_mic_jack, | ||
170 | 1, | ||
171 | &tegra_max98090_mic_jack_gpio); | ||
172 | } | ||
173 | |||
144 | return 0; | 174 | return 0; |
145 | } | 175 | } |
146 | 176 | ||
@@ -153,6 +183,11 @@ static int tegra_max98090_card_remove(struct snd_soc_card *card) | |||
153 | &tegra_max98090_hp_jack_gpio); | 183 | &tegra_max98090_hp_jack_gpio); |
154 | } | 184 | } |
155 | 185 | ||
186 | if (gpio_is_valid(machine->gpio_mic_det)) { | ||
187 | snd_soc_jack_free_gpios(&tegra_max98090_mic_jack, 1, | ||
188 | &tegra_max98090_mic_jack_gpio); | ||
189 | } | ||
190 | |||
156 | return 0; | 191 | return 0; |
157 | } | 192 | } |
158 | 193 | ||
@@ -201,6 +236,11 @@ static int tegra_max98090_probe(struct platform_device *pdev) | |||
201 | if (machine->gpio_hp_det == -EPROBE_DEFER) | 236 | if (machine->gpio_hp_det == -EPROBE_DEFER) |
202 | return -EPROBE_DEFER; | 237 | return -EPROBE_DEFER; |
203 | 238 | ||
239 | machine->gpio_mic_det = | ||
240 | of_get_named_gpio(np, "nvidia,mic-det-gpios", 0); | ||
241 | if (machine->gpio_mic_det == -EPROBE_DEFER) | ||
242 | return -EPROBE_DEFER; | ||
243 | |||
204 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | 244 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); |
205 | if (ret) | 245 | if (ret) |
206 | goto err; | 246 | goto err; |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index f0829de28708..cd71fd889d8b 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/scatterlist.h> | 17 | #include <linux/scatterlist.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/dmaengine.h> | ||
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -137,7 +138,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) | |||
137 | } | 138 | } |
138 | desc->callback = txx9aclc_dma_complete; | 139 | desc->callback = txx9aclc_dma_complete; |
139 | desc->callback_param = dmadata; | 140 | desc->callback_param = dmadata; |
140 | desc->tx_submit(desc); | 141 | dmaengine_submit(desc); |
141 | return desc; | 142 | return desc; |
142 | } | 143 | } |
143 | 144 | ||
@@ -160,7 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) | |||
160 | void __iomem *base = drvdata->base; | 161 | void __iomem *base = drvdata->base; |
161 | 162 | ||
162 | spin_unlock_irqrestore(&dmadata->dma_lock, flags); | 163 | spin_unlock_irqrestore(&dmadata->dma_lock, flags); |
163 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); | 164 | dmaengine_terminate_all(chan); |
164 | /* first time */ | 165 | /* first time */ |
165 | for (i = 0; i < NR_DMA_CHAIN; i++) { | 166 | for (i = 0; i < NR_DMA_CHAIN; i++) { |
166 | desc = txx9aclc_dma_submit(dmadata, | 167 | desc = txx9aclc_dma_submit(dmadata, |
@@ -169,7 +170,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) | |||
169 | return; | 170 | return; |
170 | } | 171 | } |
171 | dmadata->dmacount = NR_DMA_CHAIN; | 172 | dmadata->dmacount = NR_DMA_CHAIN; |
172 | chan->device->device_issue_pending(chan); | 173 | dma_async_issue_pending(chan); |
173 | spin_lock_irqsave(&dmadata->dma_lock, flags); | 174 | spin_lock_irqsave(&dmadata->dma_lock, flags); |
174 | __raw_writel(ctlbit, base + ACCTLEN); | 175 | __raw_writel(ctlbit, base + ACCTLEN); |
175 | dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags; | 176 | dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags; |
@@ -188,7 +189,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) | |||
188 | dmadata->frag_count * dmadata->frag_bytes); | 189 | dmadata->frag_count * dmadata->frag_bytes); |
189 | if (!desc) | 190 | if (!desc) |
190 | return; | 191 | return; |
191 | chan->device->device_issue_pending(chan); | 192 | dma_async_issue_pending(chan); |
192 | 193 | ||
193 | spin_lock_irqsave(&dmadata->dma_lock, flags); | 194 | spin_lock_irqsave(&dmadata->dma_lock, flags); |
194 | dmadata->frag_count++; | 195 | dmadata->frag_count++; |
@@ -266,7 +267,7 @@ static int txx9aclc_pcm_close(struct snd_pcm_substream *substream) | |||
266 | struct dma_chan *chan = dmadata->dma_chan; | 267 | struct dma_chan *chan = dmadata->dma_chan; |
267 | 268 | ||
268 | dmadata->frag_count = -1; | 269 | dmadata->frag_count = -1; |
269 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); | 270 | dmaengine_terminate_all(chan); |
270 | return 0; | 271 | return 0; |
271 | } | 272 | } |
272 | 273 | ||
@@ -398,8 +399,7 @@ static int txx9aclc_pcm_remove(struct snd_soc_platform *platform) | |||
398 | struct dma_chan *chan = dmadata->dma_chan; | 399 | struct dma_chan *chan = dmadata->dma_chan; |
399 | if (chan) { | 400 | if (chan) { |
400 | dmadata->frag_count = -1; | 401 | dmadata->frag_count = -1; |
401 | chan->device->device_control(chan, | 402 | dmaengine_terminate_all(chan); |
402 | DMA_TERMINATE_ALL, 0); | ||
403 | dma_release_channel(chan); | 403 | dma_release_channel(chan); |
404 | } | 404 | } |
405 | dev->dmadata[i].dma_chan = NULL; | 405 | dev->dmadata[i].dma_chan = NULL; |
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 7103b0908d13..272844746135 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c | |||
@@ -816,6 +816,11 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) | |||
816 | return -EINVAL; | 816 | return -EINVAL; |
817 | } | 817 | } |
818 | 818 | ||
819 | if (cdev->n_streams < 2) { | ||
820 | dev_err(dev, "bogus number of streams: %d\n", cdev->n_streams); | ||
821 | return -EINVAL; | ||
822 | } | ||
823 | |||
819 | ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0, | 824 | ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0, |
820 | cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm); | 825 | cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm); |
821 | 826 | ||
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index b2b6f398a4e1..d3d49525a16b 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -1506,6 +1506,12 @@ static struct port_info { | |||
1506 | PORT_INFO(vendor, product, num, name, 0, \ | 1506 | PORT_INFO(vendor, product, num, name, 0, \ |
1507 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | 1507 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ |
1508 | SNDRV_SEQ_PORT_TYPE_HARDWARE) | 1508 | SNDRV_SEQ_PORT_TYPE_HARDWARE) |
1509 | #define GM_SYNTH_PORT(vendor, product, num, name, voices) \ | ||
1510 | PORT_INFO(vendor, product, num, name, voices, \ | ||
1511 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | ||
1512 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ | ||
1513 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ | ||
1514 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | ||
1509 | #define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \ | 1515 | #define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \ |
1510 | PORT_INFO(vendor, product, num, name, voices, \ | 1516 | PORT_INFO(vendor, product, num, name, voices, \ |
1511 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | 1517 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ |
@@ -1525,6 +1531,11 @@ static struct port_info { | |||
1525 | SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \ | 1531 | SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \ |
1526 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ | 1532 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ |
1527 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | 1533 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) |
1534 | /* Yamaha MOTIF XF */ | ||
1535 | GM_SYNTH_PORT(0x0499, 0x105c, 0, "%s Tone Generator", 128), | ||
1536 | CONTROL_PORT(0x0499, 0x105c, 1, "%s Remote Control"), | ||
1537 | EXTERNAL_PORT(0x0499, 0x105c, 2, "%s Thru"), | ||
1538 | CONTROL_PORT(0x0499, 0x105c, 3, "%s Editor"), | ||
1528 | /* Roland UA-100 */ | 1539 | /* Roland UA-100 */ |
1529 | CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"), | 1540 | CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"), |
1530 | /* Roland SC-8850 */ | 1541 | /* Roland SC-8850 */ |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 19a921eb75f1..d2aa45a8d895 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1174,5 +1174,21 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | |||
1174 | } | 1174 | } |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | /* XMOS based USB DACs */ | ||
1178 | switch (chip->usb_id) { | ||
1179 | /* iFi Audio micro/nano iDSD */ | ||
1180 | case USB_ID(0x20b1, 0x3008): | ||
1181 | if (fp->altsetting == 2) | ||
1182 | return SNDRV_PCM_FMTBIT_DSD_U32_LE; | ||
1183 | break; | ||
1184 | /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */ | ||
1185 | case USB_ID(0x20b1, 0x2009): | ||
1186 | if (fp->altsetting == 3) | ||
1187 | return SNDRV_PCM_FMTBIT_DSD_U32_LE; | ||
1188 | break; | ||
1189 | default: | ||
1190 | break; | ||
1191 | } | ||
1192 | |||
1177 | return 0; | 1193 | return 0; |
1178 | } | 1194 | } |