Pull sound updates from Takashi Iwai: "We've received a fairly wide range of changes at this time, including for ALSA and ASoC core, but all of them are rather small changes. Here are some highlights: ALSA / ASoC Core: - Fixes of inconsistent locking around control API helpers - A few new control API functions and cleanups - Workarounds for potential UAFs by delayed kobj releases - Unified PCM copy ops with iov_iter - Continued efforts for ASoC API cleanups ASoC: - An adaptor to allow use of IIO DACs and ADCs in ASoC which pulls in some IIO changes - Create a library function for intlog10() and use it in the NAU8825 driver - Convert drivers to use the more modern maple tree register cache - Lots of work on the SOF framework, AMD and Intel drivers, including a lot of cleanup and new device support - Standardization of the presentation of jacks from drivers - Provision of some generic sound card DT properties - Support for AMD Van Gogh, AMD machines with MAX98388 and NAU8821, AWInic AW88261, Cirrus Logic CS35L36 and CS42L43, various Intel platforms including AVS machines with ES8336 and RT5663, Mediatek MT7986, NXP i.MX93, RealTek RT1017 and StarFive JH7110 Others: - New test coverage including ASoC and topology tests in KUnit; this also involves enabling UML builds of ALSA since that's the default KUnit test environment which pulls in the addition of some stubs to the driver - More enhancement of pcmtest driver - A few fixes / enhancements of MIDI 2.0 UMP core - Using PCI definitions in allover HD-audio code - Support for Cirrus CS35L56 and TI TAS2781 HD-audio sub-codecs - CS35L41 HD-audio sub-codec improvements - Continued emu10k1 improvements" * tag 'sound-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (693 commits) ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl ASoC: dwc: i2s: Fix unused functions ALSA: usb-audio: Don't try to submit URBs after disconnection ALSA: emu10k1: add separate documentation for E-MU cards ALSA: emu10k1: more documentation updates ALSA: emu10k1: de-duplicate audigy-mixer.rst vs. sb-live-mixer.rst ALSA: ump: Fix -Wformat-truncation warnings ALSA: hda: Add missing dependency on CONFIG_EFI for Cirrus/TI sub-codecs ALSA: doc: Fix missing backquote in midi-2.0.rst ALSA: hda/realtek: Add quirk for mute LEDs on HP ENVY x360 15-eu0xxx ALSA: hda/tas2781: Switch back to use struct i2c_driver's .probe() ASoC: soc-core.c: Do not error if a DAI link component is not found ASoC: codecs: Fix error code in aw88261_i2c_probe() ASoC: audio-graph-card.c: move audio_graph_parse_of() ASoC: cs42l43: Use new-style PM runtime macros ALSA: documentation: Add description for USB MIDI 2.0 gadget driver ALSA: ump: Don't create unused substreams for static blocks ALSA: ump: Fill group names for legacy rawmidi substreams ALSA: usb-audio: Attach legacy rawmidi after probing all UMP EPs ALSA: ac97: Fix possible error value of *rac97 ...
Unified · Split
| @@ -162,8 +162,10 @@ Base 2 log and power Functions · 161 unmodified lines | ||
| 162 | 162 | .. kernel-doc:: include/linux/log2.h |
| 163 | 163 | :internal: |
| 164 | 164 | |
| 165 | −Integer power Functions | |
| 166 | −----------------------- | |
| 165 | +Integer log and power Functions | |
| 166 | +------------------------------- | |
| 167 | + | |
| 168 | +.. kernel-doc:: include/linux/int_log.h | |
| 167 | 169 | |
| 168 | 170 | .. kernel-doc:: lib/math/int_pow.c |
| 169 | 171 | :export: |
| @@ -9,6 +9,9 @@ title: Amlogic AXG sound card · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Jerome Brunet <jbrunet@baylibre.com> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | const: amlogic,axg-sound-card |
| @@ -17,23 +20,12 @@ properties: · 2 unmodified lines | ||
| 17 | 20 | $ref: /schemas/types.yaml#/definitions/phandle-array |
| 18 | 21 | description: list of auxiliary devices |
| 19 | 22 | |
| 20 | − audio-routing: | |
| 21 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 22 | − description: | |
| 23 | − A list of the connections between audio components. Each entry is a | |
| 24 | − pair of strings, the first being the connection's sink, the second | |
| 25 | − being the connection's source. | |
| 26 | − | |
| 27 | 23 | audio-widgets: |
| 28 | 24 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 29 | 25 | description: |
| 30 | 26 | A list off component DAPM widget. Each entry is a pair of strings, |
| 31 | 27 | the first being the widget type, the second being the widget name |
| 32 | 28 | |
| 33 | − model: | |
| 34 | − $ref: /schemas/types.yaml#/definitions/string | |
| 35 | − description: User specified audio sound card name | |
| 36 | − | |
| 37 | 29 | patternProperties: |
| 38 | 30 | "^dai-link-[0-9]+$": |
| 39 | 31 | type: object |
| @@ -108,7 +100,6 @@ patternProperties: · 68 unmodified lines | ||
| 108 | 100 | - sound-dai |
| 109 | 101 | |
| 110 | 102 | required: |
| 111 | − - model | |
| 112 | 103 | - dai-link-0 |
| 113 | 104 | |
| 114 | 105 | unevaluatedProperties: false |
| @@ -9,6 +9,9 @@ title: Amlogic GX sound card · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Jerome Brunet <jbrunet@baylibre.com> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | items: |
| @@ -18,14 +21,6 @@ properties: · 3 unmodified lines | ||
| 18 | 21 | $ref: /schemas/types.yaml#/definitions/phandle-array |
| 19 | 22 | description: list of auxiliary devices |
| 20 | 23 | |
| 21 | − audio-routing: | |
| 22 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 23 | − minItems: 2 | |
| 24 | − description: |- | |
| 25 | − A list of the connections between audio components. Each entry is a | |
| 26 | − pair of strings, the first being the connection's sink, the second | |
| 27 | − being the connection's source. | |
| 28 | − | |
| 29 | 24 | audio-widgets: |
| 30 | 25 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 31 | 26 | minItems: 2 |
| @@ -33,10 +28,6 @@ properties: · 1 unmodified line | ||
| 33 | 28 | A list off component DAPM widget. Each entry is a pair of strings, |
| 34 | 29 | the first being the widget type, the second being the widget name |
| 35 | 30 | |
| 36 | − model: | |
| 37 | − $ref: /schemas/types.yaml#/definitions/string | |
| 38 | − description: User specified audio sound card name | |
| 39 | − | |
| 40 | 31 | patternProperties: |
| 41 | 32 | "^dai-link-[0-9]+$": |
| 42 | 33 | type: object |
| @@ -86,7 +77,7 @@ required: · 43 unmodified lines | ||
| 86 | 77 | - model |
| 87 | 78 | - dai-link-0 |
| 88 | 79 | |
| 89 | −additionalProperties: false | |
| 80 | +unevaluatedProperties: false | |
| 90 | 81 | |
| 91 | 82 | examples: |
| 92 | 83 | - | |
| @@ -0,0 +1,64 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/audio-iio-aux.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Audio IIO auxiliary | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Herve Codina <herve.codina@bootlin.com> | |
| 11 | + | |
| 12 | +description: | |
| 13 | + Auxiliary device based on Industrial I/O device channels | |
| 14 | + | |
| 15 | +allOf: | |
| 16 | + - $ref: dai-common.yaml# | |
| 17 | + | |
| 18 | +properties: | |
| 19 | + compatible: | |
| 20 | + const: audio-iio-aux | |
| 21 | + | |
| 22 | + io-channels: | |
| 23 | + description: | |
| 24 | + Industrial I/O device channels used | |
| 25 | + | |
| 26 | + io-channel-names: | |
| 27 | + description: | |
| 28 | + Industrial I/O channel names related to io-channels. | |
| 29 | + These names are used to provides sound controls, widgets and routes names. | |
| 30 | + | |
| 31 | + snd-control-invert-range: | |
| 32 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 33 | + description: | | |
| 34 | + A list of 0/1 flags defining whether or not the related channel is | |
| 35 | + inverted | |
| 36 | + items: | |
| 37 | + enum: [0, 1] | |
| 38 | + default: 0 | |
| 39 | + description: | | |
| 40 | + Invert the sound control value compared to the IIO channel raw value. | |
| 41 | + - 1: The related sound control value is inverted meaning that the | |
| 42 | + minimum sound control value correspond to the maximum IIO channel | |
| 43 | + raw value and the maximum sound control value correspond to the | |
| 44 | + minimum IIO channel raw value. | |
| 45 | + - 0: The related sound control value is not inverted meaning that the | |
| 46 | + minimum (resp maximum) sound control value correspond to the | |
| 47 | + minimum (resp maximum) IIO channel raw value. | |
| 48 | + | |
| 49 | +required: | |
| 50 | + - compatible | |
| 51 | + - io-channels | |
| 52 | + - io-channel-names | |
| 53 | + | |
| 54 | +unevaluatedProperties: false | |
| 55 | + | |
| 56 | +examples: | |
| 57 | + - | | |
| 58 | + iio-aux { | |
| 59 | + compatible = "audio-iio-aux"; | |
| 60 | + io-channels = <&iio 0>, <&iio 1>, <&iio 2>, <&iio 3>; | |
| 61 | + io-channel-names = "CH0", "CH1", "CH2", "CH3"; | |
| 62 | + /* Invert CH1 and CH2 */ | |
| 63 | + snd-control-invert-range = <0 1 1 0>; | |
| 64 | + }; | |
| @@ -19,7 +19,9 @@ allOf: · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | properties: |
| 21 | 21 | compatible: |
| 22 | − const: awinic,aw88395 | |
| 22 | + enum: | |
| 23 | + - awinic,aw88395 | |
| 24 | + - awinic,aw88261 | |
| 23 | 25 | |
| 24 | 26 | reg: |
| 25 | 27 | maxItems: 1 |
| @@ -17,6 +17,9 @@ description: | · 16 unmodified lines | ||
| 17 | 17 | such as SAI, MICFIL, .etc through building rpmsg channels between |
| 18 | 18 | Cortex-A and Cortex-M. |
| 19 | 19 | |
| 20 | +allOf: | |
| 21 | + - $ref: sound-card-common.yaml# | |
| 22 | + | |
| 20 | 23 | properties: |
| 21 | 24 | compatible: |
| 22 | 25 | enum: |
| @@ -25,10 +28,7 @@ properties: · 2 unmodified lines | ||
| 25 | 28 | - fsl,imx8mm-rpmsg-audio |
| 26 | 29 | - fsl,imx8mp-rpmsg-audio |
| 27 | 30 | - fsl,imx8ulp-rpmsg-audio |
| 28 | − | |
| 29 | − model: | |
| 30 | − $ref: /schemas/types.yaml#/definitions/string | |
| 31 | − description: User specified audio sound card name | |
| 31 | + - fsl,imx93-rpmsg-audio | |
| 32 | 32 | |
| 33 | 33 | clocks: |
| 34 | 34 | items: |
| @@ -65,13 +65,6 @@ properties: · 30 unmodified lines | ||
| 65 | 65 | $ref: /schemas/types.yaml#/definitions/phandle |
| 66 | 66 | description: The phandle to a node of audio codec |
| 67 | 67 | |
| 68 | − audio-routing: | |
| 69 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 70 | − description: | | |
| 71 | − A list of the connections between audio components. Each entry is a | |
| 72 | − pair of strings, the first being the connection's sink, the second | |
| 73 | − being the connection's source. | |
| 74 | − | |
| 75 | 68 | fsl,enable-lpa: |
| 76 | 69 | $ref: /schemas/types.yaml#/definitions/flag |
| 77 | 70 | description: enable low power audio path. |
| @@ -100,9 +93,8 @@ properties: · 22 unmodified lines | ||
| 100 | 93 | |
| 101 | 94 | required: |
| 102 | 95 | - compatible |
| 103 | − - model | |
| 104 | 96 | |
| 105 | −additionalProperties: false | |
| 97 | +unevaluatedProperties: false | |
| 106 | 98 | |
| 107 | 99 | examples: |
| 108 | 100 | - | |
| @@ -13,23 +13,15 @@ maintainers: · 12 unmodified lines | ||
| 13 | 13 | description: |
| 14 | 14 | This binding describes the SC7180 sound card which uses LPASS for audio. |
| 15 | 15 | |
| 16 | +allOf: | |
| 17 | + - $ref: sound-card-common.yaml# | |
| 18 | + | |
| 16 | 19 | properties: |
| 17 | 20 | compatible: |
| 18 | 21 | enum: |
| 19 | 22 | - google,sc7180-trogdor |
| 20 | 23 | - google,sc7180-coachz |
| 21 | 24 | |
| 22 | − audio-routing: | |
| 23 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 24 | − description: | |
| 25 | − A list of the connections between audio components. Each entry is a | |
| 26 | − pair of strings, the first being the connection's sink, the second | |
| 27 | − being the connection's source. | |
| 28 | − | |
| 29 | − model: | |
| 30 | − $ref: /schemas/types.yaml#/definitions/string | |
| 31 | − description: User specified audio sound card name | |
| 32 | − | |
| 33 | 25 | "#address-cells": |
| 34 | 26 | const: 1 |
| 35 | 27 | |
| @@ -86,11 +78,10 @@ patternProperties: · 50 unmodified lines | ||
| 86 | 78 | |
| 87 | 79 | required: |
| 88 | 80 | - compatible |
| 89 | − - model | |
| 90 | 81 | - "#address-cells" |
| 91 | 82 | - "#size-cells" |
| 92 | 83 | |
| 93 | −additionalProperties: false | |
| 84 | +unevaluatedProperties: false | |
| 94 | 85 | |
| 95 | 86 | examples: |
| 96 | 87 | |
| @@ -13,22 +13,14 @@ maintainers: · 12 unmodified lines | ||
| 13 | 13 | description: |
| 14 | 14 | This binding describes the SC7280 sound card which uses LPASS for audio. |
| 15 | 15 | |
| 16 | +allOf: | |
| 17 | + - $ref: sound-card-common.yaml# | |
| 18 | + | |
| 16 | 19 | properties: |
| 17 | 20 | compatible: |
| 18 | 21 | enum: |
| 19 | 22 | - google,sc7280-herobrine |
| 20 | 23 | |
| 21 | − audio-routing: | |
| 22 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 23 | − description: | |
| 24 | − A list of the connections between audio components. Each entry is a | |
| 25 | − pair of strings, the first being the connection's sink, the second | |
| 26 | − being the connection's source. | |
| 27 | − | |
| 28 | − model: | |
| 29 | − $ref: /schemas/types.yaml#/definitions/string | |
| 30 | − description: User specified audio sound card name | |
| 31 | − | |
| 32 | 24 | "#address-cells": |
| 33 | 25 | const: 1 |
| 34 | 26 | |
| @@ -97,11 +89,10 @@ patternProperties: · 62 unmodified lines | ||
| 97 | 89 | |
| 98 | 90 | required: |
| 99 | 91 | - compatible |
| 100 | − - model | |
| 101 | 92 | - "#address-cells" |
| 102 | 93 | - "#size-cells" |
| 103 | 94 | |
| 104 | −additionalProperties: false | |
| 95 | +unevaluatedProperties: false | |
| 105 | 96 | |
| 106 | 97 | examples: |
| 107 | 98 | |
| @@ -1,19 +0,0 @@ | ||
| 1 | −GTM601 UMTS modem audio interface CODEC | |
| 2 | − | |
| 3 | −This device has no configuration interface. The sample rate and channels are | |
| 4 | −based on the compatible string | |
| 5 | − "option,gtm601" = 8kHz mono | |
| 6 | − "broadmobi,bm818" = 48KHz stereo | |
| 7 | − | |
| 8 | −Required properties: | |
| 9 | − | |
| 10 | − - compatible : one of | |
| 11 | − "option,gtm601" | |
| 12 | − "broadmobi,bm818" | |
| 13 | − | |
| 14 | − | |
| 15 | −Example: | |
| 16 | − | |
| 17 | −codec: gtm601_codec { | |
| 18 | − compatible = "option,gtm601"; | |
| 19 | −}; | |
| @@ -9,23 +9,14 @@ title: NXP i.MX audio sound card. · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Shengjiu Wang <shengjiu.wang@nxp.com> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | enum: |
| 15 | 18 | - fsl,imx-audio-card |
| 16 | 19 | |
| 17 | − model: | |
| 18 | − $ref: /schemas/types.yaml#/definitions/string | |
| 19 | − description: User specified audio sound card name | |
| 20 | − | |
| 21 | − audio-routing: | |
| 22 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 23 | − description: | |
| 24 | − A list of the connections between audio components. Each entry is a | |
| 25 | − pair of strings, the first being the connection's sink, the second | |
| 26 | − being the connection's source. Valid names could be power supplies, | |
| 27 | − MicBias of codec and the jacks on the board. | |
| 28 | − | |
| 29 | 20 | patternProperties: |
| 30 | 21 | ".*-dai-link$": |
| 31 | 22 | description: |
| @@ -84,9 +75,8 @@ patternProperties: · 52 unmodified lines | ||
| 84 | 75 | |
| 85 | 76 | required: |
| 86 | 77 | - compatible |
| 87 | − - model | |
| 88 | 78 | |
| 89 | −additionalProperties: false | |
| 79 | +unevaluatedProperties: false | |
| 90 | 80 | |
| 91 | 81 | examples: |
| 92 | 82 | - | |
| @@ -1,44 +0,0 @@ | ||
| 1 | −Maxim Integrated MAX98925/MAX98926/MAX98927 Speaker Amplifier | |
| 2 | − | |
| 3 | −This device supports I2C. | |
| 4 | − | |
| 5 | −Required properties: | |
| 6 | − | |
| 7 | − - compatible : should be one of the following | |
| 8 | − - "maxim,max98925" | |
| 9 | − - "maxim,max98926" | |
| 10 | − - "maxim,max98927" | |
| 11 | − | |
| 12 | − - vmon-slot-no : slot number used to send voltage information | |
| 13 | − or in inteleave mode this will be used as | |
| 14 | − interleave slot. | |
| 15 | − MAX98925/MAX98926 slot range : 0 ~ 30, Default : 0 | |
| 16 | − MAX98927 slot range : 0 ~ 15, Default : 0 | |
| 17 | − | |
| 18 | − - imon-slot-no : slot number used to send current information | |
| 19 | − MAX98925/MAX98926 slot range : 0 ~ 30, Default : 0 | |
| 20 | − MAX98927 slot range : 0 ~ 15, Default : 0 | |
| 21 | − | |
| 22 | − - interleave-mode : When using two MAX9892X in a system it is | |
| 23 | − possible to create ADC data that that will | |
| 24 | − overflow the frame size. Digital Audio Interleave | |
| 25 | − mode provides a means to output VMON and IMON data | |
| 26 | − from two devices on a single DOUT line when running | |
| 27 | − smaller frames sizes such as 32 BCLKS per LRCLK or | |
| 28 | − 48 BCLKS per LRCLK. | |
| 29 | − Range : 0 (off), 1 (on), Default : 0 | |
| 30 | − | |
| 31 | − - reg : the I2C address of the device for I2C | |
| 32 | − | |
| 33 | −Optional properties: | |
| 34 | − - reset-gpios : GPIO to reset the device | |
| 35 | − | |
| 36 | −Example: | |
| 37 | − | |
| 38 | −codec: max98927@3a { | |
| 39 | − compatible = "maxim,max98927"; | |
| 40 | − vmon-slot-no = <0>; | |
| 41 | − imon-slot-no = <1>; | |
| 42 | − interleave-mode = <0>; | |
| 43 | − reg = <0x3a>; | |
| 44 | −}; | |
| @@ -0,0 +1,98 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/maxim,max98925.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Maxim Integrated MAX98925/MAX98926/MAX98927 speaker amplifier | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Ryan Lee <ryans.lee@maximintegrated.com> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + enum: | |
| 15 | + - maxim,max98925 | |
| 16 | + - maxim,max98926 | |
| 17 | + - maxim,max98927 | |
| 18 | + | |
| 19 | + reg: | |
| 20 | + maxItems: 1 | |
| 21 | + | |
| 22 | + reset-gpios: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 25 | + '#sound-dai-cells': | |
| 26 | + const: 0 | |
| 27 | + | |
| 28 | + vmon-slot-no: | |
| 29 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 30 | + minimum: 0 | |
| 31 | + maximum: 30 | |
| 32 | + default: 0 | |
| 33 | + description: | |
| 34 | + Slot number used to send voltage information or in inteleave mode this | |
| 35 | + will be used as interleave slot. | |
| 36 | + | |
| 37 | + imon-slot-no: | |
| 38 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 39 | + minimum: 0 | |
| 40 | + maximum: 30 | |
| 41 | + default: 0 | |
| 42 | + description: | |
| 43 | + Slot number used to send current information. | |
| 44 | + | |
| 45 | + maxim,interleave-mode: | |
| 46 | + type: boolean | |
| 47 | + description: | |
| 48 | + When using two MAX9892X in a system it is possible to create ADC data | |
| 49 | + that will overflow the frame size. When enabled, the Digital Audio | |
| 50 | + Interleave mode provides a means to output VMON and IMON data from two | |
| 51 | + devices on a single DOUT line when running smaller frames sizes such as | |
| 52 | + 32 BCLKS per LRCLK or 48 BCLKS per LRCLK. | |
| 53 | + | |
| 54 | +required: | |
| 55 | + - compatible | |
| 56 | + - reg | |
| 57 | + | |
| 58 | +allOf: | |
| 59 | + - $ref: dai-common.yaml# | |
| 60 | + - if: | |
| 61 | + properties: | |
| 62 | + compatible: | |
| 63 | + contains: | |
| 64 | + enum: | |
| 65 | + - maxim,max98927 | |
| 66 | + then: | |
| 67 | + properties: | |
| 68 | + vmon-slot-no: | |
| 69 | + minimum: 0 | |
| 70 | + maximum: 15 | |
| 71 | + | |
| 72 | + imon-slot-no: | |
| 73 | + minimum: 0 | |
| 74 | + maximum: 15 | |
| 75 | + | |
| 76 | +additionalProperties: false | |
| 77 | + | |
| 78 | +examples: | |
| 79 | + - | | |
| 80 | + i2c { | |
| 81 | + #address-cells = <1>; | |
| 82 | + #size-cells = <0>; | |
| 83 | + | |
| 84 | + #include <dt-bindings/gpio/gpio.h> | |
| 85 | + audio-codec@3a { | |
| 86 | + compatible = "maxim,max98927"; | |
| 87 | + reg = <0x3a>; | |
| 88 | + #sound-dai-cells = <0>; | |
| 89 | + | |
| 90 | + pinctrl-0 = <&speaker_default>; | |
| 91 | + pinctrl-names = "default"; | |
| 92 | + | |
| 93 | + reset-gpios = <&tlmm 69 GPIO_ACTIVE_LOW>; | |
| 94 | + | |
| 95 | + vmon-slot-no = <1>; | |
| 96 | + imon-slot-no = <0>; | |
| 97 | + }; | |
| 98 | + }; | |
| @@ -0,0 +1,160 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/mediatek,mt7986-afe.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: MediaTek AFE PCM controller for MT7986 | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Maso Huang <maso.huang@mediatek.com> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + oneOf: | |
| 15 | + - const: mediatek,mt7986-afe | |
| 16 | + - items: | |
| 17 | + - enum: | |
| 18 | + - mediatek,mt7981-afe | |
| 19 | + - mediatek,mt7988-afe | |
| 20 | + - const: mediatek,mt7986-afe | |
| 21 | + | |
| 22 | + reg: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 25 | + interrupts: | |
| 26 | + maxItems: 1 | |
| 27 | + | |
| 28 | + clocks: | |
| 29 | + minItems: 5 | |
| 30 | + items: | |
| 31 | + - description: audio bus clock | |
| 32 | + - description: audio 26M clock | |
| 33 | + - description: audio intbus clock | |
| 34 | + - description: audio hopping clock | |
| 35 | + - description: audio pll clock | |
| 36 | + - description: mux for pcm_mck | |
| 37 | + - description: audio i2s/pcm mck | |
| 38 | + | |
| 39 | + clock-names: | |
| 40 | + minItems: 5 | |
| 41 | + items: | |
| 42 | + - const: bus_ck | |
| 43 | + - const: 26m_ck | |
| 44 | + - const: l_ck | |
| 45 | + - const: aud_ck | |
| 46 | + - const: eg2_ck | |
| 47 | + - const: sel | |
| 48 | + - const: i2s_m | |
| 49 | + | |
| 50 | +required: | |
| 51 | + - compatible | |
| 52 | + - reg | |
| 53 | + - interrupts | |
| 54 | + - clocks | |
| 55 | + - clock-names | |
| 56 | + | |
| 57 | +allOf: | |
| 58 | + - if: | |
| 59 | + properties: | |
| 60 | + compatible: | |
| 61 | + contains: | |
| 62 | + const: mediatek,mt7986-afe | |
| 63 | + then: | |
| 64 | + properties: | |
| 65 | + clocks: | |
| 66 | + items: | |
| 67 | + - description: audio bus clock | |
| 68 | + - description: audio 26M clock | |
| 69 | + - description: audio intbus clock | |
| 70 | + - description: audio hopping clock | |
| 71 | + - description: audio pll clock | |
| 72 | + clock-names: | |
| 73 | + items: | |
| 74 | + - const: bus_ck | |
| 75 | + - const: 26m_ck | |
| 76 | + - const: l_ck | |
| 77 | + - const: aud_ck | |
| 78 | + - const: eg2_ck | |
| 79 | + | |
| 80 | + - if: | |
| 81 | + properties: | |
| 82 | + compatible: | |
| 83 | + contains: | |
| 84 | + const: mediatek,mt7981-afe | |
| 85 | + then: | |
| 86 | + properties: | |
| 87 | + clocks: | |
| 88 | + items: | |
| 89 | + - description: audio bus clock | |
| 90 | + - description: audio 26M clock | |
| 91 | + - description: audio intbus clock | |
| 92 | + - description: audio hopping clock | |
| 93 | + - description: audio pll clock | |
| 94 | + - description: mux for pcm_mck | |
| 95 | + clock-names: | |
| 96 | + items: | |
| 97 | + - const: bus_ck | |
| 98 | + - const: 26m_ck | |
| 99 | + - const: l_ck | |
| 100 | + - const: aud_ck | |
| 101 | + - const: eg2_ck | |
| 102 | + - const: sel | |
| 103 | + | |
| 104 | + - if: | |
| 105 | + properties: | |
| 106 | + compatible: | |
| 107 | + contains: | |
| 108 | + const: mediatek,mt7988-afe | |
| 109 | + then: | |
| 110 | + properties: | |
| 111 | + clocks: | |
| 112 | + items: | |
| 113 | + - description: audio bus clock | |
| 114 | + - description: audio 26M clock | |
| 115 | + - description: audio intbus clock | |
| 116 | + - description: audio hopping clock | |
| 117 | + - description: audio pll clock | |
| 118 | + - description: mux for pcm_mck | |
| 119 | + - description: audio i2s/pcm mck | |
| 120 | + clock-names: | |
| 121 | + items: | |
| 122 | + - const: bus_ck | |
| 123 | + - const: 26m_ck | |
| 124 | + - const: l_ck | |
| 125 | + - const: aud_ck | |
| 126 | + - const: eg2_ck | |
| 127 | + - const: sel | |
| 128 | + - const: i2s_m | |
| 129 | + | |
| 130 | +additionalProperties: false | |
| 131 | + | |
| 132 | +examples: | |
| 133 | + - | | |
| 134 | + #include <dt-bindings/interrupt-controller/arm-gic.h> | |
| 135 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 136 | + #include <dt-bindings/clock/mt7986-clk.h> | |
| 137 | + | |
| 138 | + afe@11210000 { | |
| 139 | + compatible = "mediatek,mt7986-afe"; | |
| 140 | + reg = <0x11210000 0x9000>; | |
| 141 | + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; | |
| 142 | + clocks = <&infracfg_ao CLK_INFRA_AUD_BUS_CK>, | |
| 143 | + <&infracfg_ao CLK_INFRA_AUD_26M_CK>, | |
| 144 | + <&infracfg_ao CLK_INFRA_AUD_L_CK>, | |
| 145 | + <&infracfg_ao CLK_INFRA_AUD_AUD_CK>, | |
| 146 | + <&infracfg_ao CLK_INFRA_AUD_EG2_CK>; | |
| 147 | + clock-names = "bus_ck", | |
| 148 | + "26m_ck", | |
| 149 | + "l_ck", | |
| 150 | + "aud_ck", | |
| 151 | + "eg2_ck"; | |
| 152 | + assigned-clocks = <&topckgen CLK_TOP_A1SYS_SEL>, | |
| 153 | + <&topckgen CLK_TOP_AUD_L_SEL>, | |
| 154 | + <&topckgen CLK_TOP_A_TUNER_SEL>; | |
| 155 | + assigned-clock-parents = <&topckgen CLK_TOP_APLL2_D4>, | |
| 156 | + <&apmixedsys CLK_APMIXED_APLL2>, | |
| 157 | + <&topckgen CLK_TOP_APLL2_D4>; | |
| 158 | + }; | |
| 159 | + | |
| 160 | +... | |
| @@ -0,0 +1,67 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/mediatek,mt7986-wm8960.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: MediaTek MT7986 sound card with WM8960 codec | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Maso Huang <maso.huang@mediatek.com> | |
| 11 | + | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + const: mediatek,mt7986-wm8960-sound | |
| 18 | + | |
| 19 | + platform: | |
| 20 | + type: object | |
| 21 | + additionalProperties: false | |
| 22 | + properties: | |
| 23 | + sound-dai: | |
| 24 | + description: The phandle of MT7986 platform. | |
| 25 | + maxItems: 1 | |
| 26 | + required: | |
| 27 | + - sound-dai | |
| 28 | + | |
| 29 | + codec: | |
| 30 | + type: object | |
| 31 | + additionalProperties: false | |
| 32 | + properties: | |
| 33 | + sound-dai: | |
| 34 | + description: The phandle of wm8960 codec. | |
| 35 | + maxItems: 1 | |
| 36 | + required: | |
| 37 | + - sound-dai | |
| 38 | + | |
| 39 | +unevaluatedProperties: false | |
| 40 | + | |
| 41 | +required: | |
| 42 | + - compatible | |
| 43 | + - audio-routing | |
| 44 | + - platform | |
| 45 | + - codec | |
| 46 | + | |
| 47 | +examples: | |
| 48 | + - | | |
| 49 | + sound { | |
| 50 | + compatible = "mediatek,mt7986-wm8960-sound"; | |
| 51 | + model = "mt7986-wm8960"; | |
| 52 | + audio-routing = | |
| 53 | + "Headphone", "HP_L", | |
| 54 | + "Headphone", "HP_R", | |
| 55 | + "LINPUT1", "AMIC", | |
| 56 | + "RINPUT1", "AMIC"; | |
| 57 | + | |
| 58 | + platform { | |
| 59 | + sound-dai = <&afe>; | |
| 60 | + }; | |
| 61 | + | |
| 62 | + codec { | |
| 63 | + sound-dai = <&wm8960>; | |
| 64 | + }; | |
| 65 | + }; | |
| 66 | + | |
| 67 | +... | |
| @@ -25,6 +25,12 @@ properties: · 24 unmodified lines | ||
| 25 | 25 | reset-names: |
| 26 | 26 | const: audiosys |
| 27 | 27 | |
| 28 | + memory-region: | |
| 29 | + maxItems: 1 | |
| 30 | + description: | | |
| 31 | + Shared memory region for AFE memif. A "shared-dma-pool". | |
| 32 | + See ../reserved-memory/reserved-memory.yaml for details. | |
| 33 | + | |
| 28 | 34 | mediatek,topckgen: |
| 29 | 35 | $ref: /schemas/types.yaml#/definitions/phandle |
| 30 | 36 | description: The phandle of the mediatek topckgen controller |
| @@ -176,6 +182,7 @@ examples: · 145 unmodified lines | ||
| 176 | 182 | interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>; |
| 177 | 183 | resets = <&watchdog 14>; |
| 178 | 184 | reset-names = "audiosys"; |
| 185 | + memory-region = <&snd_dma_mem_reserved>; | |
| 179 | 186 | mediatek,topckgen = <&topckgen>; |
| 180 | 187 | mediatek,infracfg = <&infracfg_ao>; |
| 181 | 188 | power-domains = <&spm 13>; //MT8188_POWER_DOMAIN_AUDIO |
| @@ -9,23 +9,19 @@ title: MediaTek MT8188 ASoC sound card · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Trevor Wu <trevor.wu@mediatek.com> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | enum: |
| 15 | 18 | - mediatek,mt8188-mt6359-evb |
| 16 | 19 | - mediatek,mt8188-nau8825 |
| 17 | 20 | |
| 18 | − model: | |
| 19 | − $ref: /schemas/types.yaml#/definitions/string | |
| 20 | − description: User specified audio sound card name | |
| 21 | − | |
| 22 | 21 | audio-routing: |
| 23 | − $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 24 | 22 | description: |
| 25 | − A list of the connections between audio components. Each entry is a | |
| 26 | − sink/source pair of strings. Valid names could be the input or output | |
| 27 | − widgets of audio components, power supplies, MicBias of codec and the | |
| 28 | − software switch. | |
| 23 | + Valid names could be the input or output widgets of audio components, | |
| 24 | + power supplies, MicBias of codec and the software switch. | |
| 29 | 25 | |
| 30 | 26 | mediatek,platform: |
| 31 | 27 | $ref: /schemas/types.yaml#/definitions/phandle |
| @@ -86,7 +82,7 @@ patternProperties: · 54 unmodified lines | ||
| 86 | 82 | required: |
| 87 | 83 | - link-name |
| 88 | 84 | |
| 89 | −additionalProperties: false | |
| 85 | +unevaluatedProperties: false | |
| 90 | 86 | |
| 91 | 87 | required: |
| 92 | 88 | - compatible |
| @@ -96,6 +92,7 @@ examples: · 3 unmodified lines | ||
| 96 | 92 | - | |
| 97 | 93 | sound { |
| 98 | 94 | compatible = "mediatek,mt8188-mt6359-evb"; |
| 95 | + model = "MT6359-EVB"; | |
| 99 | 96 | mediatek,platform = <&afe>; |
| 100 | 97 | pinctrl-names = "default"; |
| 101 | 98 | pinctrl-0 = <&aud_pins_default>; |
| @@ -1,55 +0,0 @@ | ||
| 1 | −Nuvoton NAU88L21 audio codec | |
| 2 | − | |
| 3 | −This device supports I2C only. | |
| 4 | − | |
| 5 | −Required properties: | |
| 6 | − - compatible : Must be "nuvoton,nau8821" | |
| 7 | − | |
| 8 | − - reg : the I2C address of the device. This is either 0x1B (CSB=0) or 0x54 (CSB=1). | |
| 9 | − | |
| 10 | −Optional properties: | |
| 11 | − - nuvoton,jkdet-enable: Enable jack detection via JKDET pin. | |
| 12 | − - nuvoton,jkdet-pull-enable: Enable JKDET pin pull. If set - pin pull enabled, | |
| 13 | − otherwise pin in high impedance state. | |
| 14 | − - nuvoton,jkdet-pull-up: Pull-up JKDET pin. If set then JKDET pin is pull up, otherwise pull down. | |
| 15 | − - nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low. | |
| 16 | − | |
| 17 | − - nuvoton,vref-impedance: VREF Impedance selection | |
| 18 | − 0 - Open | |
| 19 | − 1 - 25 kOhm | |
| 20 | − 2 - 125 kOhm | |
| 21 | − 3 - 2.5 kOhm | |
| 22 | − | |
| 23 | − - nuvoton,micbias-voltage: Micbias voltage level. | |
| 24 | − 0 - VDDA | |
| 25 | − 1 - VDDA | |
| 26 | − 2 - VDDA * 1.1 | |
| 27 | − 3 - VDDA * 1.2 | |
| 28 | − 4 - VDDA * 1.3 | |
| 29 | − 5 - VDDA * 1.4 | |
| 30 | − 6 - VDDA * 1.53 | |
| 31 | − 7 - VDDA * 1.53 | |
| 32 | − | |
| 33 | − - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms | |
| 34 | − - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms | |
| 35 | − | |
| 36 | − - nuvoton,dmic-clk-threshold: the ADC threshold of DMIC clock. | |
| 37 | − - nuvoton,key_enable: Headset button detection switch. | |
| 38 | − | |
| 39 | −Example: | |
| 40 | − | |
| 41 | − headset: nau8821@1b { | |
| 42 | − compatible = "nuvoton,nau8821"; | |
| 43 | − reg = <0x1b>; | |
| 44 | − interrupt-parent = <&gpio>; | |
| 45 | − interrupts = <23 IRQ_TYPE_LEVEL_LOW>; | |
| 46 | − nuvoton,jkdet-enable; | |
| 47 | − nuvoton,jkdet-pull-enable; | |
| 48 | − nuvoton,jkdet-pull-up; | |
| 49 | − nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; | |
| 50 | − nuvoton,vref-impedance = <2>; | |
| 51 | − nuvoton,micbias-voltage = <6>; | |
| 52 | − nuvoton,jack-insert-debounce = <7>; | |
| 53 | − nuvoton,jack-eject-debounce = <7>; | |
| 54 | − nuvoton,dmic-clk-threshold = 3072000; | |
| 55 | − }; | |
| @@ -0,0 +1,132 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/nuvoton,nau8821.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: NAU88L21 audio codec | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Seven Lee <wtli@nuvoton.com> | |
| 11 | + | |
| 12 | +allOf: | |
| 13 | + - $ref: dai-common.yaml# | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + const: nuvoton,nau8821 | |
| 18 | + | |
| 19 | + reg: | |
| 20 | + maxItems: 1 | |
| 21 | + | |
| 22 | + interrupts: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 25 | + nuvoton,jkdet-enable: | |
| 26 | + description: Enable jack detection via JKDET pin. | |
| 27 | + type: boolean | |
| 28 | + | |
| 29 | + nuvoton,jkdet-pull-enable: | |
| 30 | + description: Enable JKDET pin pull. If set - pin pull enabled, | |
| 31 | + otherwise pin in high impedance state. | |
| 32 | + type: boolean | |
| 33 | + | |
| 34 | + nuvoton,jkdet-pull-up: | |
| 35 | + description: Pull-up JKDET pin. If set then JKDET pin is pull up, | |
| 36 | + otherwise pull down. | |
| 37 | + type: boolean | |
| 38 | + | |
| 39 | + nuvoton,key-enable: | |
| 40 | + description: handles key press detection. | |
| 41 | + type: boolean | |
| 42 | + | |
| 43 | + nuvoton,jkdet-polarity: | |
| 44 | + description: JKDET pin polarity. | |
| 45 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 46 | + enum: | |
| 47 | + - 0 # active high | |
| 48 | + - 1 # active low | |
| 49 | + default: 1 | |
| 50 | + | |
| 51 | + nuvoton,micbias-voltage: | |
| 52 | + description: MICBIAS output level select. | |
| 53 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 54 | + enum: | |
| 55 | + - 0 # VDDA | |
| 56 | + - 1 # VDDA * 1 | |
| 57 | + - 2 # VDDA * 1.1 | |
| 58 | + - 3 # VDDA * 1.2 | |
| 59 | + - 4 # VDDA * 1.3 | |
| 60 | + - 5 # VDDA * 1.4 | |
| 61 | + - 6 # VDDA * 1.53 | |
| 62 | + - 7 # VDDA * 1.53 | |
| 63 | + default: 6 | |
| 64 | + | |
| 65 | + nuvoton,vref-impedance: | |
| 66 | + description: VMID Tie-off impedance select. | |
| 67 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 68 | + enum: | |
| 69 | + - 0 # open | |
| 70 | + - 1 # 25KOhms | |
| 71 | + - 2 # 125KOhms | |
| 72 | + - 3 # 2.5KOhms | |
| 73 | + default: 2 | |
| 74 | + | |
| 75 | + nuvoton,jack-insert-debounce: | |
| 76 | + description: number from 0 to 7 that sets debounce time to 2^(n+2)ms. | |
| 77 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 78 | + maximum: 7 | |
| 79 | + default: 7 | |
| 80 | + | |
| 81 | + nuvoton,jack-eject-debounce: | |
| 82 | + description: number from 0 to 7 that sets debounce time to 2^(n+2)ms. | |
| 83 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 84 | + maximum: 7 | |
| 85 | + default: 0 | |
| 86 | + | |
| 87 | + nuvoton,dmic-clk-threshold: | |
| 88 | + description: DMIC clock speed expected value. Unit is Hz. | |
| 89 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 90 | + default: 3072000 | |
| 91 | + | |
| 92 | + nuvoton,left-input-single-end: | |
| 93 | + description: Enable left input with single-ended settings if set. | |
| 94 | + For the headset mic application, the single-ended control is | |
| 95 | + just limited to the left adc for design demand. | |
| 96 | + type: boolean | |
| 97 | + | |
| 98 | + '#sound-dai-cells': | |
| 99 | + const: 0 | |
| 100 | + | |
| 101 | +required: | |
| 102 | + - compatible | |
| 103 | + - reg | |
| 104 | + | |
| 105 | +unevaluatedProperties: false | |
| 106 | + | |
| 107 | +examples: | |
| 108 | + - | | |
| 109 | + #include <dt-bindings/gpio/gpio.h> | |
| 110 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 111 | + i2c { | |
| 112 | + #address-cells = <1>; | |
| 113 | + #size-cells = <0>; | |
| 114 | + codec@1b { | |
| 115 | + compatible = "nuvoton,nau8821"; | |
| 116 | + reg = <0x1b>; | |
| 117 | + interrupt-parent = <&gpio>; | |
| 118 | + interrupts = <23 IRQ_TYPE_LEVEL_LOW>; | |
| 119 | + nuvoton,jkdet-enable; | |
| 120 | + nuvoton,jkdet-pull-enable; | |
| 121 | + nuvoton,jkdet-pull-up; | |
| 122 | + nuvoton,key-enable; | |
| 123 | + nuvoton,left-input-single-end; | |
| 124 | + nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; | |
| 125 | + nuvoton,micbias-voltage = <6>; | |
| 126 | + nuvoton,vref-impedance = <2>; | |
| 127 | + nuvoton,jack-insert-debounce = <7>; | |
| 128 | + nuvoton,jack-eject-debounce = <0>; | |
| 129 | + nuvoton,dmic-clk-threshold = <3072000>; | |
| 130 | + #sound-dai-cells = <0>; | |
| 131 | + }; | |
| 132 | + }; | |
| @@ -21,6 +21,15 @@ properties: · 20 unmodified lines | ||
| 21 | 21 | reg: |
| 22 | 22 | maxItems: 1 |
| 23 | 23 | |
| 24 | + "#sound-dai-cells": | |
| 25 | + const: 0 | |
| 26 | + | |
| 27 | + clocks: | |
| 28 | + maxItems: 1 | |
| 29 | + | |
| 30 | + clock-names: | |
| 31 | + const: mclk | |
| 32 | + | |
| 24 | 33 | nuvoton,spk-btl: |
| 25 | 34 | description: |
| 26 | 35 | If set, configure the two loudspeaker outputs as a Bridge Tied Load output |
| @@ -31,6 +40,9 @@ required: · 4 unmodified lines | ||
| 31 | 40 | - compatible |
| 32 | 41 | - reg |
| 33 | 42 | |
| 43 | +allOf: | |
| 44 | + - $ref: dai-common.yaml# | |
| 45 | + | |
| 34 | 46 | additionalProperties: false |
| 35 | 47 | |
| 36 | 48 | examples: |
| @@ -0,0 +1,42 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/option,gtm601.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: GTM601 UMTS modem audio interface CODEC | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - kernel@puri.sm | |
| 11 | + | |
| 12 | +description: > | |
| 13 | + This device has no configuration interface. The sample rate and channels are | |
| 14 | + based on the compatible string | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + compatible: | |
| 18 | + oneOf: | |
| 19 | + - description: Broadmobi BM818 (48Khz stereo) | |
| 20 | + items: | |
| 21 | + - const: broadmobi,bm818 | |
| 22 | + - const: option,gtm601 | |
| 23 | + - description: GTM601 (8kHz mono) | |
| 24 | + const: option,gtm601 | |
| 25 | + | |
| 26 | + '#sound-dai-cells': | |
| 27 | + const: 0 | |
| 28 | + | |
| 29 | +required: | |
| 30 | + - compatible | |
| 31 | + | |
| 32 | +allOf: | |
| 33 | + - $ref: dai-common.yaml# | |
| 34 | + | |
| 35 | +additionalProperties: false | |
| 36 | + | |
| 37 | +examples: | |
| 38 | + - | | |
| 39 | + codec { | |
| 40 | + compatible = "option,gtm601"; | |
| 41 | + #sound-dai-cells = <0>; | |
| 42 | + }; | |
| @@ -1,101 +0,0 @@ | ||
| 1 | −msm8916 analog audio CODEC | |
| 2 | − | |
| 3 | −Bindings for codec Analog IP which is integrated in pmic pm8916, | |
| 4 | − | |
| 5 | −## Bindings for codec core on pmic: | |
| 6 | − | |
| 7 | −Required properties | |
| 8 | − - compatible = "qcom,pm8916-wcd-analog-codec"; | |
| 9 | − - reg: represents the slave base address provided to the peripheral. | |
| 10 | − - interrupts: List of interrupts in given SPMI peripheral. | |
| 11 | − - interrupt-names: Names specified to above list of interrupts in same | |
| 12 | − order. List of supported interrupt names are: | |
| 13 | − "cdc_spk_cnp_int" - Speaker click and pop interrupt. | |
| 14 | − "cdc_spk_clip_int" - Speaker clip interrupt. | |
| 15 | − "cdc_spk_ocp_int" - Speaker over current protect interrupt. | |
| 16 | − "mbhc_ins_rem_det1" - jack insert removal detect interrupt 1. | |
| 17 | − "mbhc_but_rel_det" - button release interrupt. | |
| 18 | − "mbhc_but_press_det" - button press event | |
| 19 | − "mbhc_ins_rem_det" - jack insert removal detect interrupt. | |
| 20 | − "mbhc_switch_int" - multi button headset interrupt. | |
| 21 | − "cdc_ear_ocp_int" - Earphone over current protect interrupt. | |
| 22 | − "cdc_hphr_ocp_int" - Headphone R over current protect interrupt. | |
| 23 | − "cdc_hphl_ocp_det" - Headphone L over current protect interrupt. | |
| 24 | − "cdc_ear_cnp_int" - earphone cnp interrupt. | |
| 25 | − "cdc_hphr_cnp_int" - hphr click and pop interrupt. | |
| 26 | − "cdc_hphl_cnp_int" - hphl click and pop interrupt. | |
| 27 | − | |
| 28 | − - clocks: Handle to mclk. | |
| 29 | − - clock-names: should be "mclk" | |
| 30 | − - vdd-cdc-io-supply: phandle to VDD_CDC_IO regulator DT node. | |
| 31 | − - vdd-cdc-tx-rx-cx-supply: phandle to VDD_CDC_TX/RX/CX regulator DT node. | |
| 32 | − - vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator DT node. | |
| 33 | − | |
| 34 | −Optional Properties: | |
| 35 | − - qcom,mbhc-vthreshold-low: Array of 5 threshold voltages in mV for 5 buttons | |
| 36 | − detection on headset when the mbhc is powered up | |
| 37 | − by internal current source, this is a low power. | |
| 38 | − - qcom,mbhc-vthreshold-high: Array of 5 thresold voltages in mV for 5 buttons | |
| 39 | − detection on headset when mbhc is powered up | |
| 40 | − from micbias. | |
| 41 | −- qcom,micbias-lvl: Voltage (mV) for Mic Bias | |
| 42 | −- qcom,hphl-jack-type-normally-open: boolean, present if hphl pin on jack is a | |
| 43 | − NO (Normally Open). If not specified, then | |
| 44 | − its assumed that hphl pin on jack is NC | |
| 45 | − (Normally Closed). | |
| 46 | −- qcom,gnd-jack-type-normally-open: boolean, present if gnd pin on jack is | |
| 47 | − NO (Normally Open). If not specified, then | |
| 48 | − its assumed that gnd pin on jack is NC | |
| 49 | − (Normally Closed). | |
| 50 | −- qcom,micbias1-ext-cap: boolean, present if micbias1 has external capacitor | |
| 51 | − connected. | |
| 52 | −- qcom,micbias2-ext-cap: boolean, present if micbias2 has external capacitor | |
| 53 | − connected. | |
| 54 | − | |
| 55 | −Example: | |
| 56 | − | |
| 57 | −spmi_bus { | |
| 58 | − ... | |
| 59 | − audio-codec@f000{ | |
| 60 | − compatible = "qcom,pm8916-wcd-analog-codec"; | |
| 61 | − reg = <0xf000 0x200>; | |
| 62 | − reg-names = "pmic-codec-core"; | |
| 63 | − clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; | |
| 64 | − clock-names = "mclk"; | |
| 65 | − qcom,mbhc-vthreshold-low = <75 150 237 450 500>; | |
| 66 | − qcom,mbhc-vthreshold-high = <75 150 237 450 500>; | |
| 67 | − interrupt-parent = <&spmi_bus>; | |
| 68 | − interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>, | |
| 69 | − <0x1 0xf0 0x1 IRQ_TYPE_NONE>, | |
| 70 | − <0x1 0xf0 0x2 IRQ_TYPE_NONE>, | |
| 71 | − <0x1 0xf0 0x3 IRQ_TYPE_NONE>, | |
| 72 | − <0x1 0xf0 0x4 IRQ_TYPE_NONE>, | |
| 73 | − <0x1 0xf0 0x5 IRQ_TYPE_NONE>, | |
| 74 | − <0x1 0xf0 0x6 IRQ_TYPE_NONE>, | |
| 75 | − <0x1 0xf0 0x7 IRQ_TYPE_NONE>, | |
| 76 | − <0x1 0xf1 0x0 IRQ_TYPE_NONE>, | |
| 77 | − <0x1 0xf1 0x1 IRQ_TYPE_NONE>, | |
| 78 | − <0x1 0xf1 0x2 IRQ_TYPE_NONE>, | |
| 79 | − <0x1 0xf1 0x3 IRQ_TYPE_NONE>, | |
| 80 | − <0x1 0xf1 0x4 IRQ_TYPE_NONE>, | |
| 81 | − <0x1 0xf1 0x5 IRQ_TYPE_NONE>; | |
| 82 | − interrupt-names = "cdc_spk_cnp_int", | |
| 83 | − "cdc_spk_clip_int", | |
| 84 | − "cdc_spk_ocp_int", | |
| 85 | − "mbhc_ins_rem_det1", | |
| 86 | − "mbhc_but_rel_det", | |
| 87 | − "mbhc_but_press_det", | |
| 88 | − "mbhc_ins_rem_det", | |
| 89 | − "mbhc_switch_int", | |
| 90 | − "cdc_ear_ocp_int", | |
| 91 | − "cdc_hphr_ocp_int", | |
| 92 | − "cdc_hphl_ocp_det", | |
| 93 | − "cdc_ear_cnp_int", | |
| 94 | − "cdc_hphr_cnp_int", | |
| 95 | − "cdc_hphl_cnp_int"; | |
| 96 | − vdd-cdc-io-supply = <&pm8916_l5>; | |
| 97 | − vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; | |
| 98 | − vdd-micbias-supply = <&pm8916_l13>; | |
| 99 | − #sound-dai-cells = <1>; | |
| 100 | − }; | |
| 101 | −}; | |
| @@ -0,0 +1,153 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Qualcomm PM8916 WCD Analog Audio Codec | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Konrad Dybcio <konradybcio@kernel.org> | |
| 11 | + | |
| 12 | +description: | |
| 13 | + The analog WCD audio codec found on Qualcomm PM8916 PMIC. | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + const: qcom,pm8916-wcd-analog-codec | |
| 18 | + | |
| 19 | + reg: | |
| 20 | + maxItems: 1 | |
| 21 | + | |
| 22 | + interrupts: | |
| 23 | + maxItems: 14 | |
| 24 | + | |
| 25 | + interrupt-names: | |
| 26 | + items: | |
| 27 | + - const: cdc_spk_cnp_int | |
| 28 | + - const: cdc_spk_clip_int | |
| 29 | + - const: cdc_spk_ocp_int | |
| 30 | + - const: mbhc_ins_rem_det1 | |
| 31 | + - const: mbhc_but_rel_det | |
| 32 | + - const: mbhc_but_press_det | |
| 33 | + - const: mbhc_ins_rem_det | |
| 34 | + - const: mbhc_switch_int | |
| 35 | + - const: cdc_ear_ocp_int | |
| 36 | + - const: cdc_hphr_ocp_int | |
| 37 | + - const: cdc_hphl_ocp_det | |
| 38 | + - const: cdc_ear_cnp_int | |
| 39 | + - const: cdc_hphr_cnp_int | |
| 40 | + - const: cdc_hphl_cnp_int | |
| 41 | + | |
| 42 | + vdd-cdc-io-supply: | |
| 43 | + description: 1.8V buck supply | |
| 44 | + | |
| 45 | + vdd-cdc-tx-rx-cx-supply: | |
| 46 | + description: 1.8V SIDO buck supply | |
| 47 | + | |
| 48 | + vdd-micbias-supply: | |
| 49 | + description: micbias supply | |
| 50 | + | |
| 51 | + qcom,mbhc-vthreshold-low: | |
| 52 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 53 | + description: | |
| 54 | + Array of 5 threshold voltages in mV for 5-button detection on | |
| 55 | + headset when MBHC is powered by an internal current source. | |
| 56 | + minItems: 5 | |
| 57 | + maxItems: 5 | |
| 58 | + | |
| 59 | + qcom,mbhc-vthreshold-high: | |
| 60 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 61 | + description: | |
| 62 | + Array of 5 threshold voltages in mV for 5-button detection on | |
| 63 | + headset when MBHC is powered from micbias. | |
| 64 | + minItems: 5 | |
| 65 | + maxItems: 5 | |
| 66 | + | |
| 67 | + qcom,micbias-lvl: | |
| 68 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 69 | + description: | |
| 70 | + Voltage (mV) for Mic Bias | |
| 71 | + | |
| 72 | + qcom,hphl-jack-type-normally-open: | |
| 73 | + type: boolean | |
| 74 | + description: | |
| 75 | + True if the HPHL pin on the jack is NO (Normally Open), false if it's | |
| 76 | + NC (Normally Closed). | |
| 77 | + | |
| 78 | + qcom,gnd-jack-type-normally-open: | |
| 79 | + type: boolean | |
| 80 | + description: | |
| 81 | + True if the GND pin on the jack is NO (Normally Open), false if it's | |
| 82 | + NC (Normally Closed). | |
| 83 | + | |
| 84 | + qcom,micbias1-ext-cap: | |
| 85 | + type: boolean | |
| 86 | + description: | |
| 87 | + True if micbias1 has an external capacitor. | |
| 88 | + | |
| 89 | + qcom,micbias2-ext-cap: | |
| 90 | + type: boolean | |
| 91 | + description: | |
| 92 | + True if micbias2 has an external capacitor. | |
| 93 | + | |
| 94 | + "#sound-dai-cells": | |
| 95 | + const: 1 | |
| 96 | + | |
| 97 | +required: | |
| 98 | + - compatible | |
| 99 | + - reg | |
| 100 | + | |
| 101 | +additionalProperties: false | |
| 102 | + | |
| 103 | +examples: | |
| 104 | + - | | |
| 105 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 106 | + #include <dt-bindings/spmi/spmi.h> | |
| 107 | + | |
| 108 | + pmic@1 { | |
| 109 | + compatible = "qcom,pm8916", "qcom,spmi-pmic"; | |
| 110 | + reg = <0x1 SPMI_USID>; | |
| 111 | + #address-cells = <1>; | |
| 112 | + #size-cells = <0>; | |
| 113 | + | |
| 114 | + audio-codec@f000 { | |
| 115 | + compatible = "qcom,pm8916-wcd-analog-codec"; | |
| 116 | + reg = <0xf000>; | |
| 117 | + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; | |
| 118 | + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; | |
| 119 | + interrupt-parent = <&spmi_bus>; | |
| 120 | + interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>, | |
| 121 | + <0x1 0xf0 0x1 IRQ_TYPE_NONE>, | |
| 122 | + <0x1 0xf0 0x2 IRQ_TYPE_NONE>, | |
| 123 | + <0x1 0xf0 0x3 IRQ_TYPE_NONE>, | |
| 124 | + <0x1 0xf0 0x4 IRQ_TYPE_NONE>, | |
| 125 | + <0x1 0xf0 0x5 IRQ_TYPE_NONE>, | |
| 126 | + <0x1 0xf0 0x6 IRQ_TYPE_NONE>, | |
| 127 | + <0x1 0xf0 0x7 IRQ_TYPE_NONE>, | |
| 128 | + <0x1 0xf1 0x0 IRQ_TYPE_NONE>, | |
| 129 | + <0x1 0xf1 0x1 IRQ_TYPE_NONE>, | |
| 130 | + <0x1 0xf1 0x2 IRQ_TYPE_NONE>, | |
| 131 | + <0x1 0xf1 0x3 IRQ_TYPE_NONE>, | |
| 132 | + <0x1 0xf1 0x4 IRQ_TYPE_NONE>, | |
| 133 | + <0x1 0xf1 0x5 IRQ_TYPE_NONE>; | |
| 134 | + interrupt-names = "cdc_spk_cnp_int", | |
| 135 | + "cdc_spk_clip_int", | |
| 136 | + "cdc_spk_ocp_int", | |
| 137 | + "mbhc_ins_rem_det1", | |
| 138 | + "mbhc_but_rel_det", | |
| 139 | + "mbhc_but_press_det", | |
| 140 | + "mbhc_ins_rem_det", | |
| 141 | + "mbhc_switch_int", | |
| 142 | + "cdc_ear_ocp_int", | |
| 143 | + "cdc_hphr_ocp_int", | |
| 144 | + "cdc_hphl_ocp_det", | |
| 145 | + "cdc_ear_cnp_int", | |
| 146 | + "cdc_hphr_cnp_int", | |
| 147 | + "cdc_hphl_cnp_int"; | |
| 148 | + vdd-cdc-io-supply = <&pm8916_l5>; | |
| 149 | + vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; | |
| 150 | + vdd-micbias-supply = <&pm8916_l13>; | |
| 151 | + #sound-dai-cells = <1>; | |
| 152 | + }; | |
| 153 | + }; | |
| @@ -9,6 +9,20 @@ title: Renesas R-Car Sound Driver · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| 11 | 11 | |
| 12 | +definitions: | |
| 13 | + port-def: | |
| 14 | + $ref: audio-graph-port.yaml#/definitions/port-base | |
| 15 | + unevaluatedProperties: false | |
| 16 | + patternProperties: | |
| 17 | + "^endpoint(@[0-9a-f]+)?": | |
| 18 | + $ref: audio-graph-port.yaml#/definitions/endpoint-base | |
| 19 | + properties: | |
| 20 | + playback: | |
| 21 | + $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 22 | + capture: | |
| 23 | + $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 24 | + unevaluatedProperties: false | |
| 25 | + | |
| 12 | 26 | properties: |
| 13 | 27 | |
| 14 | 28 | compatible: |
| @@ -77,6 +91,12 @@ properties: · 62 unmodified lines | ||
| 77 | 91 | it must be 1 if your system has audio_clkout0/1/2/3 |
| 78 | 92 | enum: [0, 1] |
| 79 | 93 | |
| 94 | + "#address-cells": | |
| 95 | + const: 1 | |
| 96 | + | |
| 97 | + "#size-cells": | |
| 98 | + const: 0 | |
| 99 | + | |
| 80 | 100 | clock-frequency: |
| 81 | 101 | description: for audio_clkout0/1/2/3 |
| 82 | 102 | |
| @@ -103,35 +123,9 @@ properties: · 20 unmodified lines | ||
| 103 | 123 | description: List of necessary clock names. |
| 104 | 124 | # details are defined below |
| 105 | 125 | |
| 106 | − ports: | |
| 107 | − $ref: audio-graph-port.yaml#/definitions/port-base | |
| 108 | − unevaluatedProperties: false | |
| 109 | − patternProperties: | |
| 110 | − '^port(@[0-9a-f]+)?$': | |
| 111 | − $ref: audio-graph-port.yaml#/definitions/port-base | |
| 112 | − unevaluatedProperties: false | |
| 113 | − patternProperties: | |
| 114 | − "^endpoint(@[0-9a-f]+)?": | |
| 115 | − $ref: audio-graph-port.yaml#/definitions/endpoint-base | |
| 116 | − properties: | |
| 117 | − playback: | |
| 118 | − $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 119 | − capture: | |
| 120 | − $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 121 | − unevaluatedProperties: false | |
| 122 | − | |
| 126 | + # ports is below | |
| 123 | 127 | port: |
| 124 | − $ref: audio-graph-port.yaml#/definitions/port-base | |
| 125 | − unevaluatedProperties: false | |
| 126 | − patternProperties: | |
| 127 | − "^endpoint(@[0-9a-f]+)?": | |
| 128 | − $ref: audio-graph-port.yaml#/definitions/endpoint-base | |
| 129 | − properties: | |
| 130 | − playback: | |
| 131 | − $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 132 | − capture: | |
| 133 | − $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 134 | − unevaluatedProperties: false | |
| 128 | + $ref: "#/definitions/port-def" | |
| 135 | 129 | |
| 136 | 130 | rcar_sound,dvc: |
| 137 | 131 | description: DVC subnode. |
| @@ -248,8 +242,9 @@ properties: · 110 unmodified lines | ||
| 248 | 242 | - interrupts |
| 249 | 243 | additionalProperties: false |
| 250 | 244 | |
| 245 | +patternProperties: | |
| 251 | 246 | # For DAI base |
| 252 | − rcar_sound,dai: | |
| 247 | + 'rcar_sound,dai(@[0-9a-f]+)?$': | |
| 253 | 248 | description: DAI subnode. |
| 254 | 249 | type: object |
| 255 | 250 | patternProperties: |
| @@ -269,6 +264,13 @@ properties: · 13 unmodified lines | ||
| 269 | 264 | - capture |
| 270 | 265 | additionalProperties: false |
| 271 | 266 | |
| 267 | + 'ports(@[0-9a-f]+)?$': | |
| 268 | + $ref: audio-graph-port.yaml#/definitions/port-base | |
| 269 | + unevaluatedProperties: false | |
| 270 | + patternProperties: | |
| 271 | + '^port(@[0-9a-f]+)?$': | |
| 272 | + $ref: "#/definitions/port-def" | |
| 273 | + | |
| 272 | 274 | required: |
| 273 | 275 | - compatible |
| 274 | 276 | - reg |
| @@ -9,6 +9,9 @@ title: Samsung Aries audio complex with WM8994 codec · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Jonathan Bakker <xc-racer2@live.ca> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | enum: |
| @@ -17,10 +20,6 @@ properties: · 2 unmodified lines | ||
| 17 | 20 | # Without FM radio and modem slave |
| 18 | 21 | - samsung,fascinate4g-wm8994 |
| 19 | 22 | |
| 20 | − model: | |
| 21 | − $ref: /schemas/types.yaml#/definitions/string | |
| 22 | − description: The user-visible name of this sound complex. | |
| 23 | − | |
| 24 | 23 | cpu: |
| 25 | 24 | type: object |
| 26 | 25 | additionalProperties: false |
| @@ -46,6 +45,7 @@ properties: · 19 unmodified lines | ||
| 46 | 45 | |
| 47 | 46 | samsung,audio-routing: |
| 48 | 47 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 48 | + deprecated: true | |
| 49 | 49 | description: | |
| 50 | 50 | List of the connections between audio |
| 51 | 51 | components; each entry is a pair of strings, the first being the |
| @@ -56,6 +56,7 @@ properties: · 4 unmodified lines | ||
| 56 | 56 | or FM In |
| 57 | 57 | For samsung,fascinate4g-wm8994: HP, SPK, RCV, LINE, Main Mic, |
| 58 | 58 | or HeadsetMic |
| 59 | + Deprecated, use audio-routing. | |
| 59 | 60 | |
| 60 | 61 | extcon: |
| 61 | 62 | description: Extcon phandle for dock detection |
| @@ -87,10 +88,9 @@ properties: · 25 unmodified lines | ||
| 87 | 88 | |
| 88 | 89 | required: |
| 89 | 90 | - compatible |
| 90 | − - model | |
| 91 | 91 | - cpu |
| 92 | 92 | - codec |
| 93 | − - samsung,audio-routing | |
| 93 | + - audio-routing | |
| 94 | 94 | - extcon |
| 95 | 95 | - main-micbias-supply |
| 96 | 96 | - headset-micbias-supply |
| @@ -98,7 +98,7 @@ required: · 1 unmodified line | ||
| 98 | 98 | - headset-detect-gpios |
| 99 | 99 | - headset-key-gpios |
| 100 | 100 | |
| 101 | −additionalProperties: false | |
| 101 | +unevaluatedProperties: false | |
| 102 | 102 | |
| 103 | 103 | examples: |
| 104 | 104 | - | |
| @@ -121,7 +121,7 @@ examples: · 16 unmodified lines | ||
| 121 | 121 | headset-detect-gpios = <&gph0 6 GPIO_ACTIVE_HIGH>; |
| 122 | 122 | headset-key-gpios = <&gph3 6 GPIO_ACTIVE_HIGH>; |
| 123 | 123 | |
| 124 | − samsung,audio-routing = | |
| 124 | + audio-routing = | |
| 125 | 125 | "HP", "HPOUT1L", |
| 126 | 126 | "HP", "HPOUT1R", |
| 127 | 127 | |
| @@ -9,14 +9,13 @@ title: Samsung Midas audio complex with WM1811 codec · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Sylwester Nawrocki <s.nawrocki@samsung.com> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: sound-card-common.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | const: samsung,midas-audio |
| 15 | 18 | |
| 16 | − model: | |
| 17 | − $ref: /schemas/types.yaml#/definitions/string | |
| 18 | − description: The user-visible name of this sound complex. | |
| 19 | − | |
| 20 | 19 | cpu: |
| 21 | 20 | type: object |
| 22 | 21 | additionalProperties: false |
| @@ -38,6 +37,7 @@ properties: · 15 unmodified lines | ||
| 38 | 37 | - sound-dai |
| 39 | 38 | |
| 40 | 39 | samsung,audio-routing: |
| 40 | + deprecated: true | |
| 41 | 41 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 42 | 42 | description: | |
| 43 | 43 | List of the connections between audio components; each entry is |
| @@ -45,6 +45,7 @@ properties: · 1 unmodified line | ||
| 45 | 45 | being the connection's source; valid names for sources and sinks are |
| 46 | 46 | the WM1811's pins (as documented in its binding), and the jacks |
| 47 | 47 | on the board: HP, SPK, Main Mic, Sub Mic, Headset Mic. |
| 48 | + Deprecated, use audio-routing. | |
| 48 | 49 | |
| 49 | 50 | mic-bias-supply: |
| 50 | 51 | description: Supply for the micbias on the Main microphone |
| @@ -62,14 +63,13 @@ properties: · 11 unmodified lines | ||
| 62 | 63 | |
| 63 | 64 | required: |
| 64 | 65 | - compatible |
| 65 | − - model | |
| 66 | 66 | - cpu |
| 67 | 67 | - codec |
| 68 | − - samsung,audio-routing | |
| 68 | + - audio-routing | |
| 69 | 69 | - mic-bias-supply |
| 70 | 70 | - submic-bias-supply |
| 71 | 71 | |
| 72 | −additionalProperties: false | |
| 72 | +unevaluatedProperties: false | |
| 73 | 73 | |
| 74 | 74 | examples: |
| 75 | 75 | - | |
| @@ -84,7 +84,7 @@ examples: · 8 unmodified lines | ||
| 84 | 84 | mic-bias-supply = <&mic_bias_reg>; |
| 85 | 85 | submic-bias-supply = <&submic_bias_reg>; |
| 86 | 86 | |
| 87 | − samsung,audio-routing = | |
| 87 | + audio-routing = | |
| 88 | 88 | "HP", "HPOUT1L", |
| 89 | 89 | "HP", "HPOUT1R", |
| 90 | 90 | |
| @@ -10,6 +10,9 @@ maintainers: · 9 unmodified lines | ||
| 10 | 10 | - Krzysztof Kozlowski <krzk@kernel.org> |
| 11 | 11 | - Sylwester Nawrocki <s.nawrocki@samsung.com> |
| 12 | 12 | |
| 13 | +allOf: | |
| 14 | + - $ref: sound-card-common.yaml# | |
| 15 | + | |
| 13 | 16 | properties: |
| 14 | 17 | compatible: |
| 15 | 18 | oneOf: |
| @@ -24,10 +27,6 @@ properties: · 8 unmodified lines | ||
| 24 | 27 | - const: samsung,odroid-xu4-audio |
| 25 | 28 | deprecated: true |
| 26 | 29 | |
| 27 | − model: | |
| 28 | − $ref: /schemas/types.yaml#/definitions/string | |
| 29 | − description: The user-visible name of this sound complex. | |
| 30 | − | |
| 31 | 30 | assigned-clock-parents: true |
| 32 | 31 | assigned-clock-rates: true |
| 33 | 32 | assigned-clocks: true |
| @@ -52,6 +51,7 @@ properties: · 18 unmodified lines | ||
| 52 | 51 | |
| 53 | 52 | samsung,audio-routing: |
| 54 | 53 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 54 | + deprecated: true | |
| 55 | 55 | description: | |
| 56 | 56 | List of the connections between audio |
| 57 | 57 | components; each entry is a pair of strings, the first being the |
| @@ -61,6 +61,7 @@ properties: · 3 unmodified lines | ||
| 61 | 61 | For Odroid X2: "Headphone Jack", "Mic Jack", "DMIC" |
| 62 | 62 | For Odroid U3, XU3: "Headphone Jack", "Speakers" |
| 63 | 63 | For Odroid XU4: no entries |
| 64 | + Deprecated, use audio-routing. | |
| 64 | 65 | |
| 65 | 66 | samsung,audio-widgets: |
| 66 | 67 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| @@ -70,18 +71,17 @@ properties: · 3 unmodified lines | ||
| 70 | 71 | |
| 71 | 72 | required: |
| 72 | 73 | - compatible |
| 73 | − - model | |
| 74 | 74 | - cpu |
| 75 | 75 | - codec |
| 76 | 76 | |
| 77 | −additionalProperties: false | |
| 77 | +unevaluatedProperties: false | |
| 78 | 78 | |
| 79 | 79 | examples: |
| 80 | 80 | - | |
| 81 | 81 | sound { |
| 82 | 82 | compatible = "hardkernel,odroid-xu3-audio"; |
| 83 | 83 | model = "Odroid-XU3"; |
| 84 | − samsung,audio-routing = | |
| 84 | + audio-routing = | |
| 85 | 85 | "Headphone Jack", "HPL", |
| 86 | 86 | "Headphone Jack", "HPR", |
| 87 | 87 | "IN1", "Mic Jack", |
| @@ -10,6 +10,9 @@ maintainers: · 9 unmodified lines | ||
| 10 | 10 | - Krzysztof Kozlowski <krzk@kernel.org> |
| 11 | 11 | - Sylwester Nawrocki <s.nawrocki@samsung.com> |
| 12 | 12 | |
| 13 | +allOf: | |
| 14 | + - $ref: sound-card-common.yaml# | |
| 15 | + | |
| 13 | 16 | properties: |
| 14 | 17 | compatible: |
| 15 | 18 | const: samsung,tm2-audio |
| @@ -32,6 +35,8 @@ properties: · 16 unmodified lines | ||
| 32 | 35 | being the connection's source; valid names for sources and sinks are the |
| 33 | 36 | WM5110's and MAX98504's pins and the jacks on the board: HP, SPK, Main |
| 34 | 37 | Mic, Sub Mic, Third Mic, Headset Mic. |
| 38 | + Deprecated, use audio-routing. | |
| 39 | + deprecated: true | |
| 35 | 40 | $ref: /schemas/types.yaml#/definitions/non-unique-string-array |
| 36 | 41 | |
| 37 | 42 | i2s-controller: |
| @@ -44,20 +49,15 @@ properties: · 6 unmodified lines | ||
| 44 | 49 | mic-bias-gpios: |
| 45 | 50 | description: GPIO pin that enables the Main Mic bias regulator. |
| 46 | 51 | |
| 47 | − model: | |
| 48 | − description: The user-visible name of this sound complex. | |
| 49 | − $ref: /schemas/types.yaml#/definitions/string | |
| 50 | − | |
| 51 | 52 | required: |
| 52 | 53 | - compatible |
| 53 | 54 | - audio-amplifier |
| 54 | 55 | - audio-codec |
| 55 | − - samsung,audio-routing | |
| 56 | + - audio-routing | |
| 56 | 57 | - i2s-controller |
| 57 | 58 | - mic-bias-gpios |
| 58 | − - model | |
| 59 | 59 | |
| 60 | −additionalProperties: false | |
| 60 | +unevaluatedProperties: false | |
| 61 | 61 | |
| 62 | 62 | examples: |
| 63 | 63 | - | |
| @@ -70,7 +70,7 @@ examples: · 6 unmodified lines | ||
| 70 | 70 | audio-amplifier = <&max98504>; |
| 71 | 71 | mic-bias-gpios = <&gpr3 2 GPIO_ACTIVE_HIGH>; |
| 72 | 72 | model = "wm5110"; |
| 73 | − samsung,audio-routing = "HP", "HPOUT1L", | |
| 73 | + audio-routing = "HP", "HPOUT1L", | |
| 74 | 74 | "HP", "HPOUT1R", |
| 75 | 75 | "SPK", "SPKOUT", |
| 76 | 76 | "SPKOUT", "HPOUT2L", |
| @@ -148,6 +148,15 @@ definitions: · 147 unmodified lines | ||
| 148 | 148 | required: |
| 149 | 149 | - sound-dai |
| 150 | 150 | |
| 151 | + additional-devs: | |
| 152 | + type: object | |
| 153 | + description: | |
| 154 | + Additional devices used by the simple audio card. | |
| 155 | + patternProperties: | |
| 156 | + '^iio-aux(-.+)?$': | |
| 157 | + type: object | |
| 158 | + $ref: audio-iio-aux.yaml# | |
| 159 | + | |
| 151 | 160 | properties: |
| 152 | 161 | compatible: |
| 153 | 162 | contains: |
| @@ -187,6 +196,8 @@ properties: · 33 unmodified lines | ||
| 187 | 196 | $ref: "#/definitions/mclk-fs" |
| 188 | 197 | simple-audio-card,aux-devs: |
| 189 | 198 | $ref: "#/definitions/aux-devs" |
| 199 | + simple-audio-card,additional-devs: | |
| 200 | + $ref: "#/definitions/additional-devs" | |
| 190 | 201 | simple-audio-card,convert-rate: |
| 191 | 202 | $ref: "#/definitions/convert-rate" |
| 192 | 203 | simple-audio-card,convert-channels: |
| @@ -359,6 +370,48 @@ examples: · 166 unmodified lines | ||
| 359 | 370 | }; |
| 360 | 371 | }; |
| 361 | 372 | |
| 373 | +# -------------------- | |
| 374 | +# route audio to/from a codec through an amplifier | |
| 375 | +# designed with a potentiometer driven by IIO: | |
| 376 | +# -------------------- | |
| 377 | + - | | |
| 378 | + sound { | |
| 379 | + compatible = "simple-audio-card"; | |
| 380 | + | |
| 381 | + simple-audio-card,aux-devs = <&_in>, <&_out>; | |
| 382 | + simple-audio-card,routing = | |
| 383 | + "CODEC LEFTIN", "AMP_IN LEFT OUT", | |
| 384 | + "CODEC RIGHTIN", "AMP_IN RIGHT OUT", | |
| 385 | + "AMP_OUT LEFT IN", "CODEC LEFTOUT", | |
| 386 | + "AMP_OUT RIGHT IN", "CODEC RIGHTOUT"; | |
| 387 | + | |
| 388 | + simple-audio-card,additional-devs { | |
| 389 | + amp_out: iio-aux-out { | |
| 390 | + compatible = "audio-iio-aux"; | |
| 391 | + io-channels = <&pot_out 0>, <&pot_out 1>; | |
| 392 | + io-channel-names = "LEFT", "RIGHT"; | |
| 393 | + snd-control-invert-range = <1 1>; | |
| 394 | + sound-name-prefix = "AMP_OUT"; | |
| 395 | + }; | |
| 396 | + | |
| 397 | + amp_in: iio_aux-in { | |
| 398 | + compatible = "audio-iio-aux"; | |
| 399 | + io-channels = <&pot_in 0>, <&pot_in 1>; | |
| 400 | + io-channel-names = "LEFT", "RIGHT"; | |
| 401 | + sound-name-prefix = "AMP_IN"; | |
| 402 | + }; | |
| 403 | + }; | |
| 404 | + | |
| 405 | + simple-audio-card,cpu { | |
| 406 | + sound-dai = <&cpu>; | |
| 407 | + }; | |
| 408 | + | |
| 409 | + simple-audio-card,codec { | |
| 410 | + sound-dai = <&codec>; | |
| 411 | + clocks = <&clocks>; | |
| 412 | + }; | |
| 413 | + }; | |
| 414 | + | |
| 362 | 415 | # -------------------- |
| 363 | 416 | # Sampling Rate Conversion |
| 364 | 417 | # -------------------- |
| @@ -17,6 +17,9 @@ properties: · 16 unmodified lines | ||
| 17 | 17 | - const: snps,designware-i2s |
| 18 | 18 | - enum: |
| 19 | 19 | - snps,designware-i2s |
| 20 | + - starfive,jh7110-i2stx0 | |
| 21 | + - starfive,jh7110-i2stx1 | |
| 22 | + - starfive,jh7110-i2srx | |
| 20 | 23 | |
| 21 | 24 | reg: |
| 22 | 25 | maxItems: 1 |
| @@ -29,15 +32,36 @@ properties: · 6 unmodified lines | ||
| 29 | 32 | maxItems: 1 |
| 30 | 33 | |
| 31 | 34 | clocks: |
| 32 | − description: Sampling rate reference clock | |
| 33 | − maxItems: 1 | |
| 35 | + items: | |
| 36 | + - description: Sampling rate reference clock | |
| 37 | + - description: APB clock | |
| 38 | + - description: Audio master clock | |
| 39 | + - description: Inner audio master clock source | |
| 40 | + - description: External audio master clock source | |
| 41 | + - description: Bit clock | |
| 42 | + - description: Left/right channel clock | |
| 43 | + - description: External bit clock | |
| 44 | + - description: External left/right channel clock | |
| 45 | + minItems: 1 | |
| 34 | 46 | |
| 35 | 47 | clock-names: |
| 36 | − const: i2sclk | |
| 48 | + items: | |
| 49 | + - const: i2sclk | |
| 50 | + - const: apb | |
| 51 | + - const: mclk | |
| 52 | + - const: mclk_inner | |
| 53 | + - const: mclk_ext | |
| 54 | + - const: bclk | |
| 55 | + - const: lrck | |
| 56 | + - const: bclk_ext | |
| 57 | + - const: lrck_ext | |
| 58 | + minItems: 1 | |
| 37 | 59 | |
| 38 | 60 | resets: |
| 39 | 61 | items: |
| 40 | 62 | - description: Optional controller resets |
| 63 | + - description: controller reset of Sampling rate | |
| 64 | + minItems: 1 | |
| 41 | 65 | |
| 42 | 66 | dmas: |
| 43 | 67 | items: |
| @@ -51,6 +75,17 @@ properties: · 7 unmodified lines | ||
| 51 | 75 | - const: rx |
| 52 | 76 | minItems: 1 |
| 53 | 77 | |
| 78 | + starfive,syscon: | |
| 79 | + $ref: /schemas/types.yaml#/definitions/phandle-array | |
| 80 | + items: | |
| 81 | + - items: | |
| 82 | + - description: phandle to System Register Controller sys_syscon node. | |
| 83 | + - description: I2S-rx enabled control offset of SYS_SYSCONSAIF__SYSCFG register. | |
| 84 | + - description: I2S-rx enabled control mask | |
| 85 | + description: | |
| 86 | + The phandle to System Register Controller syscon node and the I2S-rx(ADC) | |
| 87 | + enabled control offset and mask of SYS_SYSCONSAIF__SYSCFG register. | |
| 88 | + | |
| 54 | 89 | allOf: |
| 55 | 90 | - $ref: dai-common.yaml# |
| 56 | 91 | - if: |
| @@ -66,6 +101,73 @@ allOf: · 9 unmodified lines | ||
| 66 | 101 | properties: |
| 67 | 102 | "#sound-dai-cells": |
| 68 | 103 | const: 0 |
| 104 | + - if: | |
| 105 | + properties: | |
| 106 | + compatible: | |
| 107 | + contains: | |
| 108 | + const: snps,designware-i2s | |
| 109 | + then: | |
| 110 | + properties: | |
| 111 | + clocks: | |
| 112 | + maxItems: 1 | |
| 113 | + clock-names: | |
| 114 | + maxItems: 1 | |
| 115 | + resets: | |
| 116 | + maxItems: 1 | |
| 117 | + else: | |
| 118 | + properties: | |
| 119 | + resets: | |
| 120 | + minItems: 2 | |
| 121 | + maxItems: 2 | |
| 122 | + - if: | |
| 123 | + properties: | |
| 124 | + compatible: | |
| 125 | + contains: | |
| 126 | + const: starfive,jh7110-i2stx0 | |
| 127 | + then: | |
| 128 | + properties: | |
| 129 | + clocks: | |
| 130 | + minItems: 5 | |
| 131 | + maxItems: 5 | |
| 132 | + clock-names: | |
| 133 | + minItems: 5 | |
| 134 | + maxItems: 5 | |
| 135 | + required: | |
| 136 | + - resets | |
| 137 | + - if: | |
| 138 | + properties: | |
| 139 | + compatible: | |
| 140 | + contains: | |
| 141 | + const: starfive,jh7110-i2stx1 | |
| 142 | + then: | |
| 143 | + properties: | |
| 144 | + clocks: | |
| 145 | + minItems: 9 | |
| 146 | + maxItems: 9 | |
| 147 | + clock-names: | |
| 148 | + minItems: 9 | |
| 149 | + maxItems: 9 | |
| 150 | + required: | |
| 151 | + - resets | |
| 152 | + - if: | |
| 153 | + properties: | |
| 154 | + compatible: | |
| 155 | + contains: | |
| 156 | + const: starfive,jh7110-i2srx | |
| 157 | + then: | |
| 158 | + properties: | |
| 159 | + clocks: | |
| 160 | + minItems: 9 | |
| 161 | + maxItems: 9 | |
| 162 | + clock-names: | |
| 163 | + minItems: 9 | |
| 164 | + maxItems: 9 | |
| 165 | + required: | |
| 166 | + - resets | |
| 167 | + - starfive,syscon | |
| 168 | + else: | |
| 169 | + properties: | |
| 170 | + starfive,syscon: false | |
| 69 | 171 | |
| 70 | 172 | required: |
| 71 | 173 | - compatible |
| @@ -0,0 +1,27 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/sound-card-common.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Board Sound Card Common Properties | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Mark Brown <broonie@kernel.org> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + audio-routing: | |
| 14 | + $ref: /schemas/types.yaml#/definitions/non-unique-string-array | |
| 15 | + description: | | |
| 16 | + A list of the connections between audio components. Each entry is a | |
| 17 | + pair of strings, the first being the connection's sink, the second | |
| 18 | + being the connection's source. | |
| 19 | + | |
| 20 | + model: | |
| 21 | + $ref: /schemas/types.yaml#/definitions/string | |
| 22 | + description: User specified audio sound card name | |
| 23 | + | |
| 24 | +required: | |
| 25 | + - model | |
| 26 | + | |
| 27 | +additionalProperties: true | |
| @@ -0,0 +1,74 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/sound/wlf,wm8904.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Wolfson WM8904/WM8912 audio codecs | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - patches@opensource.cirrus.com | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Pins on the device (for linking into audio routes): | |
| 14 | + IN1L, IN1R, IN2L, IN2R, IN3L, IN3R, HPOUTL, HPOUTR, LINEOUTL, LINEOUTR, | |
| 15 | + MICBIAS | |
| 16 | + | |
| 17 | +properties: | |
| 18 | + compatible: | |
| 19 | + enum: | |
| 20 | + - wlf,wm8904 | |
| 21 | + - wlf,wm8912 | |
| 22 | + | |
| 23 | + reg: | |
| 24 | + maxItems: 1 | |
| 25 | + | |
| 26 | + "#sound-dai-cells": | |
| 27 | + const: 0 | |
| 28 | + | |
| 29 | + clocks: | |
| 30 | + maxItems: 1 | |
| 31 | + | |
| 32 | + clock-names: | |
| 33 | + const: mclk | |
| 34 | + | |
| 35 | + AVDD-supply: true | |
| 36 | + CPVDD-supply: true | |
| 37 | + DBVDD-supply: true | |
| 38 | + DCVDD-supply: true | |
| 39 | + MICVDD-supply: true | |
| 40 | + | |
| 41 | +required: | |
| 42 | + - compatible | |
| 43 | + - reg | |
| 44 | + - clocks | |
| 45 | + - clock-names | |
| 46 | + - AVDD-supply | |
| 47 | + - CPVDD-supply | |
| 48 | + - DBVDD-supply | |
| 49 | + - DCVDD-supply | |
| 50 | + - MICVDD-supply | |
| 51 | + | |
| 52 | +allOf: | |
| 53 | + - $ref: dai-common.yaml# | |
| 54 | + | |
| 55 | +unevaluatedProperties: false | |
| 56 | + | |
| 57 | +examples: | |
| 58 | + - | | |
| 59 | + i2c { | |
| 60 | + #address-cells = <1>; | |
| 61 | + #size-cells = <0>; | |
| 62 | + | |
| 63 | + codec@1a { | |
| 64 | + compatible = "wlf,wm8904"; | |
| 65 | + reg = <0x1a>; | |
| 66 | + clocks = <&pck0>; | |
| 67 | + clock-names = "mclk"; | |
| 68 | + AVDD-supply = <®_1p8v>; | |
| 69 | + CPVDD-supply = <®_1p8v>; | |
| 70 | + DBVDD-supply = <®_1p8v>; | |
| 71 | + DCVDD-supply = <®_1p8v>; | |
| 72 | + MICVDD-supply = <®_1p8v>; | |
| 73 | + }; | |
| 74 | + }; | |
| @@ -26,6 +26,21 @@ properties: · 25 unmodified lines | ||
| 26 | 26 | '#sound-dai-cells': |
| 27 | 27 | const: 0 |
| 28 | 28 | |
| 29 | + AVDD-supply: | |
| 30 | + description: Analogue supply. | |
| 31 | + | |
| 32 | + DBVDD-supply: | |
| 33 | + description: Digital Buffer Supply. | |
| 34 | + | |
| 35 | + DCVDD-supply: | |
| 36 | + description: Digital Core Supply. | |
| 37 | + | |
| 38 | + SPKVDD1-supply: | |
| 39 | + description: Supply for speaker drivers 1. | |
| 40 | + | |
| 41 | + SPKVDD2-supply: | |
| 42 | + description: Supply for speaker drivers 2. | |
| 43 | + | |
| 29 | 44 | wlf,capless: |
| 30 | 45 | type: boolean |
| 31 | 46 | description: |
| @@ -84,5 +99,10 @@ examples: · 52 unmodified lines | ||
| 84 | 99 | wlf,hp-cfg = <3 2 3>; |
| 85 | 100 | wlf,gpio-cfg = <1 3>; |
| 86 | 101 | wlf,shared-lrclk; |
| 102 | + DCVDD-supply = <®_audio>; | |
| 103 | + DBVDD-supply = <®_audio>; | |
| 104 | + AVDD-supply = <®_audio>; | |
| 105 | + SPKVDD1-supply = <®_audio>; | |
| 106 | + SPKVDD2-supply = <®_audio>; | |
| 87 | 107 | }; |
| 88 | 108 | }; |
| @@ -1,33 +0,0 @@ | ||
| 1 | −WM8904 audio CODEC | |
| 2 | − | |
| 3 | −This device supports I2C only. | |
| 4 | − | |
| 5 | −Required properties: | |
| 6 | − - compatible: "wlf,wm8904" or "wlf,wm8912" | |
| 7 | − - reg: the I2C address of the device. | |
| 8 | − - clock-names: "mclk" | |
| 9 | − - clocks: reference to | |
| 10 | − <Documentation/devicetree/bindings/clock/clock-bindings.txt> | |
| 11 | − | |
| 12 | −Pins on the device (for linking into audio routes): | |
| 13 | − | |
| 14 | − * IN1L | |
| 15 | − * IN1R | |
| 16 | − * IN2L | |
| 17 | − * IN2R | |
| 18 | − * IN3L | |
| 19 | − * IN3R | |
| 20 | − * HPOUTL | |
| 21 | − * HPOUTR | |
| 22 | − * LINEOUTL | |
| 23 | − * LINEOUTR | |
| 24 | − * MICBIAS | |
| 25 | − | |
| 26 | −Examples: | |
| 27 | − | |
| 28 | −codec: wm8904@1a { | |
| 29 | − compatible = "wlf,wm8904"; | |
| 30 | − reg = <0x1a>; | |
| 31 | − clocks = <&pck0>; | |
| 32 | − clock-names = "mclk"; | |
| 33 | −}; | |
| @@ -3,15 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | Digital TV Common functions |
| 4 | 4 | --------------------------- |
| 5 | 5 | |
| 6 | −Math functions | |
| 7 | −~~~~~~~~~~~~~~ | |
| 8 | − | |
| 9 | −Provide some commonly-used math functions, usually required in order to | |
| 10 | −estimate signal strength and signal to noise measurements in dB. | |
| 11 | − | |
| 12 | −.. kernel-doc:: include/media/dvb_math.h | |
| 13 | − | |
| 14 | − | |
| 15 | 6 | DVB devices |
| 16 | 7 | ~~~~~~~~~~~ |
| 17 | 8 | |
| @@ -46,157 +46,158 @@ FX-bus · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | name='PCM Front Playback Volume',index=0 |
| 48 | 48 | ---------------------------------------- |
| 49 | −This control is used to attenuate samples for left and right front PCM FX-bus | |
| 49 | +This control is used to attenuate samples from left and right front PCM FX-bus | |
| 50 | 50 | accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM |
| 51 | −samples for 5.1 playback. The result samples are forwarded to the front DAC PCM | |
| 52 | −slots of the Philips DAC. | |
| 51 | +samples for 5.1 playback. The result samples are forwarded to the front speakers. | |
| 53 | 52 | |
| 54 | 53 | name='PCM Surround Playback Volume',index=0 |
| 55 | 54 | ------------------------------------------- |
| 56 | −This control is used to attenuate samples for left and right surround PCM FX-bus | |
| 55 | +This control is used to attenuate samples from left and right surround PCM FX-bus | |
| 57 | 56 | accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM |
| 58 | −samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM | |
| 59 | −slots of the Philips DAC. | |
| 57 | +samples for 5.1 playback. The result samples are forwarded to the surround (rear) | |
| 58 | +speakers. | |
| 59 | + | |
| 60 | +name='PCM Side Playback Volume',index=0 | |
| 61 | +--------------------------------------- | |
| 62 | +This control is used to attenuate samples from left and right side PCM FX-bus | |
| 63 | +accumulators. ALSA uses accumulators 14 and 15 for left and right side PCM | |
| 64 | +samples for 7.1 playback. The result samples are forwarded to the side speakers. | |
| 60 | 65 | |
| 61 | 66 | name='PCM Center Playback Volume',index=0 |
| 62 | 67 | ----------------------------------------- |
| 63 | −This control is used to attenuate samples for center PCM FX-bus accumulator. | |
| 64 | −ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample | |
| 65 | −is forwarded to the center DAC PCM slot of the Philips DAC. | |
| 68 | +This control is used to attenuate samples from center PCM FX-bus accumulator. | |
| 69 | +ALSA uses accumulator 6 for center PCM samples for 5.1 playback. The result | |
| 70 | +samples are forwarded to the center speaker. | |
| 66 | 71 | |
| 67 | 72 | name='PCM LFE Playback Volume',index=0 |
| 68 | 73 | -------------------------------------- |
| 69 | 74 | This control is used to attenuate sample for LFE PCM FX-bus accumulator. |
| 70 | −ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample | |
| 71 | −is forwarded to the LFE DAC PCM slot of the Philips DAC. | |
| 75 | +ALSA uses accumulator 7 for LFE PCM samples for 5.1 playback. The result | |
| 76 | +samples are forwarded to the subwoofer. | |
| 72 | 77 | |
| 73 | 78 | name='PCM Playback Volume',index=0 |
| 74 | 79 | ---------------------------------- |
| 75 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 80 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 76 | 81 | accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for |
| 77 | −stereo playback. The result samples are forwarded to the front DAC PCM slots | |
| 78 | −of the Philips DAC. | |
| 82 | +stereo playback. The result samples are forwarded to the front speakers. | |
| 79 | 83 | |
| 80 | 84 | name='PCM Capture Volume',index=0 |
| 81 | 85 | --------------------------------- |
| 82 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 83 | −accumulator. ALSA uses accumulators 0 and 1 for left and right PCM. | |
| 84 | −The result is forwarded to the ADC capture FIFO (thus to the standard capture | |
| 85 | −PCM device). | |
| 86 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 87 | +accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for | |
| 88 | +stereo playback. The result is forwarded to the standard capture PCM device. | |
| 86 | 89 | |
| 87 | 90 | name='Music Playback Volume',index=0 |
| 88 | 91 | ------------------------------------ |
| 89 | −This control is used to attenuate samples for left and right MIDI FX-bus | |
| 92 | +This control is used to attenuate samples from left and right MIDI FX-bus | |
| 90 | 93 | accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. |
| 91 | −The result samples are forwarded to the front DAC PCM slots of the AC97 codec. | |
| 94 | +The result samples are forwarded to the virtual stereo mixer. | |
| 92 | 95 | |
| 93 | 96 | name='Music Capture Volume',index=0 |
| 94 | 97 | ----------------------------------- |
| 95 | −These controls are used to attenuate samples for left and right MIDI FX-bus | |
| 96 | −accumulator. ALSA uses accumulators 4 and 5 for left and right PCM. | |
| 97 | −The result is forwarded to the ADC capture FIFO (thus to the standard capture | |
| 98 | −PCM device). | |
| 98 | +These controls are used to attenuate samples from left and right MIDI FX-bus | |
| 99 | +accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples. | |
| 100 | +The result is forwarded to the standard capture PCM device. | |
| 99 | 101 | |
| 100 | 102 | name='Mic Playback Volume',index=0 |
| 101 | 103 | ---------------------------------- |
| 102 | −This control is used to attenuate samples for left and right Mic input. | |
| 103 | −For Mic input is used AC97 codec. The result samples are forwarded to | |
| 104 | −the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic | |
| 105 | −capture FIFO (device 1 - 16bit/8KHz mono) too without volume control. | |
| 104 | +This control is used to attenuate samples from left and right Mic input of | |
| 105 | +the AC97 codec. The result samples are forwarded to the virtual stereo mixer. | |
| 106 | 106 | |
| 107 | 107 | name='Mic Capture Volume',index=0 |
| 108 | 108 | --------------------------------- |
| 109 | −This control is used to attenuate samples for left and right Mic input. | |
| 110 | −The result is forwarded to the ADC capture FIFO (thus to the standard capture | |
| 111 | −PCM device). | |
| 109 | +This control is used to attenuate samples from left and right Mic input of | |
| 110 | +the AC97 codec. The result is forwarded to the standard capture PCM device. | |
| 111 | + | |
| 112 | +The original samples are also forwarded to the Mic capture PCM device (device 1; | |
| 113 | +16bit/8KHz mono) without volume control. | |
| 112 | 114 | |
| 113 | 115 | name='Audigy CD Playback Volume',index=0 |
| 114 | 116 | ---------------------------------------- |
| 115 | 117 | This control is used to attenuate samples from left and right IEC958 TTL |
| 116 | 118 | digital inputs (usually used by a CDROM drive). The result samples are |
| 117 | −forwarded to the front DAC PCM slots of the Philips DAC. | |
| 119 | +forwarded to the virtual stereo mixer. | |
| 118 | 120 | |
| 119 | 121 | name='Audigy CD Capture Volume',index=0 |
| 120 | 122 | --------------------------------------- |
| 121 | 123 | This control is used to attenuate samples from left and right IEC958 TTL |
| 122 | −digital inputs (usually used by a CDROM drive). The result samples are | |
| 123 | −forwarded to the ADC capture FIFO (thus to the standard capture PCM device). | |
| 124 | +digital inputs (usually used by a CDROM drive). The result is forwarded | |
| 125 | +to the standard capture PCM device. | |
| 124 | 126 | |
| 125 | 127 | name='IEC958 Optical Playback Volume',index=0 |
| 126 | 128 | --------------------------------------------- |
| 127 | 129 | This control is used to attenuate samples from left and right IEC958 optical |
| 128 | −digital input. The result samples are forwarded to the front DAC PCM slots | |
| 129 | −of the Philips DAC. | |
| 130 | +digital input. The result samples are forwarded to the virtual stereo mixer. | |
| 130 | 131 | |
| 131 | 132 | name='IEC958 Optical Capture Volume',index=0 |
| 132 | 133 | -------------------------------------------- |
| 133 | 134 | This control is used to attenuate samples from left and right IEC958 optical |
| 134 | −digital inputs. The result samples are forwarded to the ADC capture FIFO | |
| 135 | −(thus to the standard capture PCM device). | |
| 135 | +digital inputs. The result is forwarded to the standard capture PCM device. | |
| 136 | 136 | |
| 137 | 137 | name='Line2 Playback Volume',index=0 |
| 138 | 138 | ------------------------------------ |
| 139 | 139 | This control is used to attenuate samples from left and right I2S ADC |
| 140 | −inputs (on the AudigyDrive). The result samples are forwarded to the front | |
| 141 | −DAC PCM slots of the Philips DAC. | |
| 140 | +inputs (on the AudigyDrive). The result samples are forwarded to the virtual | |
| 141 | +stereo mixer. | |
| 142 | 142 | |
| 143 | 143 | name='Line2 Capture Volume',index=1 |
| 144 | 144 | ----------------------------------- |
| 145 | 145 | This control is used to attenuate samples from left and right I2S ADC |
| 146 | −inputs (on the AudigyDrive). The result samples are forwarded to the ADC | |
| 147 | −capture FIFO (thus to the standard capture PCM device). | |
| 146 | +inputs (on the AudigyDrive). The result is forwarded to the standard capture | |
| 147 | +PCM device. | |
| 148 | 148 | |
| 149 | 149 | name='Analog Mix Playback Volume',index=0 |
| 150 | 150 | ----------------------------------------- |
| 151 | 151 | This control is used to attenuate samples from left and right I2S ADC |
| 152 | −inputs from Philips ADC. The result samples are forwarded to the front | |
| 153 | −DAC PCM slots of the Philips DAC. This contains mix from analog sources | |
| 154 | −like CD, Line In, Aux, .... | |
| 152 | +inputs from Philips ADC. The result samples are forwarded to the virtual | |
| 153 | +stereo mixer. This contains mix from analog sources like CD, Line In, Aux, .... | |
| 155 | 154 | |
| 156 | 155 | name='Analog Mix Capture Volume',index=1 |
| 157 | 156 | ---------------------------------------- |
| 158 | 157 | This control is used to attenuate samples from left and right I2S ADC |
| 159 | −inputs Philips ADC. The result samples are forwarded to the ADC | |
| 160 | −capture FIFO (thus to the standard capture PCM device). | |
| 158 | +inputs Philips ADC. The result is forwarded to the standard capture PCM device. | |
| 161 | 159 | |
| 162 | 160 | name='Aux2 Playback Volume',index=0 |
| 163 | 161 | ----------------------------------- |
| 164 | 162 | This control is used to attenuate samples from left and right I2S ADC |
| 165 | −inputs (on the AudigyDrive). The result samples are forwarded to the front | |
| 166 | −DAC PCM slots of the Philips DAC. | |
| 163 | +inputs (on the AudigyDrive). The result samples are forwarded to the virtual | |
| 164 | +stereo mixer. | |
| 167 | 165 | |
| 168 | 166 | name='Aux2 Capture Volume',index=1 |
| 169 | 167 | ---------------------------------- |
| 170 | 168 | This control is used to attenuate samples from left and right I2S ADC |
| 171 | −inputs (on the AudigyDrive). The result samples are forwarded to the ADC | |
| 172 | −capture FIFO (thus to the standard capture PCM device). | |
| 169 | +inputs (on the AudigyDrive). The result is forwarded to the standard capture | |
| 170 | +PCM device. | |
| 173 | 171 | |
| 174 | 172 | name='Front Playback Volume',index=0 |
| 175 | 173 | ------------------------------------ |
| 176 | −All stereo signals are mixed together and mirrored to surround, center and LFE. | |
| 177 | −This control is used to attenuate samples for left and right front speakers of | |
| 178 | −this mix. | |
| 174 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 175 | +The result samples are forwarded to the front speakers. | |
| 179 | 176 | |
| 180 | 177 | name='Surround Playback Volume',index=0 |
| 181 | 178 | --------------------------------------- |
| 182 | −All stereo signals are mixed together and mirrored to surround, center and LFE. | |
| 183 | −This control is used to attenuate samples for left and right surround speakers of | |
| 184 | −this mix. | |
| 179 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 180 | +The result samples are forwarded to the surround (rear) speakers. | |
| 181 | + | |
| 182 | +name='Side Playback Volume',index=0 | |
| 183 | +----------------------------------- | |
| 184 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 185 | +The result samples are forwarded to the side speakers. | |
| 185 | 186 | |
| 186 | 187 | name='Center Playback Volume',index=0 |
| 187 | 188 | ------------------------------------- |
| 188 | −All stereo signals are mixed together and mirrored to surround, center and LFE. | |
| 189 | −This control is used to attenuate sample for center speaker of this mix. | |
| 189 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 190 | +The result samples are forwarded to the center speaker. | |
| 190 | 191 | |
| 191 | 192 | name='LFE Playback Volume',index=0 |
| 192 | 193 | ---------------------------------- |
| 193 | −All stereo signals are mixed together and mirrored to surround, center and LFE. | |
| 194 | −This control is used to attenuate sample for LFE speaker of this mix. | |
| 194 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 195 | +The result samples are forwarded to the subwoofer. | |
| 195 | 196 | |
| 196 | 197 | name='Tone Control - Switch',index=0 |
| 197 | 198 | ------------------------------------ |
| 198 | −This control turns the tone control on or off. The samples for front, rear | |
| 199 | −and center / LFE outputs are affected. | |
| 199 | +This control turns the tone control on or off. The samples forwarded to | |
| 200 | +the speaker outputs are affected. | |
| 200 | 201 | |
| 201 | 202 | name='Tone Control - Bass',index=0 |
| 202 | 203 | ---------------------------------- |
| @@ -212,8 +213,7 @@ The closest value to pure signal is 20. · 9 unmodified lines | ||
| 212 | 213 | |
| 213 | 214 | name='Master Playback Volume',index=0 |
| 214 | 215 | ------------------------------------- |
| 215 | −This control is used to attenuate samples for front, surround, center and | |
| 216 | −LFE outputs. | |
| 216 | +This control is used to attenuate samples forwarded to the speaker outputs. | |
| 217 | 217 | |
| 218 | 218 | name='IEC958 Optical Raw Playback Switch',index=0 |
| 219 | 219 | ------------------------------------------------- |
| @@ -303,69 +303,4 @@ The channel mapping is following: · 83 unmodified lines | ||
| 303 | 303 | MANUALS/PATENTS |
| 304 | 304 | =============== |
| 305 | 305 | |
| 306 | −ftp://opensource.creative.com/pub/doc | |
| 307 | −------------------------------------- | |
| 308 | − | |
| 309 | −Note that the site is defunct, but the documents are available | |
| 310 | −from various other locations. | |
| 311 | − | |
| 312 | −LM4545.pdf | |
| 313 | − AC97 Codec | |
| 314 | − | |
| 315 | −m2049.pdf | |
| 316 | − The EMU10K1 Digital Audio Processor | |
| 317 | − | |
| 318 | −hog63.ps | |
| 319 | − FX8010 - A DSP Chip Architecture for Audio Effects | |
| 320 | − | |
| 321 | − | |
| 322 | −WIPO Patents | |
| 323 | −------------ | |
| 324 | − | |
| 325 | −WO 9901813 (A1) | |
| 326 | − Audio Effects Processor with multiple asynchronous streams | |
| 327 | − (Jan. 14, 1999) | |
| 328 | − | |
| 329 | −WO 9901814 (A1) | |
| 330 | − Processor with Instruction Set for Audio Effects (Jan. 14, 1999) | |
| 331 | − | |
| 332 | −WO 9901953 (A1) | |
| 333 | − Audio Effects Processor having Decoupled Instruction | |
| 334 | − Execution and Audio Data Sequencing (Jan. 14, 1999) | |
| 335 | − | |
| 336 | − | |
| 337 | −US Patents (https://www.uspto.gov/) | |
| 338 | −----------------------------------- | |
| 339 | − | |
| 340 | −US 5925841 | |
| 341 | − Digital Sampling Instrument employing cache memory (Jul. 20, 1999) | |
| 342 | − | |
| 343 | −US 5928342 | |
| 344 | − Audio Effects Processor integrated on a single chip | |
| 345 | − with a multiport memory onto which multiple asynchronous | |
| 346 | − digital sound samples can be concurrently loaded | |
| 347 | − (Jul. 27, 1999) | |
| 348 | − | |
| 349 | −US 5930158 | |
| 350 | − Processor with Instruction Set for Audio Effects (Jul. 27, 1999) | |
| 351 | − | |
| 352 | −US 6032235 | |
| 353 | − Memory initialization circuit (Tram) (Feb. 29, 2000) | |
| 354 | − | |
| 355 | −US 6138207 | |
| 356 | − Interpolation looping of audio samples in cache connected to | |
| 357 | − system bus with prioritization and modification of bus transfers | |
| 358 | − in accordance with loop ends and minimum block sizes | |
| 359 | − (Oct. 24, 2000) | |
| 360 | − | |
| 361 | −US 6151670 | |
| 362 | − Method for conserving memory storage using a | |
| 363 | − pool of short term memory registers | |
| 364 | − (Nov. 21, 2000) | |
| 365 | − | |
| 366 | −US 6195715 | |
| 367 | − Interrupt control for multiple programs communicating with | |
| 368 | − a common interrupt by associating programs to GP registers, | |
| 369 | − defining interrupt register, polling GP registers, and invoking | |
| 370 | − callback routine associated with defined interrupt register | |
| 371 | − (Feb. 27, 2001) | |
| 306 | +See sb-live-mixer.rst. | |
| @@ -0,0 +1,226 @@ | ||
| 1 | +================================================== | |
| 2 | +E-MU Digital Audio System mixer / default DSP code | |
| 3 | +================================================== | |
| 4 | + | |
| 5 | +This document covers the E-MU 0404/1010/1212/1616/1820 PCI/PCI-e/CardBus | |
| 6 | +cards. | |
| 7 | + | |
| 8 | +These cards use regular EMU10K2 (SoundBlaster Audigy) chips, but with an | |
| 9 | +alternative front-end geared towards semi-professional studio recording. | |
| 10 | + | |
| 11 | +This document is based on audigy-mixer.rst. | |
| 12 | + | |
| 13 | + | |
| 14 | +Hardware compatibility | |
| 15 | +====================== | |
| 16 | + | |
| 17 | +The EMU10K2 chips have a very short capture FIFO, which makes recording | |
| 18 | +unreliable if the card's PCI bus requests are not handled with the | |
| 19 | +appropriate priority. | |
| 20 | +This is the case on more modern motherboards, where the PCI bus is only a | |
| 21 | +secondary peripheral, rather than the actual arbiter of device access. | |
| 22 | +In particular, I got recording glitches during simultaneous playback on an | |
| 23 | +Intel DP55 board (memory controller in the CPU), but had success with an | |
| 24 | +Intel DP45 board (memory controller in the north bridge). | |
| 25 | + | |
| 26 | +The PCI Express variants of these cards (which have a PCI bridge on board, | |
| 27 | +but are otherwise identical) may be less problematic. | |
| 28 | + | |
| 29 | + | |
| 30 | +Driver capabilities | |
| 31 | +=================== | |
| 32 | + | |
| 33 | +This driver supports only 16-bit 44.1/48 kHz operation. The multi-channel | |
| 34 | +device (see emu10k1-jack.rst) additionally supports 24-bit capture. | |
| 35 | + | |
| 36 | +A patchset to enhance the driver is available from `a GitHub repository | |
| 37 | +<https://github.com/ossilator/linux/tree/ossis-emu10k1>`_. | |
| 38 | +Its multi-channel device supports 24-bit for both playback and capture, | |
| 39 | +and also supports full 88.2/96/176.4/192 kHz operation. | |
| 40 | +It is not going to be upstreamed due to a fundamental disagreement about | |
| 41 | +what constitutes a good user experience. | |
| 42 | + | |
| 43 | + | |
| 44 | +Digital mixer controls | |
| 45 | +====================== | |
| 46 | + | |
| 47 | +Note that the controls work as attenuators: the maximum value is the neutral | |
| 48 | +position leaving the signal unchanged. Note that if the same destination is | |
| 49 | +mentioned in multiple controls, the signal is accumulated and can be clipped | |
| 50 | +(set to maximal or minimal value without checking for overflow). | |
| 51 | + | |
| 52 | +Explanation of used abbreviations: | |
| 53 | + | |
| 54 | +DAC | |
| 55 | + digital to analog converter | |
| 56 | +ADC | |
| 57 | + analog to digital converter | |
| 58 | +LFE | |
| 59 | + low frequency effects (used as subwoofer signal) | |
| 60 | +IEC958 | |
| 61 | + S/PDIF | |
| 62 | +FX-bus | |
| 63 | + the EMU10K2 chip has an effect bus containing 64 accumulators. | |
| 64 | + Each of the synthesizer voices can feed its output to these accumulators | |
| 65 | + and the DSP microcontroller can operate with the resulting sum. | |
| 66 | + | |
| 67 | +name='Clock Source',index=0 | |
| 68 | +--------------------------- | |
| 69 | +This control allows switching the word clock between interally generated | |
| 70 | +44.1 or 48 kHz, or a number of external sources. | |
| 71 | + | |
| 72 | +Note: the sources for the 1616 CardBus card are unclear. Please report your | |
| 73 | +findings. | |
| 74 | + | |
| 75 | +name='Clock Fallback',index=0 | |
| 76 | +----------------------------- | |
| 77 | +This control determines the internal clock which the card switches to when | |
| 78 | +the selected external clock source is/becomes invalid. | |
| 79 | + | |
| 80 | +name='DAC1 0202 14dB PAD',index=0, etc. | |
| 81 | +--------------------------------------- | |
| 82 | +Output attenuation controls. Not available on 0404 cards. | |
| 83 | + | |
| 84 | +name='ADC1 14dB PAD 0202',index=0, etc. | |
| 85 | +--------------------------------------- | |
| 86 | +Input attenuation controls. Not available on 0404 cards. | |
| 87 | + | |
| 88 | +name='Optical Output Mode',index=0 | |
| 89 | +---------------------------------- | |
| 90 | +Switches the TOSLINK output port between S/PDIF and ADAT. | |
| 91 | +Not available on 0404 cards (fixed to S/PDIF). | |
| 92 | + | |
| 93 | +name='Optical Input Mode',index=0 | |
| 94 | +--------------------------------- | |
| 95 | +Switches the TOSLINK input port between S/PDIF and ADAT. | |
| 96 | +Not available on 0404 cards (fixed to S/PDIF). | |
| 97 | + | |
| 98 | +name='PCM Front Playback Volume',index=0 | |
| 99 | +---------------------------------------- | |
| 100 | +This control is used to attenuate samples from left and right front PCM FX-bus | |
| 101 | +accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM | |
| 102 | +samples for 5.1 playback. The result samples are forwarded to the DSP 0 & 1 | |
| 103 | +playback channels. | |
| 104 | + | |
| 105 | +name='PCM Surround Playback Volume',index=0 | |
| 106 | +------------------------------------------- | |
| 107 | +This control is used to attenuate samples from left and right surround PCM FX-bus | |
| 108 | +accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM | |
| 109 | +samples for 5.1 playback. The result samples are forwarded to the DSP 2 & 3 | |
| 110 | +playback channels. | |
| 111 | + | |
| 112 | +name='PCM Side Playback Volume',index=0 | |
| 113 | +--------------------------------------- | |
| 114 | +This control is used to attenuate samples from left and right side PCM FX-bus | |
| 115 | +accumulators. ALSA uses accumulators 14 and 15 for left and right side PCM | |
| 116 | +samples for 7.1 playback. The result samples are forwarded to the DSP 6 & 7 | |
| 117 | +playback channels. | |
| 118 | + | |
| 119 | +name='PCM Center Playback Volume',index=0 | |
| 120 | +----------------------------------------- | |
| 121 | +This control is used to attenuate samples from the center PCM FX-bus accumulator. | |
| 122 | +ALSA uses accumulator 6 for center PCM samples for 5.1 playback. The result samples | |
| 123 | +are forwarded to the DSP 4 playback channel. | |
| 124 | + | |
| 125 | +name='PCM LFE Playback Volume',index=0 | |
| 126 | +-------------------------------------- | |
| 127 | +This control is used to attenuate samples from the LFE PCM FX-bus accumulator. | |
| 128 | +ALSA uses accumulator 7 for LFE PCM samples for 5.1 playback. The result samples | |
| 129 | +are forwarded to the DSP 5 playback channel. | |
| 130 | + | |
| 131 | +name='PCM Playback Volume',index=0 | |
| 132 | +---------------------------------- | |
| 133 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 134 | +accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for | |
| 135 | +stereo playback. The result samples are forwarded to the virtual stereo mixer. | |
| 136 | + | |
| 137 | +name='PCM Capture Volume',index=0 | |
| 138 | +--------------------------------- | |
| 139 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 140 | +accumulators. ALSA uses accumulators 0 and 1 for left and right PCM. | |
| 141 | +The result is forwarded to the standard capture PCM device. | |
| 142 | + | |
| 143 | +name='Music Playback Volume',index=0 | |
| 144 | +------------------------------------ | |
| 145 | +This control is used to attenuate samples from left and right MIDI FX-bus | |
| 146 | +accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. | |
| 147 | +The result samples are forwarded to the virtual stereo mixer. | |
| 148 | + | |
| 149 | +name='Music Capture Volume',index=0 | |
| 150 | +----------------------------------- | |
| 151 | +These controls are used to attenuate samples from left and right MIDI FX-bus | |
| 152 | +accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples. | |
| 153 | +The result is forwarded to the standard capture PCM device. | |
| 154 | + | |
| 155 | +name='Front Playback Volume',index=0 | |
| 156 | +------------------------------------ | |
| 157 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 158 | +The result samples are forwarded to the DSP 0 & 1 playback channels. | |
| 159 | + | |
| 160 | +name='Surround Playback Volume',index=0 | |
| 161 | +--------------------------------------- | |
| 162 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 163 | +The result samples are forwarded to the DSP 2 & 3 playback channels. | |
| 164 | + | |
| 165 | +name='Side Playback Volume',index=0 | |
| 166 | +----------------------------------- | |
| 167 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 168 | +The result samples are forwarded to the DSP 6 & 7 playback channels. | |
| 169 | + | |
| 170 | +name='Center Playback Volume',index=0 | |
| 171 | +------------------------------------- | |
| 172 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 173 | +The result samples are forwarded to the DSP 4 playback channel. | |
| 174 | + | |
| 175 | +name='LFE Playback Volume',index=0 | |
| 176 | +---------------------------------- | |
| 177 | +This control is used to attenuate samples from the virtual stereo mixer. | |
| 178 | +The result samples are forwarded to the DSP 5 playback channel. | |
| 179 | + | |
| 180 | +name='Tone Control - Switch',index=0 | |
| 181 | +------------------------------------ | |
| 182 | +This control turns the tone control on or off. The samples forwarded to | |
| 183 | +the DSP playback channels are affected. | |
| 184 | + | |
| 185 | +name='Tone Control - Bass',index=0 | |
| 186 | +---------------------------------- | |
| 187 | +This control sets the bass intensity. There is no neutral value!! | |
| 188 | +When the tone control code is activated, the samples are always modified. | |
| 189 | +The closest value to pure signal is 20. | |
| 190 | + | |
| 191 | +name='Tone Control - Treble',index=0 | |
| 192 | +------------------------------------ | |
| 193 | +This control sets the treble intensity. There is no neutral value!! | |
| 194 | +When the tone control code is activated, the samples are always modified. | |
| 195 | +The closest value to pure signal is 20. | |
| 196 | + | |
| 197 | +name='Master Playback Volume',index=0 | |
| 198 | +------------------------------------- | |
| 199 | +This control is used to attenuate samples for all DSP playback channels. | |
| 200 | + | |
| 201 | +name='EMU Capture Volume',index=0 | |
| 202 | +---------------------------------- | |
| 203 | +This control is used to attenuate samples from the DSP 0 & 1 capture channels. | |
| 204 | +The result is forwarded to the standard capture PCM device. | |
| 205 | + | |
| 206 | +name='DAC Left',index=0, etc. | |
| 207 | +----------------------------- | |
| 208 | +Select the source for the given physical audio output. These may be physical | |
| 209 | +inputs, playback channels (DSP xx, specified as a decimal number), or silence. | |
| 210 | + | |
| 211 | +name='DSP x',index=0 | |
| 212 | +-------------------- | |
| 213 | +Select the source for the given capture channel (specified as a hexadecimal | |
| 214 | +digit). Same options as for the physical audio outputs. | |
| 215 | + | |
| 216 | + | |
| 217 | +PCM stream related controls | |
| 218 | +=========================== | |
| 219 | + | |
| 220 | +These controls are described in audigy-mixer.rst. | |
| 221 | + | |
| 222 | + | |
| 223 | +MANUALS/PATENTS | |
| 224 | +=============== | |
| 225 | + | |
| 226 | +See sb-live-mixer.rst. | |
| @@ -8,6 +8,7 @@ Card-Specific Information · 7 unmodified lines | ||
| 8 | 8 | cmipci |
| 9 | 9 | sb-live-mixer |
| 10 | 10 | audigy-mixer |
| 11 | + emu-mixer | |
| 11 | 12 | emu10k1-jack |
| 12 | 13 | via82xx-mixer |
| 13 | 14 | audiophile-usb |
| @@ -61,61 +61,61 @@ FX-bus · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | ``name='Wave Playback Volume',index=0`` |
| 63 | 63 | --------------------------------------- |
| 64 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 64 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 65 | 65 | accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples. |
| 66 | 66 | The result samples are forwarded to the front DAC PCM slots of the AC97 codec. |
| 67 | 67 | |
| 68 | 68 | ``name='Wave Surround Playback Volume',index=0`` |
| 69 | 69 | ------------------------------------------------ |
| 70 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 70 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 71 | 71 | accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples. |
| 72 | 72 | The result samples are forwarded to the rear I2S DACs. These DACs operates |
| 73 | 73 | separately (they are not inside the AC97 codec). |
| 74 | 74 | |
| 75 | 75 | ``name='Wave Center Playback Volume',index=0`` |
| 76 | 76 | ---------------------------------------------- |
| 77 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 77 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 78 | 78 | accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples. |
| 79 | 79 | The result is mixed to mono signal (single channel) and forwarded to |
| 80 | 80 | the ??rear?? right DAC PCM slot of the AC97 codec. |
| 81 | 81 | |
| 82 | 82 | ``name='Wave LFE Playback Volume',index=0`` |
| 83 | 83 | ------------------------------------------- |
| 84 | −This control is used to attenuate samples for left and right PCM FX-bus | |
| 84 | +This control is used to attenuate samples from left and right PCM FX-bus | |
| 85 | 85 | accumulators. ALSA uses accumulators 0 and 1 for left and right PCM. |
| 86 | 86 | The result is mixed to mono signal (single channel) and forwarded to |
| 87 | 87 | the ??rear?? left DAC PCM slot of the AC97 codec. |
| 88 | 88 | |
| 89 | 89 | ``name='Wave Capture Volume',index=0``, ``name='Wave Capture Switch',index=0`` |
| 90 | 90 | ------------------------------------------------------------------------------ |
| 91 | −These controls are used to attenuate samples for left and right PCM FX-bus | |
| 91 | +These controls are used to attenuate samples from left and right PCM FX-bus | |
| 92 | 92 | accumulator. ALSA uses accumulators 0 and 1 for left and right PCM. |
| 93 | 93 | The result is forwarded to the ADC capture FIFO (thus to the standard capture |
| 94 | 94 | PCM device). |
| 95 | 95 | |
| 96 | 96 | ``name='Synth Playback Volume',index=0`` |
| 97 | 97 | ---------------------------------------- |
| 98 | −This control is used to attenuate samples for left and right MIDI FX-bus | |
| 98 | +This control is used to attenuate samples from left and right MIDI FX-bus | |
| 99 | 99 | accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. |
| 100 | 100 | The result samples are forwarded to the front DAC PCM slots of the AC97 codec. |
| 101 | 101 | |
| 102 | 102 | ``name='Synth Capture Volume',index=0``, ``name='Synth Capture Switch',index=0`` |
| 103 | 103 | -------------------------------------------------------------------------------- |
| 104 | −These controls are used to attenuate samples for left and right MIDI FX-bus | |
| 105 | −accumulator. ALSA uses accumulators 4 and 5 for left and right PCM. | |
| 104 | +These controls are used to attenuate samples from left and right MIDI FX-bus | |
| 105 | +accumulator. ALSA uses accumulators 4 and 5 for left and right MIDI samples. | |
| 106 | 106 | The result is forwarded to the ADC capture FIFO (thus to the standard capture |
| 107 | 107 | PCM device). |
| 108 | 108 | |
| 109 | 109 | ``name='Surround Playback Volume',index=0`` |
| 110 | 110 | ------------------------------------------- |
| 111 | −This control is used to attenuate samples for left and right rear PCM FX-bus | |
| 111 | +This control is used to attenuate samples from left and right rear PCM FX-bus | |
| 112 | 112 | accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples. |
| 113 | 113 | The result samples are forwarded to the rear I2S DACs. These DACs operate |
| 114 | 114 | separately (they are not inside the AC97 codec). |
| 115 | 115 | |
| 116 | 116 | ``name='Surround Capture Volume',index=0``, ``name='Surround Capture Switch',index=0`` |
| 117 | 117 | -------------------------------------------------------------------------------------- |
| 118 | −These controls are used to attenuate samples for left and right rear PCM FX-bus | |
| 118 | +These controls are used to attenuate samples from left and right rear PCM FX-bus | |
| 119 | 119 | accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples. |
| 120 | 120 | The result is forwarded to the ADC capture FIFO (thus to the standard capture |
| 121 | 121 | PCM device). |
| @@ -134,7 +134,7 @@ to the ??rear?? left DAC PCM slot of the AC97 codec. · 12 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | ``name='AC97 Playback Volume',index=0`` |
| 136 | 136 | --------------------------------------- |
| 137 | −This control is used to attenuate samples for left and right front ADC PCM slots | |
| 137 | +This control is used to attenuate samples from left and right front ADC PCM slots | |
| 138 | 138 | of the AC97 codec. The result samples are forwarded to the front DAC PCM |
| 139 | 139 | slots of the AC97 codec. |
| 140 | 140 | |
| @@ -145,7 +145,7 @@ slots of the AC97 codec. · 4 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | ``name='AC97 Capture Volume',index=0`` |
| 147 | 147 | -------------------------------------- |
| 148 | −This control is used to attenuate samples for left and right front ADC PCM slots | |
| 148 | +This control is used to attenuate samples from left and right front ADC PCM slots | |
| 149 | 149 | of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to |
| 150 | 150 | the standard capture PCM device). |
| 151 | 151 | |
| @@ -376,3 +376,191 @@ Sequencer API Extensions · 375 unmodified lines | ||
| 376 | 376 | name and attributes accordingly, and notifies the changes via the |
| 377 | 377 | announcement to the ALSA sequencer system port, similarly like the |
| 378 | 378 | normal port change notification. |
| 379 | + | |
| 380 | + | |
| 381 | +MIDI2 USB Gadget Function Driver | |
| 382 | +================================ | |
| 383 | + | |
| 384 | +The latest kernel contains the support for USB MIDI 2.0 gadget | |
| 385 | +function driver, which can be used for prototyping and debugging MIDI | |
| 386 | +2.0 features. | |
| 387 | + | |
| 388 | +`CONFIG_USB_GADGET`, `CONFIG_USB_CONFIGFS` and | |
| 389 | +`CONFIG_USB_CONFIGFS_F_MIDI2` need to be enabled for the MIDI2 gadget | |
| 390 | +driver. | |
| 391 | + | |
| 392 | +In addition, for using a gadget driver, you need a working UDC driver. | |
| 393 | +In the example below, we use `dummy_hcd` driver (enabled via | |
| 394 | +`CONFIG_USB_DUMMY_HCD`) that is available on PC and VM for debugging | |
| 395 | +purpose. There are other UDC drivers depending on the platform, and | |
| 396 | +those can be used for a real device, instead, too. | |
| 397 | + | |
| 398 | +At first, on a system to run the gadget, load `libcomposite` module:: | |
| 399 | + | |
| 400 | + % modprobe libcomposite | |
| 401 | + | |
| 402 | +and you'll have `usb_gadget` subdirectory under configfs space | |
| 403 | +(typically `/sys/kernel/config` on modern OS). Then create a gadget | |
| 404 | +instance and add configurations there, for example:: | |
| 405 | + | |
| 406 | + % cd /sys/kernel/config | |
| 407 | + % mkdir usb_gadget/g1 | |
| 408 | + | |
| 409 | + % cd usb_gadget/g1 | |
| 410 | + % mkdir configs/c.1 | |
| 411 | + % mkdir functions/midi2.usb0 | |
| 412 | + | |
| 413 | + % echo 0x0004 > idProduct | |
| 414 | + % echo 0x17b3 > idVendor | |
| 415 | + % mkdir strings/0x409 | |
| 416 | + % echo "ACME Enterprises" > strings/0x409/manufacturer | |
| 417 | + % echo "ACMESynth" > strings/0x409/product | |
| 418 | + % echo "ABCD12345" > strings/0x409/serialnumber | |
| 419 | + | |
| 420 | + % mkdir configs/c.1/strings/0x409 | |
| 421 | + % echo "Monosynth" > configs/c.1/strings/0x409/configuration | |
| 422 | + % echo 120 > configs/c.1/MaxPower | |
| 423 | + | |
| 424 | +At this point, there must be a subdirectory `ep.0`, and that is the | |
| 425 | +configuration for a UMP Endpoint. You can fill the Endpoint | |
| 426 | +information like:: | |
| 427 | + | |
| 428 | + % echo "ACMESynth" > functions/midi2.usb0/iface_name | |
| 429 | + % echo "ACMESynth" > functions/midi2.usb0/ep.0/ep_name | |
| 430 | + % echo "ABCD12345" > functions/midi2.usb0/ep.0/product_id | |
| 431 | + % echo 0x0123 > functions/midi2.usb0/ep.0/family | |
| 432 | + % echo 0x4567 > functions/midi2.usb0/ep.0/model | |
| 433 | + % echo 0x123456 > functions/midi2.usb0/ep.0/manufacturer | |
| 434 | + % echo 0x12345678 > functions/midi2.usb0/ep.0/sw_revision | |
| 435 | + | |
| 436 | +The default MIDI protocol can be set either 1 or 2:: | |
| 437 | + | |
| 438 | + % echo 2 > functions/midi2.usb0/ep.0/protocol | |
| 439 | + | |
| 440 | +And, you can find a subdirectory `block.0` under this Endpoint | |
| 441 | +subdirectory. This defines the Function Block information:: | |
| 442 | + | |
| 443 | + % echo "Monosynth" > functions/midi2.usb0/ep.0/block.0/name | |
| 444 | + % echo 0 > functions/midi2.usb0/ep.0/block.0/first_group | |
| 445 | + % echo 1 > functions/midi2.usb0/ep.0/block.0/num_groups | |
| 446 | + | |
| 447 | +Finally, link the configuration and enable it:: | |
| 448 | + | |
| 449 | + % ln -s functions/midi2.usb0 configs/c.1 | |
| 450 | + % echo dummy_udc.0 > UDC | |
| 451 | + | |
| 452 | +where `dummy_udc.0` is an example case and it differs depending on the | |
| 453 | +system. You can find the UDC instances in `/sys/class/udc` and pass | |
| 454 | +the found name instead:: | |
| 455 | + | |
| 456 | + % ls /sys/class/udc | |
| 457 | + dummy_udc.0 | |
| 458 | + | |
| 459 | +Now, the MIDI 2.0 gadget device is enabled, and the gadget host | |
| 460 | +creates a new sound card instance containing a UMP rawmidi device by | |
| 461 | +`f_midi2` driver:: | |
| 462 | + | |
| 463 | + % cat /proc/asound/cards | |
| 464 | + .... | |
| 465 | + 1 [Gadget ]: f_midi2 - MIDI 2.0 Gadget | |
| 466 | + MIDI 2.0 Gadget | |
| 467 | + | |
| 468 | +And on the connected host, a similar card should appear, too, but with | |
| 469 | +the card and device names given in the configfs above:: | |
| 470 | + | |
| 471 | + % cat /proc/asound/cards | |
| 472 | + .... | |
| 473 | + 2 [ACMESynth ]: USB-Audio - ACMESynth | |
| 474 | + ACME Enterprises ACMESynth at usb-dummy_hcd.0-1, high speed | |
| 475 | + | |
| 476 | +You can play a MIDI file on the gadget side:: | |
| 477 | + | |
| 478 | + % aplaymidi -p 20:1 to_host.mid | |
| 479 | + | |
| 480 | +and this will appear as an input from a MIDI device on the connected | |
| 481 | +host:: | |
| 482 | + | |
| 483 | + % aseqdump -p 20:0 -u 2 | |
| 484 | + | |
| 485 | +Vice versa, a playback on the connected host will work as an input on | |
| 486 | +the gadget, too. | |
| 487 | + | |
| 488 | +Each Function Block may have different direction and UI-hint, | |
| 489 | +specified via `direction` and `ui_hint` attributes. | |
| 490 | +Passing `1` is for input-only, `2` for out-only and `3` for | |
| 491 | +bidirectional (the default value). For example:: | |
| 492 | + | |
| 493 | + % echo 2 > functions/midi2.usb0/ep.0/block.0/direction | |
| 494 | + % echo 2 > functions/midi2.usb0/ep.0/block.0/ui_hint | |
| 495 | + | |
| 496 | +When you need more than one Function Blocks, you can create | |
| 497 | +subdirectories `block.1`, `block.2`, etc dynamically, and configure | |
| 498 | +them in the configuration procedure above before linking. | |
| 499 | +For example, to create a second Function Block for a keyboard:: | |
| 500 | + | |
| 501 | + % mkdir functions/midi2.usb0/ep.0/block.1 | |
| 502 | + % echo "Keyboard" > functions/midi2.usb0/ep.0/block.1/name | |
| 503 | + % echo 1 > functions/midi2.usb0/ep.0/block.1/first_group | |
| 504 | + % echo 1 > functions/midi2.usb0/ep.0/block.1/num_groups | |
| 505 | + % echo 1 > functions/midi2.usb0/ep.0/block.1/direction | |
| 506 | + % echo 1 > functions/midi2.usb0/ep.0/block.1/ui_hint | |
| 507 | + | |
| 508 | +The `block.*` subdirectories can be removed dynamically, too (except | |
| 509 | +for `block.0` which is persistent). | |
| 510 | + | |
| 511 | +For assigning a Function Block for MIDI 1.0 I/O, set up in `is_midi1` | |
| 512 | +attribute. 1 is for MIDI 1.0, and 2 is for MIDI 1.0 with low speed | |
| 513 | +connection:: | |
| 514 | + | |
| 515 | + % echo 2 > functions/midi2.usb0/ep.0/block.1/is_midi1 | |
| 516 | + | |
| 517 | +For disabling the processing of UMP Stream messages in the gadget | |
| 518 | +driver, pass `0` to `process_ump` attribute in the top-level config:: | |
| 519 | + | |
| 520 | + % echo 0 > functions/midi2.usb0/process_ump | |
| 521 | + | |
| 522 | +The MIDI 1.0 interface at altset 0 is supported by the gadget driver, | |
| 523 | +too. When MIDI 1.0 interface is selected by the connected host, the | |
| 524 | +UMP I/O on the gadget is translated from/to USB MIDI 1.0 packets | |
| 525 | +accordingly while the gadget driver keeps communicating with the | |
| 526 | +user-space over UMP rawmidi. | |
| 527 | + | |
| 528 | +MIDI 1.0 ports are set up from the config in each Function Block. | |
| 529 | +For example:: | |
| 530 | + | |
| 531 | + % echo 0 > functions/midi2.usb0/ep.0/block.0/midi1_first_group | |
| 532 | + % echo 1 > functions/midi2.usb0/ep.0/block.0/midi1_num_groups | |
| 533 | + | |
| 534 | +The configuration above will enable the Group 1 (the index 0) for MIDI | |
| 535 | +1.0 interface. Note that those groups must be in the groups defined | |
| 536 | +for the Function Block itself. | |
| 537 | + | |
| 538 | +The gadget driver supports more than one UMP Endpoints, too. | |
| 539 | +Similarly like the Function Blocks, you can create a new subdirectory | |
| 540 | +`ep.1` (but under the card top-level config) to enable a new Endpoint:: | |
| 541 | + | |
| 542 | + % mkdir functions/midi2.usb0/ep.1 | |
| 543 | + | |
| 544 | +and create a new Function Block there. For example, to create 4 | |
| 545 | +Groups for the Function Block of this new Endpoint:: | |
| 546 | + | |
| 547 | + % mkdir functions/midi2.usb0/ep.1/block.0 | |
| 548 | + % echo 4 > functions/midi2.usb0/ep.1/block.0/num_groups | |
| 549 | + | |
| 550 | +Now, you'll have 4 rawmidi devices in total: the first two are UMP | |
| 551 | +rawmidi devices for Endpoint 0 and Endpoint 1, and other two for the | |
| 552 | +legacy MIDI 1.0 rawmidi devices corresponding to both EP 0 and EP 1. | |
| 553 | + | |
| 554 | +The current altsetting on the gadget can be informed via a control | |
| 555 | +element "Operation Mode" with `RAWMIDI` iface. e.g. you can read it | |
| 556 | +via `amixer` program running on the gadget host like:: | |
| 557 | + | |
| 558 | + % amixer -c1 cget iface=RAWMIDI,name='Operation Mode' | |
| 559 | + ; type=INTEGER,access=r--v----,values=1,min=0,max=2,step=0 | |
| 560 | + : values=2 | |
| 561 | + | |
| 562 | +The value (shown in the second returned line with `: values=`) | |
| 563 | +indicates 1 for MIDI 1.0 (altset 0), 2 for MIDI 2.0 (altset 1) and 0 | |
| 564 | +for unset. | |
| 565 | + | |
| 566 | +As of now, the configurations can't be changed after binding. | |
| @@ -2018,8 +2018,8 @@ sleeping poll threads, etc. · 2017 unmodified lines | ||
| 2018 | 2018 | |
| 2019 | 2019 | This callback is also atomic by default. |
| 2020 | 2020 | |
| 2021 | −copy_user, copy_kernel and fill_silence ops | |
| 2022 | −~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 2021 | +copy and fill_silence ops | |
| 2022 | +~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 2023 | 2023 | |
| 2024 | 2024 | These callbacks are not mandatory, and can be omitted in most cases. |
| 2025 | 2025 | These callbacks are used when the hardware buffer cannot be in the |
| @@ -3444,8 +3444,8 @@ external hardware buffer in interrupts (or in tasklets, preferably). · 1418 unmodified lines | ||
| 3444 | 3444 | |
| 3445 | 3445 | The first case works fine if the external hardware buffer is large |
| 3446 | 3446 | enough. This method doesn't need any extra buffers and thus is more |
| 3447 | −efficient. You need to define the ``copy_user`` and ``copy_kernel`` | |
| 3448 | −callbacks for the data transfer, in addition to the ``fill_silence`` | |
| 3447 | +efficient. You need to define the ``copy`` callback | |
| 3448 | +for the data transfer, in addition to the ``fill_silence`` | |
| 3449 | 3449 | callback for playback. However, there is a drawback: it cannot be |
| 3450 | 3450 | mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM. |
| 3451 | 3451 | |
| @@ -3458,22 +3458,22 @@ Another case is when the chip uses a PCI memory-map region for the · 6 unmodified lines | ||
| 3458 | 3458 | buffer instead of the host memory. In this case, mmap is available only |
| 3459 | 3459 | on certain architectures like the Intel one. In non-mmap mode, the data |
| 3460 | 3460 | cannot be transferred as in the normal way. Thus you need to define the |
| 3461 | −``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well, | |
| 3461 | +``copy`` and ``fill_silence`` callbacks as well, | |
| 3462 | 3462 | as in the cases above. Examples are found in ``rme32.c`` and |
| 3463 | 3463 | ``rme96.c``. |
| 3464 | 3464 | |
| 3465 | −The implementation of the ``copy_user``, ``copy_kernel`` and | |
| 3465 | +The implementation of the ``copy`` and | |
| 3466 | 3466 | ``silence`` callbacks depends upon whether the hardware supports |
| 3467 | −interleaved or non-interleaved samples. The ``copy_user`` callback is | |
| 3467 | +interleaved or non-interleaved samples. The ``copy`` callback is | |
| 3468 | 3468 | defined like below, a bit differently depending on whether the direction |
| 3469 | 3469 | is playback or capture:: |
| 3470 | 3470 | |
| 3471 | − static int playback_copy_user(struct snd_pcm_substream *substream, | |
| 3471 | + static int playback_copy(struct snd_pcm_substream *substream, | |
| 3472 | 3472 | int channel, unsigned long pos, |
| 3473 | − void __user *src, unsigned long count); | |
| 3474 | − static int capture_copy_user(struct snd_pcm_substream *substream, | |
| 3473 | + struct iov_iter *src, unsigned long count); | |
| 3474 | + static int capture_copy(struct snd_pcm_substream *substream, | |
| 3475 | 3475 | int channel, unsigned long pos, |
| 3476 | − void __user *dst, unsigned long count); | |
| 3476 | + struct iov_iter *dst, unsigned long count); | |
| 3477 | 3477 | |
| 3478 | 3478 | In the case of interleaved samples, the second argument (``channel``) is |
| 3479 | 3479 | not used. The third argument (``pos``) specifies the position in bytes. |
| @@ -3490,18 +3490,17 @@ of data (``count``) at the specified pointer (``src``) to the specified · 10 unmodified lines | ||
| 3490 | 3490 | offset (``pos``) in the hardware buffer. When coded like memcpy-like |
| 3491 | 3491 | way, the copy would look like:: |
| 3492 | 3492 | |
| 3493 | − my_memcpy_from_user(my_buffer + pos, src, count); | |
| 3493 | + my_memcpy_from_iter(my_buffer + pos, src, count); | |
| 3494 | 3494 | |
| 3495 | 3495 | For the capture direction, you copy the given amount of data (``count``) |
| 3496 | 3496 | at the specified offset (``pos``) in the hardware buffer to the |
| 3497 | 3497 | specified pointer (``dst``):: |
| 3498 | 3498 | |
| 3499 | − my_memcpy_to_user(dst, my_buffer + pos, count); | |
| 3499 | + my_memcpy_to_iter(dst, my_buffer + pos, count); | |
| 3500 | 3500 | |
| 3501 | −Here the functions are named ``from_user`` and ``to_user`` because | |
| 3502 | −it's the user-space buffer that is passed to these callbacks. That | |
| 3503 | −is, the callback is supposed to copy data from/to the user-space | |
| 3504 | −directly to/from the hardware buffer. | |
| 3501 | +The given ``src`` or ``dst`` a struct iov_iter pointer containing the | |
| 3502 | +pointer and the size. Use the existing helpers to copy or access the | |
| 3503 | +data as defined in ``linux/uio.h``. | |
| 3505 | 3504 | |
| 3506 | 3505 | Careful readers might notice that these callbacks receive the |
| 3507 | 3506 | arguments in bytes, not in frames like other callbacks. It's because |
| @@ -3519,25 +3518,6 @@ the given user-space buffer, but only for the given channel. For · 11 unmodified lines | ||
| 3519 | 3518 | details, please check ``isa/gus/gus_pcm.c`` or ``pci/rme9652/rme9652.c`` |
| 3520 | 3519 | as examples. |
| 3521 | 3520 | |
| 3522 | −The above callbacks are the copies from/to the user-space buffer. There | |
| 3523 | −are some cases where we want to copy from/to the kernel-space buffer | |
| 3524 | −instead. In such a case, the ``copy_kernel`` callback is called. It'd | |
| 3525 | −look like:: | |
| 3526 | − | |
| 3527 | − static int playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 3528 | − int channel, unsigned long pos, | |
| 3529 | − void *src, unsigned long count); | |
| 3530 | − static int capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 3531 | − int channel, unsigned long pos, | |
| 3532 | − void *dst, unsigned long count); | |
| 3533 | − | |
| 3534 | −As found easily, the only difference is that the buffer pointer is | |
| 3535 | −without a ``__user`` prefix; that is, a kernel-buffer pointer is passed | |
| 3536 | −in the fourth argument. Correspondingly, the implementation would be | |
| 3537 | −a version without the user-copy, such as:: | |
| 3538 | − | |
| 3539 | − my_memcpy(my_buffer + pos, src, count); | |
| 3540 | − | |
| 3541 | 3521 | Usually for the playback, another callback ``fill_silence`` is |
| 3542 | 3522 | defined. It's implemented in a similar way as the copy callbacks |
| 3543 | 3523 | above:: |
| @@ -3545,10 +3525,10 @@ above:: · 1 unmodified line | ||
| 3545 | 3525 | static int silence(struct snd_pcm_substream *substream, int channel, |
| 3546 | 3526 | unsigned long pos, unsigned long count); |
| 3547 | 3527 | |
| 3548 | −The meanings of arguments are the same as in the ``copy_user`` and | |
| 3549 | −``copy_kernel`` callbacks, although there is no buffer pointer | |
| 3528 | +The meanings of arguments are the same as in the ``copy`` callback, | |
| 3529 | +although there is no buffer pointer | |
| 3550 | 3530 | argument. In the case of interleaved samples, the channel argument has |
| 3551 | −no meaning, as for the ``copy_*`` callbacks. | |
| 3531 | +no meaning, as for the ``copy`` callback. | |
| 3552 | 3532 | |
| 3553 | 3533 | The role of the ``fill_silence`` callback is to set the given amount |
| 3554 | 3534 | (``count``) of silence data at the specified offset (``pos``) in the |
| @@ -978,7 +978,8 @@ static int cs_dsp_create_control(struct cs_dsp *dsp, · 977 unmodified lines | ||
| 978 | 978 | ctl->alg_region.alg == alg_region->alg && |
| 979 | 979 | ctl->alg_region.type == alg_region->type) { |
| 980 | 980 | if ((!subname && !ctl->subname) || |
| 981 | − (subname && !strncmp(ctl->subname, subname, ctl->subname_len))) { | |
| 981 | + (subname && (ctl->subname_len == subname_len) && | |
| 982 | + !strncmp(ctl->subname, subname, ctl->subname_len))) { | |
| 982 | 983 | if (!ctl->enabled) |
| 983 | 984 | ctl->enabled = 1; |
| 984 | 985 | return 0; |
| @@ -2615,9 +2615,13 @@ static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai) · 2614 unmodified lines | ||
| 2615 | 2615 | return 0; |
| 2616 | 2616 | } |
| 2617 | 2617 | |
| 2618 | +static const struct snd_soc_dai_ops vc4_snd_dai_ops = { | |
| 2619 | + .probe = vc4_hdmi_audio_cpu_dai_probe, | |
| 2620 | +}; | |
| 2621 | + | |
| 2618 | 2622 | static struct snd_soc_dai_driver vc4_hdmi_audio_cpu_dai_drv = { |
| 2619 | 2623 | .name = "vc4-hdmi-cpu-dai", |
| 2620 | − .probe = vc4_hdmi_audio_cpu_dai_probe, | |
| 2624 | + .ops = &vc4_snd_dai_ops, | |
| 2621 | 2625 | .playback = { |
| 2622 | 2626 | .stream_name = "Playback", |
| 2623 | 2627 | .channels_min = 1, |
| @@ -5,9 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | */ |
| 6 | 6 | #include <linux/err.h> |
| 7 | 7 | #include <linux/export.h> |
| 8 | +#include <linux/minmax.h> | |
| 9 | +#include <linux/mutex.h> | |
| 8 | 10 | #include <linux/property.h> |
| 9 | 11 | #include <linux/slab.h> |
| 10 | −#include <linux/mutex.h> | |
| 11 | 12 | |
| 12 | 13 | #include <linux/iio/iio.h> |
| 13 | 14 | #include <linux/iio/iio-opaque.h> |
| @@ -849,15 +850,14 @@ static int iio_channel_read_max(struct iio_channel *chan, · 835 unmodified lines | ||
| 849 | 850 | int *val, int *val2, int *type, |
| 850 | 851 | enum iio_chan_info_enum info) |
| 851 | 852 | { |
| 852 | − int unused; | |
| 853 | 853 | const int *vals; |
| 854 | 854 | int length; |
| 855 | 855 | int ret; |
| 856 | 856 | |
| 857 | − if (!val2) | |
| 858 | − val2 = &unused; | |
| 859 | − | |
| 860 | 857 | ret = iio_channel_read_avail(chan, &vals, type, &length, info); |
| 858 | + if (ret < 0) | |
| 859 | + return ret; | |
| 860 | + | |
| 861 | 861 | switch (ret) { |
| 862 | 862 | case IIO_AVAIL_RANGE: |
| 863 | 863 | switch (*type) { |
| @@ -866,7 +866,8 @@ static int iio_channel_read_max(struct iio_channel *chan, · 2 unmodified lines | ||
| 866 | 866 | break; |
| 867 | 867 | default: |
| 868 | 868 | *val = vals[4]; |
| 869 | − *val2 = vals[5]; | |
| 869 | + if (val2) | |
| 870 | + *val2 = vals[5]; | |
| 870 | 871 | } |
| 871 | 872 | return 0; |
| 872 | 873 | |
| @@ -875,20 +876,16 @@ static int iio_channel_read_max(struct iio_channel *chan, · 2 unmodified lines | ||
| 875 | 876 | return -EINVAL; |
| 876 | 877 | switch (*type) { |
| 877 | 878 | case IIO_VAL_INT: |
| 878 | − *val = vals[--length]; | |
| 879 | − while (length) { | |
| 880 | − if (vals[--length] > *val) | |
| 881 | − *val = vals[length]; | |
| 882 | − } | |
| 879 | + *val = max_array(vals, length); | |
| 883 | 880 | break; |
| 884 | 881 | default: |
| 885 | − /* FIXME: learn about max for other iio values */ | |
| 882 | + /* TODO: learn about max for other iio values */ | |
| 886 | 883 | return -EINVAL; |
| 887 | 884 | } |
| 888 | 885 | return 0; |
| 889 | 886 | |
| 890 | 887 | default: |
| 891 | − return ret; | |
| 888 | + return -EINVAL; | |
| 892 | 889 | } |
| 893 | 890 | } |
| 894 | 891 | |
| @@ -912,6 +909,69 @@ err_unlock: · 17 unmodified lines | ||
| 912 | 909 | } |
| 913 | 910 | EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); |
| 914 | 911 | |
| 912 | +static int iio_channel_read_min(struct iio_channel *chan, | |
| 913 | + int *val, int *val2, int *type, | |
| 914 | + enum iio_chan_info_enum info) | |
| 915 | +{ | |
| 916 | + const int *vals; | |
| 917 | + int length; | |
| 918 | + int ret; | |
| 919 | + | |
| 920 | + ret = iio_channel_read_avail(chan, &vals, type, &length, info); | |
| 921 | + if (ret < 0) | |
| 922 | + return ret; | |
| 923 | + | |
| 924 | + switch (ret) { | |
| 925 | + case IIO_AVAIL_RANGE: | |
| 926 | + switch (*type) { | |
| 927 | + case IIO_VAL_INT: | |
| 928 | + *val = vals[0]; | |
| 929 | + break; | |
| 930 | + default: | |
| 931 | + *val = vals[0]; | |
| 932 | + if (val2) | |
| 933 | + *val2 = vals[1]; | |
| 934 | + } | |
| 935 | + return 0; | |
| 936 | + | |
| 937 | + case IIO_AVAIL_LIST: | |
| 938 | + if (length <= 0) | |
| 939 | + return -EINVAL; | |
| 940 | + switch (*type) { | |
| 941 | + case IIO_VAL_INT: | |
| 942 | + *val = min_array(vals, length); | |
| 943 | + break; | |
| 944 | + default: | |
| 945 | + /* TODO: learn about min for other iio values */ | |
| 946 | + return -EINVAL; | |
| 947 | + } | |
| 948 | + return 0; | |
| 949 | + | |
| 950 | + default: | |
| 951 | + return -EINVAL; | |
| 952 | + } | |
| 953 | +} | |
| 954 | + | |
| 955 | +int iio_read_min_channel_raw(struct iio_channel *chan, int *val) | |
| 956 | +{ | |
| 957 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | |
| 958 | + int ret; | |
| 959 | + int type; | |
| 960 | + | |
| 961 | + mutex_lock(&iio_dev_opaque->info_exist_lock); | |
| 962 | + if (!chan->indio_dev->info) { | |
| 963 | + ret = -ENODEV; | |
| 964 | + goto err_unlock; | |
| 965 | + } | |
| 966 | + | |
| 967 | + ret = iio_channel_read_min(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); | |
| 968 | +err_unlock: | |
| 969 | + mutex_unlock(&iio_dev_opaque->info_exist_lock); | |
| 970 | + | |
| 971 | + return ret; | |
| 972 | +} | |
| 973 | +EXPORT_SYMBOL_GPL(iio_read_min_channel_raw); | |
| 974 | + | |
| 915 | 975 | int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) |
| 916 | 976 | { |
| 917 | 977 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); |
| @@ -8,6 +8,6 @@ dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \ |
| 10 | 10 | dvb_ca_en50221.o dvb_frontend.o \ |
| 11 | − $(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o | |
| 11 | + $(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) | |
| 12 | 12 | |
| 13 | 13 | obj-$(CONFIG_DVB_CORE) += dvb-core.o |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #define AF9013_PRIV_H |
| 13 | 13 | |
| 14 | 14 | #include <media/dvb_frontend.h> |
| 15 | −#include <media/dvb_math.h> | |
| 15 | +#include <linux/int_log.h> | |
| 16 | 16 | #include "af9013.h" |
| 17 | 17 | #include <linux/firmware.h> |
| 18 | 18 | #include <linux/i2c-mux.h> |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/math64.h> |
| 15 | 15 | #include <linux/regmap.h> |
| 16 | 16 | #include <linux/kernel.h> |
| 17 | −#include <media/dvb_math.h> | |
| 17 | +#include <linux/int_log.h> | |
| 18 | 18 | |
| 19 | 19 | struct reg_val { |
| 20 | 20 | u32 reg; |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include <linux/dvb/version.h> |
| 13 | 13 | #include <media/dvb_frontend.h> |
| 14 | −#include <media/dvb_math.h> | |
| 14 | +#include <linux/int_log.h> | |
| 15 | 15 | #include "cxd2820r.h" |
| 16 | 16 | #include <linux/gpio/driver.h> /* For gpio_chip */ |
| 17 | 17 | #include <linux/math64.h> |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/dynamic_debug.h> |
| 23 | 23 | #include <linux/kernel.h> |
| 24 | 24 | |
| 25 | −#include <media/dvb_math.h> | |
| 25 | +#include <linux/int_log.h> | |
| 26 | 26 | #include <media/dvb_frontend.h> |
| 27 | 27 | #include "cxd2841er.h" |
| 28 | 28 | #include "cxd2841er_priv.h" |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "cxd2880_tnrdmd_dvbt2.h" |
| 12 | 12 | #include "cxd2880_tnrdmd_dvbt2_mon.h" |
| 13 | 13 | |
| 14 | −#include <media/dvb_math.h> | |
| 14 | +#include <linux/int_log.h> | |
| 15 | 15 | |
| 16 | 16 | static const int ref_dbm_1000[4][8] = { |
| 17 | 17 | {-96000, -95000, -94000, -93000, -92000, -92000, -98000, -97000}, |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "cxd2880_tnrdmd_dvbt.h" |
| 12 | 12 | #include "cxd2880_tnrdmd_dvbt_mon.h" |
| 13 | 13 | |
| 14 | −#include <media/dvb_math.h> | |
| 14 | +#include <linux/int_log.h> | |
| 15 | 15 | |
| 16 | 16 | static const int ref_dbm_1000[3][5] = { |
| 17 | 17 | {-93000, -91000, -90000, -89000, -88000}, |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/spi/spi.h> |
| 12 | 12 | |
| 13 | 13 | #include <media/dvb_frontend.h> |
| 14 | −#include <media/dvb_math.h> | |
| 14 | +#include <linux/int_log.h> | |
| 15 | 15 | |
| 16 | 16 | #include "cxd2880.h" |
| 17 | 17 | #include "cxd2880_tnrdmd_mon.h" |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/mutex.h> |
| 14 | 14 | #include <asm/div64.h> |
| 15 | 15 | |
| 16 | −#include <media/dvb_math.h> | |
| 16 | +#include <linux/int_log.h> | |
| 17 | 17 | #include <media/dvb_frontend.h> |
| 18 | 18 | |
| 19 | 19 | #include "dib7000p.h" |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/mutex.h> |
| 14 | 14 | #include <asm/div64.h> |
| 15 | 15 | |
| 16 | −#include <media/dvb_math.h> | |
| 16 | +#include <linux/int_log.h> | |
| 17 | 17 | |
| 18 | 18 | #include <media/dvb_frontend.h> |
| 19 | 19 | |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/i2c.h> |
| 12 | 12 | #include <linux/mutex.h> |
| 13 | 13 | |
| 14 | −#include <media/dvb_math.h> | |
| 14 | +#include <linux/int_log.h> | |
| 15 | 15 | #include <media/dvb_frontend.h> |
| 16 | 16 | |
| 17 | 17 | #include "dib9000.h" |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <media/dvb_frontend.h> |
| 21 | 21 | #include "drxk.h" |
| 22 | 22 | #include "drxk_hard.h" |
| 23 | −#include <media/dvb_math.h> | |
| 23 | +#include <linux/int_log.h> | |
| 24 | 24 | |
| 25 | 25 | static int power_down_dvbt(struct drxk_state *state, bool set_power_mode); |
| 26 | 26 | static int power_down_qam(struct drxk_state *state); |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <asm/div64.h> |
| 11 | 11 | #include <linux/dvb/frontend.h> |
| 12 | 12 | #include <linux/slab.h> |
| 13 | −#include <media/dvb_math.h> | |
| 13 | +#include <linux/int_log.h> | |
| 14 | 14 | #include "lgdt3305.h" |
| 15 | 15 | |
| 16 | 16 | static int debug; |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <asm/div64.h> |
| 13 | 13 | #include <linux/kernel.h> |
| 14 | 14 | #include <linux/dvb/frontend.h> |
| 15 | −#include <media/dvb_math.h> | |
| 15 | +#include <linux/int_log.h> | |
| 16 | 16 | #include "lgdt3306a.h" |
| 17 | 17 | #include <linux/i2c-mux.h> |
| 18 | 18 | |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <asm/byteorder.h> |
| 29 | 29 | |
| 30 | 30 | #include <media/dvb_frontend.h> |
| 31 | −#include <media/dvb_math.h> | |
| 31 | +#include <linux/int_log.h> | |
| 32 | 32 | #include "lgdt330x_priv.h" |
| 33 | 33 | #include "lgdt330x.h" |
| 34 | 34 | |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <media/dvb_frontend.h> |
| 12 | 12 | #include "m88ds3103.h" |
| 13 | −#include <media/dvb_math.h> | |
| 13 | +#include <linux/int_log.h> | |
| 14 | 14 | #include <linux/firmware.h> |
| 15 | 15 | #include <linux/i2c-mux.h> |
| 16 | 16 | #include <linux/regmap.h> |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/gpio/consumer.h> |
| 11 | 11 | #include <linux/of_device.h> |
| 12 | 12 | #include <linux/regmap.h> |
| 13 | −#include <media/dvb_math.h> | |
| 13 | +#include <linux/int_log.h> | |
| 14 | 14 | |
| 15 | 15 | #include "mn88443x.h" |
| 16 | 16 | |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define MN88472_PRIV_H |
| 10 | 10 | |
| 11 | 11 | #include <media/dvb_frontend.h> |
| 12 | −#include <media/dvb_math.h> | |
| 12 | +#include <linux/int_log.h> | |
| 13 | 13 | #include "mn88472.h" |
| 14 | 14 | #include <linux/firmware.h> |
| 15 | 15 | #include <linux/regmap.h> |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define MN88473_PRIV_H |
| 10 | 10 | |
| 11 | 11 | #include <media/dvb_frontend.h> |
| 12 | −#include <media/dvb_math.h> | |
| 12 | +#include <linux/int_log.h> | |
| 13 | 13 | #include "mn88473.h" |
| 14 | 14 | #include <linux/math64.h> |
| 15 | 15 | #include <linux/firmware.h> |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/slab.h> |
| 28 | 28 | #include <asm/byteorder.h> |
| 29 | 29 | |
| 30 | −#include <media/dvb_math.h> | |
| 30 | +#include <linux/int_log.h> | |
| 31 | 31 | #include <media/dvb_frontend.h> |
| 32 | 32 | #include "or51132.h" |
| 33 | 33 | |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/slab.h> |
| 27 | 27 | #include <asm/byteorder.h> |
| 28 | 28 | |
| 29 | −#include <media/dvb_math.h> | |
| 29 | +#include <linux/int_log.h> | |
| 30 | 30 | #include <media/dvb_frontend.h> |
| 31 | 31 | #include "or51211.h" |
| 32 | 32 | |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define RTL2830_PRIV_H |
| 10 | 10 | |
| 11 | 11 | #include <media/dvb_frontend.h> |
| 12 | −#include <media/dvb_math.h> | |
| 12 | +#include <linux/int_log.h> | |
| 13 | 13 | #include "rtl2830.h" |
| 14 | 14 | #include <linux/i2c-mux.h> |
| 15 | 15 | #include <linux/math64.h> |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/bitops.h> |
| 15 | 15 | |
| 16 | 16 | #include <media/dvb_frontend.h> |
| 17 | −#include <media/dvb_math.h> | |
| 17 | +#include <linux/int_log.h> | |
| 18 | 18 | #include "rtl2832.h" |
| 19 | 19 | |
| 20 | 20 | struct rtl2832_dev { |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/regmap.h> |
| 20 | 20 | |
| 21 | 21 | #include <media/dvb_frontend.h> |
| 22 | −#include <media/dvb_math.h> | |
| 22 | +#include <linux/int_log.h> | |
| 23 | 23 | #include "si2165_priv.h" |
| 24 | 24 | #include "si2165.h" |
| 25 | 25 | |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/slab.h> |
| 16 | 16 | #include <linux/i2c.h> |
| 17 | 17 | |
| 18 | −#include <media/dvb_math.h> | |
| 18 | +#include <linux/int_log.h> | |
| 19 | 19 | |
| 20 | 20 | #include "stv0367.h" |
| 21 | 21 | #include "stv0367_defs.h" |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/kernel.h> |
| 22 | 22 | #include <linux/math64.h> |
| 23 | 23 | #include <linux/dvb/frontend.h> |
| 24 | −#include <media/dvb_math.h> | |
| 24 | +#include <linux/int_log.h> | |
| 25 | 25 | #include "tc90522.h" |
| 26 | 26 | |
| 27 | 27 | #define TC90522_I2C_THRU_REG 0xfe |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/math64.h> |
| 17 | 17 | #include <asm/div64.h> |
| 18 | 18 | #include <media/dvb_frontend.h> |
| 19 | −#include <media/dvb_math.h> | |
| 19 | +#include <linux/int_log.h> | |
| 20 | 20 | #include "tda10048.h" |
| 21 | 21 | |
| 22 | 22 | #define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw" |
| @@ -204,9 +204,9 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss) · 203 unmodified lines | ||
| 204 | 204 | return idx * G723_FRAMES_PER_PAGE; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | −static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel, | |
| 208 | − unsigned long pos, void __user *dst, | |
| 209 | − unsigned long count) | |
| 207 | +static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, | |
| 208 | + unsigned long pos, struct iov_iter *dst, | |
| 209 | + unsigned long count) | |
| 210 | 210 | { |
| 211 | 211 | struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); |
| 212 | 212 | struct solo_dev *solo_dev = solo_pcm->solo_dev; |
| @@ -223,35 +223,9 @@ static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel, · 10 unmodified lines | ||
| 223 | 223 | if (err) |
| 224 | 224 | return err; |
| 225 | 225 | |
| 226 | − if (copy_to_user(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES)) | |
| 226 | + if (copy_to_iter(solo_pcm->g723_buf, G723_PERIOD_BYTES, dst) != | |
| 227 | + G723_PERIOD_BYTES) | |
| 227 | 228 | return -EFAULT; |
| 228 | − dst += G723_PERIOD_BYTES; | |
| 229 | − } | |
| 230 | − | |
| 231 | − return 0; | |
| 232 | −} | |
| 233 | − | |
| 234 | −static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel, | |
| 235 | − unsigned long pos, void *dst, | |
| 236 | − unsigned long count) | |
| 237 | −{ | |
| 238 | − struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); | |
| 239 | − struct solo_dev *solo_dev = solo_pcm->solo_dev; | |
| 240 | − int err, i; | |
| 241 | − | |
| 242 | − for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) { | |
| 243 | − int page = (pos / G723_FRAMES_PER_PAGE) + i; | |
| 244 | − | |
| 245 | − err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma, | |
| 246 | − SOLO_G723_EXT_ADDR(solo_dev) + | |
| 247 | − (page * G723_PERIOD_BLOCK) + | |
| 248 | − (ss->number * G723_PERIOD_BYTES), | |
| 249 | − G723_PERIOD_BYTES, 0, 0); | |
| 250 | − if (err) | |
| 251 | − return err; | |
| 252 | − | |
| 253 | − memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES); | |
| 254 | − dst += G723_PERIOD_BYTES; | |
| 255 | 229 | } |
| 256 | 230 | |
| 257 | 231 | return 0; |
| @@ -263,8 +237,7 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = { · 5 unmodified lines | ||
| 263 | 237 | .prepare = snd_solo_pcm_prepare, |
| 264 | 238 | .trigger = snd_solo_pcm_trigger, |
| 265 | 239 | .pointer = snd_solo_pcm_pointer, |
| 266 | − .copy_user = snd_solo_pcm_copy_user, | |
| 267 | − .copy_kernel = snd_solo_pcm_copy_kernel, | |
| 240 | + .copy = snd_solo_pcm_copy, | |
| 268 | 241 | }; |
| 269 | 242 | |
| 270 | 243 | static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol, |
| @@ -807,7 +807,6 @@ int gbaudio_register_module(struct gbaudio_module_info *module) · 806 unmodified lines | ||
| 807 | 807 | { |
| 808 | 808 | int ret; |
| 809 | 809 | struct snd_soc_component *comp; |
| 810 | − struct snd_card *card; | |
| 811 | 810 | struct gbaudio_jack *jack = NULL; |
| 812 | 811 | |
| 813 | 812 | if (!gbcodec) { |
| @@ -816,21 +815,20 @@ int gbaudio_register_module(struct gbaudio_module_info *module) · 2 unmodified lines | ||
| 816 | 815 | } |
| 817 | 816 | |
| 818 | 817 | comp = gbcodec->component; |
| 819 | − card = comp->card->snd_card; | |
| 820 | 818 | |
| 821 | − down_write(&card->controls_rwsem); | |
| 819 | + mutex_lock(&gbcodec->register_mutex); | |
| 822 | 820 | |
| 823 | 821 | if (module->num_dais) { |
| 824 | 822 | dev_err(gbcodec->dev, |
| 825 | 823 | "%d:DAIs not supported via gbcodec driver\n", |
| 826 | 824 | module->num_dais); |
| 827 | − up_write(&card->controls_rwsem); | |
| 825 | + mutex_unlock(&gbcodec->register_mutex); | |
| 828 | 826 | return -EINVAL; |
| 829 | 827 | } |
| 830 | 828 | |
| 831 | 829 | ret = gbaudio_init_jack(module, comp->card); |
| 832 | 830 | if (ret) { |
| 833 | − up_write(&card->controls_rwsem); | |
| 831 | + mutex_unlock(&gbcodec->register_mutex); | |
| 834 | 832 | return ret; |
| 835 | 833 | } |
| 836 | 834 | |
| @@ -867,7 +865,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) · 30 unmodified lines | ||
| 867 | 865 | ret = snd_soc_dapm_new_widgets(comp->card); |
| 868 | 866 | dev_dbg(comp->dev, "Registered %s module\n", module->name); |
| 869 | 867 | |
| 870 | − up_write(&card->controls_rwsem); | |
| 868 | + mutex_unlock(&gbcodec->register_mutex); | |
| 871 | 869 | return ret; |
| 872 | 870 | } |
| 873 | 871 | EXPORT_SYMBOL(gbaudio_register_module); |
| @@ -935,13 +933,12 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) · 61 unmodified lines | ||
| 935 | 933 | void gbaudio_unregister_module(struct gbaudio_module_info *module) |
| 936 | 934 | { |
| 937 | 935 | struct snd_soc_component *comp = gbcodec->component; |
| 938 | − struct snd_card *card = comp->card->snd_card; | |
| 939 | 936 | struct gbaudio_jack *jack, *n; |
| 940 | 937 | int mask; |
| 941 | 938 | |
| 942 | 939 | dev_dbg(comp->dev, "Unregister %s module\n", module->name); |
| 943 | 940 | |
| 944 | − down_write(&card->controls_rwsem); | |
| 941 | + mutex_lock(&gbcodec->register_mutex); | |
| 945 | 942 | mutex_lock(&gbcodec->lock); |
| 946 | 943 | gbaudio_codec_cleanup(module); |
| 947 | 944 | list_del(&module->list); |
| @@ -978,10 +975,8 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) · 30 unmodified lines | ||
| 978 | 975 | dev_dbg(comp->dev, "Removing %d controls\n", |
| 979 | 976 | module->num_controls); |
| 980 | 977 | /* release control semaphore */ |
| 981 | − up_write(&card->controls_rwsem); | |
| 982 | 978 | gbaudio_remove_component_controls(comp, module->controls, |
| 983 | 979 | module->num_controls); |
| 984 | − down_write(&card->controls_rwsem); | |
| 985 | 980 | } |
| 986 | 981 | if (module->dapm_widgets) { |
| 987 | 982 | dev_dbg(comp->dev, "Removing %d widgets\n", |
| @@ -992,7 +987,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) · 4 unmodified lines | ||
| 992 | 987 | |
| 993 | 988 | dev_dbg(comp->dev, "Unregistered %s module\n", module->name); |
| 994 | 989 | |
| 995 | − up_write(&card->controls_rwsem); | |
| 990 | + mutex_unlock(&gbcodec->register_mutex); | |
| 996 | 991 | } |
| 997 | 992 | EXPORT_SYMBOL(gbaudio_unregister_module); |
| 998 | 993 | |
| @@ -1012,6 +1007,7 @@ static int gbcodec_probe(struct snd_soc_component *comp) · 13 unmodified lines | ||
| 1012 | 1007 | info->dev = comp->dev; |
| 1013 | 1008 | INIT_LIST_HEAD(&info->module_list); |
| 1014 | 1009 | mutex_init(&info->lock); |
| 1010 | + mutex_init(&info->register_mutex); | |
| 1015 | 1011 | INIT_LIST_HEAD(&info->dai_list); |
| 1016 | 1012 | |
| 1017 | 1013 | /* init dai_list used to maintain runtime stream info */ |
| @@ -71,6 +71,7 @@ struct gbaudio_codec_info { · 70 unmodified lines | ||
| 71 | 71 | /* to maintain runtime stream params for each DAI */ |
| 72 | 72 | struct list_head dai_list; |
| 73 | 73 | struct mutex lock; |
| 74 | + struct mutex register_mutex; | |
| 74 | 75 | }; |
| 75 | 76 | |
| 76 | 77 | struct gbaudio_widget { |
| @@ -149,7 +149,6 @@ static int gbaudio_remove_controls(struct snd_card *card, struct device *dev, · 148 unmodified lines | ||
| 149 | 149 | for (i = 0; i < num_controls; i++) { |
| 150 | 150 | const struct snd_kcontrol_new *control = &controls[i]; |
| 151 | 151 | struct snd_ctl_elem_id id; |
| 152 | − struct snd_kcontrol *kctl; | |
| 153 | 152 | |
| 154 | 153 | if (prefix) |
| 155 | 154 | snprintf(id.name, sizeof(id.name), "%s %s", prefix, |
| @@ -161,17 +160,10 @@ static int gbaudio_remove_controls(struct snd_card *card, struct device *dev, · 5 unmodified lines | ||
| 161 | 160 | id.device = control->device; |
| 162 | 161 | id.subdevice = control->subdevice; |
| 163 | 162 | id.index = control->index; |
| 164 | − kctl = snd_ctl_find_id(card, &id); | |
| 165 | − if (!kctl) { | |
| 166 | − dev_err(dev, "Failed to find %s\n", control->name); | |
| 167 | − continue; | |
| 168 | − } | |
| 169 | − err = snd_ctl_remove(card, kctl); | |
| 170 | − if (err < 0) { | |
| 163 | + err = snd_ctl_remove_id(card, &id); | |
| 164 | + if (err < 0) | |
| 171 | 165 | dev_err(dev, "%d: Failed to remove %s\n", err, |
| 172 | 166 | control->name); |
| 173 | − continue; | |
| 174 | − } | |
| 175 | 167 | } |
| 176 | 168 | return 0; |
| 177 | 169 | } |
| @@ -181,11 +173,7 @@ int gbaudio_remove_component_controls(struct snd_soc_component *component, · 3 unmodified lines | ||
| 181 | 173 | unsigned int num_controls) |
| 182 | 174 | { |
| 183 | 175 | struct snd_card *card = component->card->snd_card; |
| 184 | − int err; | |
| 185 | 176 | |
| 186 | − down_write(&card->controls_rwsem); | |
| 187 | − err = gbaudio_remove_controls(card, component->dev, controls, | |
| 188 | − num_controls, component->name_prefix); | |
| 189 | − up_write(&card->controls_rwsem); | |
| 190 | − return err; | |
| 177 | + return gbaudio_remove_controls(card, component->dev, controls, | |
| 178 | + num_controls, component->name_prefix); | |
| 191 | 179 | } |
| @@ -349,6 +349,7 @@ unsigned long devm_get_free_pages(struct device *dev, · 348 unmodified lines | ||
| 349 | 349 | gfp_t gfp_mask, unsigned int order); |
| 350 | 350 | void devm_free_pages(struct device *dev, unsigned long addr); |
| 351 | 351 | |
| 352 | +#ifdef CONFIG_HAS_IOMEM | |
| 352 | 353 | void __iomem *devm_ioremap_resource(struct device *dev, |
| 353 | 354 | const struct resource *res); |
| 354 | 355 | void __iomem *devm_ioremap_resource_wc(struct device *dev, |
| @@ -357,6 +358,31 @@ void __iomem *devm_ioremap_resource_wc(struct device *dev, · 2 unmodified lines | ||
| 357 | 358 | void __iomem *devm_of_iomap(struct device *dev, |
| 358 | 359 | struct device_node *node, int index, |
| 359 | 360 | resource_size_t *size); |
| 361 | +#else | |
| 362 | + | |
| 363 | +static inline | |
| 364 | +void __iomem *devm_ioremap_resource(struct device *dev, | |
| 365 | + const struct resource *res) | |
| 366 | +{ | |
| 367 | + return ERR_PTR(-EINVAL); | |
| 368 | +} | |
| 369 | + | |
| 370 | +static inline | |
| 371 | +void __iomem *devm_ioremap_resource_wc(struct device *dev, | |
| 372 | + const struct resource *res) | |
| 373 | +{ | |
| 374 | + return ERR_PTR(-EINVAL); | |
| 375 | +} | |
| 376 | + | |
| 377 | +static inline | |
| 378 | +void __iomem *devm_of_iomap(struct device *dev, | |
| 379 | + struct device_node *node, int index, | |
| 380 | + resource_size_t *size) | |
| 381 | +{ | |
| 382 | + return ERR_PTR(-EINVAL); | |
| 383 | +} | |
| 384 | + | |
| 385 | +#endif | |
| 360 | 386 | |
| 361 | 387 | /* allows to add/remove a custom action to devres stack */ |
| 362 | 388 | void devm_remove_action(struct device *dev, void (*action)(void *), void *data); |
| @@ -37,17 +37,11 @@ struct imx_dsp_ipc { · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data) |
| 39 | 39 | { |
| 40 | − if (!ipc) | |
| 41 | − return; | |
| 42 | − | |
| 43 | 40 | ipc->private_data = data; |
| 44 | 41 | } |
| 45 | 42 | |
| 46 | 43 | static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc) |
| 47 | 44 | { |
| 48 | − if (!ipc) | |
| 49 | − return NULL; | |
| 50 | − | |
| 51 | 45 | return ipc->private_data; |
| 52 | 46 | } |
| 53 | 47 | |
| @@ -46,17 +46,11 @@ struct mtk_adsp_ipc { · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | static inline void mtk_adsp_ipc_set_data(struct mtk_adsp_ipc *ipc, void *data) |
| 48 | 48 | { |
| 49 | − if (!ipc) | |
| 50 | − return; | |
| 51 | − | |
| 52 | 49 | ipc->private_data = data; |
| 53 | 50 | } |
| 54 | 51 | |
| 55 | 52 | static inline void *mtk_adsp_ipc_get_data(struct mtk_adsp_ipc *ipc) |
| 56 | 53 | { |
| 57 | − if (!ipc) | |
| 58 | − return NULL; | |
| 59 | − | |
| 60 | 54 | return ipc->private_data; |
| 61 | 55 | } |
| 62 | 56 | |
| @@ -201,8 +201,9 @@ struct iio_dev · 200 unmodified lines | ||
| 201 | 201 | * @chan: The channel being queried. |
| 202 | 202 | * @val: Value read back. |
| 203 | 203 | * |
| 204 | − * Note raw reads from iio channels are in adc counts and hence | |
| 205 | − * scale will need to be applied if standard units required. | |
| 204 | + * Note, if standard units are required, raw reads from iio channels | |
| 205 | + * need the offset (default 0) and scale (default 1) to be applied | |
| 206 | + * as (raw + offset) * scale. | |
| 206 | 207 | */ |
| 207 | 208 | int iio_read_channel_raw(struct iio_channel *chan, |
| 208 | 209 | int *val); |
| @@ -212,8 +213,9 @@ int iio_read_channel_raw(struct iio_channel *chan, · 3 unmodified lines | ||
| 212 | 213 | * @chan: The channel being queried. |
| 213 | 214 | * @val: Value read back. |
| 214 | 215 | * |
| 215 | − * Note raw reads from iio channels are in adc counts and hence | |
| 216 | − * scale will need to be applied if standard units required. | |
| 216 | + * Note, if standard units are required, raw reads from iio channels | |
| 217 | + * need the offset (default 0) and scale (default 1) to be applied | |
| 218 | + * as (raw + offset) * scale. | |
| 217 | 219 | * |
| 218 | 220 | * In opposit to the normal iio_read_channel_raw this function |
| 219 | 221 | * returns the average of multiple reads. |
| @@ -281,8 +283,9 @@ int iio_read_channel_attribute(struct iio_channel *chan, int *val, · 61 unmodified lines | ||
| 281 | 283 | * @chan: The channel being queried. |
| 282 | 284 | * @val: Value being written. |
| 283 | 285 | * |
| 284 | − * Note raw writes to iio channels are in dac counts and hence | |
| 285 | − * scale will need to be applied if standard units required. | |
| 286 | + * Note that for raw writes to iio channels, if the value provided is | |
| 287 | + * in standard units, the affect of the scale and offset must be removed | |
| 288 | + * as (value / scale) - offset. | |
| 286 | 289 | */ |
| 287 | 290 | int iio_write_channel_raw(struct iio_channel *chan, int val); |
| 288 | 291 | |
| @@ -292,11 +295,24 @@ int iio_write_channel_raw(struct iio_channel *chan, int val); · 3 unmodified lines | ||
| 292 | 295 | * @chan: The channel being queried. |
| 293 | 296 | * @val: Value read back. |
| 294 | 297 | * |
| 295 | − * Note raw reads from iio channels are in adc counts and hence | |
| 296 | − * scale will need to be applied if standard units are required. | |
| 298 | + * Note, if standard units are required, raw reads from iio channels | |
| 299 | + * need the offset (default 0) and scale (default 1) to be applied | |
| 300 | + * as (raw + offset) * scale. | |
| 297 | 301 | */ |
| 298 | 302 | int iio_read_max_channel_raw(struct iio_channel *chan, int *val); |
| 299 | 303 | |
| 304 | +/** | |
| 305 | + * iio_read_min_channel_raw() - read minimum available raw value from a given | |
| 306 | + * channel, i.e. the minimum possible value. | |
| 307 | + * @chan: The channel being queried. | |
| 308 | + * @val: Value read back. | |
| 309 | + * | |
| 310 | + * Note, if standard units are required, raw reads from iio channels | |
| 311 | + * need the offset (default 0) and scale (default 1) to be applied | |
| 312 | + * as (raw + offset) * scale. | |
| 313 | + */ | |
| 314 | +int iio_read_min_channel_raw(struct iio_channel *chan, int *val); | |
| 315 | + | |
| 300 | 316 | /** |
| 301 | 317 | * iio_read_avail_channel_raw() - read available raw values from a given channel |
| 302 | 318 | * @chan: The channel being queried. |
| @@ -308,8 +324,9 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val); · 5 unmodified lines | ||
| 308 | 324 | * For ranges, three vals are always returned; min, step and max. |
| 309 | 325 | * For lists, all the possible values are enumerated. |
| 310 | 326 | * |
| 311 | − * Note raw available values from iio channels are in adc counts and | |
| 312 | − * hence scale will need to be applied if standard units are required. | |
| 327 | + * Note, if standard units are required, raw available values from iio | |
| 328 | + * channels need the offset (default 0) and scale (default 1) to be applied | |
| 329 | + * as (raw + offset) * scale. | |
| 313 | 330 | */ |
| 314 | 331 | int iio_read_avail_channel_raw(struct iio_channel *chan, |
| 315 | 332 | const int **vals, int *length); |
| @@ -1,22 +1,12 @@ | ||
| 1 | +/* SPDX-License-Identifier: LGPL-2.1-or-later */ | |
| 1 | 2 | /* |
| 2 | − * dvb-math provides some complex fixed-point math | |
| 3 | − * operations shared between the dvb related stuff | |
| 3 | + * Provides fixed-point logarithm operations. | |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) |
| 6 | − * | |
| 7 | − * This library is free software; you can redistribute it and/or modify | |
| 8 | − * it under the terms of the GNU Lesser General Public License as | |
| 9 | − * published by the Free Software Foundation; either version 2.1 of | |
| 10 | − * the License, or (at your option) any later version. | |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU Lesser General Public License for more details. | |
| 16 | 6 | */ |
| 17 | 7 | |
| 18 | −#ifndef __DVB_MATH_H | |
| 19 | −#define __DVB_MATH_H | |
| 8 | +#ifndef __LINUX_INT_LOG_H | |
| 9 | +#define __LINUX_INT_LOG_H | |
| 20 | 10 | |
| 21 | 11 | #include <linux/types.h> |
| 22 | 12 | |
| @@ -134,6 +134,70 @@ · 133 unmodified lines | ||
| 134 | 134 | */ |
| 135 | 135 | #define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >) |
| 136 | 136 | |
| 137 | +/* | |
| 138 | + * Remove a const qualifier from integer types | |
| 139 | + * _Generic(foo, type-name: association, ..., default: association) performs a | |
| 140 | + * comparison against the foo type (not the qualified type). | |
| 141 | + * Do not use the const keyword in the type-name as it will not match the | |
| 142 | + * unqualified type of foo. | |
| 143 | + */ | |
| 144 | +#define __unconst_integer_type_cases(type) \ | |
| 145 | + unsigned type: (unsigned type)0, \ | |
| 146 | + signed type: (signed type)0 | |
| 147 | + | |
| 148 | +#define __unconst_integer_typeof(x) typeof( \ | |
| 149 | + _Generic((x), \ | |
| 150 | + char: (char)0, \ | |
| 151 | + __unconst_integer_type_cases(char), \ | |
| 152 | + __unconst_integer_type_cases(short), \ | |
| 153 | + __unconst_integer_type_cases(int), \ | |
| 154 | + __unconst_integer_type_cases(long), \ | |
| 155 | + __unconst_integer_type_cases(long long), \ | |
| 156 | + default: (x))) | |
| 157 | + | |
| 158 | +/* | |
| 159 | + * Do not check the array parameter using __must_be_array(). | |
| 160 | + * In the following legit use-case where the "array" passed is a simple pointer, | |
| 161 | + * __must_be_array() will return a failure. | |
| 162 | + * --- 8< --- | |
| 163 | + * int *buff | |
| 164 | + * ... | |
| 165 | + * min = min_array(buff, nb_items); | |
| 166 | + * --- 8< --- | |
| 167 | + * | |
| 168 | + * The first typeof(&(array)[0]) is needed in order to support arrays of both | |
| 169 | + * 'int *buff' and 'int buff[N]' types. | |
| 170 | + * | |
| 171 | + * The array can be an array of const items. | |
| 172 | + * typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order | |
| 173 | + * to discard the const qualifier for the __element variable. | |
| 174 | + */ | |
| 175 | +#define __minmax_array(op, array, len) ({ \ | |
| 176 | + typeof(&(array)[0]) __array = (array); \ | |
| 177 | + typeof(len) __len = (len); \ | |
| 178 | + __unconst_integer_typeof(__array[0]) __element = __array[--__len]; \ | |
| 179 | + while (__len--) \ | |
| 180 | + __element = op(__element, __array[__len]); \ | |
| 181 | + __element; }) | |
| 182 | + | |
| 183 | +/** | |
| 184 | + * min_array - return minimum of values present in an array | |
| 185 | + * @array: array | |
| 186 | + * @len: array length | |
| 187 | + * | |
| 188 | + * Note that @len must not be zero (empty array). | |
| 189 | + */ | |
| 190 | +#define min_array(array, len) __minmax_array(min, array, len) | |
| 191 | + | |
| 192 | +/** | |
| 193 | + * max_array - return maximum of values present in an array | |
| 194 | + * @array: array | |
| 195 | + * @len: array length | |
| 196 | + * | |
| 197 | + * Note that @len must not be zero (empty array). | |
| 198 | + */ | |
| 199 | +#define max_array(array, len) __minmax_array(max, array, len) | |
| 200 | + | |
| 137 | 201 | /** |
| 138 | 202 | * clamp_t - return a value clamped to a given range using a given type |
| 139 | 203 | * @type: the type of variable to use |
| @@ -2646,6 +2646,7 @@ · 2645 unmodified lines | ||
| 2646 | 2646 | |
| 2647 | 2647 | #define PCI_VENDOR_ID_INTEL 0x8086 |
| 2648 | 2648 | #define PCI_DEVICE_ID_INTEL_EESSC 0x0008 |
| 2649 | +#define PCI_DEVICE_ID_INTEL_HDA_CML_LP 0x02c8 | |
| 2649 | 2650 | #define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 |
| 2650 | 2651 | #define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 |
| 2651 | 2652 | #define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 |
| @@ -2661,8 +2662,10 @@ · 9 unmodified lines | ||
| 2661 | 2662 | #define PCI_DEVICE_ID_INTEL_82424 0x0483 |
| 2662 | 2663 | #define PCI_DEVICE_ID_INTEL_82378 0x0484 |
| 2663 | 2664 | #define PCI_DEVICE_ID_INTEL_82425 0x0486 |
| 2665 | +#define PCI_DEVICE_ID_INTEL_HDA_CML_H 0x06c8 | |
| 2664 | 2666 | #define PCI_DEVICE_ID_INTEL_MRST_SD0 0x0807 |
| 2665 | 2667 | #define PCI_DEVICE_ID_INTEL_MRST_SD1 0x0808 |
| 2668 | +#define PCI_DEVICE_ID_INTEL_HDA_OAKTRAIL 0x080a | |
| 2666 | 2669 | #define PCI_DEVICE_ID_INTEL_MFD_SD 0x0820 |
| 2667 | 2670 | #define PCI_DEVICE_ID_INTEL_MFD_SDIO1 0x0821 |
| 2668 | 2671 | #define PCI_DEVICE_ID_INTEL_MFD_SDIO2 0x0822 |
| @@ -2672,15 +2675,19 @@ · 3 unmodified lines | ||
| 2672 | 2675 | #define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095e |
| 2673 | 2676 | #define PCI_DEVICE_ID_INTEL_I960 0x0960 |
| 2674 | 2677 | #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 |
| 2678 | +#define PCI_DEVICE_ID_INTEL_HDA_HSW_0 0x0a0c | |
| 2679 | +#define PCI_DEVICE_ID_INTEL_HDA_HSW_2 0x0c0c | |
| 2675 | 2680 | #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 |
| 2681 | +#define PCI_DEVICE_ID_INTEL_HDA_HSW_3 0x0d0c | |
| 2682 | +#define PCI_DEVICE_ID_INTEL_HDA_BYT 0x0f04 | |
| 2683 | +#define PCI_DEVICE_ID_INTEL_SST_BYT 0x0f28 | |
| 2676 | 2684 | #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 |
| 2677 | 2685 | #define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085 |
| 2678 | 2686 | #define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108f |
| 2679 | 2687 | #define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 |
| 2680 | 2688 | #define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 |
| 2689 | +#define PCI_DEVICE_ID_INTEL_SST_TNG 0x119a | |
| 2681 | 2690 | #define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 |
| 2682 | −#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 | |
| 2683 | −#define PCI_DEVICE_ID_INTEL_7205_0 0x255d | |
| 2684 | 2691 | #define PCI_DEVICE_ID_INTEL_82437 0x122d |
| 2685 | 2692 | #define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e |
| 2686 | 2693 | #define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230 |
| @@ -2706,20 +2713,26 @@ · 19 unmodified lines | ||
| 2706 | 2713 | #define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 |
| 2707 | 2714 | #define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 |
| 2708 | 2715 | #define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 |
| 2716 | +#define PCI_DEVICE_ID_INTEL_HDA_BDW 0x160c | |
| 2709 | 2717 | #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 |
| 2710 | 2718 | #define PCI_DEVICE_ID_INTEL_QAT_C3XXX 0x19e2 |
| 2711 | 2719 | #define PCI_DEVICE_ID_INTEL_QAT_C3XXX_VF 0x19e3 |
| 2712 | 2720 | #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 |
| 2713 | 2721 | #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 |
| 2714 | 2722 | #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 |
| 2723 | +#define PCI_DEVICE_ID_INTEL_HDA_CPT 0x1c20 | |
| 2715 | 2724 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41 |
| 2716 | 2725 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f |
| 2726 | +#define PCI_DEVICE_ID_INTEL_HDA_PBG 0x1d20 | |
| 2717 | 2727 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 |
| 2718 | 2728 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 |
| 2729 | +#define PCI_DEVICE_ID_INTEL_HDA_PPT 0x1e20 | |
| 2719 | 2730 | #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31 |
| 2720 | 2731 | #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40 |
| 2721 | 2732 | #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f |
| 2722 | 2733 | #define PCI_DEVICE_ID_INTEL_VMD_201D 0x201d |
| 2734 | +#define PCI_DEVICE_ID_INTEL_HDA_BSW 0x2284 | |
| 2735 | +#define PCI_DEVICE_ID_INTEL_SST_BSW 0x22a8 | |
| 2723 | 2736 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 |
| 2724 | 2737 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f |
| 2725 | 2738 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 |
| @@ -2774,6 +2787,8 @@ · 48 unmodified lines | ||
| 2774 | 2787 | #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 |
| 2775 | 2788 | #define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 |
| 2776 | 2789 | #define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c |
| 2790 | +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 | |
| 2791 | +#define PCI_DEVICE_ID_INTEL_7205_0 0x255d | |
| 2777 | 2792 | #define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 |
| 2778 | 2793 | #define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 |
| 2779 | 2794 | #define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 |
| @@ -2795,12 +2810,14 @@ · 15 unmodified lines | ||
| 2795 | 2810 | #define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 |
| 2796 | 2811 | #define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 |
| 2797 | 2812 | #define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 |
| 2813 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH6 0x2668 | |
| 2798 | 2814 | #define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a |
| 2799 | 2815 | #define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d |
| 2800 | 2816 | #define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e |
| 2801 | 2817 | #define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f |
| 2802 | 2818 | #define PCI_DEVICE_ID_INTEL_ESB2_0 0x2670 |
| 2803 | 2819 | #define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698 |
| 2820 | +#define PCI_DEVICE_ID_INTEL_HDA_ESB2 0x269a | |
| 2804 | 2821 | #define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b |
| 2805 | 2822 | #define PCI_DEVICE_ID_INTEL_ESB2_18 0x269e |
| 2806 | 2823 | #define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 |
| @@ -2808,11 +2825,12 @@ · 1 unmodified line | ||
| 2808 | 2825 | #define PCI_DEVICE_ID_INTEL_3000_HB 0x2778 |
| 2809 | 2826 | #define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27a0 |
| 2810 | 2827 | #define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27a2 |
| 2828 | +#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 | |
| 2811 | 2829 | #define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 |
| 2812 | 2830 | #define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 |
| 2813 | −#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 | |
| 2814 | 2831 | #define PCI_DEVICE_ID_INTEL_TGP_LPC 0x27bc |
| 2815 | 2832 | #define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd |
| 2833 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH7 0x27d8 | |
| 2816 | 2834 | #define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da |
| 2817 | 2835 | #define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd |
| 2818 | 2836 | #define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de |
| @@ -2823,17 +2841,20 @@ · 4 unmodified lines | ||
| 2823 | 2841 | #define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814 |
| 2824 | 2842 | #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 |
| 2825 | 2843 | #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e |
| 2844 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH8 0x284b | |
| 2826 | 2845 | #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 |
| 2827 | 2846 | #define PCI_DEVICE_ID_INTEL_VMD_28C0 0x28c0 |
| 2828 | 2847 | #define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 |
| 2829 | −#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 | |
| 2830 | 2848 | #define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 |
| 2831 | 2849 | #define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913 |
| 2832 | 2850 | #define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914 |
| 2833 | −#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919 | |
| 2834 | −#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 | |
| 2835 | 2851 | #define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 |
| 2852 | +#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 | |
| 2836 | 2853 | #define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 |
| 2854 | +#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919 | |
| 2855 | +#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 | |
| 2856 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH9_0 0x293e | |
| 2857 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH9_1 0x293f | |
| 2837 | 2858 | #define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18 |
| 2838 | 2859 | #define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19 |
| 2839 | 2860 | #define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a |
| @@ -2850,8 +2871,8 @@ · 10 unmodified lines | ||
| 2850 | 2871 | #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31 |
| 2851 | 2872 | #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 |
| 2852 | 2873 | #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 |
| 2853 | −#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 | |
| 2854 | 2874 | #define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 |
| 2875 | +#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 | |
| 2855 | 2876 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50 |
| 2856 | 2877 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51 |
| 2857 | 2878 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70 |
| @@ -2885,6 +2906,7 @@ · 27 unmodified lines | ||
| 2885 | 2906 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1 |
| 2886 | 2907 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2 |
| 2887 | 2908 | #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3 |
| 2909 | +#define PCI_DEVICE_ID_INTEL_HDA_GML 0x3198 | |
| 2888 | 2910 | #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 |
| 2889 | 2911 | #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 |
| 2890 | 2912 | #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a |
| @@ -2895,12 +2917,13 @@ · 4 unmodified lines | ||
| 2895 | 2917 | #define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431 |
| 2896 | 2918 | #define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432 |
| 2897 | 2919 | #define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433 |
| 2920 | +#define PCI_DEVICE_ID_INTEL_HDA_ICL_LP 0x34c8 | |
| 2898 | 2921 | #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 |
| 2899 | 2922 | #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 |
| 2900 | −#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c | |
| 2901 | −#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e | |
| 2902 | 2923 | #define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 |
| 2903 | 2924 | #define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 |
| 2925 | +#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c | |
| 2926 | +#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e | |
| 2904 | 2927 | #define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 |
| 2905 | 2928 | #define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 |
| 2906 | 2929 | #define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595 |
| @@ -2910,11 +2933,11 @@ · 3 unmodified lines | ||
| 2910 | 2933 | #define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 |
| 2911 | 2934 | #define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a |
| 2912 | 2935 | #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e |
| 2936 | +#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b | |
| 2937 | +#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c | |
| 2913 | 2938 | #define PCI_DEVICE_ID_INTEL_I7300_MCH_ERR 0x360c |
| 2914 | 2939 | #define PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 0x360f |
| 2915 | 2940 | #define PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 0x3610 |
| 2916 | −#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b | |
| 2917 | −#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c | |
| 2918 | 2941 | #define PCI_DEVICE_ID_INTEL_IOAT_JSF0 0x3710 |
| 2919 | 2942 | #define PCI_DEVICE_ID_INTEL_IOAT_JSF1 0x3711 |
| 2920 | 2943 | #define PCI_DEVICE_ID_INTEL_IOAT_JSF2 0x3712 |
| @@ -2927,14 +2950,19 @@ · 6 unmodified lines | ||
| 2927 | 2950 | #define PCI_DEVICE_ID_INTEL_IOAT_JSF9 0x3719 |
| 2928 | 2951 | #define PCI_DEVICE_ID_INTEL_QAT_C62X 0x37c8 |
| 2929 | 2952 | #define PCI_DEVICE_ID_INTEL_QAT_C62X_VF 0x37c9 |
| 2953 | +#define PCI_DEVICE_ID_INTEL_HDA_ICL_N 0x38c8 | |
| 2930 | 2954 | #define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14 |
| 2931 | 2955 | #define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16 |
| 2932 | 2956 | #define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18 |
| 2933 | 2957 | #define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a |
| 2934 | 2958 | #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 |
| 2959 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH10_0 0x3a3e | |
| 2935 | 2960 | #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 |
| 2961 | +#define PCI_DEVICE_ID_INTEL_HDA_ICH10_1 0x3a6e | |
| 2936 | 2962 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00 |
| 2937 | 2963 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f |
| 2964 | +#define PCI_DEVICE_ID_INTEL_HDA_5_3400_SERIES_0 0x3b56 | |
| 2965 | +#define PCI_DEVICE_ID_INTEL_HDA_5_3400_SERIES_1 0x3b57 | |
| 2938 | 2966 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20 |
| 2939 | 2967 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21 |
| 2940 | 2968 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22 |
| @@ -2945,16 +2973,12 @@ · 4 unmodified lines | ||
| 2945 | 2973 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27 |
| 2946 | 2974 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e |
| 2947 | 2975 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f |
| 2948 | −#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46 | |
| 2949 | −#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0 | |
| 2950 | −#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1 | |
| 2951 | −#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4 | |
| 2952 | −#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5 | |
| 2953 | 2976 | #define PCI_DEVICE_ID_INTEL_UNC_QPI0 0x3c41 |
| 2954 | 2977 | #define PCI_DEVICE_ID_INTEL_UNC_QPI1 0x3c42 |
| 2955 | 2978 | #define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43 |
| 2956 | 2979 | #define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44 |
| 2957 | 2980 | #define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45 |
| 2981 | +#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46 | |
| 2958 | 2982 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS 0x3c71 /* 15.1 */ |
| 2959 | 2983 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0 0x3c72 /* 16.2 */ |
| 2960 | 2984 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1 0x3c73 /* 16.3 */ |
| @@ -2966,17 +2990,40 @@ · 5 unmodified lines | ||
| 2966 | 2990 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1 0x3cab /* 15.3 */ |
| 2967 | 2991 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2 0x3cac /* 15.4 */ |
| 2968 | 2992 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3 0x3cad /* 15.5 */ |
| 2993 | +#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0 | |
| 2994 | +#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1 | |
| 2995 | +#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4 | |
| 2996 | +#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5 | |
| 2969 | 2997 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO 0x3cb8 /* 17.0 */ |
| 2970 | 2998 | #define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0 |
| 2971 | 2999 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0 0x3cf4 /* 12.6 */ |
| 2972 | 3000 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */ |
| 2973 | 3001 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1 0x3cf6 /* 12.7 */ |
| 3002 | +#define PCI_DEVICE_ID_INTEL_HDA_ICL_H 0x3dc8 | |
| 2974 | 3003 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f |
| 2975 | 3004 | #define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 |
| 2976 | 3005 | #define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 |
| 2977 | 3006 | #define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 |
| 3007 | +#define PCI_DEVICE_ID_INTEL_HDA_TGL_H 0x43c8 | |
| 3008 | +#define PCI_DEVICE_ID_INTEL_HDA_DG1 0x490d | |
| 3009 | +#define PCI_DEVICE_ID_INTEL_HDA_EHL_0 0x4b55 | |
| 3010 | +#define PCI_DEVICE_ID_INTEL_HDA_EHL_3 0x4b58 | |
| 3011 | +#define PCI_DEVICE_ID_INTEL_HDA_JSL_N 0x4dc8 | |
| 3012 | +#define PCI_DEVICE_ID_INTEL_HDA_DG2_0 0x4f90 | |
| 3013 | +#define PCI_DEVICE_ID_INTEL_HDA_DG2_1 0x4f91 | |
| 3014 | +#define PCI_DEVICE_ID_INTEL_HDA_DG2_2 0x4f92 | |
| 2978 | 3015 | #define PCI_DEVICE_ID_INTEL_EP80579_0 0x5031 |
| 2979 | 3016 | #define PCI_DEVICE_ID_INTEL_EP80579_1 0x5032 |
| 3017 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_P 0x51c8 | |
| 3018 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_PS 0x51c9 | |
| 3019 | +#define PCI_DEVICE_ID_INTEL_HDA_RPL_P_0 0x51ca | |
| 3020 | +#define PCI_DEVICE_ID_INTEL_HDA_RPL_P_1 0x51cb | |
| 3021 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_M 0x51cc | |
| 3022 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_PX 0x51cd | |
| 3023 | +#define PCI_DEVICE_ID_INTEL_HDA_RPL_M 0x51ce | |
| 3024 | +#define PCI_DEVICE_ID_INTEL_HDA_RPL_PX 0x51cf | |
| 3025 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_N 0x54c8 | |
| 3026 | +#define PCI_DEVICE_ID_INTEL_HDA_APL 0x5a98 | |
| 2980 | 3027 | #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 |
| 2981 | 3028 | #define PCI_DEVICE_ID_INTEL_5100_19 0x65f3 |
| 2982 | 3029 | #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 |
| @@ -3010,8 +3057,13 @@ · 27 unmodified lines | ||
| 3010 | 3057 | #define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 |
| 3011 | 3058 | #define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2 |
| 3012 | 3059 | #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 |
| 3060 | +#define PCI_DEVICE_ID_INTEL_HDA_RPL_S 0x7a50 | |
| 3061 | +#define PCI_DEVICE_ID_INTEL_HDA_ADL_S 0x7ad0 | |
| 3062 | +#define PCI_DEVICE_ID_INTEL_HDA_MTL 0x7e28 | |
| 3063 | +#define PCI_DEVICE_ID_INTEL_HDA_ARL_S 0x7f50 | |
| 3013 | 3064 | #define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 |
| 3014 | 3065 | #define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a |
| 3066 | +#define PCI_DEVICE_ID_INTEL_HDA_POULSBO 0x811b | |
| 3015 | 3067 | #define PCI_DEVICE_ID_INTEL_E6XX_CU 0x8183 |
| 3016 | 3068 | #define PCI_DEVICE_ID_INTEL_ITC_LPC 0x8186 |
| 3017 | 3069 | #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 |
| @@ -3020,9 +3072,31 @@ · 2 unmodified lines | ||
| 3020 | 3072 | #define PCI_DEVICE_ID_INTEL_82454NX 0x84cb |
| 3021 | 3073 | #define PCI_DEVICE_ID_INTEL_84460GX 0x84ea |
| 3022 | 3074 | #define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500 |
| 3075 | +#define PCI_DEVICE_ID_INTEL_HDA_LPT 0x8c20 | |
| 3076 | +#define PCI_DEVICE_ID_INTEL_HDA_9_SERIES 0x8ca0 | |
| 3077 | +#define PCI_DEVICE_ID_INTEL_HDA_WBG_0 0x8d20 | |
| 3078 | +#define PCI_DEVICE_ID_INTEL_HDA_WBG_1 0x8d21 | |
| 3023 | 3079 | #define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 |
| 3080 | +#define PCI_DEVICE_ID_INTEL_HDA_LKF 0x98c8 | |
| 3024 | 3081 | #define PCI_DEVICE_ID_INTEL_VMD_9A0B 0x9a0b |
| 3082 | +#define PCI_DEVICE_ID_INTEL_HDA_LPT_LP_0 0x9c20 | |
| 3083 | +#define PCI_DEVICE_ID_INTEL_HDA_LPT_LP_1 0x9c21 | |
| 3084 | +#define PCI_DEVICE_ID_INTEL_HDA_WPT_LP 0x9ca0 | |
| 3085 | +#define PCI_DEVICE_ID_INTEL_HDA_SKL_LP 0x9d70 | |
| 3086 | +#define PCI_DEVICE_ID_INTEL_HDA_KBL_LP 0x9d71 | |
| 3087 | +#define PCI_DEVICE_ID_INTEL_HDA_CNL_LP 0x9dc8 | |
| 3088 | +#define PCI_DEVICE_ID_INTEL_HDA_TGL_LP 0xa0c8 | |
| 3089 | +#define PCI_DEVICE_ID_INTEL_HDA_SKL 0xa170 | |
| 3090 | +#define PCI_DEVICE_ID_INTEL_HDA_KBL 0xa171 | |
| 3091 | +#define PCI_DEVICE_ID_INTEL_HDA_LBG_0 0xa1f0 | |
| 3092 | +#define PCI_DEVICE_ID_INTEL_HDA_LBG_1 0xa270 | |
| 3093 | +#define PCI_DEVICE_ID_INTEL_HDA_KBL_H 0xa2f0 | |
| 3094 | +#define PCI_DEVICE_ID_INTEL_HDA_CNL_H 0xa348 | |
| 3095 | +#define PCI_DEVICE_ID_INTEL_HDA_CML_S 0xa3f0 | |
| 3096 | +#define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828 | |
| 3025 | 3097 | #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 |
| 3098 | +#define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8 | |
| 3099 | +#define PCI_DEVICE_ID_INTEL_HDA_RKL_S 0xf1c8 | |
| 3026 | 3100 | |
| 3027 | 3101 | #define PCI_VENDOR_ID_WANGXUN 0x8088 |
| 3028 | 3102 | |
| @@ -63,6 +63,8 @@ extern struct resource *platform_get_mem_or_io(struct platform_device *, · 62 unmodified lines | ||
| 63 | 63 | extern struct device * |
| 64 | 64 | platform_find_device_by_driver(struct device *start, |
| 65 | 65 | const struct device_driver *drv); |
| 66 | + | |
| 67 | +#ifdef CONFIG_HAS_IOMEM | |
| 66 | 68 | extern void __iomem * |
| 67 | 69 | devm_platform_get_and_ioremap_resource(struct platform_device *pdev, |
| 68 | 70 | unsigned int index, struct resource **res); |
| @@ -72,6 +74,32 @@ devm_platform_ioremap_resource(struct platform_device *pdev, · 3 unmodified lines | ||
| 72 | 74 | extern void __iomem * |
| 73 | 75 | devm_platform_ioremap_resource_byname(struct platform_device *pdev, |
| 74 | 76 | const char *name); |
| 77 | +#else | |
| 78 | + | |
| 79 | +static inline void __iomem * | |
| 80 | +devm_platform_get_and_ioremap_resource(struct platform_device *pdev, | |
| 81 | + unsigned int index, struct resource **res) | |
| 82 | +{ | |
| 83 | + return ERR_PTR(-EINVAL); | |
| 84 | +} | |
| 85 | + | |
| 86 | + | |
| 87 | +static inline void __iomem * | |
| 88 | +devm_platform_ioremap_resource(struct platform_device *pdev, | |
| 89 | + unsigned int index) | |
| 90 | +{ | |
| 91 | + return ERR_PTR(-EINVAL); | |
| 92 | +} | |
| 93 | + | |
| 94 | +static inline void __iomem * | |
| 95 | +devm_platform_ioremap_resource_byname(struct platform_device *pdev, | |
| 96 | + const char *name) | |
| 97 | +{ | |
| 98 | + return ERR_PTR(-EINVAL); | |
| 99 | +} | |
| 100 | + | |
| 101 | +#endif | |
| 102 | + | |
| 75 | 103 | extern int platform_get_irq(struct platform_device *, unsigned int); |
| 76 | 104 | extern int platform_get_irq_optional(struct platform_device *, unsigned int); |
| 77 | 105 | extern int platform_irq_count(struct platform_device *); |
| @@ -486,6 +486,11 @@ struct sdw_slave_id { · 485 unmodified lines | ||
| 486 | 486 | __u8 sdw_version:4; |
| 487 | 487 | }; |
| 488 | 488 | |
| 489 | +struct sdw_extended_slave_id { | |
| 490 | + int link_id; | |
| 491 | + struct sdw_slave_id id; | |
| 492 | +}; | |
| 493 | + | |
| 489 | 494 | /* |
| 490 | 495 | * Helper macros to extract the MIPI-defined IDs |
| 491 | 496 | * |
| @@ -264,11 +264,6 @@ struct sdw_intel_link_dev; · 263 unmodified lines | ||
| 264 | 264 | */ |
| 265 | 265 | #define SDW_INTEL_CLK_STOP_BUS_RESET BIT(3) |
| 266 | 266 | |
| 267 | −struct sdw_intel_slave_id { | |
| 268 | − int link_id; | |
| 269 | − struct sdw_slave_id id; | |
| 270 | −}; | |
| 271 | − | |
| 272 | 267 | struct hdac_bus; |
| 273 | 268 | |
| 274 | 269 | /** |
| @@ -298,7 +293,7 @@ struct sdw_intel_ctx { · 23 unmodified lines | ||
| 298 | 293 | int num_slaves; |
| 299 | 294 | acpi_handle handle; |
| 300 | 295 | struct sdw_intel_link_dev **ldev; |
| 301 | − struct sdw_intel_slave_id *ids; | |
| 296 | + struct sdw_extended_slave_id *ids; | |
| 302 | 297 | struct list_head link_list; |
| 303 | 298 | struct mutex shim_lock; /* lock for access to shared SHIM registers */ |
| 304 | 299 | u32 shim_mask; |
| @@ -148,7 +148,7 @@ struct snd_compr_ops { · 147 unmodified lines | ||
| 148 | 148 | */ |
| 149 | 149 | struct snd_compr { |
| 150 | 150 | const char *name; |
| 151 | − struct device dev; | |
| 151 | + struct device *dev; | |
| 152 | 152 | struct snd_compr_ops *ops; |
| 153 | 153 | void *private_data; |
| 154 | 154 | struct snd_card *card; |
| @@ -140,8 +140,32 @@ int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); · 139 unmodified lines | ||
| 140 | 140 | int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); |
| 141 | 141 | void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name); |
| 142 | 142 | int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active); |
| 143 | −struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); | |
| 144 | −struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id); | |
| 143 | +struct snd_kcontrol *snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid); | |
| 144 | +struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid); | |
| 145 | +struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, const struct snd_ctl_elem_id *id); | |
| 146 | +struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id); | |
| 147 | + | |
| 148 | +/** | |
| 149 | + * snd_ctl_find_id_mixer - find the control instance with the given name string | |
| 150 | + * @card: the card instance | |
| 151 | + * @name: the name string | |
| 152 | + * | |
| 153 | + * Finds the control instance with the given name and | |
| 154 | + * @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero. | |
| 155 | + * | |
| 156 | + * This is merely a wrapper to snd_ctl_find_id(). | |
| 157 | + * | |
| 158 | + * Return: The pointer of the instance if found, or %NULL if not. | |
| 159 | + */ | |
| 160 | +static inline struct snd_kcontrol * | |
| 161 | +snd_ctl_find_id_mixer(struct snd_card *card, const char *name) | |
| 162 | +{ | |
| 163 | + struct snd_ctl_elem_id id = {}; | |
| 164 | + | |
| 165 | + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 166 | + strscpy(id.name, name, sizeof(id.name)); | |
| 167 | + return snd_ctl_find_id(card, &id); | |
| 168 | +} | |
| 145 | 169 | |
| 146 | 170 | int snd_ctl_create(struct snd_card *card); |
| 147 | 171 | |
| @@ -238,6 +262,9 @@ snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower) · 90 unmodified lines | ||
| 238 | 262 | return _snd_ctl_add_follower(master, follower, 0); |
| 239 | 263 | } |
| 240 | 264 | |
| 265 | +int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master, | |
| 266 | + const char * const *list); | |
| 267 | + | |
| 241 | 268 | /** |
| 242 | 269 | * snd_ctl_add_follower_uncached - Add a virtual follower control |
| 243 | 270 | * @master: vmaster element |
| @@ -96,7 +96,7 @@ struct snd_card { · 95 unmodified lines | ||
| 96 | 96 | private data */ |
| 97 | 97 | struct list_head devices; /* devices */ |
| 98 | 98 | |
| 99 | − struct device ctl_dev; /* control device */ | |
| 99 | + struct device *ctl_dev; /* control device */ | |
| 100 | 100 | unsigned int last_numid; /* last used numeric ID */ |
| 101 | 101 | struct rw_semaphore controls_rwsem; /* controls lock (list and values) */ |
| 102 | 102 | rwlock_t ctl_files_rwlock; /* ctl_files list lock */ |
| @@ -239,7 +239,7 @@ extern struct dentry *sound_debugfs_root; · 136 unmodified lines | ||
| 239 | 239 | |
| 240 | 240 | void snd_request_card(int card); |
| 241 | 241 | |
| 242 | −void snd_device_initialize(struct device *dev, struct snd_card *card); | |
| 242 | +int snd_device_alloc(struct device **dev_p, struct snd_card *card); | |
| 243 | 243 | |
| 244 | 244 | int snd_register_device(int type, struct snd_card *card, int dev, |
| 245 | 245 | const struct file_operations *f_ops, |
| @@ -829,6 +829,7 @@ enum cs35l41_cspl_mbox_cmd { · 828 unmodified lines | ||
| 829 | 829 | CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, |
| 830 | 830 | CSPL_MBOX_CMD_HIBERNATE = 5, |
| 831 | 831 | CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, |
| 832 | + CSPL_MBOX_CMD_SPK_OUT_ENABLE = 7, | |
| 832 | 833 | CSPL_MBOX_CMD_UNKNOWN_CMD = -1, |
| 833 | 834 | CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, |
| 834 | 835 | }; |
| @@ -901,7 +902,7 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); · 66 unmodified lines | ||
| 901 | 902 | int cs35l41_init_boost(struct device *dev, struct regmap *regmap, |
| 902 | 903 | struct cs35l41_hw_cfg *hw_cfg); |
| 903 | 904 | bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); |
| 904 | −int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, | |
| 905 | − struct completion *pll_lock); | |
| 905 | +int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type, | |
| 906 | + int enable, struct completion *pll_lock, bool firmware_running); | |
| 906 | 907 | |
| 907 | 908 | #endif /* __CS35L41_H */ |
| @@ -252,15 +252,40 @@ · 251 unmodified lines | ||
| 252 | 252 | #define CS35L56_NUM_BULK_SUPPLIES 3 |
| 253 | 253 | #define CS35L56_NUM_DSP_REGIONS 5 |
| 254 | 254 | |
| 255 | +struct cs35l56_base { | |
| 256 | + struct device *dev; | |
| 257 | + struct regmap *regmap; | |
| 258 | + int irq; | |
| 259 | + struct mutex irq_lock; | |
| 260 | + u8 rev; | |
| 261 | + bool init_done; | |
| 262 | + bool fw_patched; | |
| 263 | + bool secured; | |
| 264 | + bool can_hibernate; | |
| 265 | + struct gpio_desc *reset_gpio; | |
| 266 | +}; | |
| 267 | + | |
| 255 | 268 | extern struct regmap_config cs35l56_regmap_i2c; |
| 256 | 269 | extern struct regmap_config cs35l56_regmap_spi; |
| 257 | 270 | extern struct regmap_config cs35l56_regmap_sdw; |
| 258 | 271 | |
| 259 | −extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; | |
| 260 | 272 | extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; |
| 261 | 273 | extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; |
| 262 | 274 | |
| 263 | −void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); | |
| 275 | +int cs35l56_set_patch(struct cs35l56_base *cs35l56_base); | |
| 276 | +int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); | |
| 277 | +int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); | |
| 278 | +int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); | |
| 279 | +void cs35l56_wait_control_port_ready(void); | |
| 280 | +void cs35l56_wait_min_reset_pulse(void); | |
| 281 | +void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire); | |
| 282 | +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); | |
| 283 | +irqreturn_t cs35l56_irq(int irq, void *data); | |
| 284 | +int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); | |
| 285 | +int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); | |
| 286 | +int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); | |
| 287 | +void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); | |
| 288 | +int cs35l56_hw_init(struct cs35l56_base *cs35l56_base); | |
| 264 | 289 | int cs35l56_get_bclk_freq_id(unsigned int freq); |
| 265 | 290 | void cs35l56_fill_supply_names(struct regulator_bulk_data *data); |
| 266 | 291 | |
| @@ -0,0 +1,17 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +/* | |
| 3 | + * CS42L43 CODEC driver external data | |
| 4 | + * | |
| 5 | + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and | |
| 6 | + * Cirrus Logic International Semiconductor Ltd. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef CS42L43_ASOC_EXT_H | |
| 10 | +#define CS42L43_ASOC_EXT_H | |
| 11 | + | |
| 12 | +#define CS42L43_SYSCLK 0 | |
| 13 | + | |
| 14 | +#define CS42L43_SYSCLK_MCLK 0 | |
| 15 | +#define CS42L43_SYSCLK_SDW 1 | |
| 16 | + | |
| 17 | +#endif /* CS42L43_ASOC_EXT_H */ | |
| @@ -21,6 +21,8 @@ struct i2s_clk_config_data { · 20 unmodified lines | ||
| 21 | 21 | u32 sample_rate; |
| 22 | 22 | }; |
| 23 | 23 | |
| 24 | +struct dw_i2s_dev; | |
| 25 | + | |
| 24 | 26 | struct i2s_platform_data { |
| 25 | 27 | #define DWC_I2S_PLAY (1 << 0) |
| 26 | 28 | #define DWC_I2S_RECORD (1 << 1) |
| @@ -42,6 +44,7 @@ struct i2s_platform_data { · 15 unmodified lines | ||
| 42 | 44 | void *capture_dma_data; |
| 43 | 45 | bool (*filter)(struct dma_chan *chan, void *slave); |
| 44 | 46 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); |
| 47 | + int (*i2s_pd_init)(struct dw_i2s_dev *dev); | |
| 45 | 48 | }; |
| 46 | 49 | |
| 47 | 50 | struct i2s_dma_data { |
| @@ -142,7 +142,7 @@ struct snd_dmaengine_pcm_config { · 141 unmodified lines | ||
| 142 | 142 | struct snd_pcm_substream *substream); |
| 143 | 143 | int (*process)(struct snd_pcm_substream *substream, |
| 144 | 144 | int channel, unsigned long hwoff, |
| 145 | − void *buf, unsigned long bytes); | |
| 145 | + struct iov_iter *buf, unsigned long bytes); | |
| 146 | 146 | dma_filter_fn compat_filter_fn; |
| 147 | 147 | struct device *dma_dev; |
| 148 | 148 | const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; |
| @@ -902,6 +902,11 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM · 901 unmodified lines | ||
| 902 | 902 | #define A_TTDA 0x7a /* Tank Table DMA Address */ |
| 903 | 903 | #define A_TTDD 0x7b /* Tank Table DMA Data */ |
| 904 | 904 | |
| 905 | +// In A_FXRT1 & A_FXRT2, the 0x80 bit of each byte completely disables the | |
| 906 | +// filter (CVCF_CURRENTFILTER) for the corresponding channel. There is no | |
| 907 | +// effect on the volume (CVCF_CURRENTVOLUME) or the interpolator's filter | |
| 908 | +// (CCCA_INTERPROM_MASK). | |
| 909 | + | |
| 905 | 910 | #define A_FXRT2 0x7c |
| 906 | 911 | #define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ |
| 907 | 912 | #define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */ |
| @@ -914,8 +919,6 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM · 6 unmodified lines | ||
| 914 | 919 | #define A_FXSENDAMOUNT_G_MASK 0x0000FF00 |
| 915 | 920 | #define A_FXSENDAMOUNT_H_MASK 0x000000FF |
| 916 | 921 | |
| 917 | −/* 0x7c, 0x7e "high bit is used for filtering" */ | |
| 918 | − | |
| 919 | 922 | /* The send amounts for this one are the same as used with the emu10k1 */ |
| 920 | 923 | #define A_FXRT1 0x7e |
| 921 | 924 | #define A_FXRT_CHANNELA 0x0000003f |
| @@ -992,6 +995,9 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM · 70 unmodified lines | ||
| 992 | 995 | #define EMU_HANA_WCLOCK_4X 0x10 |
| 993 | 996 | #define EMU_HANA_WCLOCK_MULT_RESERVED 0x18 |
| 994 | 997 | |
| 998 | +// If the selected external clock source is/becomes invalid or incompatible | |
| 999 | +// with the clock multiplier, the clock source is reset to this value, and | |
| 1000 | +// a WCLK_CHANGED interrupt is raised. | |
| 995 | 1001 | #define EMU_HANA_DEFCLOCK 0x06 /* 000000x 1 bits Default Word Clock */ |
| 996 | 1002 | #define EMU_HANA_DEFCLOCK_48K 0x00 |
| 997 | 1003 | #define EMU_HANA_DEFCLOCK_44_1K 0x01 |
| @@ -1523,10 +1529,10 @@ struct snd_emu10k1_pcm_mixer { · 525 unmodified lines | ||
| 1523 | 1529 | ((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16) |
| 1524 | 1530 | |
| 1525 | 1531 | #define snd_emu10k1_compose_audigy_fxrt1(route) \ |
| 1526 | −((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24)) | |
| 1532 | +((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24) | 0x80808080) | |
| 1527 | 1533 | |
| 1528 | 1534 | #define snd_emu10k1_compose_audigy_fxrt2(route) \ |
| 1529 | −((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24)) | |
| 1535 | +((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24) | 0x80808080) | |
| 1530 | 1536 | |
| 1531 | 1537 | #define snd_emu10k1_compose_audigy_sendamounts(vol) \ |
| 1532 | 1538 | (((unsigned int)vol[4] << 24) | ((unsigned int)vol[5] << 16) | ((unsigned int)vol[6] << 8) | (unsigned int)vol[7]) |
| @@ -1678,8 +1684,8 @@ struct snd_emu1010 { · 145 unmodified lines | ||
| 1678 | 1684 | unsigned int clock_fallback; |
| 1679 | 1685 | unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ |
| 1680 | 1686 | unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ |
| 1681 | − struct delayed_work firmware_work; | |
| 1682 | − u32 last_reg; | |
| 1687 | + struct work_struct firmware_work; | |
| 1688 | + struct work_struct clock_work; | |
| 1683 | 1689 | }; |
| 1684 | 1690 | |
| 1685 | 1691 | struct snd_emu10k1 { |
| @@ -1754,6 +1760,7 @@ struct snd_emu10k1 { · 68 unmodified lines | ||
| 1754 | 1760 | struct snd_kcontrol *ctl_efx_send_routing; |
| 1755 | 1761 | struct snd_kcontrol *ctl_efx_send_volume; |
| 1756 | 1762 | struct snd_kcontrol *ctl_efx_attn; |
| 1763 | + struct snd_kcontrol *ctl_clock_source; | |
| 1757 | 1764 | |
| 1758 | 1765 | void (*hwvol_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| 1759 | 1766 | void (*capture_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| @@ -1761,6 +1768,7 @@ struct snd_emu10k1 { · 1 unmodified line | ||
| 1761 | 1768 | void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| 1762 | 1769 | void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status); |
| 1763 | 1770 | void (*dsp_interrupt)(struct snd_emu10k1 *emu); |
| 1771 | + void (*gpio_interrupt)(struct snd_emu10k1 *emu); | |
| 1764 | 1772 | void (*p16v_interrupt)(struct snd_emu10k1 *emu); |
| 1765 | 1773 | |
| 1766 | 1774 | struct snd_pcm_substream *pcm_capture_substream; |
| @@ -42,6 +42,7 @@ int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, i · 41 unmodified lines | ||
| 42 | 42 | int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink); |
| 43 | 43 | int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink); |
| 44 | 44 | |
| 45 | +int hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16 *lsdiid); | |
| 45 | 46 | int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num); |
| 46 | 47 | |
| 47 | 48 | int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y, |
| @@ -145,6 +146,9 @@ hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) { return 0 · 97 unmodified lines | ||
| 145 | 146 | static inline int |
| 146 | 147 | hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; } |
| 147 | 148 | |
| 149 | +static inline int | |
| 150 | +hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16 *lsdiid) { return 0; } | |
| 151 | + | |
| 148 | 152 | static inline int |
| 149 | 153 | hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; } |
| 150 | 154 | |
| @@ -18,9 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <sound/hda_verbs.h> |
| 19 | 19 | #include <sound/hda_regmap.h> |
| 20 | 20 | |
| 21 | −#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) | |
| 22 | −#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) | |
| 23 | − | |
| 24 | 21 | /* |
| 25 | 22 | * Structures |
| 26 | 23 | */ |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/io.h> |
| 12 | 12 | #include <linux/io-64-nonatomic-lo-hi.h> |
| 13 | 13 | #include <linux/iopoll.h> |
| 14 | +#include <linux/pci.h> | |
| 14 | 15 | #include <linux/pm_runtime.h> |
| 15 | 16 | #include <linux/timecounter.h> |
| 16 | 17 | #include <sound/core.h> |
| @@ -704,4 +705,29 @@ static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) · 687 unmodified lines | ||
| 704 | 705 | for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \ |
| 705 | 706 | (ptr) = snd_array_elem(array, ++(idx))) |
| 706 | 707 | |
| 708 | +/* | |
| 709 | + * Device matching | |
| 710 | + */ | |
| 711 | + | |
| 712 | +#define HDA_CONTROLLER_IS_HSW(pci) (pci_match_id((struct pci_device_id []){ \ | |
| 713 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_0) }, \ | |
| 714 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_2) }, \ | |
| 715 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_3) }, \ | |
| 716 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_BDW) }, \ | |
| 717 | + { } \ | |
| 718 | + }, pci)) | |
| 719 | + | |
| 720 | +#define HDA_CONTROLLER_IS_APL(pci) (pci_match_id((struct pci_device_id []){ \ | |
| 721 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_APL) }, \ | |
| 722 | + { } \ | |
| 723 | + }, pci)) | |
| 724 | + | |
| 725 | +#define HDA_CONTROLLER_IN_GPU(pci) (pci_match_id((struct pci_device_id []){ \ | |
| 726 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG1) }, \ | |
| 727 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_0) }, \ | |
| 728 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_1) }, \ | |
| 729 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_2) }, \ | |
| 730 | + { } \ | |
| 731 | + }, pci) || HDA_CONTROLLER_IS_HSW(pci)) | |
| 732 | + | |
| 707 | 733 | #endif /* __SOUND_HDAUDIO_H */ |
| @@ -53,7 +53,7 @@ struct snd_hwdep { · 52 unmodified lines | ||
| 53 | 53 | wait_queue_head_t open_wait; |
| 54 | 54 | void *private_data; |
| 55 | 55 | void (*private_free) (struct snd_hwdep *hwdep); |
| 56 | − struct device dev; | |
| 56 | + struct device *dev; | |
| 57 | 57 | |
| 58 | 58 | struct mutex open_mutex; |
| 59 | 59 | int used; /* reference counter */ |
| @@ -118,8 +118,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, · 117 unmodified lines | ||
| 118 | 118 | const char *name, |
| 119 | 119 | struct snd_info_entry *parent); |
| 120 | 120 | void snd_info_free_entry(struct snd_info_entry *entry); |
| 121 | −int snd_info_store_text(struct snd_info_entry *entry); | |
| 122 | −int snd_info_restore_text(struct snd_info_entry *entry); | |
| 123 | 121 | |
| 124 | 122 | int snd_info_card_create(struct snd_card *card); |
| 125 | 123 | int snd_info_card_register(struct snd_card *card); |
| @@ -1,28 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _L3_H_ | |
| 3 | −#define _L3_H_ 1 | |
| 4 | − | |
| 5 | −struct l3_pins { | |
| 6 | − void (*setdat)(struct l3_pins *, int); | |
| 7 | − void (*setclk)(struct l3_pins *, int); | |
| 8 | − void (*setmode)(struct l3_pins *, int); | |
| 9 | − | |
| 10 | − int gpio_data; | |
| 11 | − int gpio_clk; | |
| 12 | − int gpio_mode; | |
| 13 | − int use_gpios; | |
| 14 | − | |
| 15 | − int data_hold; | |
| 16 | − int data_setup; | |
| 17 | − int clock_high; | |
| 18 | − int mode_hold; | |
| 19 | − int mode; | |
| 20 | − int mode_setup; | |
| 21 | −}; | |
| 22 | − | |
| 23 | −struct device; | |
| 24 | − | |
| 25 | −int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len); | |
| 26 | −int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap); | |
| 27 | − | |
| 28 | −#endif | |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/bitops.h> |
| 17 | 17 | #include <linux/pm_qos.h> |
| 18 | 18 | #include <linux/refcount.h> |
| 19 | +#include <linux/uio.h> | |
| 19 | 20 | |
| 20 | 21 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) |
| 21 | 22 | #define snd_pcm_chip(pcm) ((pcm)->private_data) |
| @@ -68,11 +69,8 @@ struct snd_pcm_ops { · 46 unmodified lines | ||
| 68 | 69 | struct snd_pcm_audio_tstamp_report *audio_tstamp_report); |
| 69 | 70 | int (*fill_silence)(struct snd_pcm_substream *substream, int channel, |
| 70 | 71 | unsigned long pos, unsigned long bytes); |
| 71 | − int (*copy_user)(struct snd_pcm_substream *substream, int channel, | |
| 72 | − unsigned long pos, void __user *buf, | |
| 73 | − unsigned long bytes); | |
| 74 | − int (*copy_kernel)(struct snd_pcm_substream *substream, int channel, | |
| 75 | − unsigned long pos, void *buf, unsigned long bytes); | |
| 72 | + int (*copy)(struct snd_pcm_substream *substream, int channel, | |
| 73 | + unsigned long pos, struct iov_iter *iter, unsigned long bytes); | |
| 76 | 74 | struct page *(*page)(struct snd_pcm_substream *substream, |
| 77 | 75 | unsigned long offset); |
| 78 | 76 | int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); |
| @@ -510,7 +508,7 @@ struct snd_pcm_str { · 431 unmodified lines | ||
| 510 | 508 | #endif |
| 511 | 509 | #endif |
| 512 | 510 | struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */ |
| 513 | − struct device dev; | |
| 511 | + struct device *dev; | |
| 514 | 512 | }; |
| 515 | 513 | |
| 516 | 514 | struct snd_pcm { |
| @@ -1556,6 +1554,11 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) · 1039 unmodified lines | ||
| 1556 | 1554 | #define pcm_dbg(pcm, fmt, args...) \ |
| 1557 | 1555 | dev_dbg((pcm)->card->dev, fmt, ##args) |
| 1558 | 1556 | |
| 1557 | +/* helpers for copying between iov_iter and iomem */ | |
| 1558 | +int copy_to_iter_fromio(struct iov_iter *itert, const void __iomem *src, | |
| 1559 | + size_t count); | |
| 1560 | +int copy_from_iter_toio(void __iomem *dst, struct iov_iter *iter, size_t count); | |
| 1561 | + | |
| 1559 | 1562 | struct snd_pcm_status64 { |
| 1560 | 1563 | snd_pcm_state_t state; /* stream state */ |
| 1561 | 1564 | u8 rsvd[4]; |
| @@ -135,7 +135,7 @@ struct snd_rawmidi { · 134 unmodified lines | ||
| 135 | 135 | struct mutex open_mutex; |
| 136 | 136 | wait_queue_head_t open_wait; |
| 137 | 137 | |
| 138 | − struct device dev; | |
| 138 | + struct device *dev; | |
| 139 | 139 | |
| 140 | 140 | struct snd_info_entry *proc_entry; |
| 141 | 141 | |
| @@ -31,8 +31,6 @@ struct rt5665_platform_data { · 30 unmodified lines | ||
| 31 | 31 | bool in3_diff; |
| 32 | 32 | bool in4_diff; |
| 33 | 33 | |
| 34 | − int ldo1_en; /* GPIO for LDO1_EN */ | |
| 35 | − | |
| 36 | 34 | enum rt5665_dmic1_data_pin dmic1_data_pin; |
| 37 | 35 | enum rt5665_dmic2_data_pin dmic2_data_pin; |
| 38 | 36 | enum rt5665_jd_src jd_src; |
| @@ -25,9 +25,6 @@ enum rt5668_jd_src { · 24 unmodified lines | ||
| 25 | 25 | }; |
| 26 | 26 | |
| 27 | 27 | struct rt5668_platform_data { |
| 28 | − | |
| 29 | − int ldo1_en; /* GPIO for LDO1_EN */ | |
| 30 | − | |
| 31 | 28 | enum rt5668_dmic1_data_pin dmic1_data_pin; |
| 32 | 29 | enum rt5668_dmic1_clk_pin dmic1_clk_pin; |
| 33 | 30 | enum rt5668_jd_src jd_src; |
| @@ -31,9 +31,6 @@ enum rt5682_dai_clks { · 30 unmodified lines | ||
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | 33 | struct rt5682_platform_data { |
| 34 | − | |
| 35 | − int ldo1_en; /* GPIO for LDO1_EN */ | |
| 36 | − | |
| 37 | 34 | enum rt5682_dmic1_data_pin dmic1_data_pin; |
| 38 | 35 | enum rt5682_dmic1_clk_pin dmic1_clk_pin; |
| 39 | 36 | enum rt5682_jd_src jd_src; |
| @@ -32,9 +32,6 @@ enum rt5682s_dai_clks { · 31 unmodified lines | ||
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | struct rt5682s_platform_data { |
| 35 | − | |
| 36 | − int ldo1_en; /* GPIO for LDO1_EN */ | |
| 37 | − | |
| 38 | 35 | enum rt5682s_dmic1_data_pin dmic1_data_pin; |
| 39 | 36 | enum rt5682s_dmic1_clk_pin dmic1_clk_pin; |
| 40 | 37 | enum rt5682s_jd_src jd_src; |
| @@ -192,9 +192,8 @@ int asoc_simple_remove(struct platform_device *pdev); · 191 unmodified lines | ||
| 192 | 192 | |
| 193 | 193 | int asoc_graph_card_probe(struct snd_soc_card *card); |
| 194 | 194 | int asoc_graph_is_ports0(struct device_node *port); |
| 195 | −int asoc_graph_parse_dai(struct device_node *ep, | |
| 196 | − struct snd_soc_dai_link_component *dlc, | |
| 197 | − int *is_single_link); | |
| 195 | +int asoc_graph_parse_dai(struct device *dev, struct device_node *ep, | |
| 196 | + struct snd_soc_dai_link_component *dlc, int *is_single_link); | |
| 198 | 197 | |
| 199 | 198 | #ifdef DEBUG |
| 200 | 199 | static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/stddef.h> |
| 10 | 10 | #include <linux/acpi.h> |
| 11 | 11 | #include <linux/mod_devicetable.h> |
| 12 | +#include <linux/soundwire/sdw.h> | |
| 12 | 13 | |
| 13 | 14 | struct snd_soc_acpi_package_context { |
| 14 | 15 | char *name; /* package name */ |
| @@ -150,6 +151,7 @@ struct snd_soc_acpi_link_adr { · 135 unmodified lines | ||
| 150 | 151 | * all firmware/topology related fields. |
| 151 | 152 | * |
| 152 | 153 | * @id: ACPI ID (usually the codec's) used to find a matching machine driver. |
| 154 | + * @uid: ACPI Unique ID, can be used to disambiguate matches. | |
| 153 | 155 | * @comp_ids: list of compatible audio codecs using the same machine driver, |
| 154 | 156 | * firmware and topology |
| 155 | 157 | * @link_mask: describes required board layout, e.g. for SoundWire. |
| @@ -208,4 +210,9 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev) · 52 unmodified lines | ||
| 208 | 210 | !strncmp(dev->parent->driver->name, "sof-audio-acpi", strlen("sof-audio-acpi")); |
| 209 | 211 | } |
| 210 | 212 | |
| 213 | +bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, | |
| 214 | + const struct snd_soc_acpi_link_adr *link, | |
| 215 | + struct sdw_extended_slave_id *ids, | |
| 216 | + int num_slaves); | |
| 217 | + | |
| 211 | 218 | #endif |
| @@ -137,10 +137,10 @@ struct snd_soc_component_driver { · 136 unmodified lines | ||
| 137 | 137 | struct timespec64 *audio_ts, |
| 138 | 138 | struct snd_pcm_audio_tstamp_config *audio_tstamp_config, |
| 139 | 139 | struct snd_pcm_audio_tstamp_report *audio_tstamp_report); |
| 140 | − int (*copy_user)(struct snd_soc_component *component, | |
| 141 | − struct snd_pcm_substream *substream, int channel, | |
| 142 | − unsigned long pos, void __user *buf, | |
| 143 | − unsigned long bytes); | |
| 140 | + int (*copy)(struct snd_soc_component *component, | |
| 141 | + struct snd_pcm_substream *substream, int channel, | |
| 142 | + unsigned long pos, struct iov_iter *buf, | |
| 143 | + unsigned long bytes); | |
| 144 | 144 | struct page *(*page)(struct snd_soc_component *component, |
| 145 | 145 | struct snd_pcm_substream *substream, |
| 146 | 146 | unsigned long offset); |
| @@ -509,9 +509,9 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); · 362 unmodified lines | ||
| 509 | 509 | int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, |
| 510 | 510 | unsigned int cmd, void *arg); |
| 511 | 511 | int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream); |
| 512 | −int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, | |
| 513 | − int channel, unsigned long pos, | |
| 514 | − void __user *buf, unsigned long bytes); | |
| 512 | +int snd_soc_pcm_component_copy(struct snd_pcm_substream *substream, | |
| 513 | + int channel, unsigned long pos, | |
| 514 | + struct iov_iter *buf, unsigned long bytes); | |
| 515 | 515 | struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, |
| 516 | 516 | unsigned long offset); |
| 517 | 517 | int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, |
| @@ -271,7 +271,18 @@ int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, · 270 unmodified lines | ||
| 271 | 271 | struct snd_compr_stream *cstream, |
| 272 | 272 | struct snd_compr_metadata *metadata); |
| 273 | 273 | |
| 274 | +const char *snd_soc_dai_name_get(struct snd_soc_dai *dai); | |
| 275 | + | |
| 274 | 276 | struct snd_soc_dai_ops { |
| 277 | + /* DAI driver callbacks */ | |
| 278 | + int (*probe)(struct snd_soc_dai *dai); | |
| 279 | + int (*remove)(struct snd_soc_dai *dai); | |
| 280 | + /* compress dai */ | |
| 281 | + int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); | |
| 282 | + /* Optional Callback used at pcm creation*/ | |
| 283 | + int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, | |
| 284 | + struct snd_soc_dai *dai); | |
| 285 | + | |
| 275 | 286 | /* |
| 276 | 287 | * DAI clocking configuration, all optional. |
| 277 | 288 | * Called by soc_card drivers, normally in their hw_params. |
| @@ -353,6 +364,10 @@ struct snd_soc_dai_ops { · 75 unmodified lines | ||
| 353 | 364 | u64 *auto_selectable_formats; |
| 354 | 365 | int num_auto_selectable_formats; |
| 355 | 366 | |
| 367 | + /* probe ordering - for components with runtime dependencies */ | |
| 368 | + int probe_order; | |
| 369 | + int remove_order; | |
| 370 | + | |
| 356 | 371 | /* bit field */ |
| 357 | 372 | unsigned int no_capture_mute:1; |
| 358 | 373 | }; |
| @@ -397,15 +412,7 @@ struct snd_soc_dai_driver { · 38 unmodified lines | ||
| 397 | 412 | unsigned int id; |
| 398 | 413 | unsigned int base; |
| 399 | 414 | struct snd_soc_dobj dobj; |
| 400 | − | |
| 401 | − /* DAI driver callbacks */ | |
| 402 | − int (*probe)(struct snd_soc_dai *dai); | |
| 403 | − int (*remove)(struct snd_soc_dai *dai); | |
| 404 | − /* compress dai */ | |
| 405 | − int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); | |
| 406 | − /* Optional Callback used at pcm creation*/ | |
| 407 | − int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, | |
| 408 | − struct snd_soc_dai *dai); | |
| 415 | + struct of_phandle_args *dai_args; | |
| 409 | 416 | |
| 410 | 417 | /* ops */ |
| 411 | 418 | const struct snd_soc_dai_ops *ops; |
| @@ -417,10 +424,6 @@ struct snd_soc_dai_driver { · 5 unmodified lines | ||
| 417 | 424 | unsigned int symmetric_rate:1; |
| 418 | 425 | unsigned int symmetric_channels:1; |
| 419 | 426 | unsigned int symmetric_sample_bits:1; |
| 420 | − | |
| 421 | − /* probe ordering - for components with runtime dependencies */ | |
| 422 | − int probe_order; | |
| 423 | − int remove_order; | |
| 424 | 427 | }; |
| 425 | 428 | |
| 426 | 429 | /* for Playback/Capture */ |
| @@ -42,36 +42,45 @@ struct soc_enum; · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | /* codec domain */ |
| 44 | 44 | #define SND_SOC_DAPM_VMID(wname) \ |
| 45 | −{ .id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \ | |
| 45 | +(struct snd_soc_dapm_widget) { \ | |
| 46 | + .id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \ | |
| 46 | 47 | .num_kcontrols = 0} |
| 47 | 48 | |
| 48 | 49 | /* platform domain */ |
| 49 | 50 | #define SND_SOC_DAPM_SIGGEN(wname) \ |
| 50 | −{ .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \ | |
| 51 | +(struct snd_soc_dapm_widget) { \ | |
| 52 | + .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \ | |
| 51 | 53 | .num_kcontrols = 0, .reg = SND_SOC_NOPM } |
| 52 | 54 | #define SND_SOC_DAPM_SINK(wname) \ |
| 53 | −{ .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \ | |
| 55 | +(struct snd_soc_dapm_widget) { \ | |
| 56 | + .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \ | |
| 54 | 57 | .num_kcontrols = 0, .reg = SND_SOC_NOPM } |
| 55 | 58 | #define SND_SOC_DAPM_INPUT(wname) \ |
| 56 | −{ .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \ | |
| 59 | +(struct snd_soc_dapm_widget) { \ | |
| 60 | + .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \ | |
| 57 | 61 | .num_kcontrols = 0, .reg = SND_SOC_NOPM } |
| 58 | 62 | #define SND_SOC_DAPM_OUTPUT(wname) \ |
| 59 | −{ .id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \ | |
| 63 | +(struct snd_soc_dapm_widget) { \ | |
| 64 | + .id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \ | |
| 60 | 65 | .num_kcontrols = 0, .reg = SND_SOC_NOPM } |
| 61 | 66 | #define SND_SOC_DAPM_MIC(wname, wevent) \ |
| 62 | −{ .id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \ | |
| 67 | +(struct snd_soc_dapm_widget) { \ | |
| 68 | + .id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \ | |
| 63 | 69 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 64 | 70 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} |
| 65 | 71 | #define SND_SOC_DAPM_HP(wname, wevent) \ |
| 66 | −{ .id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \ | |
| 72 | +(struct snd_soc_dapm_widget) { \ | |
| 73 | + .id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \ | |
| 67 | 74 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 68 | 75 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} |
| 69 | 76 | #define SND_SOC_DAPM_SPK(wname, wevent) \ |
| 70 | −{ .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \ | |
| 77 | +(struct snd_soc_dapm_widget) { \ | |
| 78 | + .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \ | |
| 71 | 79 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 72 | 80 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} |
| 73 | 81 | #define SND_SOC_DAPM_LINE(wname, wevent) \ |
| 74 | −{ .id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \ | |
| 82 | +(struct snd_soc_dapm_widget) { \ | |
| 83 | + .id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \ | |
| 75 | 84 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 76 | 85 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} |
| 77 | 86 | |
| @@ -82,93 +91,110 @@ struct soc_enum; · 4 unmodified lines | ||
| 82 | 91 | /* path domain */ |
| 83 | 92 | #define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ |
| 84 | 93 | wcontrols, wncontrols) \ |
| 85 | −{ .id = snd_soc_dapm_pga, .name = wname, \ | |
| 94 | +(struct snd_soc_dapm_widget) { \ | |
| 95 | + .id = snd_soc_dapm_pga, .name = wname, \ | |
| 86 | 96 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 87 | 97 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} |
| 88 | 98 | #define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ |
| 89 | 99 | wcontrols, wncontrols) \ |
| 90 | −{ .id = snd_soc_dapm_out_drv, .name = wname, \ | |
| 100 | +(struct snd_soc_dapm_widget) { \ | |
| 101 | + .id = snd_soc_dapm_out_drv, .name = wname, \ | |
| 91 | 102 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 92 | 103 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} |
| 93 | 104 | #define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ |
| 94 | 105 | wcontrols, wncontrols)\ |
| 95 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 106 | +(struct snd_soc_dapm_widget) { \ | |
| 107 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 96 | 108 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 97 | 109 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} |
| 98 | 110 | #define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ |
| 99 | 111 | wcontrols, wncontrols)\ |
| 100 | −{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ | |
| 112 | +(struct snd_soc_dapm_widget) { \ | |
| 113 | + .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ | |
| 101 | 114 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 102 | 115 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} |
| 103 | 116 | /* DEPRECATED: use SND_SOC_DAPM_SUPPLY */ |
| 104 | 117 | #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ |
| 105 | −{ .id = snd_soc_dapm_micbias, .name = wname, \ | |
| 118 | +(struct snd_soc_dapm_widget) { \ | |
| 119 | + .id = snd_soc_dapm_micbias, .name = wname, \ | |
| 106 | 120 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 107 | 121 | .kcontrol_news = NULL, .num_kcontrols = 0} |
| 108 | 122 | #define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ |
| 109 | −{ .id = snd_soc_dapm_switch, .name = wname, \ | |
| 123 | +(struct snd_soc_dapm_widget) { \ | |
| 124 | + .id = snd_soc_dapm_switch, .name = wname, \ | |
| 110 | 125 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 111 | 126 | .kcontrol_news = wcontrols, .num_kcontrols = 1} |
| 112 | 127 | #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ |
| 113 | −{ .id = snd_soc_dapm_mux, .name = wname, \ | |
| 128 | +(struct snd_soc_dapm_widget) { \ | |
| 129 | + .id = snd_soc_dapm_mux, .name = wname, \ | |
| 114 | 130 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 115 | 131 | .kcontrol_news = wcontrols, .num_kcontrols = 1} |
| 116 | 132 | #define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \ |
| 117 | −{ .id = snd_soc_dapm_demux, .name = wname, \ | |
| 133 | +(struct snd_soc_dapm_widget) { \ | |
| 134 | + .id = snd_soc_dapm_demux, .name = wname, \ | |
| 118 | 135 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 119 | 136 | .kcontrol_news = wcontrols, .num_kcontrols = 1} |
| 120 | 137 | |
| 121 | 138 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ |
| 122 | 139 | #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ |
| 123 | 140 | wcontrols) \ |
| 124 | −{ .id = snd_soc_dapm_pga, .name = wname, \ | |
| 141 | +(struct snd_soc_dapm_widget) { \ | |
| 142 | + .id = snd_soc_dapm_pga, .name = wname, \ | |
| 125 | 143 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 126 | 144 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} |
| 127 | 145 | #define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ |
| 128 | 146 | wcontrols)\ |
| 129 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 147 | +(struct snd_soc_dapm_widget) { \ | |
| 148 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 130 | 149 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 131 | 150 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} |
| 132 | 151 | #define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ |
| 133 | 152 | wcontrols)\ |
| 134 | −{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ | |
| 153 | +(struct snd_soc_dapm_widget) { \ | |
| 154 | + .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ | |
| 135 | 155 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 136 | 156 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} |
| 137 | 157 | |
| 138 | 158 | /* path domain with event - event handler must return 0 for success */ |
| 139 | 159 | #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 140 | 160 | wncontrols, wevent, wflags) \ |
| 141 | −{ .id = snd_soc_dapm_pga, .name = wname, \ | |
| 161 | +(struct snd_soc_dapm_widget) { \ | |
| 162 | + .id = snd_soc_dapm_pga, .name = wname, \ | |
| 142 | 163 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 143 | 164 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ |
| 144 | 165 | .event = wevent, .event_flags = wflags} |
| 145 | 166 | #define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 146 | 167 | wncontrols, wevent, wflags) \ |
| 147 | −{ .id = snd_soc_dapm_out_drv, .name = wname, \ | |
| 168 | +(struct snd_soc_dapm_widget) { \ | |
| 169 | + .id = snd_soc_dapm_out_drv, .name = wname, \ | |
| 148 | 170 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 149 | 171 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ |
| 150 | 172 | .event = wevent, .event_flags = wflags} |
| 151 | 173 | #define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 152 | 174 | wncontrols, wevent, wflags) \ |
| 153 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 175 | +(struct snd_soc_dapm_widget) { \ | |
| 176 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 154 | 177 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 155 | 178 | .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ |
| 156 | 179 | .event = wevent, .event_flags = wflags} |
| 157 | 180 | #define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ |
| 158 | 181 | wcontrols, wncontrols, wevent, wflags) \ |
| 159 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 182 | +(struct snd_soc_dapm_widget) { \ | |
| 183 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 160 | 184 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 161 | 185 | .kcontrol_news = wcontrols, \ |
| 162 | 186 | .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} |
| 163 | 187 | #define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 164 | 188 | wevent, wflags) \ |
| 165 | −{ .id = snd_soc_dapm_switch, .name = wname, \ | |
| 189 | +(struct snd_soc_dapm_widget) { \ | |
| 190 | + .id = snd_soc_dapm_switch, .name = wname, \ | |
| 166 | 191 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 167 | 192 | .kcontrol_news = wcontrols, .num_kcontrols = 1, \ |
| 168 | 193 | .event = wevent, .event_flags = wflags} |
| 169 | 194 | #define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ |
| 170 | 195 | wevent, wflags) \ |
| 171 | −{ .id = snd_soc_dapm_mux, .name = wname, \ | |
| 196 | +(struct snd_soc_dapm_widget) { \ | |
| 197 | + .id = snd_soc_dapm_mux, .name = wname, \ | |
| 172 | 198 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 173 | 199 | .kcontrol_news = wcontrols, .num_kcontrols = 1, \ |
| 174 | 200 | .event = wevent, .event_flags = wflags} |
| @@ -176,101 +202,121 @@ struct soc_enum; · 1 unmodified line | ||
| 176 | 202 | /* additional sequencing control within an event type */ |
| 177 | 203 | #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ |
| 178 | 204 | wevent, wflags) \ |
| 179 | −{ .id = snd_soc_dapm_pga, .name = wname, \ | |
| 205 | +(struct snd_soc_dapm_widget) { \ | |
| 206 | + .id = snd_soc_dapm_pga, .name = wname, \ | |
| 180 | 207 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 181 | 208 | .event = wevent, .event_flags = wflags, \ |
| 182 | 209 | .subseq = wsubseq} |
| 183 | 210 | #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ |
| 184 | 211 | wflags) \ |
| 185 | −{ .id = snd_soc_dapm_supply, .name = wname, \ | |
| 212 | +(struct snd_soc_dapm_widget) { \ | |
| 213 | + .id = snd_soc_dapm_supply, .name = wname, \ | |
| 186 | 214 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 187 | 215 | .event = wevent, .event_flags = wflags, .subseq = wsubseq} |
| 188 | 216 | |
| 189 | 217 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ |
| 190 | 218 | #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ |
| 191 | 219 | wevent, wflags) \ |
| 192 | −{ .id = snd_soc_dapm_pga, .name = wname, \ | |
| 220 | +(struct snd_soc_dapm_widget) { \ | |
| 221 | + .id = snd_soc_dapm_pga, .name = wname, \ | |
| 193 | 222 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 194 | 223 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ |
| 195 | 224 | .event = wevent, .event_flags = wflags} |
| 196 | 225 | #define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ |
| 197 | 226 | wevent, wflags) \ |
| 198 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 227 | +(struct snd_soc_dapm_widget) { \ | |
| 228 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 199 | 229 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 200 | 230 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ |
| 201 | 231 | .event = wevent, .event_flags = wflags} |
| 202 | 232 | #define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ |
| 203 | 233 | wcontrols, wevent, wflags) \ |
| 204 | −{ .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 234 | +(struct snd_soc_dapm_widget) { \ | |
| 235 | + .id = snd_soc_dapm_mixer, .name = wname, \ | |
| 205 | 236 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 206 | 237 | .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ |
| 207 | 238 | .event = wevent, .event_flags = wflags} |
| 208 | 239 | |
| 209 | 240 | /* events that are pre and post DAPM */ |
| 210 | 241 | #define SND_SOC_DAPM_PRE(wname, wevent) \ |
| 211 | −{ .id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \ | |
| 242 | +(struct snd_soc_dapm_widget) { \ | |
| 243 | + .id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \ | |
| 212 | 244 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 213 | 245 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD} |
| 214 | 246 | #define SND_SOC_DAPM_POST(wname, wevent) \ |
| 215 | −{ .id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \ | |
| 247 | +(struct snd_soc_dapm_widget) { \ | |
| 248 | + .id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \ | |
| 216 | 249 | .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ |
| 217 | 250 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD} |
| 218 | 251 | |
| 219 | 252 | /* stream domain */ |
| 220 | 253 | #define SND_SOC_DAPM_AIF_IN(wname, stname, wchan, wreg, wshift, winvert) \ |
| 221 | −{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | |
| 254 | +(struct snd_soc_dapm_widget) { \ | |
| 255 | + .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | |
| 222 | 256 | .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 223 | 257 | #define SND_SOC_DAPM_AIF_IN_E(wname, stname, wchan, wreg, wshift, winvert, \ |
| 224 | 258 | wevent, wflags) \ |
| 225 | −{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | |
| 259 | +(struct snd_soc_dapm_widget) { \ | |
| 260 | + .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ | |
| 226 | 261 | .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 227 | 262 | .event = wevent, .event_flags = wflags } |
| 228 | 263 | #define SND_SOC_DAPM_AIF_OUT(wname, stname, wchan, wreg, wshift, winvert) \ |
| 229 | −{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | |
| 264 | +(struct snd_soc_dapm_widget) { \ | |
| 265 | + .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | |
| 230 | 266 | .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 231 | 267 | #define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wchan, wreg, wshift, winvert, \ |
| 232 | 268 | wevent, wflags) \ |
| 233 | −{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | |
| 269 | +(struct snd_soc_dapm_widget) { \ | |
| 270 | + .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ | |
| 234 | 271 | .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 235 | 272 | .event = wevent, .event_flags = wflags } |
| 236 | 273 | #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ |
| 237 | −{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ | |
| 274 | +(struct snd_soc_dapm_widget) { \ | |
| 275 | + .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ | |
| 238 | 276 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) } |
| 239 | 277 | #define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ |
| 240 | 278 | wevent, wflags) \ |
| 241 | −{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ | |
| 279 | +(struct snd_soc_dapm_widget) { \ | |
| 280 | + .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ | |
| 242 | 281 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 243 | 282 | .event = wevent, .event_flags = wflags} |
| 244 | 283 | |
| 245 | 284 | #define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ |
| 246 | −{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ | |
| 285 | +(struct snd_soc_dapm_widget) { \ | |
| 286 | + .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ | |
| 247 | 287 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } |
| 248 | 288 | #define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ |
| 249 | 289 | wevent, wflags) \ |
| 250 | −{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ | |
| 290 | +(struct snd_soc_dapm_widget) { \ | |
| 291 | + .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ | |
| 251 | 292 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 252 | 293 | .event = wevent, .event_flags = wflags} |
| 253 | 294 | #define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ |
| 254 | −{ .id = snd_soc_dapm_clock_supply, .name = wname, \ | |
| 295 | +(struct snd_soc_dapm_widget) { \ | |
| 296 | + .id = snd_soc_dapm_clock_supply, .name = wname, \ | |
| 255 | 297 | .reg = SND_SOC_NOPM, .event = dapm_clock_event, \ |
| 256 | 298 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } |
| 257 | 299 | |
| 258 | 300 | /* generic widgets */ |
| 259 | 301 | #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ |
| 260 | −{ .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ | |
| 302 | +(struct snd_soc_dapm_widget) { \ | |
| 303 | + .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ | |
| 261 | 304 | .reg = wreg, .shift = wshift, .mask = wmask, \ |
| 262 | 305 | .on_val = won_val, .off_val = woff_val, } |
| 263 | 306 | #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ |
| 264 | −{ .id = snd_soc_dapm_supply, .name = wname, \ | |
| 307 | +(struct snd_soc_dapm_widget) { \ | |
| 308 | + .id = snd_soc_dapm_supply, .name = wname, \ | |
| 265 | 309 | SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ |
| 266 | 310 | .event = wevent, .event_flags = wflags} |
| 267 | 311 | #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ |
| 268 | −{ .id = snd_soc_dapm_regulator_supply, .name = wname, \ | |
| 312 | +(struct snd_soc_dapm_widget) { \ | |
| 313 | + .id = snd_soc_dapm_regulator_supply, .name = wname, \ | |
| 269 | 314 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ |
| 270 | 315 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ |
| 271 | 316 | .on_val = wflags} |
| 272 | 317 | #define SND_SOC_DAPM_PINCTRL(wname, active, sleep) \ |
| 273 | −{ .id = snd_soc_dapm_pinctrl, .name = wname, \ | |
| 318 | +(struct snd_soc_dapm_widget) { \ | |
| 319 | + .id = snd_soc_dapm_pinctrl, .name = wname, \ | |
| 274 | 320 | .priv = (&(struct snd_soc_dapm_pinctrl_priv) \ |
| 275 | 321 | { .active_state = active, .sleep_state = sleep,}), \ |
| 276 | 322 | .reg = SND_SOC_NOPM, .event = dapm_pinctrl_event, \ |
| @@ -604,6 +650,7 @@ struct snd_soc_dapm_widget { · 327 unmodified lines | ||
| 604 | 650 | unsigned char power_checked:1; /* power checked this run */ |
| 605 | 651 | unsigned char is_supply:1; /* Widget is a supply type widget */ |
| 606 | 652 | unsigned char is_ep:2; /* Widget is a endpoint type widget */ |
| 653 | + unsigned char no_wname_in_kcontrol_name:1; /* No widget name prefix in kcontrol name */ | |
| 607 | 654 | int subseq; /* sort within widget type */ |
| 608 | 655 | |
| 609 | 656 | int (*power_check)(struct snd_soc_dapm_widget *w); |
| @@ -651,6 +651,7 @@ struct snd_soc_dai_link_component { · 650 unmodified lines | ||
| 651 | 651 | const char *name; |
| 652 | 652 | struct device_node *of_node; |
| 653 | 653 | const char *dai_name; |
| 654 | + struct of_phandle_args *dai_args; | |
| 654 | 655 | }; |
| 655 | 656 | |
| 656 | 657 | struct snd_soc_dai_link_codec_ch_map { |
| @@ -1335,6 +1336,11 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, · 678 unmodified lines | ||
| 1335 | 1336 | void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, |
| 1336 | 1337 | struct snd_soc_pcm_runtime *rtd); |
| 1337 | 1338 | |
| 1339 | +void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, | |
| 1340 | + struct snd_soc_dai_link_component *cpus); | |
| 1341 | +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, | |
| 1342 | + struct of_phandle_args *args); | |
| 1343 | +struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args); | |
| 1338 | 1344 | struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, |
| 1339 | 1345 | struct snd_soc_dai_driver *dai_drv, |
| 1340 | 1346 | bool legacy_dai_naming); |
| @@ -26,9 +26,9 @@ enum sof_comp_type { · 25 unmodified lines | ||
| 26 | 26 | SOF_COMP_MIXER, |
| 27 | 27 | SOF_COMP_MUX, |
| 28 | 28 | SOF_COMP_SRC, |
| 29 | − SOF_COMP_SPLITTER, | |
| 29 | + SOF_COMP_DEPRECATED0, /* Formerly SOF_COMP_SPLITTER */ | |
| 30 | 30 | SOF_COMP_TONE, |
| 31 | − SOF_COMP_SWITCH, | |
| 31 | + SOF_COMP_DEPRECATED1, /* Formerly SOF_COMP_SWITCH */ | |
| 32 | 32 | SOF_COMP_BUFFER, |
| 33 | 33 | SOF_COMP_EQ_IIR, |
| 34 | 34 | SOF_COMP_EQ_FIR, |
| @@ -1,24 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | −/* | |
| 3 | − * uda134x.h -- UDA134x ALSA SoC Codec driver | |
| 4 | − * | |
| 5 | − * Copyright 2007 Dension Audio Systems Ltd. | |
| 6 | − * Author: Zoltan Devai | |
| 7 | − */ | |
| 8 | − | |
| 9 | −#ifndef _UDA134X_H | |
| 10 | −#define _UDA134X_H | |
| 11 | − | |
| 12 | −#include <sound/l3.h> | |
| 13 | − | |
| 14 | −struct uda134x_platform_data { | |
| 15 | − struct l3_pins l3; | |
| 16 | − void (*power) (int); | |
| 17 | − int model; | |
| 18 | −#define UDA134X_UDA1340 1 | |
| 19 | −#define UDA134X_UDA1341 2 | |
| 20 | −#define UDA134X_UDA1344 3 | |
| 21 | −#define UDA134X_UDA1345 4 | |
| 22 | −}; | |
| 23 | − | |
| 24 | −#endif /* _UDA134X_H */ | |
| @@ -45,6 +45,7 @@ struct snd_ump_endpoint { · 44 unmodified lines | ||
| 45 | 45 | spinlock_t legacy_locks[2]; |
| 46 | 46 | struct snd_rawmidi *legacy_rmidi; |
| 47 | 47 | struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS]; |
| 48 | + unsigned char legacy_mapping[SNDRV_UMP_MAX_GROUPS]; | |
| 48 | 49 | |
| 49 | 50 | /* for legacy output; need to open the actual substream unlike input */ |
| 50 | 51 | int legacy_out_opens; |
| @@ -99,7 +99,11 @@ · 98 unmodified lines | ||
| 99 | 99 | #define SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME 414 |
| 100 | 100 | #define SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS 415 |
| 101 | 101 | #define SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS 416 |
| 102 | − | |
| 102 | +/* | |
| 103 | + * The token value is copied to the dapm_widget's | |
| 104 | + * no_wname_in_kcontrol_name. | |
| 105 | + */ | |
| 106 | +#define SOF_TKN_COMP_NO_WNAME_IN_KCONTROL_NAME 417 | |
| 103 | 107 | |
| 104 | 108 | /* SSP */ |
| 105 | 109 | #define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500 |
| @@ -1557,6 +1557,7 @@ int import_ubuf(int rw, void __user *buf, size_t len, struct iov_iter *i) · 1556 unmodified lines | ||
| 1557 | 1557 | iov_iter_ubuf(i, rw, buf, len); |
| 1558 | 1558 | return 0; |
| 1559 | 1559 | } |
| 1560 | +EXPORT_SYMBOL_GPL(import_ubuf); | |
| 1560 | 1561 | |
| 1561 | 1562 | /** |
| 1562 | 1563 | * iov_iter_restore() - Restore a &struct iov_iter to the same state as when |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | −obj-y += div64.o gcd.o lcm.o int_pow.o int_sqrt.o reciprocal_div.o | |
| 2 | +obj-y += div64.o gcd.o lcm.o int_log.o int_pow.o int_sqrt.o reciprocal_div.o | |
| 3 | 3 | |
| 4 | 4 | obj-$(CONFIG_CORDIC) += cordic.o |
| 5 | 5 | obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o |
| @@ -1,25 +1,17 @@ | ||
| 1 | +// SPDX-License-Identifier: LGPL-2.1-or-later | |
| 1 | 2 | /* |
| 2 | − * dvb-math provides some complex fixed-point math | |
| 3 | − * operations shared between the dvb related stuff | |
| 3 | + * Provides fixed-point logarithm operations. | |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) |
| 6 | − * | |
| 7 | − * This library is free software; you can redistribute it and/or modify | |
| 8 | − * it under the terms of the GNU Lesser General Public License as | |
| 9 | − * published by the Free Software Foundation; either version 2.1 of | |
| 10 | − * the License, or (at your option) any later version. | |
| 11 | − * | |
| 12 | − * This program is distributed in the hope that it will be useful, | |
| 13 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | − * GNU Lesser General Public License for more details. | |
| 16 | 6 | */ |
| 17 | 7 | |
| 18 | 8 | #include <linux/bitops.h> |
| 9 | +#include <linux/export.h> | |
| 10 | +#include <linux/int_log.h> | |
| 19 | 11 | #include <linux/kernel.h> |
| 20 | −#include <linux/module.h> | |
| 12 | +#include <linux/types.h> | |
| 13 | + | |
| 21 | 14 | #include <asm/bug.h> |
| 22 | −#include <media/dvb_math.h> | |
| 23 | 15 | |
| 24 | 16 | static const unsigned short logtable[256] = { |
| 25 | 17 | 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, |
| @@ -53,7 +45,7 @@ static const unsigned short logtable[256] = { · 27 unmodified lines | ||
| 53 | 45 | 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, |
| 54 | 46 | 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, |
| 55 | 47 | 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, |
| 56 | − 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 | |
| 48 | + 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47, | |
| 57 | 49 | }; |
| 58 | 50 | |
| 59 | 51 | unsigned int intlog2(u32 value) |
| @@ -90,7 +82,7 @@ unsigned int intlog2(u32 value) · 30 unmodified lines | ||
| 90 | 82 | * so we would use the entry 0x18 |
| 91 | 83 | */ |
| 92 | 84 | significand = value << (31 - msb); |
| 93 | − logentry = (significand >> 23) & 0xff; | |
| 85 | + logentry = (significand >> 23) % ARRAY_SIZE(logtable); | |
| 94 | 86 | |
| 95 | 87 | /** |
| 96 | 88 | * last step we do is interpolation because of the |
| @@ -108,7 +100,7 @@ unsigned int intlog2(u32 value) · 11 unmodified lines | ||
| 108 | 100 | * logtable_next is 256 |
| 109 | 101 | */ |
| 110 | 102 | interpolation = ((significand & 0x7fffff) * |
| 111 | − ((logtable[(logentry + 1) & 0xff] - | |
| 103 | + ((logtable[(logentry + 1) % ARRAY_SIZE(logtable)] - | |
| 112 | 104 | logtable[logentry]) & 0xffff)) >> 15; |
| 113 | 105 | |
| 114 | 106 | /* now we return the result */ |
| @@ -39,8 +39,6 @@ config SOUND_OSS_CORE_PRECLAIM · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | source "sound/oss/dmasound/Kconfig" |
| 41 | 41 | |
| 42 | −if !UML | |
| 43 | − | |
| 44 | 42 | menuconfig SND |
| 45 | 43 | tristate "Advanced Linux Sound Architecture" |
| 46 | 44 | help |
| @@ -103,8 +101,6 @@ source "sound/virtio/Kconfig" · 56 unmodified lines | ||
| 103 | 101 | |
| 104 | 102 | endif # SND |
| 105 | 103 | |
| 106 | −endif # !UML | |
| 107 | − | |
| 108 | 104 | endif # SOUND |
| 109 | 105 | |
| 110 | 106 | config AC97_BUS |
| @@ -462,7 +462,7 @@ static ssize_t vendor_id_show(struct device *dev, · 461 unmodified lines | ||
| 462 | 462 | |
| 463 | 463 | return sysfs_emit(buf, "%08x", codec->vendor_id); |
| 464 | 464 | } |
| 465 | −DEVICE_ATTR_RO(vendor_id); | |
| 465 | +static DEVICE_ATTR_RO(vendor_id); | |
| 466 | 466 | |
| 467 | 467 | static struct attribute *ac97_dev_attrs[] = { |
| 468 | 468 | &dev_attr_vendor_id.attr, |
| @@ -972,7 +972,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, · 971 unmodified lines | ||
| 972 | 972 | goto out_put_ci_module; |
| 973 | 973 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, |
| 974 | 974 | &i2sbus_playback_ops); |
| 975 | − dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev.parent = | |
| 975 | + dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev->parent = | |
| 976 | 976 | &dev->ofdev.dev; |
| 977 | 977 | i2sdev->out.created = 1; |
| 978 | 978 | } |
| @@ -989,7 +989,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, · 10 unmodified lines | ||
| 989 | 989 | goto out_put_ci_module; |
| 990 | 990 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, |
| 991 | 991 | &i2sbus_record_ops); |
| 992 | − dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev.parent = | |
| 992 | + dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev->parent = | |
| 993 | 993 | &dev->ofdev.dev; |
| 994 | 994 | i2sdev->in.created = 1; |
| 995 | 995 | } |
| @@ -12,13 +12,12 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/gpio/consumer.h> |
| 13 | 13 | #include <linux/init.h> |
| 14 | 14 | #include <linux/interrupt.h> |
| 15 | +#include <linux/mod_devicetable.h> | |
| 15 | 16 | #include <linux/module.h> |
| 16 | 17 | #include <linux/platform_device.h> |
| 17 | 18 | #include <linux/mutex.h> |
| 18 | 19 | #include <linux/types.h> |
| 19 | 20 | #include <linux/io.h> |
| 20 | −#include <linux/of.h> | |
| 21 | −#include <linux/of_device.h> | |
| 22 | 21 | |
| 23 | 22 | #include <sound/core.h> |
| 24 | 23 | #include <sound/initval.h> |
| @@ -546,7 +546,7 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, · 545 unmodified lines | ||
| 546 | 546 | if (stream->runtime->dma_buffer_p) { |
| 547 | 547 | |
| 548 | 548 | if (buffer_size > stream->runtime->dma_buffer_p->bytes) |
| 549 | − dev_err(&stream->device->dev, | |
| 549 | + dev_err(stream->device->dev, | |
| 550 | 550 | "Not enough DMA buffer"); |
| 551 | 551 | else |
| 552 | 552 | buffer = stream->runtime->dma_buffer_p->area; |
| @@ -1070,7 +1070,7 @@ static int snd_compress_dev_register(struct snd_device *device) · 517 unmodified lines | ||
| 1070 | 1070 | /* register compressed device */ |
| 1071 | 1071 | ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, |
| 1072 | 1072 | compr->card, compr->device, |
| 1073 | − &snd_compr_file_ops, compr, &compr->dev); | |
| 1073 | + &snd_compr_file_ops, compr, compr->dev); | |
| 1074 | 1074 | if (ret < 0) { |
| 1075 | 1075 | pr_err("snd_register_device failed %d\n", ret); |
| 1076 | 1076 | return ret; |
| @@ -1084,7 +1084,7 @@ static int snd_compress_dev_disconnect(struct snd_device *device) · 7 unmodified lines | ||
| 1084 | 1084 | struct snd_compr *compr; |
| 1085 | 1085 | |
| 1086 | 1086 | compr = device->device_data; |
| 1087 | − snd_unregister_device(&compr->dev); | |
| 1087 | + snd_unregister_device(compr->dev); | |
| 1088 | 1088 | return 0; |
| 1089 | 1089 | } |
| 1090 | 1090 | |
| @@ -1158,7 +1158,7 @@ static int snd_compress_dev_free(struct snd_device *device) · 67 unmodified lines | ||
| 1158 | 1158 | |
| 1159 | 1159 | compr = device->device_data; |
| 1160 | 1160 | snd_compress_proc_done(compr); |
| 1161 | − put_device(&compr->dev); | |
| 1161 | + put_device(compr->dev); | |
| 1162 | 1162 | return 0; |
| 1163 | 1163 | } |
| 1164 | 1164 | |
| @@ -1189,12 +1189,16 @@ int snd_compress_new(struct snd_card *card, int device, · 24 unmodified lines | ||
| 1189 | 1189 | |
| 1190 | 1190 | snd_compress_set_id(compr, id); |
| 1191 | 1191 | |
| 1192 | − snd_device_initialize(&compr->dev, card); | |
| 1193 | − dev_set_name(&compr->dev, "comprC%iD%i", card->number, device); | |
| 1192 | + ret = snd_device_alloc(&compr->dev, card); | |
| 1193 | + if (ret) | |
| 1194 | + return ret; | |
| 1195 | + dev_set_name(compr->dev, "comprC%iD%i", card->number, device); | |
| 1194 | 1196 | |
| 1195 | 1197 | ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops); |
| 1196 | 1198 | if (ret == 0) |
| 1197 | 1199 | snd_compress_proc_init(compr); |
| 1200 | + else | |
| 1201 | + put_device(compr->dev); | |
| 1198 | 1202 | |
| 1199 | 1203 | return ret; |
| 1200 | 1204 | } |
| @@ -39,6 +39,9 @@ static LIST_HEAD(snd_control_compat_ioctls); · 38 unmodified lines | ||
| 39 | 39 | #endif |
| 40 | 40 | static struct snd_ctl_layer_ops *snd_ctl_layer; |
| 41 | 41 | |
| 42 | +static int snd_ctl_remove_locked(struct snd_card *card, | |
| 43 | + struct snd_kcontrol *kcontrol); | |
| 44 | + | |
| 42 | 45 | static int snd_ctl_open(struct inode *inode, struct file *file) |
| 43 | 46 | { |
| 44 | 47 | unsigned long flags; |
| @@ -466,11 +469,13 @@ static int __snd_ctl_add_replace(struct snd_card *card, · 421 unmodified lines | ||
| 466 | 469 | struct snd_kcontrol *old; |
| 467 | 470 | int err; |
| 468 | 471 | |
| 472 | + lockdep_assert_held_write(&card->controls_rwsem); | |
| 473 | + | |
| 469 | 474 | id = kcontrol->id; |
| 470 | 475 | if (id.index > UINT_MAX - kcontrol->count) |
| 471 | 476 | return -EINVAL; |
| 472 | 477 | |
| 473 | − old = snd_ctl_find_id(card, &id); | |
| 478 | + old = snd_ctl_find_id_locked(card, &id); | |
| 474 | 479 | if (!old) { |
| 475 | 480 | if (mode == CTL_REPLACE) |
| 476 | 481 | return -EINVAL; |
| @@ -483,7 +488,7 @@ static int __snd_ctl_add_replace(struct snd_card *card, · 6 unmodified lines | ||
| 483 | 488 | return -EBUSY; |
| 484 | 489 | } |
| 485 | 490 | |
| 486 | − err = snd_ctl_remove(card, old); | |
| 491 | + err = snd_ctl_remove_locked(card, old); | |
| 487 | 492 | if (err < 0) |
| 488 | 493 | return err; |
| 489 | 494 | } |
| @@ -575,6 +580,8 @@ static int __snd_ctl_remove(struct snd_card *card, · 85 unmodified lines | ||
| 575 | 580 | { |
| 576 | 581 | unsigned int idx; |
| 577 | 582 | |
| 583 | + lockdep_assert_held_write(&card->controls_rwsem); | |
| 584 | + | |
| 578 | 585 | if (snd_BUG_ON(!card || !kcontrol)) |
| 579 | 586 | return -EINVAL; |
| 580 | 587 | list_del(&kcontrol->list); |
| @@ -589,20 +596,32 @@ static int __snd_ctl_remove(struct snd_card *card, · 8 unmodified lines | ||
| 589 | 596 | return 0; |
| 590 | 597 | } |
| 591 | 598 | |
| 599 | +static inline int snd_ctl_remove_locked(struct snd_card *card, | |
| 600 | + struct snd_kcontrol *kcontrol) | |
| 601 | +{ | |
| 602 | + return __snd_ctl_remove(card, kcontrol, true); | |
| 603 | +} | |
| 604 | + | |
| 592 | 605 | /** |
| 593 | 606 | * snd_ctl_remove - remove the control from the card and release it |
| 594 | 607 | * @card: the card instance |
| 595 | 608 | * @kcontrol: the control instance to remove |
| 596 | 609 | * |
| 597 | 610 | * Removes the control from the card and then releases the instance. |
| 598 | − * You don't need to call snd_ctl_free_one(). You must be in | |
| 599 | − * the write lock - down_write(&card->controls_rwsem). | |
| 611 | + * You don't need to call snd_ctl_free_one(). | |
| 600 | 612 | * |
| 601 | 613 | * Return: 0 if successful, or a negative error code on failure. |
| 614 | + * | |
| 615 | + * Note that this function takes card->controls_rwsem lock internally. | |
| 602 | 616 | */ |
| 603 | 617 | int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) |
| 604 | 618 | { |
| 605 | − return __snd_ctl_remove(card, kcontrol, true); | |
| 619 | + int ret; | |
| 620 | + | |
| 621 | + down_write(&card->controls_rwsem); | |
| 622 | + ret = snd_ctl_remove_locked(card, kcontrol); | |
| 623 | + up_write(&card->controls_rwsem); | |
| 624 | + return ret; | |
| 606 | 625 | } |
| 607 | 626 | EXPORT_SYMBOL(snd_ctl_remove); |
| 608 | 627 | |
| @@ -622,12 +641,12 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) · 13 unmodified lines | ||
| 622 | 641 | int ret; |
| 623 | 642 | |
| 624 | 643 | down_write(&card->controls_rwsem); |
| 625 | − kctl = snd_ctl_find_id(card, id); | |
| 644 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 626 | 645 | if (kctl == NULL) { |
| 627 | 646 | up_write(&card->controls_rwsem); |
| 628 | 647 | return -ENOENT; |
| 629 | 648 | } |
| 630 | − ret = snd_ctl_remove(card, kctl); | |
| 649 | + ret = snd_ctl_remove_locked(card, kctl); | |
| 631 | 650 | up_write(&card->controls_rwsem); |
| 632 | 651 | return ret; |
| 633 | 652 | } |
| @@ -651,7 +670,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, · 17 unmodified lines | ||
| 651 | 670 | int idx, ret; |
| 652 | 671 | |
| 653 | 672 | down_write(&card->controls_rwsem); |
| 654 | − kctl = snd_ctl_find_id(card, id); | |
| 673 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 655 | 674 | if (kctl == NULL) { |
| 656 | 675 | ret = -ENOENT; |
| 657 | 676 | goto error; |
| @@ -665,7 +684,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, · 7 unmodified lines | ||
| 665 | 684 | ret = -EBUSY; |
| 666 | 685 | goto error; |
| 667 | 686 | } |
| 668 | − ret = snd_ctl_remove(card, kctl); | |
| 687 | + ret = snd_ctl_remove_locked(card, kctl); | |
| 669 | 688 | error: |
| 670 | 689 | up_write(&card->controls_rwsem); |
| 671 | 690 | return ret; |
| @@ -692,7 +711,7 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, · 20 unmodified lines | ||
| 692 | 711 | int ret; |
| 693 | 712 | |
| 694 | 713 | down_write(&card->controls_rwsem); |
| 695 | − kctl = snd_ctl_find_id(card, id); | |
| 714 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 696 | 715 | if (kctl == NULL) { |
| 697 | 716 | ret = -ENOENT; |
| 698 | 717 | goto unlock; |
| @@ -746,7 +765,7 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id, · 47 unmodified lines | ||
| 746 | 765 | int saved_numid; |
| 747 | 766 | |
| 748 | 767 | down_write(&card->controls_rwsem); |
| 749 | − kctl = snd_ctl_find_id(card, src_id); | |
| 768 | + kctl = snd_ctl_find_id_locked(card, src_id); | |
| 750 | 769 | if (kctl == NULL) { |
| 751 | 770 | up_write(&card->controls_rwsem); |
| 752 | 771 | return -ENOENT; |
| @@ -769,11 +788,12 @@ EXPORT_SYMBOL(snd_ctl_rename_id); · 16 unmodified lines | ||
| 769 | 788 | * |
| 770 | 789 | * Renames the specified control on the card to the new name. |
| 771 | 790 | * |
| 772 | − * Make sure to take the control write lock - down_write(&card->controls_rwsem). | |
| 791 | + * Note that this function takes card->controls_rwsem lock internally. | |
| 773 | 792 | */ |
| 774 | 793 | void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, |
| 775 | 794 | const char *name) |
| 776 | 795 | { |
| 796 | + down_write(&card->controls_rwsem); | |
| 777 | 797 | remove_hash_entries(card, kctl); |
| 778 | 798 | |
| 779 | 799 | if (strscpy(kctl->id.name, name, sizeof(kctl->id.name)) < 0) |
| @@ -781,6 +801,7 @@ void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, · 1 unmodified line | ||
| 781 | 801 | name, kctl->id.name); |
| 782 | 802 | |
| 783 | 803 | add_hash_entries(card, kctl); |
| 804 | + up_write(&card->controls_rwsem); | |
| 784 | 805 | } |
| 785 | 806 | EXPORT_SYMBOL(snd_ctl_rename); |
| 786 | 807 | |
| @@ -799,7 +820,7 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid) · 12 unmodified lines | ||
| 799 | 820 | #endif /* !CONFIG_SND_CTL_FAST_LOOKUP */ |
| 800 | 821 | |
| 801 | 822 | /** |
| 802 | − * snd_ctl_find_numid - find the control instance with the given number-id | |
| 823 | + * snd_ctl_find_numid_locked - find the control instance with the given number-id | |
| 803 | 824 | * @card: the card instance |
| 804 | 825 | * @numid: the number-id to search |
| 805 | 826 | * |
| @@ -809,22 +830,46 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid) · 3 unmodified lines | ||
| 809 | 830 | * (if the race condition can happen). |
| 810 | 831 | * |
| 811 | 832 | * Return: The pointer of the instance if found, or %NULL if not. |
| 812 | − * | |
| 813 | 833 | */ |
| 814 | −struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid) | |
| 834 | +struct snd_kcontrol * | |
| 835 | +snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid) | |
| 815 | 836 | { |
| 816 | 837 | if (snd_BUG_ON(!card || !numid)) |
| 817 | 838 | return NULL; |
| 839 | + lockdep_assert_held(&card->controls_rwsem); | |
| 818 | 840 | #ifdef CONFIG_SND_CTL_FAST_LOOKUP |
| 819 | 841 | return xa_load(&card->ctl_numids, numid); |
| 820 | 842 | #else |
| 821 | 843 | return snd_ctl_find_numid_slow(card, numid); |
| 822 | 844 | #endif |
| 823 | 845 | } |
| 846 | +EXPORT_SYMBOL(snd_ctl_find_numid_locked); | |
| 847 | + | |
| 848 | +/** | |
| 849 | + * snd_ctl_find_numid - find the control instance with the given number-id | |
| 850 | + * @card: the card instance | |
| 851 | + * @numid: the number-id to search | |
| 852 | + * | |
| 853 | + * Finds the control instance with the given number-id from the card. | |
| 854 | + * | |
| 855 | + * Return: The pointer of the instance if found, or %NULL if not. | |
| 856 | + * | |
| 857 | + * Note that this function takes card->controls_rwsem lock internally. | |
| 858 | + */ | |
| 859 | +struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, | |
| 860 | + unsigned int numid) | |
| 861 | +{ | |
| 862 | + struct snd_kcontrol *kctl; | |
| 863 | + | |
| 864 | + down_read(&card->controls_rwsem); | |
| 865 | + kctl = snd_ctl_find_numid_locked(card, numid); | |
| 866 | + up_read(&card->controls_rwsem); | |
| 867 | + return kctl; | |
| 868 | +} | |
| 824 | 869 | EXPORT_SYMBOL(snd_ctl_find_numid); |
| 825 | 870 | |
| 826 | 871 | /** |
| 827 | − * snd_ctl_find_id - find the control instance with the given id | |
| 872 | + * snd_ctl_find_id_locked - find the control instance with the given id | |
| 828 | 873 | * @card: the card instance |
| 829 | 874 | * @id: the id to search |
| 830 | 875 | * |
| @@ -834,17 +879,17 @@ EXPORT_SYMBOL(snd_ctl_find_numid); · 3 unmodified lines | ||
| 834 | 879 | * (if the race condition can happen). |
| 835 | 880 | * |
| 836 | 881 | * Return: The pointer of the instance if found, or %NULL if not. |
| 837 | − * | |
| 838 | 882 | */ |
| 839 | −struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, | |
| 840 | − struct snd_ctl_elem_id *id) | |
| 883 | +struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, | |
| 884 | + const struct snd_ctl_elem_id *id) | |
| 841 | 885 | { |
| 842 | 886 | struct snd_kcontrol *kctl; |
| 843 | 887 | |
| 844 | 888 | if (snd_BUG_ON(!card || !id)) |
| 845 | 889 | return NULL; |
| 890 | + lockdep_assert_held(&card->controls_rwsem); | |
| 846 | 891 | if (id->numid != 0) |
| 847 | − return snd_ctl_find_numid(card, id->numid); | |
| 892 | + return snd_ctl_find_numid_locked(card, id->numid); | |
| 848 | 893 | #ifdef CONFIG_SND_CTL_FAST_LOOKUP |
| 849 | 894 | kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id)); |
| 850 | 895 | if (kctl && elem_id_matches(kctl, id)) |
| @@ -859,6 +904,29 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, · 8 unmodified lines | ||
| 859 | 904 | |
| 860 | 905 | return NULL; |
| 861 | 906 | } |
| 907 | +EXPORT_SYMBOL(snd_ctl_find_id_locked); | |
| 908 | + | |
| 909 | +/** | |
| 910 | + * snd_ctl_find_id - find the control instance with the given id | |
| 911 | + * @card: the card instance | |
| 912 | + * @id: the id to search | |
| 913 | + * | |
| 914 | + * Finds the control instance with the given id from the card. | |
| 915 | + * | |
| 916 | + * Return: The pointer of the instance if found, or %NULL if not. | |
| 917 | + * | |
| 918 | + * Note that this function takes card->controls_rwsem lock internally. | |
| 919 | + */ | |
| 920 | +struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, | |
| 921 | + const struct snd_ctl_elem_id *id) | |
| 922 | +{ | |
| 923 | + struct snd_kcontrol *kctl; | |
| 924 | + | |
| 925 | + down_read(&card->controls_rwsem); | |
| 926 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 927 | + up_read(&card->controls_rwsem); | |
| 928 | + return kctl; | |
| 929 | +} | |
| 862 | 930 | EXPORT_SYMBOL(snd_ctl_find_id); |
| 863 | 931 | |
| 864 | 932 | static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, |
| @@ -1173,7 +1241,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, · 308 unmodified lines | ||
| 1173 | 1241 | int result; |
| 1174 | 1242 | |
| 1175 | 1243 | down_read(&card->controls_rwsem); |
| 1176 | − kctl = snd_ctl_find_id(card, &info->id); | |
| 1244 | + kctl = snd_ctl_find_id_locked(card, &info->id); | |
| 1177 | 1245 | if (kctl == NULL) |
| 1178 | 1246 | result = -ENOENT; |
| 1179 | 1247 | else |
| @@ -1212,7 +1280,7 @@ static int snd_ctl_elem_read(struct snd_card *card, · 32 unmodified lines | ||
| 1212 | 1280 | int ret; |
| 1213 | 1281 | |
| 1214 | 1282 | down_read(&card->controls_rwsem); |
| 1215 | − kctl = snd_ctl_find_id(card, &control->id); | |
| 1283 | + kctl = snd_ctl_find_id_locked(card, &control->id); | |
| 1216 | 1284 | if (kctl == NULL) { |
| 1217 | 1285 | ret = -ENOENT; |
| 1218 | 1286 | goto unlock; |
| @@ -1289,7 +1357,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, · 70 unmodified lines | ||
| 1289 | 1357 | int result; |
| 1290 | 1358 | |
| 1291 | 1359 | down_write(&card->controls_rwsem); |
| 1292 | − kctl = snd_ctl_find_id(card, &control->id); | |
| 1360 | + kctl = snd_ctl_find_id_locked(card, &control->id); | |
| 1293 | 1361 | if (kctl == NULL) { |
| 1294 | 1362 | up_write(&card->controls_rwsem); |
| 1295 | 1363 | return -ENOENT; |
| @@ -1370,7 +1438,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file, · 74 unmodified lines | ||
| 1370 | 1438 | if (copy_from_user(&id, _id, sizeof(id))) |
| 1371 | 1439 | return -EFAULT; |
| 1372 | 1440 | down_write(&card->controls_rwsem); |
| 1373 | − kctl = snd_ctl_find_id(card, &id); | |
| 1441 | + kctl = snd_ctl_find_id_locked(card, &id); | |
| 1374 | 1442 | if (kctl == NULL) { |
| 1375 | 1443 | result = -ENOENT; |
| 1376 | 1444 | } else { |
| @@ -1398,7 +1466,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file, · 21 unmodified lines | ||
| 1398 | 1466 | if (copy_from_user(&id, _id, sizeof(id))) |
| 1399 | 1467 | return -EFAULT; |
| 1400 | 1468 | down_write(&card->controls_rwsem); |
| 1401 | − kctl = snd_ctl_find_id(card, &id); | |
| 1469 | + kctl = snd_ctl_find_id_locked(card, &id); | |
| 1402 | 1470 | if (kctl == NULL) { |
| 1403 | 1471 | result = -ENOENT; |
| 1404 | 1472 | } else { |
| @@ -1507,6 +1575,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf, · 102 unmodified lines | ||
| 1507 | 1575 | int i; |
| 1508 | 1576 | int change; |
| 1509 | 1577 | |
| 1578 | + lockdep_assert_held_write(&ue->card->controls_rwsem); | |
| 1579 | + | |
| 1510 | 1580 | if (size > 1024 * 128) /* sane value */ |
| 1511 | 1581 | return -EINVAL; |
| 1512 | 1582 | |
| @@ -1583,6 +1653,8 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue) · 70 unmodified lines | ||
| 1583 | 1653 | unsigned int i; |
| 1584 | 1654 | const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr; |
| 1585 | 1655 | |
| 1656 | + lockdep_assert_held_write(&ue->card->controls_rwsem); | |
| 1657 | + | |
| 1586 | 1658 | buf_len = ue->info.value.enumerated.names_length; |
| 1587 | 1659 | if (buf_len > 64 * 1024) |
| 1588 | 1660 | return -EINVAL; |
| @@ -1887,6 +1959,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, · 298 unmodified lines | ||
| 1887 | 1959 | struct snd_ctl_elem_id id; |
| 1888 | 1960 | struct snd_kcontrol_volatile *vd; |
| 1889 | 1961 | |
| 1962 | + lockdep_assert_held(&file->card->controls_rwsem); | |
| 1963 | + | |
| 1890 | 1964 | if (copy_from_user(&header, buf, sizeof(header))) |
| 1891 | 1965 | return -EFAULT; |
| 1892 | 1966 | |
| @@ -1900,7 +1974,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, · 7 unmodified lines | ||
| 1900 | 1974 | container_size = header.length; |
| 1901 | 1975 | container = buf->tlv; |
| 1902 | 1976 | |
| 1903 | − kctl = snd_ctl_find_numid(file->card, header.numid); | |
| 1977 | + kctl = snd_ctl_find_numid_locked(file->card, header.numid); | |
| 1904 | 1978 | if (kctl == NULL) |
| 1905 | 1979 | return -ENOENT; |
| 1906 | 1980 | |
| @@ -2315,7 +2389,7 @@ static int snd_ctl_dev_register(struct snd_device *device) · 408 unmodified lines | ||
| 2315 | 2389 | int err; |
| 2316 | 2390 | |
| 2317 | 2391 | err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, |
| 2318 | − &snd_ctl_f_ops, card, &card->ctl_dev); | |
| 2392 | + &snd_ctl_f_ops, card, card->ctl_dev); | |
| 2319 | 2393 | if (err < 0) |
| 2320 | 2394 | return err; |
| 2321 | 2395 | down_read(&card->controls_rwsem); |
| @@ -2351,7 +2425,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) · 29 unmodified lines | ||
| 2351 | 2425 | up_read(&snd_ctl_layer_rwsem); |
| 2352 | 2426 | up_read(&card->controls_rwsem); |
| 2353 | 2427 | |
| 2354 | − return snd_unregister_device(&card->ctl_dev); | |
| 2428 | + return snd_unregister_device(card->ctl_dev); | |
| 2355 | 2429 | } |
| 2356 | 2430 | |
| 2357 | 2431 | /* |
| @@ -2373,7 +2447,7 @@ static int snd_ctl_dev_free(struct snd_device *device) · 15 unmodified lines | ||
| 2373 | 2447 | xa_destroy(&card->ctl_hash); |
| 2374 | 2448 | #endif |
| 2375 | 2449 | up_write(&card->controls_rwsem); |
| 2376 | − put_device(&card->ctl_dev); | |
| 2450 | + put_device(card->ctl_dev); | |
| 2377 | 2451 | return 0; |
| 2378 | 2452 | } |
| 2379 | 2453 | |
| @@ -2395,12 +2469,14 @@ int snd_ctl_create(struct snd_card *card) · 15 unmodified lines | ||
| 2395 | 2469 | if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS)) |
| 2396 | 2470 | return -ENXIO; |
| 2397 | 2471 | |
| 2398 | − snd_device_initialize(&card->ctl_dev, card); | |
| 2399 | − dev_set_name(&card->ctl_dev, "controlC%d", card->number); | |
| 2472 | + err = snd_device_alloc(&card->ctl_dev, card); | |
| 2473 | + if (err < 0) | |
| 2474 | + return err; | |
| 2475 | + dev_set_name(card->ctl_dev, "controlC%d", card->number); | |
| 2400 | 2476 | |
| 2401 | 2477 | err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); |
| 2402 | 2478 | if (err < 0) |
| 2403 | − put_device(&card->ctl_dev); | |
| 2479 | + put_device(card->ctl_dev); | |
| 2404 | 2480 | return err; |
| 2405 | 2481 | } |
| 2406 | 2482 | |
| @@ -173,7 +173,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, · 172 unmodified lines | ||
| 173 | 173 | int err; |
| 174 | 174 | |
| 175 | 175 | down_read(&card->controls_rwsem); |
| 176 | − kctl = snd_ctl_find_id(card, id); | |
| 176 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 177 | 177 | if (! kctl) { |
| 178 | 178 | up_read(&card->controls_rwsem); |
| 179 | 179 | return -ENOENT; |
| @@ -251,7 +251,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id, · 250 unmodified lines | ||
| 251 | 251 | card = snd_card_ref(card_number); |
| 252 | 252 | if (card) { |
| 253 | 253 | down_write(&card->controls_rwsem); |
| 254 | − kctl = snd_ctl_find_id(card, id); | |
| 254 | + kctl = snd_ctl_find_id_locked(card, id); | |
| 255 | 255 | if (kctl) { |
| 256 | 256 | ioff = snd_ctl_get_ioff(kctl, id); |
| 257 | 257 | vd = &kctl->vd[ioff]; |
| @@ -688,7 +688,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card) · 430 unmodified lines | ||
| 688 | 688 | goto cerr; |
| 689 | 689 | led->cards[card->number] = led_card; |
| 690 | 690 | snprintf(link_name, sizeof(link_name), "led-%s", led->name); |
| 691 | − WARN(sysfs_create_link(&card->ctl_dev.kobj, &led_card->dev.kobj, link_name), | |
| 691 | + WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name), | |
| 692 | 692 | "can't create symlink to controlC%i device\n", card->number); |
| 693 | 693 | WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"), |
| 694 | 694 | "can't create symlink to card%i\n", card->number); |
| @@ -714,7 +714,7 @@ static void snd_ctl_led_sysfs_remove(struct snd_card *card) · 19 unmodified lines | ||
| 714 | 714 | if (!led_card) |
| 715 | 715 | continue; |
| 716 | 716 | snprintf(link_name, sizeof(link_name), "led-%s", led->name); |
| 717 | − sysfs_remove_link(&card->ctl_dev.kobj, link_name); | |
| 717 | + sysfs_remove_link(&card->ctl_dev->kobj, link_name); | |
| 718 | 718 | sysfs_remove_link(&led_card->dev.kobj, "card"); |
| 719 | 719 | device_unregister(&led_card->dev); |
| 720 | 720 | led->cards[card->number] = NULL; |
| @@ -338,9 +338,14 @@ static const struct file_operations snd_hwdep_f_ops = · 337 unmodified lines | ||
| 338 | 338 | .mmap = snd_hwdep_mmap, |
| 339 | 339 | }; |
| 340 | 340 | |
| 341 | −static void release_hwdep_device(struct device *dev) | |
| 341 | +static void snd_hwdep_free(struct snd_hwdep *hwdep) | |
| 342 | 342 | { |
| 343 | − kfree(container_of(dev, struct snd_hwdep, dev)); | |
| 343 | + if (!hwdep) | |
| 344 | + return; | |
| 345 | + if (hwdep->private_free) | |
| 346 | + hwdep->private_free(hwdep); | |
| 347 | + put_device(hwdep->dev); | |
| 348 | + kfree(hwdep); | |
| 344 | 349 | } |
| 345 | 350 | |
| 346 | 351 | /** |
| @@ -382,16 +387,20 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, · 35 unmodified lines | ||
| 382 | 387 | if (id) |
| 383 | 388 | strscpy(hwdep->id, id, sizeof(hwdep->id)); |
| 384 | 389 | |
| 385 | − snd_device_initialize(&hwdep->dev, card); | |
| 386 | − hwdep->dev.release = release_hwdep_device; | |
| 387 | − dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device); | |
| 390 | + err = snd_device_alloc(&hwdep->dev, card); | |
| 391 | + if (err < 0) { | |
| 392 | + snd_hwdep_free(hwdep); | |
| 393 | + return err; | |
| 394 | + } | |
| 395 | + | |
| 396 | + dev_set_name(hwdep->dev, "hwC%iD%i", card->number, device); | |
| 388 | 397 | #ifdef CONFIG_SND_OSSEMUL |
| 389 | 398 | hwdep->oss_type = -1; |
| 390 | 399 | #endif |
| 391 | 400 | |
| 392 | 401 | err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops); |
| 393 | 402 | if (err < 0) { |
| 394 | − put_device(&hwdep->dev); | |
| 403 | + snd_hwdep_free(hwdep); | |
| 395 | 404 | return err; |
| 396 | 405 | } |
| 397 | 406 | |
| @@ -403,12 +412,7 @@ EXPORT_SYMBOL(snd_hwdep_new); · 5 unmodified lines | ||
| 403 | 412 | |
| 404 | 413 | static int snd_hwdep_dev_free(struct snd_device *device) |
| 405 | 414 | { |
| 406 | − struct snd_hwdep *hwdep = device->device_data; | |
| 407 | − if (!hwdep) | |
| 408 | − return 0; | |
| 409 | − if (hwdep->private_free) | |
| 410 | − hwdep->private_free(hwdep); | |
| 411 | − put_device(&hwdep->dev); | |
| 415 | + snd_hwdep_free(device->device_data); | |
| 412 | 416 | return 0; |
| 413 | 417 | } |
| 414 | 418 | |
| @@ -426,9 +430,9 @@ static int snd_hwdep_dev_register(struct snd_device *device) · 11 unmodified lines | ||
| 426 | 430 | list_add_tail(&hwdep->list, &snd_hwdep_devices); |
| 427 | 431 | err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, |
| 428 | 432 | hwdep->card, hwdep->device, |
| 429 | − &snd_hwdep_f_ops, hwdep, &hwdep->dev); | |
| 433 | + &snd_hwdep_f_ops, hwdep, hwdep->dev); | |
| 430 | 434 | if (err < 0) { |
| 431 | − dev_err(&hwdep->dev, "unable to register\n"); | |
| 435 | + dev_err(hwdep->dev, "unable to register\n"); | |
| 432 | 436 | list_del(&hwdep->list); |
| 433 | 437 | mutex_unlock(®ister_mutex); |
| 434 | 438 | return err; |
| @@ -439,12 +443,12 @@ static int snd_hwdep_dev_register(struct snd_device *device) · 4 unmodified lines | ||
| 439 | 443 | if (hwdep->oss_type >= 0) { |
| 440 | 444 | if (hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM && |
| 441 | 445 | hwdep->device) |
| 442 | − dev_warn(&hwdep->dev, | |
| 446 | + dev_warn(hwdep->dev, | |
| 443 | 447 | "only hwdep device 0 can be registered as OSS direct FM device!\n"); |
| 444 | 448 | else if (snd_register_oss_device(hwdep->oss_type, |
| 445 | 449 | card, hwdep->device, |
| 446 | 450 | &snd_hwdep_f_ops, hwdep) < 0) |
| 447 | − dev_warn(&hwdep->dev, | |
| 451 | + dev_warn(hwdep->dev, | |
| 448 | 452 | "unable to register OSS compatibility device\n"); |
| 449 | 453 | else |
| 450 | 454 | hwdep->ossreg = 1; |
| @@ -471,7 +475,7 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) · 20 unmodified lines | ||
| 471 | 475 | if (hwdep->ossreg) |
| 472 | 476 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
| 473 | 477 | #endif |
| 474 | − snd_unregister_device(&hwdep->dev); | |
| 478 | + snd_unregister_device(hwdep->dev); | |
| 475 | 479 | list_del_init(&hwdep->list); |
| 476 | 480 | mutex_unlock(&hwdep->open_mutex); |
| 477 | 481 | mutex_unlock(®ister_mutex); |
| @@ -111,28 +111,36 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), · 110 unmodified lines | ||
| 111 | 111 | return mask; /* unchanged */ |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | −/* the default release callback set in snd_device_initialize() below; | |
| 115 | − * this is just NOP for now, as almost all jobs are already done in | |
| 116 | − * dev_free callback of snd_device chain instead. | |
| 117 | − */ | |
| 118 | −static void default_release(struct device *dev) | |
| 114 | +/* the default release callback set in snd_device_alloc() */ | |
| 115 | +static void default_release_alloc(struct device *dev) | |
| 119 | 116 | { |
| 117 | + kfree(dev); | |
| 120 | 118 | } |
| 121 | 119 | |
| 122 | 120 | /** |
| 123 | − * snd_device_initialize - Initialize struct device for sound devices | |
| 124 | − * @dev: device to initialize | |
| 121 | + * snd_device_alloc - Allocate and initialize struct device for sound devices | |
| 122 | + * @dev_p: pointer to store the allocated device | |
| 125 | 123 | * @card: card to assign, optional |
| 124 | + * | |
| 125 | + * For releasing the allocated device, call put_device(). | |
| 126 | 126 | */ |
| 127 | −void snd_device_initialize(struct device *dev, struct snd_card *card) | |
| 127 | +int snd_device_alloc(struct device **dev_p, struct snd_card *card) | |
| 128 | 128 | { |
| 129 | + struct device *dev; | |
| 130 | + | |
| 131 | + *dev_p = NULL; | |
| 132 | + dev = kzalloc(sizeof(*dev), GFP_KERNEL); | |
| 133 | + if (!dev) | |
| 134 | + return -ENOMEM; | |
| 129 | 135 | device_initialize(dev); |
| 130 | 136 | if (card) |
| 131 | 137 | dev->parent = &card->card_dev; |
| 132 | 138 | dev->class = &sound_class; |
| 133 | − dev->release = default_release; | |
| 139 | + dev->release = default_release_alloc; | |
| 140 | + *dev_p = dev; | |
| 141 | + return 0; | |
| 134 | 142 | } |
| 135 | −EXPORT_SYMBOL_GPL(snd_device_initialize); | |
| 143 | +EXPORT_SYMBOL_GPL(snd_device_alloc); | |
| 136 | 144 | |
| 137 | 145 | static int snd_card_init(struct snd_card *card, struct device *parent, |
| 138 | 146 | int idx, const char *xid, struct module *module, |
| @@ -66,12 +66,10 @@ static int snd_jack_dev_free(struct snd_device *device) · 65 unmodified lines | ||
| 66 | 66 | struct snd_card *card = device->card; |
| 67 | 67 | struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl; |
| 68 | 68 | |
| 69 | − down_write(&card->controls_rwsem); | |
| 70 | 69 | list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) { |
| 71 | 70 | list_del_init(&jack_kctl->list); |
| 72 | 71 | snd_ctl_remove(card, jack_kctl->kctl); |
| 73 | 72 | } |
| 74 | − up_write(&card->controls_rwsem); | |
| 75 | 73 | |
| 76 | 74 | if (jack->private_free) |
| 77 | 75 | jack->private_free(jack); |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/io.h> |
| 10 | 10 | #include <linux/uaccess.h> |
| 11 | 11 | #include <sound/core.h> |
| 12 | +#include <sound/pcm.h> | |
| 12 | 13 | |
| 13 | 14 | /** |
| 14 | 15 | * copy_to_user_fromio - copy data from mmio-space to user-space |
| @@ -21,9 +22,30 @@ · 6 unmodified lines | ||
| 21 | 22 | * Return: Zero if successful, or non-zero on failure. |
| 22 | 23 | */ |
| 23 | 24 | int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count) |
| 25 | +{ | |
| 26 | + struct iov_iter iter; | |
| 27 | + | |
| 28 | + if (import_ubuf(ITER_DEST, dst, count, &iter)) | |
| 29 | + return -EFAULT; | |
| 30 | + return copy_to_iter_fromio(&iter, (const void __iomem *)src, count); | |
| 31 | +} | |
| 32 | +EXPORT_SYMBOL(copy_to_user_fromio); | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * copy_to_iter_fromio - copy data from mmio-space to iov_iter | |
| 36 | + * @dst: the destination iov_iter | |
| 37 | + * @src: the source pointer on mmio | |
| 38 | + * @count: the data size to copy in bytes | |
| 39 | + * | |
| 40 | + * Copies the data from mmio-space to iov_iter. | |
| 41 | + * | |
| 42 | + * Return: Zero if successful, or non-zero on failure. | |
| 43 | + */ | |
| 44 | +int copy_to_iter_fromio(struct iov_iter *dst, const void __iomem *src, | |
| 45 | + size_t count) | |
| 24 | 46 | { |
| 25 | 47 | #if defined(__i386__) || defined(CONFIG_SPARC32) |
| 26 | − return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0; | |
| 48 | + return copy_to_iter((const void __force *)src, count, dst) == count ? 0 : -EFAULT; | |
| 27 | 49 | #else |
| 28 | 50 | char buf[256]; |
| 29 | 51 | while (count) { |
| @@ -31,16 +53,15 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size · 1 unmodified line | ||
| 31 | 53 | if (c > sizeof(buf)) |
| 32 | 54 | c = sizeof(buf); |
| 33 | 55 | memcpy_fromio(buf, (void __iomem *)src, c); |
| 34 | − if (copy_to_user(dst, buf, c)) | |
| 56 | + if (copy_to_iter(buf, c, dst) != c) | |
| 35 | 57 | return -EFAULT; |
| 36 | 58 | count -= c; |
| 37 | − dst += c; | |
| 38 | 59 | src += c; |
| 39 | 60 | } |
| 40 | 61 | return 0; |
| 41 | 62 | #endif |
| 42 | 63 | } |
| 43 | −EXPORT_SYMBOL(copy_to_user_fromio); | |
| 64 | +EXPORT_SYMBOL(copy_to_iter_fromio); | |
| 44 | 65 | |
| 45 | 66 | /** |
| 46 | 67 | * copy_from_user_toio - copy data from user-space to mmio-space |
| @@ -53,23 +74,42 @@ EXPORT_SYMBOL(copy_to_user_fromio); · 6 unmodified lines | ||
| 53 | 74 | * Return: Zero if successful, or non-zero on failure. |
| 54 | 75 | */ |
| 55 | 76 | int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count) |
| 77 | +{ | |
| 78 | + struct iov_iter iter; | |
| 79 | + | |
| 80 | + if (import_ubuf(ITER_SOURCE, (void __user *)src, count, &iter)) | |
| 81 | + return -EFAULT; | |
| 82 | + return copy_from_iter_toio((void __iomem *)dst, &iter, count); | |
| 83 | +} | |
| 84 | +EXPORT_SYMBOL(copy_from_user_toio); | |
| 85 | + | |
| 86 | +/** | |
| 87 | + * copy_from_iter_toio - copy data from iov_iter to mmio-space | |
| 88 | + * @dst: the destination pointer on mmio-space | |
| 89 | + * @src: the source iov_iter | |
| 90 | + * @count: the data size to copy in bytes | |
| 91 | + * | |
| 92 | + * Copies the data from iov_iter to mmio-space. | |
| 93 | + * | |
| 94 | + * Return: Zero if successful, or non-zero on failure. | |
| 95 | + */ | |
| 96 | +int copy_from_iter_toio(void __iomem *dst, struct iov_iter *src, size_t count) | |
| 56 | 97 | { |
| 57 | 98 | #if defined(__i386__) || defined(CONFIG_SPARC32) |
| 58 | − return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0; | |
| 99 | + return copy_from_iter((void __force *)dst, count, src) == count ? 0 : -EFAULT; | |
| 59 | 100 | #else |
| 60 | 101 | char buf[256]; |
| 61 | 102 | while (count) { |
| 62 | 103 | size_t c = count; |
| 63 | 104 | if (c > sizeof(buf)) |
| 64 | 105 | c = sizeof(buf); |
| 65 | − if (copy_from_user(buf, src, c)) | |
| 106 | + if (copy_from_iter(buf, c, src) != c) | |
| 66 | 107 | return -EFAULT; |
| 67 | 108 | memcpy_toio(dst, buf, c); |
| 68 | 109 | count -= c; |
| 69 | 110 | dst += c; |
| 70 | − src += c; | |
| 71 | 111 | } |
| 72 | 112 | return 0; |
| 73 | 113 | #endif |
| 74 | 114 | } |
| 75 | −EXPORT_SYMBOL(copy_from_user_toio); | |
| 115 | +EXPORT_SYMBOL(copy_from_iter_toio); | |
| @@ -524,7 +524,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c · 523 unmodified lines | ||
| 524 | 524 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
| 525 | 525 | strscpy(id.name, name, sizeof(id.name)); |
| 526 | 526 | id.index = index; |
| 527 | − return snd_ctl_find_id(card, &id); | |
| 527 | + return snd_ctl_find_id_locked(card, &id); | |
| 528 | 528 | } |
| 529 | 529 | |
| 530 | 530 | static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, |
| @@ -540,7 +540,7 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, · 9 unmodified lines | ||
| 540 | 540 | if (numid == ID_UNKNOWN) |
| 541 | 541 | return; |
| 542 | 542 | down_read(&card->controls_rwsem); |
| 543 | − kctl = snd_ctl_find_numid(card, numid); | |
| 543 | + kctl = snd_ctl_find_numid_locked(card, numid); | |
| 544 | 544 | if (!kctl) { |
| 545 | 545 | up_read(&card->controls_rwsem); |
| 546 | 546 | return; |
| @@ -579,7 +579,7 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, · 32 unmodified lines | ||
| 579 | 579 | if (numid == ID_UNKNOWN) |
| 580 | 580 | return; |
| 581 | 581 | down_read(&card->controls_rwsem); |
| 582 | − kctl = snd_ctl_find_numid(card, numid); | |
| 582 | + kctl = snd_ctl_find_numid_locked(card, numid); | |
| 583 | 583 | if (!kctl) { |
| 584 | 584 | up_read(&card->controls_rwsem); |
| 585 | 585 | return; |
| @@ -645,7 +645,7 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, · 59 unmodified lines | ||
| 645 | 645 | if (numid == ID_UNKNOWN) |
| 646 | 646 | return; |
| 647 | 647 | down_read(&card->controls_rwsem); |
| 648 | − kctl = snd_ctl_find_numid(card, numid); | |
| 648 | + kctl = snd_ctl_find_numid_locked(card, numid); | |
| 649 | 649 | if (!kctl) { |
| 650 | 650 | up_read(&card->controls_rwsem); |
| 651 | 651 | return; |
| @@ -688,7 +688,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, · 36 unmodified lines | ||
| 688 | 688 | if (numid == ID_UNKNOWN) |
| 689 | 689 | return; |
| 690 | 690 | down_read(&card->controls_rwsem); |
| 691 | − kctl = snd_ctl_find_numid(card, numid); | |
| 691 | + kctl = snd_ctl_find_numid_locked(card, numid); | |
| 692 | 692 | if (!kctl) { |
| 693 | 693 | up_read(&card->controls_rwsem); |
| 694 | 694 | return; |
| @@ -604,7 +604,7 @@ static const struct attribute_group *pcm_dev_attr_groups[]; · 603 unmodified lines | ||
| 604 | 604 | #ifdef CONFIG_PM_SLEEP |
| 605 | 605 | static int do_pcm_suspend(struct device *dev) |
| 606 | 606 | { |
| 607 | − struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev); | |
| 607 | + struct snd_pcm_str *pstr = dev_get_drvdata(dev); | |
| 608 | 608 | |
| 609 | 609 | if (!pstr->pcm->no_device_suspend) |
| 610 | 610 | snd_pcm_suspend_all(pstr->pcm); |
| @@ -650,11 +650,14 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) · 39 unmodified lines | ||
| 650 | 650 | if (!substream_count) |
| 651 | 651 | return 0; |
| 652 | 652 | |
| 653 | − snd_device_initialize(&pstr->dev, pcm->card); | |
| 654 | − pstr->dev.groups = pcm_dev_attr_groups; | |
| 655 | − pstr->dev.type = &pcm_dev_type; | |
| 656 | − dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device, | |
| 653 | + err = snd_device_alloc(&pstr->dev, pcm->card); | |
| 654 | + if (err < 0) | |
| 655 | + return err; | |
| 656 | + dev_set_name(pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device, | |
| 657 | 657 | stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'); |
| 658 | + pstr->dev->groups = pcm_dev_attr_groups; | |
| 659 | + pstr->dev->type = &pcm_dev_type; | |
| 660 | + dev_set_drvdata(pstr->dev, pstr); | |
| 658 | 661 | |
| 659 | 662 | if (!pcm->internal) { |
| 660 | 663 | err = snd_pcm_stream_proc_init(pstr); |
| @@ -814,9 +817,7 @@ static void free_chmap(struct snd_pcm_str *pstr) · 153 unmodified lines | ||
| 814 | 817 | if (pstr->chmap_kctl) { |
| 815 | 818 | struct snd_card *card = pstr->pcm->card; |
| 816 | 819 | |
| 817 | − down_write(&card->controls_rwsem); | |
| 818 | 820 | snd_ctl_remove(card, pstr->chmap_kctl); |
| 819 | − up_write(&card->controls_rwsem); | |
| 820 | 821 | pstr->chmap_kctl = NULL; |
| 821 | 822 | } |
| 822 | 823 | } |
| @@ -847,7 +848,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) · 24 unmodified lines | ||
| 847 | 848 | #endif |
| 848 | 849 | free_chmap(pstr); |
| 849 | 850 | if (pstr->substream_count) |
| 850 | − put_device(&pstr->dev); | |
| 851 | + put_device(pstr->dev); | |
| 851 | 852 | } |
| 852 | 853 | |
| 853 | 854 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
| @@ -1017,7 +1018,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) · 163 unmodified lines | ||
| 1017 | 1018 | static ssize_t pcm_class_show(struct device *dev, |
| 1018 | 1019 | struct device_attribute *attr, char *buf) |
| 1019 | 1020 | { |
| 1020 | − struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev); | |
| 1021 | + struct snd_pcm_str *pstr = dev_get_drvdata(dev); | |
| 1021 | 1022 | struct snd_pcm *pcm = pstr->pcm; |
| 1022 | 1023 | const char *str; |
| 1023 | 1024 | static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = { |
| @@ -1078,7 +1079,7 @@ static int snd_pcm_dev_register(struct snd_device *device) · 54 unmodified lines | ||
| 1078 | 1079 | /* register pcm */ |
| 1079 | 1080 | err = snd_register_device(devtype, pcm->card, pcm->device, |
| 1080 | 1081 | &snd_pcm_f_ops[cidx], pcm, |
| 1081 | − &pcm->streams[cidx].dev); | |
| 1082 | + pcm->streams[cidx].dev); | |
| 1082 | 1083 | if (err < 0) { |
| 1083 | 1084 | list_del_init(&pcm->list); |
| 1084 | 1085 | goto unlock; |
| @@ -1125,7 +1126,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) · 40 unmodified lines | ||
| 1125 | 1126 | |
| 1126 | 1127 | pcm_call_notify(pcm, n_disconnect); |
| 1127 | 1128 | for (cidx = 0; cidx < 2; cidx++) { |
| 1128 | − snd_unregister_device(&pcm->streams[cidx].dev); | |
| 1129 | + if (pcm->streams[cidx].dev) | |
| 1130 | + snd_unregister_device(pcm->streams[cidx].dev); | |
| 1129 | 1131 | free_chmap(&pcm->streams[cidx]); |
| 1130 | 1132 | } |
| 1131 | 1133 | mutex_unlock(&pcm->open_mutex); |
| @@ -253,10 +253,14 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, · 252 unmodified lines | ||
| 253 | 253 | goto error; |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | − if (refine) | |
| 256 | + if (refine) { | |
| 257 | 257 | err = snd_pcm_hw_refine(substream, data); |
| 258 | − else | |
| 258 | + if (err < 0) | |
| 259 | + goto error; | |
| 260 | + err = fixup_unreferenced_params(substream, data); | |
| 261 | + } else { | |
| 259 | 262 | err = snd_pcm_hw_params(substream, data); |
| 263 | + } | |
| 260 | 264 | if (err < 0) |
| 261 | 265 | goto error; |
| 262 | 266 | if (copy_to_user(data32, data, sizeof(*data32)) || |
| @@ -1973,10 +1973,11 @@ static int wait_for_avail(struct snd_pcm_substream *substream, · 1972 unmodified lines | ||
| 1973 | 1973 | |
| 1974 | 1974 | typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream, |
| 1975 | 1975 | int channel, unsigned long hwoff, |
| 1976 | − void *buf, unsigned long bytes); | |
| 1976 | + struct iov_iter *iter, unsigned long bytes); | |
| 1977 | 1977 | |
| 1978 | 1978 | typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *, |
| 1979 | − snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f); | |
| 1979 | + snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f, | |
| 1980 | + bool); | |
| 1980 | 1981 | |
| 1981 | 1982 | /* calculate the target DMA-buffer position to be written/read */ |
| 1982 | 1983 | static void *get_dma_ptr(struct snd_pcm_runtime *runtime, |
| @@ -1986,32 +1987,24 @@ static void *get_dma_ptr(struct snd_pcm_runtime *runtime, · 3 unmodified lines | ||
| 1986 | 1987 | channel * (runtime->dma_bytes / runtime->channels); |
| 1987 | 1988 | } |
| 1988 | 1989 | |
| 1989 | −/* default copy_user ops for write; used for both interleaved and non- modes */ | |
| 1990 | +/* default copy ops for write; used for both interleaved and non- modes */ | |
| 1990 | 1991 | static int default_write_copy(struct snd_pcm_substream *substream, |
| 1991 | 1992 | int channel, unsigned long hwoff, |
| 1992 | − void *buf, unsigned long bytes) | |
| 1993 | + struct iov_iter *iter, unsigned long bytes) | |
| 1993 | 1994 | { |
| 1994 | − if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff), | |
| 1995 | − (void __user *)buf, bytes)) | |
| 1995 | + if (!copy_from_iter(get_dma_ptr(substream->runtime, channel, hwoff), | |
| 1996 | + bytes, iter)) | |
| 1996 | 1997 | return -EFAULT; |
| 1997 | 1998 | return 0; |
| 1998 | 1999 | } |
| 1999 | 2000 | |
| 2000 | −/* default copy_kernel ops for write */ | |
| 2001 | −static int default_write_copy_kernel(struct snd_pcm_substream *substream, | |
| 2002 | − int channel, unsigned long hwoff, | |
| 2003 | − void *buf, unsigned long bytes) | |
| 2004 | −{ | |
| 2005 | − memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes); | |
| 2006 | − return 0; | |
| 2007 | −} | |
| 2008 | − | |
| 2009 | 2001 | /* fill silence instead of copy data; called as a transfer helper |
| 2010 | 2002 | * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when |
| 2011 | 2003 | * a NULL buffer is passed |
| 2012 | 2004 | */ |
| 2013 | 2005 | static int fill_silence(struct snd_pcm_substream *substream, int channel, |
| 2014 | − unsigned long hwoff, void *buf, unsigned long bytes) | |
| 2006 | + unsigned long hwoff, struct iov_iter *iter, | |
| 2007 | + unsigned long bytes) | |
| 2015 | 2008 | { |
| 2016 | 2009 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 2017 | 2010 | |
| @@ -2027,25 +2020,41 @@ static int fill_silence(struct snd_pcm_substream *substream, int channel, · 9 unmodified lines | ||
| 2027 | 2020 | return 0; |
| 2028 | 2021 | } |
| 2029 | 2022 | |
| 2030 | −/* default copy_user ops for read; used for both interleaved and non- modes */ | |
| 2023 | +/* default copy ops for read; used for both interleaved and non- modes */ | |
| 2031 | 2024 | static int default_read_copy(struct snd_pcm_substream *substream, |
| 2032 | 2025 | int channel, unsigned long hwoff, |
| 2033 | − void *buf, unsigned long bytes) | |
| 2026 | + struct iov_iter *iter, unsigned long bytes) | |
| 2034 | 2027 | { |
| 2035 | − if (copy_to_user((void __user *)buf, | |
| 2036 | − get_dma_ptr(substream->runtime, channel, hwoff), | |
| 2037 | − bytes)) | |
| 2028 | + if (!copy_to_iter(get_dma_ptr(substream->runtime, channel, hwoff), | |
| 2029 | + bytes, iter)) | |
| 2038 | 2030 | return -EFAULT; |
| 2039 | 2031 | return 0; |
| 2040 | 2032 | } |
| 2041 | 2033 | |
| 2042 | −/* default copy_kernel ops for read */ | |
| 2043 | −static int default_read_copy_kernel(struct snd_pcm_substream *substream, | |
| 2044 | − int channel, unsigned long hwoff, | |
| 2045 | − void *buf, unsigned long bytes) | |
| 2034 | +/* call transfer with the filled iov_iter */ | |
| 2035 | +static int do_transfer(struct snd_pcm_substream *substream, int c, | |
| 2036 | + unsigned long hwoff, void *data, unsigned long bytes, | |
| 2037 | + pcm_transfer_f transfer, bool in_kernel) | |
| 2046 | 2038 | { |
| 2047 | − memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes); | |
| 2048 | − return 0; | |
| 2039 | + struct iov_iter iter; | |
| 2040 | + int err, type; | |
| 2041 | + | |
| 2042 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
| 2043 | + type = ITER_SOURCE; | |
| 2044 | + else | |
| 2045 | + type = ITER_DEST; | |
| 2046 | + | |
| 2047 | + if (in_kernel) { | |
| 2048 | + struct kvec kvec = { data, bytes }; | |
| 2049 | + | |
| 2050 | + iov_iter_kvec(&iter, type, &kvec, 1, bytes); | |
| 2051 | + return transfer(substream, c, hwoff, &iter, bytes); | |
| 2052 | + } | |
| 2053 | + | |
| 2054 | + err = import_ubuf(type, (__force void __user *)data, bytes, &iter); | |
| 2055 | + if (err) | |
| 2056 | + return err; | |
| 2057 | + return transfer(substream, c, hwoff, &iter, bytes); | |
| 2049 | 2058 | } |
| 2050 | 2059 | |
| 2051 | 2060 | /* call transfer function with the converted pointers and sizes; |
| @@ -2055,7 +2064,8 @@ static int interleaved_copy(struct snd_pcm_substream *substream, · 3 unmodified lines | ||
| 2055 | 2064 | snd_pcm_uframes_t hwoff, void *data, |
| 2056 | 2065 | snd_pcm_uframes_t off, |
| 2057 | 2066 | snd_pcm_uframes_t frames, |
| 2058 | − pcm_transfer_f transfer) | |
| 2067 | + pcm_transfer_f transfer, | |
| 2068 | + bool in_kernel) | |
| 2059 | 2069 | { |
| 2060 | 2070 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 2061 | 2071 | |
| @@ -2063,7 +2073,9 @@ static int interleaved_copy(struct snd_pcm_substream *substream, · 1 unmodified line | ||
| 2063 | 2073 | hwoff = frames_to_bytes(runtime, hwoff); |
| 2064 | 2074 | off = frames_to_bytes(runtime, off); |
| 2065 | 2075 | frames = frames_to_bytes(runtime, frames); |
| 2066 | − return transfer(substream, 0, hwoff, data + off, frames); | |
| 2076 | + | |
| 2077 | + return do_transfer(substream, 0, hwoff, data + off, frames, transfer, | |
| 2078 | + in_kernel); | |
| 2067 | 2079 | } |
| 2068 | 2080 | |
| 2069 | 2081 | /* call transfer function with the converted pointers and sizes for each |
| @@ -2073,7 +2085,8 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream, · 3 unmodified lines | ||
| 2073 | 2085 | snd_pcm_uframes_t hwoff, void *data, |
| 2074 | 2086 | snd_pcm_uframes_t off, |
| 2075 | 2087 | snd_pcm_uframes_t frames, |
| 2076 | − pcm_transfer_f transfer) | |
| 2088 | + pcm_transfer_f transfer, | |
| 2089 | + bool in_kernel) | |
| 2077 | 2090 | { |
| 2078 | 2091 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 2079 | 2092 | int channels = runtime->channels; |
| @@ -2091,8 +2104,8 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream, · 11 unmodified lines | ||
| 2091 | 2104 | if (!data || !*bufs) |
| 2092 | 2105 | err = fill_silence(substream, c, hwoff, NULL, frames); |
| 2093 | 2106 | else |
| 2094 | − err = transfer(substream, c, hwoff, *bufs + off, | |
| 2095 | − frames); | |
| 2107 | + err = do_transfer(substream, c, hwoff, *bufs + off, | |
| 2108 | + frames, transfer, in_kernel); | |
| 2096 | 2109 | if (err < 0) |
| 2097 | 2110 | return err; |
| 2098 | 2111 | } |
| @@ -2108,10 +2121,10 @@ static int fill_silence_frames(struct snd_pcm_substream *substream, · 9 unmodified lines | ||
| 2108 | 2121 | if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || |
| 2109 | 2122 | substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
| 2110 | 2123 | return interleaved_copy(substream, off, NULL, 0, frames, |
| 2111 | − fill_silence); | |
| 2124 | + fill_silence, true); | |
| 2112 | 2125 | else |
| 2113 | 2126 | return noninterleaved_copy(substream, off, NULL, 0, frames, |
| 2114 | − fill_silence); | |
| 2127 | + fill_silence, true); | |
| 2115 | 2128 | } |
| 2116 | 2129 | |
| 2117 | 2130 | /* sanity-check for read/write methods */ |
| @@ -2121,7 +2134,7 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) · 3 unmodified lines | ||
| 2121 | 2134 | if (PCM_RUNTIME_CHECK(substream)) |
| 2122 | 2135 | return -ENXIO; |
| 2123 | 2136 | runtime = substream->runtime; |
| 2124 | − if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) | |
| 2137 | + if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) | |
| 2125 | 2138 | return -EINVAL; |
| 2126 | 2139 | if (runtime->state == SNDRV_PCM_STATE_OPEN) |
| 2127 | 2140 | return -EBADFD; |
| @@ -2226,15 +2239,9 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, · 98 unmodified lines | ||
| 2226 | 2239 | transfer = fill_silence; |
| 2227 | 2240 | else |
| 2228 | 2241 | return -EINVAL; |
| 2229 | − } else if (in_kernel) { | |
| 2230 | − if (substream->ops->copy_kernel) | |
| 2231 | − transfer = substream->ops->copy_kernel; | |
| 2232 | − else | |
| 2233 | − transfer = is_playback ? | |
| 2234 | − default_write_copy_kernel : default_read_copy_kernel; | |
| 2235 | 2242 | } else { |
| 2236 | − if (substream->ops->copy_user) | |
| 2237 | − transfer = (pcm_transfer_f)substream->ops->copy_user; | |
| 2243 | + if (substream->ops->copy) | |
| 2244 | + transfer = substream->ops->copy; | |
| 2238 | 2245 | else |
| 2239 | 2246 | transfer = is_playback ? |
| 2240 | 2247 | default_write_copy : default_read_copy; |
| @@ -2307,7 +2314,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, · 66 unmodified lines | ||
| 2307 | 2314 | if (!is_playback) |
| 2308 | 2315 | snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_CPU); |
| 2309 | 2316 | err = writer(substream, appl_ofs, data, offset, frames, |
| 2310 | − transfer); | |
| 2317 | + transfer, in_kernel); | |
| 2311 | 2318 | if (is_playback) |
| 2312 | 2319 | snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE); |
| 2313 | 2320 | snd_pcm_stream_lock_irq(substream); |
| @@ -809,7 +809,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, · 808 unmodified lines | ||
| 809 | 809 | runtime->boundary *= 2; |
| 810 | 810 | |
| 811 | 811 | /* clear the buffer for avoiding possible kernel info leaks */ |
| 812 | − if (runtime->dma_area && !substream->ops->copy_user) { | |
| 812 | + if (runtime->dma_area && !substream->ops->copy) { | |
| 813 | 813 | size_t size = runtime->dma_bytes; |
| 814 | 814 | |
| 815 | 815 | if (runtime->info & SNDRV_PCM_INFO_MMAP) |
| @@ -44,11 +44,11 @@ static LIST_HEAD(snd_rawmidi_devices); · 43 unmodified lines | ||
| 44 | 44 | static DEFINE_MUTEX(register_mutex); |
| 45 | 45 | |
| 46 | 46 | #define rmidi_err(rmidi, fmt, args...) \ |
| 47 | − dev_err(&(rmidi)->dev, fmt, ##args) | |
| 47 | + dev_err((rmidi)->dev, fmt, ##args) | |
| 48 | 48 | #define rmidi_warn(rmidi, fmt, args...) \ |
| 49 | − dev_warn(&(rmidi)->dev, fmt, ##args) | |
| 49 | + dev_warn((rmidi)->dev, fmt, ##args) | |
| 50 | 50 | #define rmidi_dbg(rmidi, fmt, args...) \ |
| 51 | − dev_dbg(&(rmidi)->dev, fmt, ##args) | |
| 51 | + dev_dbg((rmidi)->dev, fmt, ##args) | |
| 52 | 52 | |
| 53 | 53 | struct snd_rawmidi_status32 { |
| 54 | 54 | s32 stream; |
| @@ -1877,11 +1877,6 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi, · 1822 unmodified lines | ||
| 1877 | 1877 | return 0; |
| 1878 | 1878 | } |
| 1879 | 1879 | |
| 1880 | −static void release_rawmidi_device(struct device *dev) | |
| 1881 | −{ | |
| 1882 | − kfree(container_of(dev, struct snd_rawmidi, dev)); | |
| 1883 | −} | |
| 1884 | − | |
| 1885 | 1880 | /* used for both rawmidi and ump */ |
| 1886 | 1881 | int snd_rawmidi_init(struct snd_rawmidi *rmidi, |
| 1887 | 1882 | struct snd_card *card, char *id, int device, |
| @@ -1906,12 +1901,13 @@ int snd_rawmidi_init(struct snd_rawmidi *rmidi, · 18 unmodified lines | ||
| 1906 | 1901 | if (id != NULL) |
| 1907 | 1902 | strscpy(rmidi->id, id, sizeof(rmidi->id)); |
| 1908 | 1903 | |
| 1909 | − snd_device_initialize(&rmidi->dev, card); | |
| 1910 | − rmidi->dev.release = release_rawmidi_device; | |
| 1904 | + err = snd_device_alloc(&rmidi->dev, card); | |
| 1905 | + if (err < 0) | |
| 1906 | + return err; | |
| 1911 | 1907 | if (rawmidi_is_ump(rmidi)) |
| 1912 | − dev_set_name(&rmidi->dev, "umpC%iD%i", card->number, device); | |
| 1908 | + dev_set_name(rmidi->dev, "umpC%iD%i", card->number, device); | |
| 1913 | 1909 | else |
| 1914 | − dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device); | |
| 1910 | + dev_set_name(rmidi->dev, "midiC%iD%i", card->number, device); | |
| 1915 | 1911 | |
| 1916 | 1912 | err = snd_rawmidi_alloc_substreams(rmidi, |
| 1917 | 1913 | &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], |
| @@ -1996,7 +1992,8 @@ int snd_rawmidi_free(struct snd_rawmidi *rmidi) · 78 unmodified lines | ||
| 1996 | 1992 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); |
| 1997 | 1993 | if (rmidi->private_free) |
| 1998 | 1994 | rmidi->private_free(rmidi); |
| 1999 | − put_device(&rmidi->dev); | |
| 1995 | + put_device(rmidi->dev); | |
| 1996 | + kfree(rmidi); | |
| 2000 | 1997 | return 0; |
| 2001 | 1998 | } |
| 2002 | 1999 | EXPORT_SYMBOL_GPL(snd_rawmidi_free); |
| @@ -2038,7 +2035,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) · 35 unmodified lines | ||
| 2038 | 2035 | |
| 2039 | 2036 | err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, |
| 2040 | 2037 | rmidi->card, rmidi->device, |
| 2041 | − &snd_rawmidi_f_ops, rmidi, &rmidi->dev); | |
| 2038 | + &snd_rawmidi_f_ops, rmidi, rmidi->dev); | |
| 2042 | 2039 | if (err < 0) { |
| 2043 | 2040 | rmidi_err(rmidi, "unable to register\n"); |
| 2044 | 2041 | goto error; |
| @@ -2103,7 +2100,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) · 58 unmodified lines | ||
| 2103 | 2100 | return 0; |
| 2104 | 2101 | |
| 2105 | 2102 | error_unregister: |
| 2106 | − snd_unregister_device(&rmidi->dev); | |
| 2103 | + snd_unregister_device(rmidi->dev); | |
| 2107 | 2104 | error: |
| 2108 | 2105 | mutex_lock(®ister_mutex); |
| 2109 | 2106 | list_del(&rmidi->list); |
| @@ -2142,7 +2139,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) · 32 unmodified lines | ||
| 2142 | 2139 | rmidi->ossreg = 0; |
| 2143 | 2140 | } |
| 2144 | 2141 | #endif /* CONFIG_SND_OSSEMUL */ |
| 2145 | − snd_unregister_device(&rmidi->dev); | |
| 2142 | + snd_unregister_device(rmidi->dev); | |
| 2146 | 2143 | mutex_unlock(&rmidi->open_mutex); |
| 2147 | 2144 | mutex_unlock(®ister_mutex); |
| 2148 | 2145 | return 0; |
| @@ -2721,7 +2721,7 @@ static const struct file_operations snd_seq_f_ops = · 2720 unmodified lines | ||
| 2721 | 2721 | .compat_ioctl = snd_seq_ioctl_compat, |
| 2722 | 2722 | }; |
| 2723 | 2723 | |
| 2724 | −static struct device seq_dev; | |
| 2724 | +static struct device *seq_dev; | |
| 2725 | 2725 | |
| 2726 | 2726 | /* |
| 2727 | 2727 | * register sequencer device |
| @@ -2730,15 +2730,17 @@ int __init snd_sequencer_device_init(void) · 2 unmodified lines | ||
| 2730 | 2730 | { |
| 2731 | 2731 | int err; |
| 2732 | 2732 | |
| 2733 | − snd_device_initialize(&seq_dev, NULL); | |
| 2734 | − dev_set_name(&seq_dev, "seq"); | |
| 2733 | + err = snd_device_alloc(&seq_dev, NULL); | |
| 2734 | + if (err < 0) | |
| 2735 | + return err; | |
| 2736 | + dev_set_name(seq_dev, "seq"); | |
| 2735 | 2737 | |
| 2736 | 2738 | mutex_lock(®ister_mutex); |
| 2737 | 2739 | err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, |
| 2738 | − &snd_seq_f_ops, NULL, &seq_dev); | |
| 2740 | + &snd_seq_f_ops, NULL, seq_dev); | |
| 2739 | 2741 | mutex_unlock(®ister_mutex); |
| 2740 | 2742 | if (err < 0) { |
| 2741 | − put_device(&seq_dev); | |
| 2743 | + put_device(seq_dev); | |
| 2742 | 2744 | return err; |
| 2743 | 2745 | } |
| 2744 | 2746 | |
| @@ -2752,6 +2754,6 @@ int __init snd_sequencer_device_init(void) · 7 unmodified lines | ||
| 2752 | 2754 | */ |
| 2753 | 2755 | void snd_sequencer_device_done(void) |
| 2754 | 2756 | { |
| 2755 | − snd_unregister_device(&seq_dev); | |
| 2756 | − put_device(&seq_dev); | |
| 2757 | + snd_unregister_device(seq_dev); | |
| 2758 | + put_device(seq_dev); | |
| 2757 | 2759 | } |
| @@ -2301,7 +2301,7 @@ static void snd_timer_free_all(void) · 2300 unmodified lines | ||
| 2301 | 2301 | snd_timer_free(timer); |
| 2302 | 2302 | } |
| 2303 | 2303 | |
| 2304 | −static struct device timer_dev; | |
| 2304 | +static struct device *timer_dev; | |
| 2305 | 2305 | |
| 2306 | 2306 | /* |
| 2307 | 2307 | * ENTRY functions |
| @@ -2311,8 +2311,10 @@ static int __init alsa_timer_init(void) · 3 unmodified lines | ||
| 2311 | 2311 | { |
| 2312 | 2312 | int err; |
| 2313 | 2313 | |
| 2314 | − snd_device_initialize(&timer_dev, NULL); | |
| 2315 | − dev_set_name(&timer_dev, "timer"); | |
| 2314 | + err = snd_device_alloc(&timer_dev, NULL); | |
| 2315 | + if (err < 0) | |
| 2316 | + return err; | |
| 2317 | + dev_set_name(timer_dev, "timer"); | |
| 2316 | 2318 | |
| 2317 | 2319 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
| 2318 | 2320 | snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, |
| @@ -2326,7 +2328,7 @@ static int __init alsa_timer_init(void) · 7 unmodified lines | ||
| 2326 | 2328 | } |
| 2327 | 2329 | |
| 2328 | 2330 | err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, |
| 2329 | − &snd_timer_f_ops, NULL, &timer_dev); | |
| 2331 | + &snd_timer_f_ops, NULL, timer_dev); | |
| 2330 | 2332 | if (err < 0) { |
| 2331 | 2333 | pr_err("ALSA: unable to register timer device (%i)\n", err); |
| 2332 | 2334 | snd_timer_free_all(); |
| @@ -2337,15 +2339,15 @@ static int __init alsa_timer_init(void) · 4 unmodified lines | ||
| 2337 | 2339 | return 0; |
| 2338 | 2340 | |
| 2339 | 2341 | put_timer: |
| 2340 | − put_device(&timer_dev); | |
| 2342 | + put_device(timer_dev); | |
| 2341 | 2343 | return err; |
| 2342 | 2344 | } |
| 2343 | 2345 | |
| 2344 | 2346 | static void __exit alsa_timer_exit(void) |
| 2345 | 2347 | { |
| 2346 | − snd_unregister_device(&timer_dev); | |
| 2348 | + snd_unregister_device(timer_dev); | |
| 2347 | 2349 | snd_timer_free_all(); |
| 2348 | − put_device(&timer_dev); | |
| 2350 | + put_device(timer_dev); | |
| 2349 | 2351 | snd_timer_proc_done(); |
| 2350 | 2352 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
| 2351 | 2353 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1); |
| @@ -13,10 +13,10 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <sound/ump.h> |
| 14 | 14 | #include <sound/ump_convert.h> |
| 15 | 15 | |
| 16 | −#define ump_err(ump, fmt, args...) dev_err(&(ump)->core.dev, fmt, ##args) | |
| 17 | −#define ump_warn(ump, fmt, args...) dev_warn(&(ump)->core.dev, fmt, ##args) | |
| 18 | −#define ump_info(ump, fmt, args...) dev_info(&(ump)->core.dev, fmt, ##args) | |
| 19 | −#define ump_dbg(ump, fmt, args...) dev_dbg(&(ump)->core.dev, fmt, ##args) | |
| 16 | +#define ump_err(ump, fmt, args...) dev_err((ump)->core.dev, fmt, ##args) | |
| 17 | +#define ump_warn(ump, fmt, args...) dev_warn((ump)->core.dev, fmt, ##args) | |
| 18 | +#define ump_info(ump, fmt, args...) dev_info((ump)->core.dev, fmt, ##args) | |
| 19 | +#define ump_dbg(ump, fmt, args...) dev_dbg((ump)->core.dev, fmt, ##args) | |
| 20 | 20 | |
| 21 | 21 | static int snd_ump_dev_register(struct snd_rawmidi *rmidi); |
| 22 | 22 | static int snd_ump_dev_unregister(struct snd_rawmidi *rmidi); |
| @@ -984,7 +984,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) · 961 unmodified lines | ||
| 984 | 984 | { |
| 985 | 985 | struct snd_ump_endpoint *ump = substream->rmidi->private_data; |
| 986 | 986 | int dir = substream->stream; |
| 987 | − int group = substream->number; | |
| 987 | + int group = ump->legacy_mapping[substream->number]; | |
| 988 | 988 | int err; |
| 989 | 989 | |
| 990 | 990 | mutex_lock(&ump->open_mutex); |
| @@ -1016,7 +1016,7 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream) · 25 unmodified lines | ||
| 1016 | 1016 | { |
| 1017 | 1017 | struct snd_ump_endpoint *ump = substream->rmidi->private_data; |
| 1018 | 1018 | int dir = substream->stream; |
| 1019 | − int group = substream->number; | |
| 1019 | + int group = ump->legacy_mapping[substream->number]; | |
| 1020 | 1020 | |
| 1021 | 1021 | mutex_lock(&ump->open_mutex); |
| 1022 | 1022 | spin_lock_irq(&ump->legacy_locks[dir]); |
| @@ -1123,21 +1123,62 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src, · 100 unmodified lines | ||
| 1123 | 1123 | spin_unlock_irqrestore(&ump->legacy_locks[dir], flags); |
| 1124 | 1124 | } |
| 1125 | 1125 | |
| 1126 | +/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */ | |
| 1127 | +static int fill_legacy_mapping(struct snd_ump_endpoint *ump) | |
| 1128 | +{ | |
| 1129 | + struct snd_ump_block *fb; | |
| 1130 | + unsigned int group_maps = 0; | |
| 1131 | + int i, num; | |
| 1132 | + | |
| 1133 | + if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) { | |
| 1134 | + list_for_each_entry(fb, &ump->block_list, list) { | |
| 1135 | + for (i = 0; i < fb->info.num_groups; i++) | |
| 1136 | + group_maps |= 1U << (fb->info.first_group + i); | |
| 1137 | + } | |
| 1138 | + if (!group_maps) | |
| 1139 | + ump_info(ump, "No UMP Group is found in FB\n"); | |
| 1140 | + } | |
| 1141 | + | |
| 1142 | + /* use all groups for non-static case */ | |
| 1143 | + if (!group_maps) | |
| 1144 | + group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1; | |
| 1145 | + | |
| 1146 | + num = 0; | |
| 1147 | + for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) | |
| 1148 | + if (group_maps & (1U << i)) | |
| 1149 | + ump->legacy_mapping[num++] = i; | |
| 1150 | + | |
| 1151 | + return num; | |
| 1152 | +} | |
| 1153 | + | |
| 1154 | +static void fill_substream_names(struct snd_ump_endpoint *ump, | |
| 1155 | + struct snd_rawmidi *rmidi, int dir) | |
| 1156 | +{ | |
| 1157 | + struct snd_rawmidi_substream *s; | |
| 1158 | + | |
| 1159 | + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) | |
| 1160 | + snprintf(s->name, sizeof(s->name), "Group %d (%.16s)", | |
| 1161 | + ump->legacy_mapping[s->number] + 1, ump->info.name); | |
| 1162 | +} | |
| 1163 | + | |
| 1126 | 1164 | int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, |
| 1127 | 1165 | char *id, int device) |
| 1128 | 1166 | { |
| 1129 | 1167 | struct snd_rawmidi *rmidi; |
| 1130 | 1168 | bool input, output; |
| 1131 | − int err; | |
| 1169 | + int err, num; | |
| 1132 | 1170 | |
| 1133 | − ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL); | |
| 1171 | + ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS, | |
| 1172 | + sizeof(*ump->out_cvts), GFP_KERNEL); | |
| 1134 | 1173 | if (!ump->out_cvts) |
| 1135 | 1174 | return -ENOMEM; |
| 1136 | 1175 | |
| 1176 | + num = fill_legacy_mapping(ump); | |
| 1177 | + | |
| 1137 | 1178 | input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT; |
| 1138 | 1179 | output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT; |
| 1139 | 1180 | err = snd_rawmidi_new(ump->core.card, id, device, |
| 1140 | − output ? 16 : 0, input ? 16 : 0, | |
| 1181 | + output ? num : 0, input ? num : 0, | |
| 1141 | 1182 | &rmidi); |
| 1142 | 1183 | if (err < 0) { |
| 1143 | 1184 | kfree(ump->out_cvts); |
| @@ -1150,10 +1191,17 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, · 6 unmodified lines | ||
| 1150 | 1191 | if (output) |
| 1151 | 1192 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, |
| 1152 | 1193 | &snd_ump_legacy_output_ops); |
| 1194 | + snprintf(rmidi->name, sizeof(rmidi->name), "%.68s (MIDI 1.0)", | |
| 1195 | + ump->info.name); | |
| 1153 | 1196 | rmidi->info_flags = ump->core.info_flags & ~SNDRV_RAWMIDI_INFO_UMP; |
| 1154 | 1197 | rmidi->ops = &snd_ump_legacy_ops; |
| 1155 | 1198 | rmidi->private_data = ump; |
| 1156 | 1199 | ump->legacy_rmidi = rmidi; |
| 1200 | + if (input) | |
| 1201 | + fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT); | |
| 1202 | + if (output) | |
| 1203 | + fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT); | |
| 1204 | + | |
| 1157 | 1205 | ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id); |
| 1158 | 1206 | return 0; |
| 1159 | 1207 | } |
| @@ -280,6 +280,34 @@ int _snd_ctl_add_follower(struct snd_kcontrol *master, · 279 unmodified lines | ||
| 280 | 280 | } |
| 281 | 281 | EXPORT_SYMBOL(_snd_ctl_add_follower); |
| 282 | 282 | |
| 283 | +/** | |
| 284 | + * snd_ctl_add_followers - add multiple followers to vmaster | |
| 285 | + * @card: card instance | |
| 286 | + * @master: the target vmaster kcontrol object | |
| 287 | + * @list: NULL-terminated list of name strings of followers to be added | |
| 288 | + * | |
| 289 | + * Adds the multiple follower kcontrols with the given names. | |
| 290 | + * Returns 0 for success or a negative error code. | |
| 291 | + */ | |
| 292 | +int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master, | |
| 293 | + const char * const *list) | |
| 294 | +{ | |
| 295 | + struct snd_kcontrol *follower; | |
| 296 | + int err; | |
| 297 | + | |
| 298 | + for (; *list; list++) { | |
| 299 | + follower = snd_ctl_find_id_mixer(card, *list); | |
| 300 | + if (follower) { | |
| 301 | + err = snd_ctl_add_follower(master, follower); | |
| 302 | + if (err < 0) | |
| 303 | + return err; | |
| 304 | + } | |
| 305 | + } | |
| 306 | + | |
| 307 | + return 0; | |
| 308 | +} | |
| 309 | +EXPORT_SYMBOL_GPL(snd_ctl_add_followers); | |
| 310 | + | |
| 283 | 311 | /* |
| 284 | 312 | * ctl callbacks for master controls |
| 285 | 313 | */ |
| @@ -111,6 +111,7 @@ config SND_ALOOP · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | config SND_PCMTEST |
| 113 | 113 | tristate "Virtual PCM test driver" |
| 114 | + depends on DEBUG_FS | |
| 114 | 115 | select SND_PCM |
| 115 | 116 | help |
| 116 | 117 | Say 'Y' or 'M' to include support for the Virtual PCM test driver. |
| @@ -626,14 +626,7 @@ static int alloc_fake_buffer(void) · 625 unmodified lines | ||
| 626 | 626 | |
| 627 | 627 | static int dummy_pcm_copy(struct snd_pcm_substream *substream, |
| 628 | 628 | int channel, unsigned long pos, |
| 629 | − void __user *dst, unsigned long bytes) | |
| 630 | −{ | |
| 631 | − return 0; /* do nothing */ | |
| 632 | −} | |
| 633 | − | |
| 634 | −static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream, | |
| 635 | − int channel, unsigned long pos, | |
| 636 | − void *dst, unsigned long bytes) | |
| 629 | + struct iov_iter *iter, unsigned long bytes) | |
| 637 | 630 | { |
| 638 | 631 | return 0; /* do nothing */ |
| 639 | 632 | } |
| @@ -667,8 +660,7 @@ static const struct snd_pcm_ops dummy_pcm_ops_no_buf = { · 27 unmodified lines | ||
| 667 | 660 | .prepare = dummy_pcm_prepare, |
| 668 | 661 | .trigger = dummy_pcm_trigger, |
| 669 | 662 | .pointer = dummy_pcm_pointer, |
| 670 | − .copy_user = dummy_pcm_copy, | |
| 671 | − .copy_kernel = dummy_pcm_copy_kernel, | |
| 663 | + .copy = dummy_pcm_copy, | |
| 672 | 664 | .fill_silence = dummy_pcm_silence, |
| 673 | 665 | .page = dummy_pcm_page, |
| 674 | 666 | }; |
| @@ -41,8 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <linux/debugfs.h> |
| 42 | 42 | #include <linux/delay.h> |
| 43 | 43 | |
| 44 | −#define DEVNAME "pcmtestd" | |
| 45 | −#define CARD_NAME "pcm-test-card" | |
| 46 | 44 | #define TIMER_PER_SEC 5 |
| 47 | 45 | #define TIMER_INTERVAL (HZ / TIMER_PER_SEC) |
| 48 | 46 | #define DELAY_JIFFIES HZ |
| @@ -65,6 +63,7 @@ static int inject_delay; · 16 unmodified lines | ||
| 65 | 63 | static bool inject_hwpars_err; |
| 66 | 64 | static bool inject_prepare_err; |
| 67 | 65 | static bool inject_trigger_err; |
| 66 | +static bool inject_open_err; | |
| 68 | 67 | |
| 69 | 68 | static short fill_mode = FILL_MODE_PAT; |
| 70 | 69 | |
| @@ -73,11 +72,11 @@ static u8 ioctl_reset_test; · 2 unmodified lines | ||
| 73 | 72 | static struct dentry *driver_debug_dir; |
| 74 | 73 | |
| 75 | 74 | module_param(index, int, 0444); |
| 76 | −MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard"); | |
| 75 | +MODULE_PARM_DESC(index, "Index value for pcmtest soundcard"); | |
| 77 | 76 | module_param(id, charp, 0444); |
| 78 | −MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard"); | |
| 77 | +MODULE_PARM_DESC(id, "ID string for pcmtest soundcard"); | |
| 79 | 78 | module_param(enable, bool, 0444); |
| 80 | −MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | |
| 79 | +MODULE_PARM_DESC(enable, "Enable pcmtest soundcard."); | |
| 81 | 80 | module_param(fill_mode, short, 0600); |
| 82 | 81 | MODULE_PARM_DESC(fill_mode, "Buffer fill mode: rand(0) or pattern(1)"); |
| 83 | 82 | module_param(inject_delay, int, 0600); |
| @@ -88,6 +87,8 @@ module_param(inject_prepare_err, bool, 0600); · 4 unmodified lines | ||
| 88 | 87 | MODULE_PARM_DESC(inject_prepare_err, "Inject EINVAL error in the 'prepare' callback"); |
| 89 | 88 | module_param(inject_trigger_err, bool, 0600); |
| 90 | 89 | MODULE_PARM_DESC(inject_trigger_err, "Inject EINVAL error in the 'trigger' callback"); |
| 90 | +module_param(inject_open_err, bool, 0600); | |
| 91 | +MODULE_PARM_DESC(inject_open_err, "Inject EBUSY error in the 'open' callback"); | |
| 91 | 92 | |
| 92 | 93 | struct pcmtst { |
| 93 | 94 | struct snd_pcm *pcm; |
| @@ -107,6 +108,7 @@ struct pcmtst_buf_iter { · 13 unmodified lines | ||
| 107 | 108 | size_t total_bytes; // Total bytes read/written |
| 108 | 109 | size_t chan_block; // Bytes in one channel buffer when non-interleaved |
| 109 | 110 | struct snd_pcm_substream *substream; |
| 111 | + bool suspend; // We need to pause timer without shutting it down | |
| 110 | 112 | struct timer_list timer_instance; |
| 111 | 113 | }; |
| 112 | 114 | |
| @@ -114,7 +116,8 @@ static struct snd_pcm_hardware snd_pcmtst_hw = { · 1 unmodified line | ||
| 114 | 116 | .info = (SNDRV_PCM_INFO_INTERLEAVED | |
| 115 | 117 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| 116 | 118 | SNDRV_PCM_INFO_NONINTERLEAVED | |
| 117 | − SNDRV_PCM_INFO_MMAP_VALID), | |
| 119 | + SNDRV_PCM_INFO_MMAP_VALID | | |
| 120 | + SNDRV_PCM_INFO_PAUSE), | |
| 118 | 121 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, |
| 119 | 122 | .rates = SNDRV_PCM_RATE_8000_48000, |
| 120 | 123 | .rate_min = 8000, |
| @@ -140,7 +143,8 @@ static inline void inc_buf_pos(struct pcmtst_buf_iter *v_iter, size_t by, size_t · 19 unmodified lines | ||
| 140 | 143 | { |
| 141 | 144 | v_iter->total_bytes += by; |
| 142 | 145 | v_iter->buf_pos += by; |
| 143 | − v_iter->buf_pos %= bytes; | |
| 146 | + if (v_iter->buf_pos >= bytes) | |
| 147 | + v_iter->buf_pos %= bytes; | |
| 144 | 148 | } |
| 145 | 149 | |
| 146 | 150 | /* |
| @@ -196,10 +200,10 @@ static void check_buf_block_ni(struct pcmtst_buf_iter *v_iter, struct snd_pcm_ru · 49 unmodified lines | ||
| 196 | 200 | u8 current_byte; |
| 197 | 201 | |
| 198 | 202 | for (i = 0; i < v_iter->b_rw; i++) { |
| 199 | − current_byte = runtime->dma_area[buf_pos_n(v_iter, channels, i % channels)]; | |
| 203 | + ch_num = i % channels; | |
| 204 | + current_byte = runtime->dma_area[buf_pos_n(v_iter, channels, ch_num)]; | |
| 200 | 205 | if (!current_byte) |
| 201 | 206 | break; |
| 202 | − ch_num = i % channels; | |
| 203 | 207 | if (current_byte != patt_bufs[ch_num].buf[(v_iter->total_bytes / channels) |
| 204 | 208 | % patt_bufs[ch_num].len]) { |
| 205 | 209 | v_iter->is_buf_corrupted = true; |
| @@ -225,7 +229,7 @@ static void check_buf_block(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runti · 19 unmodified lines | ||
| 225 | 229 | |
| 226 | 230 | /* |
| 227 | 231 | * Fill buffer in the non-interleaved mode. The order of samples is C0, ..., C0, C1, ..., C1, C2... |
| 228 | − * The channel buffers lay in the DMA buffer continuously (see default copy_user and copy_kernel | |
| 232 | + * The channel buffers lay in the DMA buffer continuously (see default copy | |
| 229 | 233 | * handlers in the pcm_lib.c file). |
| 230 | 234 | * |
| 231 | 235 | * Here we increment the DMA buffer position every time we write a byte to any channel 'buffer'. |
| @@ -239,7 +243,7 @@ static void fill_block_pattern_n(struct pcmtst_buf_iter *v_iter, struct snd_pcm_ · 7 unmodified lines | ||
| 239 | 243 | |
| 240 | 244 | for (i = 0; i < v_iter->b_rw; i++) { |
| 241 | 245 | ch_num = i % channels; |
| 242 | − runtime->dma_area[buf_pos_n(v_iter, channels, i % channels)] = | |
| 246 | + runtime->dma_area[buf_pos_n(v_iter, channels, ch_num)] = | |
| 243 | 247 | patt_bufs[ch_num].buf[(v_iter->total_bytes / channels) |
| 244 | 248 | % patt_bufs[ch_num].len]; |
| 245 | 249 | inc_buf_pos(v_iter, 1, runtime->dma_bytes); |
| @@ -344,6 +348,9 @@ static void timer_timeout(struct timer_list *data) · 98 unmodified lines | ||
| 344 | 348 | v_iter = from_timer(v_iter, data, timer_instance); |
| 345 | 349 | substream = v_iter->substream; |
| 346 | 350 | |
| 351 | + if (v_iter->suspend) | |
| 352 | + return; | |
| 353 | + | |
| 347 | 354 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !v_iter->is_buf_corrupted) |
| 348 | 355 | check_buf_block(v_iter, substream->runtime); |
| 349 | 356 | else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
| @@ -356,7 +363,9 @@ static void timer_timeout(struct timer_list *data) · 6 unmodified lines | ||
| 356 | 363 | v_iter->period_pos %= v_iter->period_bytes; |
| 357 | 364 | snd_pcm_period_elapsed(substream); |
| 358 | 365 | } |
| 359 | − mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL + inject_delay); | |
| 366 | + | |
| 367 | + if (!v_iter->suspend) | |
| 368 | + mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL + inject_delay); | |
| 360 | 369 | } |
| 361 | 370 | |
| 362 | 371 | static int snd_pcmtst_pcm_open(struct snd_pcm_substream *substream) |
| @@ -364,23 +373,22 @@ static int snd_pcmtst_pcm_open(struct snd_pcm_substream *substream) · 1 unmodified line | ||
| 364 | 373 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 365 | 374 | struct pcmtst_buf_iter *v_iter; |
| 366 | 375 | |
| 376 | + if (inject_open_err) | |
| 377 | + return -EBUSY; | |
| 378 | + | |
| 367 | 379 | v_iter = kzalloc(sizeof(*v_iter), GFP_KERNEL); |
| 368 | 380 | if (!v_iter) |
| 369 | 381 | return -ENOMEM; |
| 370 | 382 | |
| 383 | + v_iter->substream = substream; | |
| 371 | 384 | runtime->hw = snd_pcmtst_hw; |
| 372 | 385 | runtime->private_data = v_iter; |
| 373 | − v_iter->substream = substream; | |
| 374 | − v_iter->buf_pos = 0; | |
| 375 | − v_iter->is_buf_corrupted = false; | |
| 376 | − v_iter->period_pos = 0; | |
| 377 | − v_iter->total_bytes = 0; | |
| 378 | 386 | |
| 379 | 387 | playback_capture_test = 0; |
| 380 | 388 | ioctl_reset_test = 0; |
| 381 | 389 | |
| 382 | 390 | timer_setup(&v_iter->timer_instance, timer_timeout, 0); |
| 383 | − mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL); | |
| 391 | + | |
| 384 | 392 | return 0; |
| 385 | 393 | } |
| 386 | 394 | |
| @@ -395,26 +403,40 @@ static int snd_pcmtst_pcm_close(struct snd_pcm_substream *substream) · 8 unmodified lines | ||
| 395 | 403 | return 0; |
| 396 | 404 | } |
| 397 | 405 | |
| 406 | +static inline void reset_buf_iterator(struct pcmtst_buf_iter *v_iter) | |
| 407 | +{ | |
| 408 | + v_iter->buf_pos = 0; | |
| 409 | + v_iter->is_buf_corrupted = false; | |
| 410 | + v_iter->period_pos = 0; | |
| 411 | + v_iter->total_bytes = 0; | |
| 412 | +} | |
| 413 | + | |
| 414 | +static inline void start_pcmtest_timer(struct pcmtst_buf_iter *v_iter) | |
| 415 | +{ | |
| 416 | + v_iter->suspend = false; | |
| 417 | + mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL); | |
| 418 | +} | |
| 419 | + | |
| 398 | 420 | static int snd_pcmtst_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
| 399 | 421 | { |
| 400 | − struct snd_pcm_runtime *runtime = substream->runtime; | |
| 401 | − struct pcmtst_buf_iter *v_iter = runtime->private_data; | |
| 422 | + struct pcmtst_buf_iter *v_iter = substream->runtime->private_data; | |
| 402 | 423 | |
| 403 | 424 | if (inject_trigger_err) |
| 404 | 425 | return -EINVAL; |
| 405 | − | |
| 406 | − v_iter->sample_bytes = runtime->sample_bits / 8; | |
| 407 | − v_iter->period_bytes = frames_to_bytes(runtime, runtime->period_size); | |
| 408 | − if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED || | |
| 409 | − runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) { | |
| 410 | − v_iter->chan_block = runtime->dma_bytes / runtime->channels; | |
| 411 | − v_iter->interleaved = false; | |
| 412 | − } else { | |
| 413 | − v_iter->interleaved = true; | |
| 426 | + switch (cmd) { | |
| 427 | + case SNDRV_PCM_TRIGGER_START: | |
| 428 | + reset_buf_iterator(v_iter); | |
| 429 | + start_pcmtest_timer(v_iter); | |
| 430 | + break; | |
| 431 | + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | |
| 432 | + start_pcmtest_timer(v_iter); | |
| 433 | + break; | |
| 434 | + case SNDRV_PCM_TRIGGER_STOP: | |
| 435 | + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | |
| 436 | + // We can't call timer_shutdown_sync here, as it is forbidden to sleep here | |
| 437 | + v_iter->suspend = true; | |
| 438 | + break; | |
| 414 | 439 | } |
| 415 | − // We want to record RATE * ch_cnt samples per sec, it is rate * sample_bytes * ch_cnt bytes | |
| 416 | − v_iter->s_rw_ch = runtime->rate / TIMER_PER_SEC; | |
| 417 | − v_iter->b_rw = v_iter->s_rw_ch * v_iter->sample_bytes * runtime->channels; | |
| 418 | 440 | |
| 419 | 441 | return 0; |
| 420 | 442 | } |
| @@ -446,8 +468,24 @@ static void pcmtst_pdev_release(struct device *dev) · 25 unmodified lines | ||
| 446 | 468 | |
| 447 | 469 | static int snd_pcmtst_pcm_prepare(struct snd_pcm_substream *substream) |
| 448 | 470 | { |
| 471 | + struct snd_pcm_runtime *runtime = substream->runtime; | |
| 472 | + struct pcmtst_buf_iter *v_iter = runtime->private_data; | |
| 473 | + | |
| 449 | 474 | if (inject_prepare_err) |
| 450 | 475 | return -EINVAL; |
| 476 | + | |
| 477 | + v_iter->sample_bytes = samples_to_bytes(runtime, 1); | |
| 478 | + v_iter->period_bytes = snd_pcm_lib_period_bytes(substream); | |
| 479 | + v_iter->interleaved = true; | |
| 480 | + if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED || | |
| 481 | + runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) { | |
| 482 | + v_iter->chan_block = snd_pcm_lib_buffer_bytes(substream) / runtime->channels; | |
| 483 | + v_iter->interleaved = false; | |
| 484 | + } | |
| 485 | + // We want to record RATE * ch_cnt samples per sec, it is rate * sample_bytes * ch_cnt bytes | |
| 486 | + v_iter->s_rw_ch = runtime->rate / TIMER_PER_SEC; | |
| 487 | + v_iter->b_rw = v_iter->s_rw_ch * v_iter->sample_bytes * runtime->channels; | |
| 488 | + | |
| 451 | 489 | return 0; |
| 452 | 490 | } |
| 453 | 491 | |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/io.h> |
| 17 | 17 | #include <linux/ioport.h> |
| 18 | 18 | #include <linux/module.h> |
| 19 | −#include <linux/of_device.h> | |
| 19 | +#include <linux/of.h> | |
| 20 | 20 | #include <linux/serdev.h> |
| 21 | 21 | #include <linux/serial_reg.h> |
| 22 | 22 | #include <linux/slab.h> |
| @@ -366,7 +366,7 @@ MODULE_DEVICE_TABLE(of, snd_serial_generic_dt_ids); · 343 unmodified lines | ||
| 366 | 366 | static struct serdev_device_driver snd_serial_generic_driver = { |
| 367 | 367 | .driver = { |
| 368 | 368 | .name = "snd-serial-generic", |
| 369 | − .of_match_table = of_match_ptr(snd_serial_generic_dt_ids), | |
| 369 | + .of_match_table = snd_serial_generic_dt_ids, | |
| 370 | 370 | }, |
| 371 | 371 | .probe = snd_serial_generic_probe, |
| 372 | 372 | }; |
| @@ -2,5 +2,5 @@ · 1 unmodified line | ||
| 2 | 2 | snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ |
| 3 | 3 | dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \ |
| 4 | 4 | dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o \ |
| 5 | − dice-harman.o dice-focusrite.o | |
| 5 | + dice-harman.o dice-focusrite.o dice-weiss.o | |
| 6 | 6 | obj-$(CONFIG_SND_DICE) += snd-dice.o |
| @@ -0,0 +1,104 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +// dice-weiss.c - a part of driver for DICE based devices | |
| 3 | +// | |
| 4 | +// Copyright (c) 2023 Rolf Anderegg and Michele Perrone | |
| 5 | + | |
| 6 | +#include "dice.h" | |
| 7 | + | |
| 8 | +struct dice_weiss_spec { | |
| 9 | + unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT]; | |
| 10 | + unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT]; | |
| 11 | +}; | |
| 12 | + | |
| 13 | +// Weiss DAC202: 192kHz 2-channel DAC | |
| 14 | +static const struct dice_weiss_spec dac202 = { | |
| 15 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 16 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 17 | +}; | |
| 18 | + | |
| 19 | +// Weiss MAN301: 192kHz 2-channel music archive network player | |
| 20 | +static const struct dice_weiss_spec man301 = { | |
| 21 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 22 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 23 | +}; | |
| 24 | + | |
| 25 | +// Weiss INT202: 192kHz unidirectional 2-channel digital Firewire nterface | |
| 26 | +static const struct dice_weiss_spec int202 = { | |
| 27 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 28 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 29 | +}; | |
| 30 | + | |
| 31 | +// Weiss INT203: 192kHz bidirectional 2-channel digital Firewire nterface | |
| 32 | +static const struct dice_weiss_spec int203 = { | |
| 33 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 34 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 35 | +}; | |
| 36 | + | |
| 37 | +// Weiss ADC2: 192kHz A/D converter with microphone preamps and line nputs | |
| 38 | +static const struct dice_weiss_spec adc2 = { | |
| 39 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 40 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 41 | +}; | |
| 42 | + | |
| 43 | +// Weiss DAC2/Minerva: 192kHz 2-channel DAC | |
| 44 | +static const struct dice_weiss_spec dac2_minerva = { | |
| 45 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 46 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 47 | +}; | |
| 48 | + | |
| 49 | +// Weiss Vesta: 192kHz 2-channel Firewire to AES/EBU interface | |
| 50 | +static const struct dice_weiss_spec vesta = { | |
| 51 | + .tx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 52 | + .rx_pcm_chs = {{2, 2, 2}, {0, 0, 0} }, | |
| 53 | +}; | |
| 54 | + | |
| 55 | +// Weiss AFI1: 192kHz 24-channel Firewire to ADAT or AES/EBU interface | |
| 56 | +static const struct dice_weiss_spec afi1 = { | |
| 57 | + .tx_pcm_chs = {{24, 16, 8}, {0, 0, 0} }, | |
| 58 | + .rx_pcm_chs = {{24, 16, 8}, {0, 0, 0} }, | |
| 59 | +}; | |
| 60 | + | |
| 61 | +int snd_dice_detect_weiss_formats(struct snd_dice *dice) | |
| 62 | +{ | |
| 63 | + static const struct { | |
| 64 | + u32 model_id; | |
| 65 | + const struct dice_weiss_spec *spec; | |
| 66 | + } *entry, entries[] = { | |
| 67 | + {0x000007, &dac202}, | |
| 68 | + {0x000008, &dac202}, // Maya edition: same audio I/O as DAC202. | |
| 69 | + {0x000006, &int202}, | |
| 70 | + {0x00000a, &int203}, | |
| 71 | + {0x00000b, &man301}, | |
| 72 | + {0x000001, &adc2}, | |
| 73 | + {0x000003, &dac2_minerva}, | |
| 74 | + {0x000002, &vesta}, | |
| 75 | + {0x000004, &afi1}, | |
| 76 | + }; | |
| 77 | + struct fw_csr_iterator it; | |
| 78 | + int key, val, model_id; | |
| 79 | + int i; | |
| 80 | + | |
| 81 | + model_id = 0; | |
| 82 | + fw_csr_iterator_init(&it, dice->unit->directory); | |
| 83 | + while (fw_csr_iterator_next(&it, &key, &val)) { | |
| 84 | + if (key == CSR_MODEL) { | |
| 85 | + model_id = val; | |
| 86 | + break; | |
| 87 | + } | |
| 88 | + } | |
| 89 | + | |
| 90 | + for (i = 0; i < ARRAY_SIZE(entries); ++i) { | |
| 91 | + entry = entries + i; | |
| 92 | + if (entry->model_id == model_id) | |
| 93 | + break; | |
| 94 | + } | |
| 95 | + if (i == ARRAY_SIZE(entries)) | |
| 96 | + return -ENODEV; | |
| 97 | + | |
| 98 | + memcpy(dice->tx_pcm_chs, entry->spec->tx_pcm_chs, | |
| 99 | + MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int)); | |
| 100 | + memcpy(dice->rx_pcm_chs, entry->spec->rx_pcm_chs, | |
| 101 | + MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int)); | |
| 102 | + | |
| 103 | + return 0; | |
| 104 | +} | |
| @@ -392,6 +392,69 @@ static const struct ieee1394_device_id dice_id_table[] = { · 391 unmodified lines | ||
| 392 | 392 | .model_id = 0x0000de, |
| 393 | 393 | .driver_data = (kernel_ulong_t)snd_dice_detect_focusrite_pro40_tcd3070_formats, |
| 394 | 394 | }, |
| 395 | + // Weiss DAC202: 192kHz 2-channel DAC | |
| 396 | + { | |
| 397 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 398 | + .vendor_id = OUI_WEISS, | |
| 399 | + .model_id = 0x000007, | |
| 400 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 401 | + }, | |
| 402 | + // Weiss DAC202: 192kHz 2-channel DAC (Maya edition) | |
| 403 | + { | |
| 404 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 405 | + .vendor_id = OUI_WEISS, | |
| 406 | + .model_id = 0x000008, | |
| 407 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 408 | + }, | |
| 409 | + // Weiss MAN301: 192kHz 2-channel music archive network player | |
| 410 | + { | |
| 411 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 412 | + .vendor_id = OUI_WEISS, | |
| 413 | + .model_id = 0x00000b, | |
| 414 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 415 | + }, | |
| 416 | + // Weiss INT202: 192kHz unidirectional 2-channel digital Firewire face | |
| 417 | + { | |
| 418 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 419 | + .vendor_id = OUI_WEISS, | |
| 420 | + .model_id = 0x000006, | |
| 421 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 422 | + }, | |
| 423 | + // Weiss INT203: 192kHz bidirectional 2-channel digital Firewire face | |
| 424 | + { | |
| 425 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 426 | + .vendor_id = OUI_WEISS, | |
| 427 | + .model_id = 0x00000a, | |
| 428 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 429 | + }, | |
| 430 | + // Weiss ADC2: 192kHz A/D converter with microphone preamps and inputs | |
| 431 | + { | |
| 432 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 433 | + .vendor_id = OUI_WEISS, | |
| 434 | + .model_id = 0x000001, | |
| 435 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 436 | + }, | |
| 437 | + // Weiss DAC2/Minerva: 192kHz 2-channel DAC | |
| 438 | + { | |
| 439 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 440 | + .vendor_id = OUI_WEISS, | |
| 441 | + .model_id = 0x000003, | |
| 442 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 443 | + }, | |
| 444 | + // Weiss Vesta: 192kHz 2-channel Firewire to AES/EBU interface | |
| 445 | + { | |
| 446 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 447 | + .vendor_id = OUI_WEISS, | |
| 448 | + .model_id = 0x000002, | |
| 449 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 450 | + }, | |
| 451 | + // Weiss AFI1: 192kHz 24-channel Firewire to ADAT or AES/EBU face | |
| 452 | + { | |
| 453 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID, | |
| 454 | + .vendor_id = OUI_WEISS, | |
| 455 | + .model_id = 0x000004, | |
| 456 | + .driver_data = (kernel_ulong_t)snd_dice_detect_weiss_formats, | |
| 457 | + }, | |
| 395 | 458 | { |
| 396 | 459 | .match_flags = IEEE1394_MATCH_VERSION, |
| 397 | 460 | .version = DICE_INTERFACE, |
| @@ -232,5 +232,6 @@ int snd_dice_detect_mytek_formats(struct snd_dice *dice); · 231 unmodified lines | ||
| 232 | 232 | int snd_dice_detect_presonus_formats(struct snd_dice *dice); |
| 233 | 233 | int snd_dice_detect_harman_formats(struct snd_dice *dice); |
| 234 | 234 | int snd_dice_detect_focusrite_pro40_tcd3070_formats(struct snd_dice *dice); |
| 235 | +int snd_dice_detect_weiss_formats(struct snd_dice *dice); | |
| 235 | 236 | |
| 236 | 237 | #endif |
| @@ -11,11 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <sound/hda_i915.h> |
| 12 | 12 | #include <sound/hda_register.h> |
| 13 | 13 | |
| 14 | −#define IS_HSW_CONTROLLER(pci) (((pci)->device == 0x0a0c) || \ | |
| 15 | − ((pci)->device == 0x0c0c) || \ | |
| 16 | − ((pci)->device == 0x0d0c) || \ | |
| 17 | − ((pci)->device == 0x160c)) | |
| 18 | − | |
| 19 | 14 | /** |
| 20 | 15 | * snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW |
| 21 | 16 | * @bus: HDA core bus |
| @@ -39,7 +34,7 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus) · 17 unmodified lines | ||
| 39 | 34 | |
| 40 | 35 | if (!acomp || !acomp->ops || !acomp->ops->get_cdclk_freq) |
| 41 | 36 | return; /* only for i915 binding */ |
| 42 | − if (!IS_HSW_CONTROLLER(pci)) | |
| 37 | + if (!HDA_CONTROLLER_IS_HSW(pci)) | |
| 43 | 38 | return; /* only HSW/BDW */ |
| 44 | 39 | |
| 45 | 40 | cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev); |
| @@ -80,14 +75,20 @@ static bool connectivity_check(struct pci_dev *i915, struct pci_dev *hdac) · 34 unmodified lines | ||
| 80 | 75 | if (bus_a == bus_b) |
| 81 | 76 | return true; |
| 82 | 77 | |
| 83 | − /* | |
| 84 | − * on i915 discrete GPUs with embedded HDA audio, the two | |
| 85 | − * devices are connected via 2nd level PCI bridge | |
| 86 | − */ | |
| 87 | 78 | bus_a = bus_a->parent; |
| 88 | 79 | bus_b = bus_b->parent; |
| 80 | + | |
| 81 | + /* connected via parent bus (may be NULL!) */ | |
| 82 | + if (bus_a == bus_b) | |
| 83 | + return true; | |
| 84 | + | |
| 89 | 85 | if (!bus_a || !bus_b) |
| 90 | 86 | return false; |
| 87 | + | |
| 88 | + /* | |
| 89 | + * on i915 discrete GPUs with embedded HDA audio, the two | |
| 90 | + * devices are connected via 2nd level PCI bridge | |
| 91 | + */ | |
| 91 | 92 | bus_a = bus_a->parent; |
| 92 | 93 | bus_b = bus_b->parent; |
| 93 | 94 | if (bus_a && bus_a == bus_b) |
| @@ -50,14 +50,7 @@ static const struct config_entry config_table[] = { · 49 unmodified lines | ||
| 50 | 50 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) |
| 51 | 51 | { |
| 52 | 52 | .flags = FLAG_SOF, |
| 53 | − .device = 0x119a, | |
| 54 | − }, | |
| 55 | −#endif | |
| 56 | −/* Broxton-T */ | |
| 57 | −#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) | |
| 58 | − { | |
| 59 | − .flags = FLAG_SOF, | |
| 60 | − .device = 0x1a98, | |
| 53 | + .device = PCI_DEVICE_ID_INTEL_SST_TNG, | |
| 61 | 54 | }, |
| 62 | 55 | #endif |
| 63 | 56 | /* |
| @@ -68,7 +61,7 @@ static const struct config_entry config_table[] = { · 4 unmodified lines | ||
| 68 | 61 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) |
| 69 | 62 | { |
| 70 | 63 | .flags = FLAG_SOF, |
| 71 | − .device = 0x5a98, | |
| 64 | + .device = PCI_DEVICE_ID_INTEL_HDA_APL, | |
| 72 | 65 | .dmi_table = (const struct dmi_system_id []) { |
| 73 | 66 | { |
| 74 | 67 | .ident = "Up Squared", |
| @@ -82,14 +75,14 @@ static const struct config_entry config_table[] = { · 7 unmodified lines | ||
| 82 | 75 | }, |
| 83 | 76 | { |
| 84 | 77 | .flags = FLAG_SOF, |
| 85 | − .device = 0x5a98, | |
| 78 | + .device = PCI_DEVICE_ID_INTEL_HDA_APL, | |
| 86 | 79 | .codec_hid = &essx_83x6, |
| 87 | 80 | }, |
| 88 | 81 | #endif |
| 89 | 82 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) |
| 90 | 83 | { |
| 91 | 84 | .flags = FLAG_SST, |
| 92 | − .device = 0x5a98, | |
| 85 | + .device = PCI_DEVICE_ID_INTEL_HDA_APL, | |
| 93 | 86 | .dmi_table = (const struct dmi_system_id []) { |
| 94 | 87 | { |
| 95 | 88 | .ident = "Google Chromebooks", |
| @@ -110,7 +103,7 @@ static const struct config_entry config_table[] = { · 14 unmodified lines | ||
| 110 | 103 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) |
| 111 | 104 | { |
| 112 | 105 | .flags = FLAG_SST, |
| 113 | − .device = 0x9d70, | |
| 106 | + .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, | |
| 114 | 107 | .dmi_table = (const struct dmi_system_id []) { |
| 115 | 108 | { |
| 116 | 109 | .ident = "Google Chromebooks", |
| @@ -123,14 +116,14 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 123 | 116 | }, |
| 124 | 117 | { |
| 125 | 118 | .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, |
| 126 | − .device = 0x9d70, | |
| 119 | + .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, | |
| 127 | 120 | }, |
| 128 | 121 | #endif |
| 129 | 122 | /* Kabylake-LP */ |
| 130 | 123 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) |
| 131 | 124 | { |
| 132 | 125 | .flags = FLAG_SST, |
| 133 | − .device = 0x9d71, | |
| 126 | + .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, | |
| 134 | 127 | .dmi_table = (const struct dmi_system_id []) { |
| 135 | 128 | { |
| 136 | 129 | .ident = "Google Chromebooks", |
| @@ -143,7 +136,7 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 143 | 136 | }, |
| 144 | 137 | { |
| 145 | 138 | .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, |
| 146 | − .device = 0x9d71, | |
| 139 | + .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, | |
| 147 | 140 | }, |
| 148 | 141 | #endif |
| 149 | 142 | |
| @@ -155,7 +148,7 @@ static const struct config_entry config_table[] = { · 5 unmodified lines | ||
| 155 | 148 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) |
| 156 | 149 | { |
| 157 | 150 | .flags = FLAG_SOF, |
| 158 | − .device = 0x3198, | |
| 151 | + .device = PCI_DEVICE_ID_INTEL_HDA_GML, | |
| 159 | 152 | .dmi_table = (const struct dmi_system_id []) { |
| 160 | 153 | { |
| 161 | 154 | .ident = "Google Chromebooks", |
| @@ -168,16 +161,16 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 168 | 161 | }, |
| 169 | 162 | { |
| 170 | 163 | .flags = FLAG_SOF, |
| 171 | − .device = 0x3198, | |
| 164 | + .device = PCI_DEVICE_ID_INTEL_HDA_GML, | |
| 172 | 165 | .codec_hid = &essx_83x6, |
| 173 | 166 | }, |
| 174 | 167 | #endif |
| 175 | 168 | |
| 176 | 169 | /* |
| 177 | − * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake use legacy | |
| 178 | − * HDAudio driver except for Google Chromebooks and when DMICs are | |
| 179 | − * present. Two cases are required since Coreboot does not expose NHLT | |
| 180 | − * tables. | |
| 170 | + * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake, AlderLake, | |
| 171 | + * RaptorLake use legacy HDAudio driver except for Google Chromebooks | |
| 172 | + * and when DMICs are present. Two cases are required since Coreboot | |
| 173 | + * does not expose NHLT tables. | |
| 181 | 174 | * |
| 182 | 175 | * When the Chromebook quirk is not present, it's based on information |
| 183 | 176 | * that no such device exists. When the quirk is present, it could be |
| @@ -188,7 +181,7 @@ static const struct config_entry config_table[] = { · 4 unmodified lines | ||
| 188 | 181 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) |
| 189 | 182 | { |
| 190 | 183 | .flags = FLAG_SOF, |
| 191 | − .device = 0x9dc8, | |
| 184 | + .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, | |
| 192 | 185 | .dmi_table = (const struct dmi_system_id []) { |
| 193 | 186 | { |
| 194 | 187 | .ident = "Google Chromebooks", |
| @@ -207,12 +200,12 @@ static const struct config_entry config_table[] = { · 12 unmodified lines | ||
| 207 | 200 | }, |
| 208 | 201 | { |
| 209 | 202 | .flags = FLAG_SOF, |
| 210 | − .device = 0x09dc8, | |
| 203 | + .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, | |
| 211 | 204 | .codec_hid = &essx_83x6, |
| 212 | 205 | }, |
| 213 | 206 | { |
| 214 | 207 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 215 | − .device = 0x9dc8, | |
| 208 | + .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, | |
| 216 | 209 | }, |
| 217 | 210 | #endif |
| 218 | 211 | |
| @@ -220,7 +213,7 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 220 | 213 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) |
| 221 | 214 | { |
| 222 | 215 | .flags = FLAG_SOF, |
| 223 | − .device = 0xa348, | |
| 216 | + .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, | |
| 224 | 217 | .dmi_table = (const struct dmi_system_id []) { |
| 225 | 218 | { |
| 226 | 219 | .ident = "Google Chromebooks", |
| @@ -233,7 +226,7 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 233 | 226 | }, |
| 234 | 227 | { |
| 235 | 228 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 236 | − .device = 0xa348, | |
| 229 | + .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, | |
| 237 | 230 | }, |
| 238 | 231 | #endif |
| 239 | 232 | |
| @@ -241,7 +234,7 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 241 | 234 | /* Cometlake-LP */ |
| 242 | 235 | { |
| 243 | 236 | .flags = FLAG_SOF, |
| 244 | − .device = 0x02c8, | |
| 237 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, | |
| 245 | 238 | .dmi_table = (const struct dmi_system_id []) { |
| 246 | 239 | { |
| 247 | 240 | .ident = "Google Chromebooks", |
| @@ -267,17 +260,17 @@ static const struct config_entry config_table[] = { · 19 unmodified lines | ||
| 267 | 260 | }, |
| 268 | 261 | { |
| 269 | 262 | .flags = FLAG_SOF, |
| 270 | − .device = 0x02c8, | |
| 263 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, | |
| 271 | 264 | .codec_hid = &essx_83x6, |
| 272 | 265 | }, |
| 273 | 266 | { |
| 274 | 267 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 275 | − .device = 0x02c8, | |
| 268 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, | |
| 276 | 269 | }, |
| 277 | 270 | /* Cometlake-H */ |
| 278 | 271 | { |
| 279 | 272 | .flags = FLAG_SOF, |
| 280 | − .device = 0x06c8, | |
| 273 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, | |
| 281 | 274 | .dmi_table = (const struct dmi_system_id []) { |
| 282 | 275 | { |
| 283 | 276 | .matches = { |
| @@ -296,12 +289,12 @@ static const struct config_entry config_table[] = { · 12 unmodified lines | ||
| 296 | 289 | }, |
| 297 | 290 | { |
| 298 | 291 | .flags = FLAG_SOF, |
| 299 | − .device = 0x06c8, | |
| 292 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, | |
| 300 | 293 | .codec_hid = &essx_83x6, |
| 301 | 294 | }, |
| 302 | 295 | { |
| 303 | 296 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 304 | − .device = 0x06c8, | |
| 297 | + .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, | |
| 305 | 298 | }, |
| 306 | 299 | #endif |
| 307 | 300 | |
| @@ -309,7 +302,7 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 309 | 302 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) |
| 310 | 303 | { |
| 311 | 304 | .flags = FLAG_SOF, |
| 312 | − .device = 0x34c8, | |
| 305 | + .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, | |
| 313 | 306 | .dmi_table = (const struct dmi_system_id []) { |
| 314 | 307 | { |
| 315 | 308 | .ident = "Google Chromebooks", |
| @@ -322,12 +315,12 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 322 | 315 | }, |
| 323 | 316 | { |
| 324 | 317 | .flags = FLAG_SOF, |
| 325 | − .device = 0x34c8, | |
| 318 | + .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, | |
| 326 | 319 | .codec_hid = &essx_83x6, |
| 327 | 320 | }, |
| 328 | 321 | { |
| 329 | 322 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 330 | − .device = 0x34c8, | |
| 323 | + .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, | |
| 331 | 324 | }, |
| 332 | 325 | #endif |
| 333 | 326 | |
| @@ -335,7 +328,7 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 335 | 328 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) |
| 336 | 329 | { |
| 337 | 330 | .flags = FLAG_SOF, |
| 338 | − .device = 0x4dc8, | |
| 331 | + .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, | |
| 339 | 332 | .dmi_table = (const struct dmi_system_id []) { |
| 340 | 333 | { |
| 341 | 334 | .ident = "Google Chromebooks", |
| @@ -348,12 +341,12 @@ static const struct config_entry config_table[] = { · 6 unmodified lines | ||
| 348 | 341 | }, |
| 349 | 342 | { |
| 350 | 343 | .flags = FLAG_SOF, |
| 351 | − .device = 0x4dc8, | |
| 344 | + .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, | |
| 352 | 345 | .codec_hid = &essx_83x6, |
| 353 | 346 | }, |
| 354 | 347 | { |
| 355 | 348 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, |
| 356 | − .device = 0x4dc8, | |
| 349 | + .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, | |
| 357 | 350 | }, |
| 358 | 351 | #endif |
| 359 | 352 | |
| @@ -361,7 +354,7 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 361 | 354 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) |
| 362 | 355 | { |
| 363 | 356 | .flags = FLAG_SOF, |
| 364 | − .device = 0xa0c8, | |
| 357 | + .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, | |
| 365 | 358 | .dmi_table = (const struct dmi_system_id []) { |
| 366 | 359 | { |
| 367 | 360 | .ident = "Google Chromebooks", |
| @@ -380,16 +373,16 @@ static const struct config_entry config_table[] = { · 12 unmodified lines | ||
| 380 | 373 | }, |
| 381 | 374 | { |
| 382 | 375 | .flags = FLAG_SOF, |
| 383 | − .device = 0xa0c8, | |
| 376 | + .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, | |
| 384 | 377 | .codec_hid = &essx_83x6, |
| 385 | 378 | }, |
| 386 | 379 | { |
| 387 | 380 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 388 | − .device = 0xa0c8, | |
| 381 | + .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, | |
| 389 | 382 | }, |
| 390 | 383 | { |
| 391 | 384 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 392 | − .device = 0x43c8, | |
| 385 | + .device = PCI_DEVICE_ID_INTEL_HDA_TGL_H, | |
| 393 | 386 | }, |
| 394 | 387 | #endif |
| 395 | 388 | |
| @@ -397,78 +390,121 @@ static const struct config_entry config_table[] = { · 1 unmodified line | ||
| 397 | 390 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) |
| 398 | 391 | { |
| 399 | 392 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, |
| 400 | − .device = 0x4b55, | |
| 393 | + .device = PCI_DEVICE_ID_INTEL_HDA_EHL_0, | |
| 401 | 394 | }, |
| 402 | 395 | { |
| 403 | 396 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, |
| 404 | − .device = 0x4b58, | |
| 397 | + .device = PCI_DEVICE_ID_INTEL_HDA_EHL_3, | |
| 405 | 398 | }, |
| 406 | 399 | #endif |
| 407 | 400 | |
| 408 | −/* Alder Lake */ | |
| 401 | +/* Alder Lake / Raptor Lake */ | |
| 409 | 402 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) |
| 410 | − /* Alderlake-S */ | |
| 411 | 403 | { |
| 412 | 404 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 413 | − .device = 0x7ad0, | |
| 405 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_S, | |
| 414 | 406 | }, |
| 415 | − /* RaptorLake-S */ | |
| 416 | 407 | { |
| 417 | 408 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 418 | − .device = 0x7a50, | |
| 409 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_S, | |
| 419 | 410 | }, |
| 420 | − /* Alderlake-P */ | |
| 421 | 411 | { |
| 422 | 412 | .flags = FLAG_SOF, |
| 423 | − .device = 0x51c8, | |
| 413 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, | |
| 414 | + .dmi_table = (const struct dmi_system_id []) { | |
| 415 | + { | |
| 416 | + .ident = "Google Chromebooks", | |
| 417 | + .matches = { | |
| 418 | + DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
| 419 | + } | |
| 420 | + }, | |
| 421 | + {} | |
| 422 | + } | |
| 423 | + }, | |
| 424 | + { | |
| 425 | + .flags = FLAG_SOF, | |
| 426 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, | |
| 424 | 427 | .codec_hid = &essx_83x6, |
| 425 | 428 | }, |
| 426 | 429 | { |
| 427 | 430 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 428 | − .device = 0x51c8, | |
| 431 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, | |
| 429 | 432 | }, |
| 430 | 433 | { |
| 431 | 434 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 432 | − .device = 0x51cd, | |
| 435 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PX, | |
| 433 | 436 | }, |
| 434 | − /* Alderlake-PS */ | |
| 435 | 437 | { |
| 436 | 438 | .flags = FLAG_SOF, |
| 437 | − .device = 0x51c9, | |
| 439 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS, | |
| 438 | 440 | .codec_hid = &essx_83x6, |
| 439 | 441 | }, |
| 440 | 442 | { |
| 441 | 443 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 442 | − .device = 0x51c9, | |
| 444 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS, | |
| 443 | 445 | }, |
| 444 | − /* Alderlake-M */ | |
| 445 | 446 | { |
| 446 | 447 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 447 | − .device = 0x51cc, | |
| 448 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_M, | |
| 449 | + }, | |
| 450 | + { | |
| 451 | + .flags = FLAG_SOF, | |
| 452 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N, | |
| 453 | + .dmi_table = (const struct dmi_system_id []) { | |
| 454 | + { | |
| 455 | + .ident = "Google Chromebooks", | |
| 456 | + .matches = { | |
| 457 | + DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
| 458 | + } | |
| 459 | + }, | |
| 460 | + {} | |
| 461 | + } | |
| 448 | 462 | }, |
| 449 | − /* Alderlake-N */ | |
| 450 | 463 | { |
| 451 | 464 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 452 | − .device = 0x54c8, | |
| 465 | + .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N, | |
| 466 | + }, | |
| 467 | + { | |
| 468 | + .flags = FLAG_SOF, | |
| 469 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0, | |
| 470 | + .dmi_table = (const struct dmi_system_id []) { | |
| 471 | + { | |
| 472 | + .ident = "Google Chromebooks", | |
| 473 | + .matches = { | |
| 474 | + DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
| 475 | + } | |
| 476 | + }, | |
| 477 | + {} | |
| 478 | + } | |
| 453 | 479 | }, |
| 454 | − /* RaptorLake-P */ | |
| 455 | 480 | { |
| 456 | 481 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 457 | − .device = 0x51ca, | |
| 482 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0, | |
| 483 | + }, | |
| 484 | + { | |
| 485 | + .flags = FLAG_SOF, | |
| 486 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1, | |
| 487 | + .dmi_table = (const struct dmi_system_id []) { | |
| 488 | + { | |
| 489 | + .ident = "Google Chromebooks", | |
| 490 | + .matches = { | |
| 491 | + DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
| 492 | + } | |
| 493 | + }, | |
| 494 | + {} | |
| 495 | + } | |
| 458 | 496 | }, |
| 459 | 497 | { |
| 460 | 498 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 461 | − .device = 0x51cb, | |
| 499 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1, | |
| 462 | 500 | }, |
| 463 | − /* RaptorLake-M */ | |
| 464 | 501 | { |
| 465 | 502 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 466 | − .device = 0x51ce, | |
| 503 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_M, | |
| 467 | 504 | }, |
| 468 | − /* RaptorLake-PX */ | |
| 469 | 505 | { |
| 470 | 506 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 471 | − .device = 0x51cf, | |
| 507 | + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_PX, | |
| 472 | 508 | }, |
| 473 | 509 | #endif |
| 474 | 510 | |
| @@ -477,10 +513,18 @@ static const struct config_entry config_table[] = { · 2 unmodified lines | ||
| 477 | 513 | /* Meteorlake-P */ |
| 478 | 514 | { |
| 479 | 515 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 480 | − .device = 0x7e28, | |
| 516 | + .device = PCI_DEVICE_ID_INTEL_HDA_MTL, | |
| 481 | 517 | }, |
| 482 | 518 | #endif |
| 483 | 519 | |
| 520 | +/* Lunar Lake */ | |
| 521 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE) | |
| 522 | + /* Lunarlake-P */ | |
| 523 | + { | |
| 524 | + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
| 525 | + .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P, | |
| 526 | + }, | |
| 527 | +#endif | |
| 484 | 528 | }; |
| 485 | 529 | |
| 486 | 530 | static const struct config_entry *snd_intel_dsp_find_config |
| @@ -549,7 +593,7 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) · 62 unmodified lines | ||
| 549 | 593 | const struct config_entry *cfg; |
| 550 | 594 | |
| 551 | 595 | /* Intel vendor only */ |
| 552 | − if (pci->vendor != 0x8086) | |
| 596 | + if (pci->vendor != PCI_VENDOR_ID_INTEL) | |
| 553 | 597 | return SND_INTEL_DSP_DRIVER_ANY; |
| 554 | 598 | |
| 555 | 599 | /* |
| @@ -557,12 +601,12 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) · 1 unmodified line | ||
| 557 | 601 | * for HDMI/DP support, ignore kernel parameter |
| 558 | 602 | */ |
| 559 | 603 | switch (pci->device) { |
| 560 | − case 0x160c: /* Broadwell */ | |
| 561 | − case 0x0a0c: /* Haswell */ | |
| 562 | − case 0x0c0c: | |
| 563 | − case 0x0d0c: | |
| 564 | − case 0x0f04: /* Baytrail */ | |
| 565 | − case 0x2284: /* Braswell */ | |
| 604 | + case PCI_DEVICE_ID_INTEL_HDA_BDW: | |
| 605 | + case PCI_DEVICE_ID_INTEL_HDA_HSW_0: | |
| 606 | + case PCI_DEVICE_ID_INTEL_HDA_HSW_2: | |
| 607 | + case PCI_DEVICE_ID_INTEL_HDA_HSW_3: | |
| 608 | + case PCI_DEVICE_ID_INTEL_HDA_BYT: | |
| 609 | + case PCI_DEVICE_ID_INTEL_HDA_BSW: | |
| 566 | 610 | return SND_INTEL_DSP_DRIVER_ANY; |
| 567 | 611 | } |
| 568 | 612 | |
| @@ -369,7 +369,7 @@ static int playback_copy_ack(struct snd_pcm_substream *substream, · 368 unmodified lines | ||
| 369 | 369 | |
| 370 | 370 | static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, |
| 371 | 371 | int voice, unsigned long pos, |
| 372 | − void __user *src, unsigned long count) | |
| 372 | + struct iov_iter *src, unsigned long count) | |
| 373 | 373 | { |
| 374 | 374 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 375 | 375 | struct gus_pcm_private *pcmp = runtime->private_data; |
| @@ -379,27 +379,11 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, · 3 unmodified lines | ||
| 379 | 379 | bpos = get_bpos(pcmp, voice, pos, len); |
| 380 | 380 | if (bpos < 0) |
| 381 | 381 | return pos; |
| 382 | − if (copy_from_user(runtime->dma_area + bpos, src, len)) | |
| 382 | + if (copy_from_iter(runtime->dma_area + bpos, len, src) != len) | |
| 383 | 383 | return -EFAULT; |
| 384 | 384 | return playback_copy_ack(substream, bpos, len); |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | −static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 388 | − int voice, unsigned long pos, | |
| 389 | − void *src, unsigned long count) | |
| 390 | −{ | |
| 391 | − struct snd_pcm_runtime *runtime = substream->runtime; | |
| 392 | − struct gus_pcm_private *pcmp = runtime->private_data; | |
| 393 | − unsigned int len = count; | |
| 394 | − int bpos; | |
| 395 | − | |
| 396 | − bpos = get_bpos(pcmp, voice, pos, len); | |
| 397 | − if (bpos < 0) | |
| 398 | − return pos; | |
| 399 | − memcpy(runtime->dma_area + bpos, src, len); | |
| 400 | − return playback_copy_ack(substream, bpos, len); | |
| 401 | −} | |
| 402 | − | |
| 403 | 387 | static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, |
| 404 | 388 | int voice, unsigned long pos, |
| 405 | 389 | unsigned long count) |
| @@ -830,8 +814,7 @@ static const struct snd_pcm_ops snd_gf1_pcm_playback_ops = { · 424 unmodified lines | ||
| 830 | 814 | .prepare = snd_gf1_pcm_playback_prepare, |
| 831 | 815 | .trigger = snd_gf1_pcm_playback_trigger, |
| 832 | 816 | .pointer = snd_gf1_pcm_playback_pointer, |
| 833 | − .copy_user = snd_gf1_pcm_playback_copy, | |
| 834 | − .copy_kernel = snd_gf1_pcm_playback_copy_kernel, | |
| 817 | + .copy = snd_gf1_pcm_playback_copy, | |
| 835 | 818 | .fill_silence = snd_gf1_pcm_playback_silence, |
| 836 | 819 | }; |
| 837 | 820 | |
| @@ -1040,10 +1040,8 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) · 1039 unmodified lines | ||
| 1040 | 1040 | |
| 1041 | 1041 | __error: |
| 1042 | 1042 | for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { |
| 1043 | − down_write(&card->controls_rwsem); | |
| 1044 | 1043 | if (emu->controls[i]) |
| 1045 | 1044 | snd_ctl_remove(card, emu->controls[i]); |
| 1046 | − up_write(&card->controls_rwsem); | |
| 1047 | 1045 | } |
| 1048 | 1046 | return err; |
| 1049 | 1047 | } |
| @@ -409,39 +409,25 @@ do { \ · 408 unmodified lines | ||
| 409 | 409 | return -EAGAIN;\ |
| 410 | 410 | } while (0) |
| 411 | 411 | |
| 412 | −enum { | |
| 413 | − COPY_USER, COPY_KERNEL, FILL_SILENCE, | |
| 414 | −}; | |
| 415 | − | |
| 416 | −#define GET_VAL(sval, buf, mode) \ | |
| 412 | +#define GET_VAL(sval, iter) \ | |
| 417 | 413 | do { \ |
| 418 | − switch (mode) { \ | |
| 419 | − case FILL_SILENCE: \ | |
| 414 | + if (!iter) \ | |
| 420 | 415 | sval = 0; \ |
| 421 | − break; \ | |
| 422 | − case COPY_KERNEL: \ | |
| 423 | − sval = *buf++; \ | |
| 424 | − break; \ | |
| 425 | − default: \ | |
| 426 | − if (get_user(sval, (unsigned short __user *)buf)) \ | |
| 427 | − return -EFAULT; \ | |
| 428 | − buf++; \ | |
| 429 | − break; \ | |
| 430 | − } \ | |
| 416 | + else if (copy_from_iter(&sval, 2, iter) != 2) \ | |
| 417 | + return -EFAULT; \ | |
| 431 | 418 | } while (0) |
| 432 | 419 | |
| 433 | 420 | #ifdef USE_NONINTERLEAVE |
| 434 | 421 | |
| 435 | −#define LOOP_WRITE(rec, offset, _buf, count, mode) \ | |
| 422 | +#define LOOP_WRITE(rec, offset, iter, count) \ | |
| 436 | 423 | do { \ |
| 437 | 424 | struct snd_emu8000 *emu = (rec)->emu; \ |
| 438 | − unsigned short *buf = (__force unsigned short *)(_buf); \ | |
| 439 | 425 | snd_emu8000_write_wait(emu, 1); \ |
| 440 | 426 | EMU8000_SMALW_WRITE(emu, offset); \ |
| 441 | 427 | while (count > 0) { \ |
| 442 | 428 | unsigned short sval; \ |
| 443 | 429 | CHECK_SCHEDULER(); \ |
| 444 | − GET_VAL(sval, buf, mode); \ | |
| 430 | + GET_VAL(sval, iter); \ | |
| 445 | 431 | EMU8000_SMLD_WRITE(emu, sval); \ |
| 446 | 432 | count--; \ |
| 447 | 433 | } \ |
| @@ -450,27 +436,14 @@ enum { · 2 unmodified lines | ||
| 450 | 436 | /* copy one channel block */ |
| 451 | 437 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, |
| 452 | 438 | int voice, unsigned long pos, |
| 453 | − void __user *src, unsigned long count) | |
| 439 | + struct iov_iter *src, unsigned long count) | |
| 454 | 440 | { |
| 455 | 441 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
| 456 | 442 | |
| 457 | 443 | /* convert to word unit */ |
| 458 | 444 | pos = (pos << 1) + rec->loop_start[voice]; |
| 459 | 445 | count <<= 1; |
| 460 | − LOOP_WRITE(rec, pos, src, count, COPY_USER); | |
| 461 | − return 0; | |
| 462 | −} | |
| 463 | − | |
| 464 | −static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, | |
| 465 | − int voice, unsigned long pos, | |
| 466 | − void *src, unsigned long count) | |
| 467 | −{ | |
| 468 | − struct snd_emu8k_pcm *rec = subs->runtime->private_data; | |
| 469 | − | |
| 470 | − /* convert to word unit */ | |
| 471 | − pos = (pos << 1) + rec->loop_start[voice]; | |
| 472 | − count <<= 1; | |
| 473 | − LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); | |
| 446 | + LOOP_WRITE(rec, pos, src, count); | |
| 474 | 447 | return 0; |
| 475 | 448 | } |
| 476 | 449 | |
| @@ -483,16 +456,15 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, · 6 unmodified lines | ||
| 483 | 456 | /* convert to word unit */ |
| 484 | 457 | pos = (pos << 1) + rec->loop_start[voice]; |
| 485 | 458 | count <<= 1; |
| 486 | − LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); | |
| 459 | + LOOP_WRITE(rec, pos, USER_SOCKPTR(NULL), count); | |
| 487 | 460 | return 0; |
| 488 | 461 | } |
| 489 | 462 | |
| 490 | 463 | #else /* interleave */ |
| 491 | 464 | |
| 492 | −#define LOOP_WRITE(rec, pos, _buf, count, mode) \ | |
| 465 | +#define LOOP_WRITE(rec, pos, iter, count) \ | |
| 493 | 466 | do { \ |
| 494 | 467 | struct snd_emu8000 *emu = rec->emu; \ |
| 495 | − unsigned short *buf = (__force unsigned short *)(_buf); \ | |
| 496 | 468 | snd_emu8000_write_wait(emu, 1); \ |
| 497 | 469 | EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \ |
| 498 | 470 | if (rec->voices > 1) \ |
| @@ -500,11 +472,11 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, · 1 unmodified line | ||
| 500 | 472 | while (count > 0) { \ |
| 501 | 473 | unsigned short sval; \ |
| 502 | 474 | CHECK_SCHEDULER(); \ |
| 503 | − GET_VAL(sval, buf, mode); \ | |
| 475 | + GET_VAL(sval, iter); \ | |
| 504 | 476 | EMU8000_SMLD_WRITE(emu, sval); \ |
| 505 | 477 | if (rec->voices > 1) { \ |
| 506 | 478 | CHECK_SCHEDULER(); \ |
| 507 | − GET_VAL(sval, buf, mode); \ | |
| 479 | + GET_VAL(sval, iter); \ | |
| 508 | 480 | EMU8000_SMRD_WRITE(emu, sval); \ |
| 509 | 481 | } \ |
| 510 | 482 | count--; \ |
| @@ -518,27 +490,14 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, · 7 unmodified lines | ||
| 518 | 490 | */ |
| 519 | 491 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, |
| 520 | 492 | int voice, unsigned long pos, |
| 521 | − void __user *src, unsigned long count) | |
| 522 | −{ | |
| 523 | − struct snd_emu8k_pcm *rec = subs->runtime->private_data; | |
| 524 | − | |
| 525 | − /* convert to frames */ | |
| 526 | − pos = bytes_to_frames(subs->runtime, pos); | |
| 527 | − count = bytes_to_frames(subs->runtime, count); | |
| 528 | − LOOP_WRITE(rec, pos, src, count, COPY_USER); | |
| 529 | − return 0; | |
| 530 | −} | |
| 531 | − | |
| 532 | −static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, | |
| 533 | − int voice, unsigned long pos, | |
| 534 | − void *src, unsigned long count) | |
| 493 | + struct iov_iter *src, unsigned long count) | |
| 535 | 494 | { |
| 536 | 495 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
| 537 | 496 | |
| 538 | 497 | /* convert to frames */ |
| 539 | 498 | pos = bytes_to_frames(subs->runtime, pos); |
| 540 | 499 | count = bytes_to_frames(subs->runtime, count); |
| 541 | − LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); | |
| 500 | + LOOP_WRITE(rec, pos, src, count); | |
| 542 | 501 | return 0; |
| 543 | 502 | } |
| 544 | 503 | |
| @@ -550,7 +509,7 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, · 5 unmodified lines | ||
| 550 | 509 | /* convert to frames */ |
| 551 | 510 | pos = bytes_to_frames(subs->runtime, pos); |
| 552 | 511 | count = bytes_to_frames(subs->runtime, count); |
| 553 | − LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); | |
| 512 | + LOOP_WRITE(rec, pos, NULL, count); | |
| 554 | 513 | return 0; |
| 555 | 514 | } |
| 556 | 515 | #endif |
| @@ -666,8 +625,7 @@ static const struct snd_pcm_ops emu8k_pcm_ops = { · 109 unmodified lines | ||
| 666 | 625 | .prepare = emu8k_pcm_prepare, |
| 667 | 626 | .trigger = emu8k_pcm_trigger, |
| 668 | 627 | .pointer = emu8k_pcm_pointer, |
| 669 | − .copy_user = emu8k_pcm_copy, | |
| 670 | − .copy_kernel = emu8k_pcm_copy_kernel, | |
| 628 | + .copy = emu8k_pcm_copy, | |
| 671 | 629 | .fill_silence = emu8k_pcm_silence, |
| 672 | 630 | }; |
| 673 | 631 | |
| @@ -1080,7 +1080,6 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) · 1079 unmodified lines | ||
| 1080 | 1080 | |
| 1081 | 1081 | card = p->chip->card; |
| 1082 | 1082 | |
| 1083 | − down_write(&card->controls_rwsem); | |
| 1084 | 1083 | if (p->qsound_switch) { |
| 1085 | 1084 | snd_ctl_remove(card, p->qsound_switch); |
| 1086 | 1085 | p->qsound_switch = NULL; |
| @@ -1089,7 +1088,6 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) · 2 unmodified lines | ||
| 1089 | 1088 | snd_ctl_remove(card, p->qsound_space); |
| 1090 | 1089 | p->qsound_space = NULL; |
| 1091 | 1090 | } |
| 1092 | − up_write(&card->controls_rwsem); | |
| 1093 | 1091 | |
| 1094 | 1092 | /* cancel pending transfer of QSound parameters */ |
| 1095 | 1093 | spin_lock_irqsave (&p->q_lock, flags); |
| @@ -2069,10 +2069,9 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, · 2068 unmodified lines | ||
| 2069 | 2069 | .dev_disconnect = snd_ac97_dev_disconnect, |
| 2070 | 2070 | }; |
| 2071 | 2071 | |
| 2072 | − if (!rac97) | |
| 2073 | − return -EINVAL; | |
| 2074 | − if (snd_BUG_ON(!bus || !template)) | |
| 2072 | + if (snd_BUG_ON(!bus || !template || !rac97)) | |
| 2075 | 2073 | return -EINVAL; |
| 2074 | + *rac97 = NULL; | |
| 2076 | 2075 | if (snd_BUG_ON(template->num >= 4)) |
| 2077 | 2076 | return -EINVAL; |
| 2078 | 2077 | if (bus->codec[template->num]) |
| @@ -3431,11 +3431,7 @@ static const char * const follower_sws_vt1616[] = { · 3430 unmodified lines | ||
| 3431 | 3431 | static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, |
| 3432 | 3432 | const char *name) |
| 3433 | 3433 | { |
| 3434 | − struct snd_ctl_elem_id id; | |
| 3435 | − memset(&id, 0, sizeof(id)); | |
| 3436 | − id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 3437 | − strcpy(id.name, name); | |
| 3438 | − return snd_ctl_find_id(ac97->bus->card, &id); | |
| 3434 | + return snd_ctl_find_id_mixer(ac97->bus->card, name); | |
| 3439 | 3435 | } |
| 3440 | 3436 | |
| 3441 | 3437 | /* create a virtual master control and add followers */ |
| @@ -3444,7 +3440,6 @@ static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, · 2 unmodified lines | ||
| 3444 | 3440 | const char * const *followers) |
| 3445 | 3441 | { |
| 3446 | 3442 | struct snd_kcontrol *kctl; |
| 3447 | − const char * const *s; | |
| 3448 | 3443 | int err; |
| 3449 | 3444 | |
| 3450 | 3445 | kctl = snd_ctl_make_virtual_master(name, tlv); |
| @@ -3454,20 +3449,7 @@ static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, · 3 unmodified lines | ||
| 3454 | 3449 | if (err < 0) |
| 3455 | 3450 | return err; |
| 3456 | 3451 | |
| 3457 | − for (s = followers; *s; s++) { | |
| 3458 | − struct snd_kcontrol *sctl; | |
| 3459 | − | |
| 3460 | − sctl = snd_ac97_find_mixer_ctl(ac97, *s); | |
| 3461 | − if (!sctl) { | |
| 3462 | − dev_dbg(ac97->bus->card->dev, | |
| 3463 | − "Cannot find follower %s, skipped\n", *s); | |
| 3464 | − continue; | |
| 3465 | − } | |
| 3466 | − err = snd_ctl_add_follower(kctl, sctl); | |
| 3467 | − if (err < 0) | |
| 3468 | − return err; | |
| 3469 | − } | |
| 3470 | − return 0; | |
| 3452 | + return snd_ctl_add_followers(ac97->bus->card, kctl, followers); | |
| 3471 | 3453 | } |
| 3472 | 3454 | |
| 3473 | 3455 | static int patch_vt1616_specific(struct snd_ac97 * ac97) |
| @@ -1191,19 +1191,6 @@ u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode, · 1190 unmodified lines | ||
| 1191 | 1191 | |
| 1192 | 1192 | u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode); |
| 1193 | 1193 | |
| 1194 | −u16 hpi_adapter_get_assert2(u16 adapter_index, u16 *p_assert_count, | |
| 1195 | − char *psz_assert, u32 *p_param1, u32 *p_param2, | |
| 1196 | − u32 *p_dsp_string_addr, u16 *p_processor_id); | |
| 1197 | − | |
| 1198 | −u16 hpi_adapter_test_assert(u16 adapter_index, u16 assert_id); | |
| 1199 | − | |
| 1200 | −u16 hpi_adapter_enable_capability(u16 adapter_index, u16 capability, u32 key); | |
| 1201 | − | |
| 1202 | −u16 hpi_adapter_self_test(u16 adapter_index); | |
| 1203 | − | |
| 1204 | −u16 hpi_adapter_debug_read(u16 adapter_index, u32 dsp_address, char *p_bytes, | |
| 1205 | − int *count_bytes); | |
| 1206 | − | |
| 1207 | 1194 | u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 paramter1, |
| 1208 | 1195 | u16 paramter2); |
| 1209 | 1196 | |
| @@ -1488,9 +1475,6 @@ u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY); · 278 unmodified lines | ||
| 1488 | 1475 | |
| 1489 | 1476 | u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI); |
| 1490 | 1477 | |
| 1491 | −u16 hpi_pad_get_program_type_string(u32 h_control, const u32 data_type, | |
| 1492 | − const u32 pTY, char *psz_string, const u32 string_length); | |
| 1493 | − | |
| 1494 | 1478 | /****************************/ |
| 1495 | 1479 | /* AES/EBU Receiver control */ |
| 1496 | 1480 | /****************************/ |
| @@ -1394,17 +1394,12 @@ u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index, · 1393 unmodified lines | ||
| 1394 | 1394 | void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); |
| 1395 | 1395 | |
| 1396 | 1396 | /* used in PnP OS/driver */ |
| 1397 | −u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, | |
| 1398 | − u16 *pw_adapter_index); | |
| 1399 | − | |
| 1400 | 1397 | u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, |
| 1401 | 1398 | struct hpi_hostbuffer_status **pp_status); |
| 1402 | 1399 | |
| 1403 | 1400 | u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer, |
| 1404 | 1401 | struct hpi_hostbuffer_status **pp_status); |
| 1405 | 1402 | |
| 1406 | −u16 hpi_adapter_restart(u16 adapter_index); | |
| 1407 | − | |
| 1408 | 1403 | /* |
| 1409 | 1404 | The following 3 functions were last declared in header files for |
| 1410 | 1405 | driver 3.10. HPI_ControlQuery() used to be the recommended way |
| @@ -706,19 +706,9 @@ static int remove_ctl(struct snd_card *card, const char *name) · 705 unmodified lines | ||
| 706 | 706 | return snd_ctl_remove_id(card, &id); |
| 707 | 707 | } |
| 708 | 708 | |
| 709 | −static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) | |
| 710 | −{ | |
| 711 | − struct snd_ctl_elem_id sid; | |
| 712 | − memset(&sid, 0, sizeof(sid)); | |
| 713 | − /* FIXME: strcpy is bad. */ | |
| 714 | − strcpy(sid.name, name); | |
| 715 | − sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 716 | − return snd_ctl_find_id(card, &sid); | |
| 717 | −} | |
| 718 | − | |
| 719 | 709 | static int rename_ctl(struct snd_card *card, const char *src, const char *dst) |
| 720 | 710 | { |
| 721 | − struct snd_kcontrol *kctl = ctl_find(card, src); | |
| 711 | + struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card, src); | |
| 722 | 712 | if (kctl) { |
| 723 | 713 | snd_ctl_rename(card, kctl, dst); |
| 724 | 714 | return 0; |
| @@ -761,16 +751,6 @@ static const char * const follower_sws[] = { · 36 unmodified lines | ||
| 761 | 751 | NULL |
| 762 | 752 | }; |
| 763 | 753 | |
| 764 | −static void add_followers(struct snd_card *card, | |
| 765 | − struct snd_kcontrol *master, const char * const *list) | |
| 766 | −{ | |
| 767 | − for (; *list; list++) { | |
| 768 | − struct snd_kcontrol *follower = ctl_find(card, *list); | |
| 769 | − if (follower) | |
| 770 | − snd_ctl_add_follower(master, follower); | |
| 771 | − } | |
| 772 | −} | |
| 773 | − | |
| 774 | 754 | int snd_ca0106_mixer(struct snd_ca0106 *emu) |
| 775 | 755 | { |
| 776 | 756 | int err; |
| @@ -852,7 +832,9 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu) · 75 unmodified lines | ||
| 852 | 832 | err = snd_ctl_add(card, vmaster); |
| 853 | 833 | if (err < 0) |
| 854 | 834 | return err; |
| 855 | − add_followers(card, vmaster, follower_vols); | |
| 835 | + err = snd_ctl_add_followers(card, vmaster, follower_vols); | |
| 836 | + if (err < 0) | |
| 837 | + return err; | |
| 856 | 838 | |
| 857 | 839 | if (emu->details->spi_dac) { |
| 858 | 840 | vmaster = snd_ctl_make_virtual_master("Master Playback Switch", |
| @@ -862,7 +844,9 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu) · 3 unmodified lines | ||
| 862 | 844 | err = snd_ctl_add(card, vmaster); |
| 863 | 845 | if (err < 0) |
| 864 | 846 | return err; |
| 865 | − add_followers(card, vmaster, follower_sws); | |
| 847 | + err = snd_ctl_add_followers(card, vmaster, follower_sws); | |
| 848 | + if (err < 0) | |
| 849 | + return err; | |
| 866 | 850 | } |
| 867 | 851 | |
| 868 | 852 | strcpy(card->mixername, "CA0106"); |
| @@ -2734,12 +2734,8 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) · 2733 unmodified lines | ||
| 2734 | 2734 | } |
| 2735 | 2735 | |
| 2736 | 2736 | for (idx = 0; idx < CM_SAVED_MIXERS; idx++) { |
| 2737 | − struct snd_ctl_elem_id elem_id; | |
| 2738 | 2737 | struct snd_kcontrol *ctl; |
| 2739 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 2740 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2741 | − strcpy(elem_id.name, cm_saved_mixer[idx].name); | |
| 2742 | − ctl = snd_ctl_find_id(cm->card, &elem_id); | |
| 2738 | + ctl = snd_ctl_find_id_mixer(cm->card, cm_saved_mixer[idx].name); | |
| 2743 | 2739 | if (ctl) |
| 2744 | 2740 | cm->mixer_res_ctl[idx] = ctl; |
| 2745 | 2741 | } |
| @@ -2449,7 +2449,6 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) · 2448 unmodified lines | ||
| 2449 | 2449 | int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) |
| 2450 | 2450 | { |
| 2451 | 2451 | struct snd_card *card = chip->card; |
| 2452 | − struct snd_ctl_elem_id id; | |
| 2453 | 2452 | int err; |
| 2454 | 2453 | unsigned int idx; |
| 2455 | 2454 | static const struct snd_ac97_bus_ops ops = { |
| @@ -2490,10 +2489,8 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) · 34 unmodified lines | ||
| 2490 | 2489 | } |
| 2491 | 2490 | |
| 2492 | 2491 | /* get EAPD mixer switch (for voyetra hack) */ |
| 2493 | − memset(&id, 0, sizeof(id)); | |
| 2494 | − id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2495 | − strcpy(id.name, "External Amplifier"); | |
| 2496 | − chip->eapd_switch = snd_ctl_find_id(chip->card, &id); | |
| 2492 | + chip->eapd_switch = snd_ctl_find_id_mixer(chip->card, | |
| 2493 | + "External Amplifier"); | |
| 2497 | 2494 | |
| 2498 | 2495 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
| 2499 | 2496 | if (chip->nr_ac97_codecs == 1) { |
| @@ -2,9 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * The driver for the EMU10K1 (SB Live!) based soundcards |
| 4 | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 5 | − * | |
| 6 | − * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | |
| 7 | − * Added support for Audigy 2 Value. | |
| 5 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 8 | 6 | */ |
| 9 | 7 | |
| 10 | 8 | #include <linux/init.h> |
| @@ -176,9 +174,6 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, · 165 unmodified lines | ||
| 176 | 174 | if (err < 0) |
| 177 | 175 | return err; |
| 178 | 176 | |
| 179 | − if (emu->card_capabilities->emu_model) | |
| 180 | − schedule_delayed_work(&emu->emu1010.firmware_work, 0); | |
| 181 | − | |
| 182 | 177 | pci_set_drvdata(pci, card); |
| 183 | 178 | dev++; |
| 184 | 179 | return 0; |
| @@ -194,7 +189,8 @@ static int snd_emu10k1_suspend(struct device *dev) · 9 unmodified lines | ||
| 194 | 189 | |
| 195 | 190 | emu->suspend = 1; |
| 196 | 191 | |
| 197 | − cancel_delayed_work_sync(&emu->emu1010.firmware_work); | |
| 192 | + cancel_work_sync(&emu->emu1010.firmware_work); | |
| 193 | + cancel_work_sync(&emu->emu1010.clock_work); | |
| 198 | 194 | |
| 199 | 195 | snd_ac97_suspend(emu->ac97); |
| 200 | 196 | |
| @@ -224,9 +220,6 @@ static int snd_emu10k1_resume(struct device *dev) · 23 unmodified lines | ||
| 224 | 220 | |
| 225 | 221 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 226 | 222 | |
| 227 | − if (emu->card_capabilities->emu_model) | |
| 228 | − schedule_delayed_work(&emu->emu1010.firmware_work, 0); | |
| 229 | − | |
| 230 | 223 | return 0; |
| 231 | 224 | } |
| 232 | 225 | |
| @@ -1,19 +1,11 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 5 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 4 | 6 | * Creative Labs, Inc. |
| 5 | − * Routines for control of EMU10K1 chips | |
| 6 | − * | |
| 7 | − * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> | |
| 8 | − * Added support for Audigy 2 Value. | |
| 9 | − * Added EMU 1010 support. | |
| 10 | − * General bug fixes and enhancements. | |
| 11 | 7 | * |
| 12 | − * BUGS: | |
| 13 | − * -- | |
| 14 | − * | |
| 15 | − * TODO: | |
| 16 | − * -- | |
| 8 | + * Routines for control of EMU10K1 chips | |
| 17 | 9 | */ |
| 18 | 10 | |
| 19 | 11 | #include <linux/sched.h> |
| @@ -391,7 +383,10 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) · 371 unmodified lines | ||
| 391 | 383 | } |
| 392 | 384 | #endif |
| 393 | 385 | |
| 394 | − snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); | |
| 386 | + if (emu->card_capabilities->emu_model) | |
| 387 | + snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE | INTE_A_GPIOENABLE); | |
| 388 | + else | |
| 389 | + snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); | |
| 395 | 390 | } |
| 396 | 391 | |
| 397 | 392 | int snd_emu10k1_done(struct snd_emu10k1 *emu) |
| @@ -664,7 +659,6 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, · 266 unmodified lines | ||
| 664 | 659 | u16 reg; |
| 665 | 660 | u8 value; |
| 666 | 661 | __always_unused u16 write_post; |
| 667 | − unsigned long flags; | |
| 668 | 662 | |
| 669 | 663 | if (!fw_entry) |
| 670 | 664 | return -EIO; |
| @@ -676,7 +670,7 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, · 5 unmodified lines | ||
| 676 | 670 | * GPIO5 -> FPGA DIN |
| 677 | 671 | * FPGA CONFIG OFF -> FPGA PGMN |
| 678 | 672 | */ |
| 679 | − spin_lock_irqsave(&emu->emu_lock, flags); | |
| 673 | + spin_lock_irq(&emu->emu_lock); | |
| 680 | 674 | outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */ |
| 681 | 675 | write_post = inw(emu->port + A_GPIO); |
| 682 | 676 | udelay(100); |
| @@ -699,7 +693,7 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, · 16 unmodified lines | ||
| 699 | 693 | /* After programming, set GPIO bit 4 high again. */ |
| 700 | 694 | outw(0x10, emu->port + A_GPIO); |
| 701 | 695 | write_post = inw(emu->port + A_GPIO); |
| 702 | − spin_unlock_irqrestore(&emu->emu_lock, flags); | |
| 696 | + spin_unlock_irq(&emu->emu_lock); | |
| 703 | 697 | |
| 704 | 698 | return 0; |
| 705 | 699 | } |
| @@ -745,14 +739,13 @@ static void emu1010_firmware_work(struct work_struct *work) · 39 unmodified lines | ||
| 745 | 739 | int err; |
| 746 | 740 | |
| 747 | 741 | emu = container_of(work, struct snd_emu10k1, |
| 748 | − emu1010.firmware_work.work); | |
| 742 | + emu1010.firmware_work); | |
| 749 | 743 | if (emu->card->shutdown) |
| 750 | 744 | return; |
| 751 | 745 | #ifdef CONFIG_PM_SLEEP |
| 752 | 746 | if (emu->suspend) |
| 753 | 747 | return; |
| 754 | 748 | #endif |
| 755 | − snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ | |
| 756 | 749 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ |
| 757 | 750 | if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { |
| 758 | 751 | /* Audio Dock attached */ |
| @@ -763,13 +756,8 @@ static void emu1010_firmware_work(struct work_struct *work) · 4 unmodified lines | ||
| 763 | 756 | EMU_HANA_FPGA_CONFIG_AUDIODOCK); |
| 764 | 757 | err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); |
| 765 | 758 | if (err < 0) |
| 766 | − goto next; | |
| 767 | − | |
| 759 | + return; | |
| 768 | 760 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); |
| 769 | − snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); | |
| 770 | − dev_info(emu->card->dev, | |
| 771 | − "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp); | |
| 772 | − /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | |
| 773 | 761 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); |
| 774 | 762 | dev_info(emu->card->dev, |
| 775 | 763 | "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); |
| @@ -778,7 +766,7 @@ static void emu1010_firmware_work(struct work_struct *work) · 2 unmodified lines | ||
| 778 | 766 | dev_info(emu->card->dev, |
| 779 | 767 | "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", |
| 780 | 768 | tmp); |
| 781 | − goto next; | |
| 769 | + return; | |
| 782 | 770 | } |
| 783 | 771 | dev_info(emu->card->dev, |
| 784 | 772 | "emu1010: Audio Dock Firmware loaded\n"); |
| @@ -790,18 +778,48 @@ static void emu1010_firmware_work(struct work_struct *work) · 5 unmodified lines | ||
| 790 | 778 | msleep(10); |
| 791 | 779 | /* Unmute all. Default is muted after a firmware load */ |
| 792 | 780 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); |
| 793 | − } else if (!reg && emu->emu1010.last_reg) { | |
| 781 | + } | |
| 782 | +} | |
| 783 | + | |
| 784 | +static void emu1010_clock_work(struct work_struct *work) | |
| 785 | +{ | |
| 786 | + struct snd_emu10k1 *emu; | |
| 787 | + struct snd_ctl_elem_id id; | |
| 788 | + | |
| 789 | + emu = container_of(work, struct snd_emu10k1, | |
| 790 | + emu1010.clock_work); | |
| 791 | + if (emu->card->shutdown) | |
| 792 | + return; | |
| 793 | +#ifdef CONFIG_PM_SLEEP | |
| 794 | + if (emu->suspend) | |
| 795 | + return; | |
| 796 | +#endif | |
| 797 | + | |
| 798 | + spin_lock_irq(&emu->reg_lock); | |
| 799 | + // This is the only thing that can actually happen. | |
| 800 | + emu->emu1010.clock_source = emu->emu1010.clock_fallback; | |
| 801 | + emu->emu1010.wclock = 1 - emu->emu1010.clock_source; | |
| 802 | + snd_emu1010_update_clock(emu); | |
| 803 | + spin_unlock_irq(&emu->reg_lock); | |
| 804 | + snd_ctl_build_ioff(&id, emu->ctl_clock_source, 0); | |
| 805 | + snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); | |
| 806 | +} | |
| 807 | + | |
| 808 | +static void emu1010_interrupt(struct snd_emu10k1 *emu) | |
| 809 | +{ | |
| 810 | + u32 sts; | |
| 811 | + | |
| 812 | + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); | |
| 813 | + if (sts & EMU_HANA_IRQ_DOCK_LOST) { | |
| 794 | 814 | /* Audio Dock removed */ |
| 795 | 815 | dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); |
| 796 | 816 | /* The hardware auto-mutes all, so we unmute again */ |
| 797 | 817 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); |
| 818 | + } else if (sts & EMU_HANA_IRQ_DOCK) { | |
| 819 | + schedule_work(&emu->emu1010.firmware_work); | |
| 798 | 820 | } |
| 799 | − | |
| 800 | − next: | |
| 801 | − emu->emu1010.last_reg = reg; | |
| 802 | − if (!emu->card->shutdown) | |
| 803 | − schedule_delayed_work(&emu->emu1010.firmware_work, | |
| 804 | − msecs_to_jiffies(1000)); | |
| 821 | + if (sts & EMU_HANA_IRQ_WCLK_CHANGED) | |
| 822 | + schedule_work(&emu->emu1010.clock_work); | |
| 805 | 823 | } |
| 806 | 824 | |
| 807 | 825 | /* |
| @@ -870,6 +888,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 62 unmodified lines | ||
| 870 | 888 | |
| 871 | 889 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); |
| 872 | 890 | dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); |
| 891 | + if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) | |
| 892 | + schedule_work(&emu->emu1010.firmware_work); | |
| 873 | 893 | if (emu->card_capabilities->no_adat) { |
| 874 | 894 | emu->emu1010.optical_in = 0; /* IN_SPDIF */ |
| 875 | 895 | emu->emu1010.optical_out = 0; /* OUT_SPDIF */ |
| @@ -895,10 +915,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) · 19 unmodified lines | ||
| 895 | 915 | /* MIDI routing */ |
| 896 | 916 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, EMU_HANA_MIDI_INA_FROM_HAMOA | EMU_HANA_MIDI_INB_FROM_DOCK2); |
| 897 | 917 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, EMU_HANA_MIDI_OUT_DOCK2 | EMU_HANA_MIDI_OUT_SYNC2); |
| 898 | − /* IRQ Enable: All on */ | |
| 899 | − /* snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x0f); */ | |
| 900 | − /* IRQ Enable: All off */ | |
| 901 | − snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); | |
| 918 | + | |
| 919 | + emu->gpio_interrupt = emu1010_interrupt; | |
| 920 | + // Note: The Audigy INTE is set later | |
| 921 | + snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, | |
| 922 | + EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST | EMU_HANA_IRQ_WCLK_CHANGED); | |
| 923 | + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); // Clear pending IRQs | |
| 902 | 924 | |
| 903 | 925 | emu->emu1010.clock_source = 1; /* 48000 */ |
| 904 | 926 | emu->emu1010.clock_fallback = 1; /* 48000 */ |
| @@ -938,7 +960,8 @@ static void snd_emu10k1_free(struct snd_card *card) · 33 unmodified lines | ||
| 938 | 960 | /* Disable 48Volt power to Audio Dock */ |
| 939 | 961 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); |
| 940 | 962 | } |
| 941 | − cancel_delayed_work_sync(&emu->emu1010.firmware_work); | |
| 963 | + cancel_work_sync(&emu->emu1010.firmware_work); | |
| 964 | + cancel_work_sync(&emu->emu1010.clock_work); | |
| 942 | 965 | release_firmware(emu->firmware); |
| 943 | 966 | release_firmware(emu->dock_fw); |
| 944 | 967 | snd_util_memhdr_free(emu->memhdr); |
| @@ -1517,7 +1540,8 @@ int snd_emu10k1_create(struct snd_card *card, · 572 unmodified lines | ||
| 1517 | 1540 | emu->irq = -1; |
| 1518 | 1541 | emu->synth = NULL; |
| 1519 | 1542 | emu->get_synth_voice = NULL; |
| 1520 | − INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); | |
| 1543 | + INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); | |
| 1544 | + INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work); | |
| 1521 | 1545 | /* read revision & serial */ |
| 1522 | 1546 | emu->revision = pci->revision; |
| 1523 | 1547 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); |
| @@ -22,7 +22,6 @@ static int snd_emu10k1_synth_probe(struct device *_dev) · 21 unmodified lines | ||
| 22 | 22 | struct snd_emux *emux; |
| 23 | 23 | struct snd_emu10k1 *hw; |
| 24 | 24 | struct snd_emu10k1_synth_arg *arg; |
| 25 | − unsigned long flags; | |
| 26 | 25 | |
| 27 | 26 | arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); |
| 28 | 27 | if (arg == NULL) |
| @@ -56,10 +55,10 @@ static int snd_emu10k1_synth_probe(struct device *_dev) · 27 unmodified lines | ||
| 56 | 55 | return -ENOMEM; |
| 57 | 56 | } |
| 58 | 57 | |
| 59 | − spin_lock_irqsave(&hw->voice_lock, flags); | |
| 58 | + spin_lock_irq(&hw->voice_lock); | |
| 60 | 59 | hw->synth = emux; |
| 61 | 60 | hw->get_synth_voice = snd_emu10k1_synth_get_voice; |
| 62 | − spin_unlock_irqrestore(&hw->voice_lock, flags); | |
| 61 | + spin_unlock_irq(&hw->voice_lock); | |
| 63 | 62 | |
| 64 | 63 | dev->driver_data = emux; |
| 65 | 64 | |
| @@ -71,7 +70,6 @@ static int snd_emu10k1_synth_remove(struct device *_dev) · 5 unmodified lines | ||
| 71 | 70 | struct snd_seq_device *dev = to_seq_dev(_dev); |
| 72 | 71 | struct snd_emux *emux; |
| 73 | 72 | struct snd_emu10k1 *hw; |
| 74 | − unsigned long flags; | |
| 75 | 73 | |
| 76 | 74 | if (dev->driver_data == NULL) |
| 77 | 75 | return 0; /* not registered actually */ |
| @@ -79,10 +77,10 @@ static int snd_emu10k1_synth_remove(struct device *_dev) · 1 unmodified line | ||
| 79 | 77 | emux = dev->driver_data; |
| 80 | 78 | |
| 81 | 79 | hw = emux->hw; |
| 82 | − spin_lock_irqsave(&hw->voice_lock, flags); | |
| 80 | + spin_lock_irq(&hw->voice_lock); | |
| 83 | 81 | hw->synth = NULL; |
| 84 | 82 | hw->get_synth_voice = NULL; |
| 85 | − spin_unlock_irqrestore(&hw->voice_lock, flags); | |
| 83 | + spin_unlock_irq(&hw->voice_lock); | |
| 86 | 84 | |
| 87 | 85 | snd_emux_free(emux); |
| 88 | 86 | return 0; |
| @@ -1,17 +1,11 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 5 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 4 | 6 | * Creative Labs, Inc. |
| 5 | − * Routines for effect processor FX8010 | |
| 6 | − * | |
| 7 | − * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> | |
| 8 | − * Added EMU 1010 support. | |
| 9 | 7 | * |
| 10 | − * BUGS: | |
| 11 | − * -- | |
| 12 | − * | |
| 13 | − * TODO: | |
| 14 | − * -- | |
| 8 | + * Routines for effect processor FX8010 | |
| 15 | 9 | */ |
| 16 | 10 | |
| 17 | 11 | #include <linux/pci.h> |
| @@ -799,13 +793,10 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, · 781 unmodified lines | ||
| 799 | 793 | if (snd_emu10k1_look_for_ctl(emu, &gctl->id)) |
| 800 | 794 | continue; |
| 801 | 795 | gctl_id = (struct snd_ctl_elem_id *)&gctl->id; |
| 802 | − down_read(&emu->card->controls_rwsem); | |
| 803 | 796 | if (snd_ctl_find_id(emu->card, gctl_id)) { |
| 804 | − up_read(&emu->card->controls_rwsem); | |
| 805 | 797 | err = -EEXIST; |
| 806 | 798 | goto __error; |
| 807 | 799 | } |
| 808 | − up_read(&emu->card->controls_rwsem); | |
| 809 | 800 | if (gctl_id->iface != SNDRV_CTL_ELEM_IFACE_MIXER && |
| 810 | 801 | gctl_id->iface != SNDRV_CTL_ELEM_IFACE_PCM) { |
| 811 | 802 | err = -EINVAL; |
| @@ -977,11 +968,9 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, · 165 unmodified lines | ||
| 977 | 968 | in_kernel); |
| 978 | 969 | if (err < 0) |
| 979 | 970 | return err; |
| 980 | − down_write(&card->controls_rwsem); | |
| 981 | 971 | ctl = snd_emu10k1_look_for_ctl(emu, &id); |
| 982 | 972 | if (ctl) |
| 983 | 973 | snd_ctl_remove(card, ctl->kcontrol); |
| 984 | − up_write(&card->controls_rwsem); | |
| 985 | 974 | } |
| 986 | 975 | return 0; |
| 987 | 976 | } |
| @@ -2,18 +2,12 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
| 4 | 4 | * Takashi Iwai <tiwai@suse.de> |
| 5 | + * Lee Revell <rlrevell@joe-job.com> | |
| 6 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 7 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 5 | 8 | * Creative Labs, Inc. |
| 6 | − * Routines for control of EMU10K1 chips / mixer routines | |
| 7 | − * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> | |
| 8 | − * | |
| 9 | − * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> | |
| 10 | − * Added EMU 1010 support. | |
| 11 | − * | |
| 12 | − * BUGS: | |
| 13 | − * -- | |
| 14 | 9 | * |
| 15 | − * TODO: | |
| 16 | − * -- | |
| 10 | + * Routines for control of EMU10K1 chips / mixer routines | |
| 17 | 11 | */ |
| 18 | 12 | |
| 19 | 13 | #include <linux/time.h> |
| @@ -770,18 +764,21 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct · 750 unmodified lines | ||
| 770 | 764 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 771 | 765 | unsigned int mask = snd_emu1010_adc_pad_regs[kcontrol->private_value]; |
| 772 | 766 | unsigned int val, cache; |
| 767 | + int change; | |
| 768 | + | |
| 773 | 769 | val = ucontrol->value.integer.value[0]; |
| 774 | 770 | cache = emu->emu1010.adc_pads; |
| 775 | 771 | if (val == 1) |
| 776 | 772 | cache = cache | mask; |
| 777 | 773 | else |
| 778 | 774 | cache = cache & ~mask; |
| 779 | − if (cache != emu->emu1010.adc_pads) { | |
| 775 | + change = (cache != emu->emu1010.adc_pads); | |
| 776 | + if (change) { | |
| 780 | 777 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); |
| 781 | 778 | emu->emu1010.adc_pads = cache; |
| 782 | 779 | } |
| 783 | 780 | |
| 784 | − return 0; | |
| 781 | + return change; | |
| 785 | 782 | } |
| 786 | 783 | |
| 787 | 784 | static const struct snd_kcontrol_new emu1010_adc_pads_ctl = { |
| @@ -983,17 +980,21 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, · 195 unmodified lines | ||
| 983 | 980 | val = ucontrol->value.enumerated.item[0] ; |
| 984 | 981 | if (val >= emu_ci->num) |
| 985 | 982 | return -EINVAL; |
| 983 | + spin_lock_irq(&emu->reg_lock); | |
| 986 | 984 | change = (emu->emu1010.clock_source != val); |
| 987 | 985 | if (change) { |
| 988 | 986 | emu->emu1010.clock_source = val; |
| 989 | 987 | emu->emu1010.wclock = emu_ci->vals[val]; |
| 988 | + snd_emu1010_update_clock(emu); | |
| 990 | 989 | |
| 991 | 990 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE); |
| 992 | 991 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, emu->emu1010.wclock); |
| 992 | + spin_unlock_irq(&emu->reg_lock); | |
| 993 | + | |
| 993 | 994 | msleep(10); // Allow DLL to settle |
| 994 | 995 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); |
| 995 | − | |
| 996 | − snd_emu1010_update_clock(emu); | |
| 996 | + } else { | |
| 997 | + spin_unlock_irq(&emu->reg_lock); | |
| 997 | 998 | } |
| 998 | 999 | return change; |
| 999 | 1000 | } |
| @@ -1190,7 +1191,6 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, · 190 unmodified lines | ||
| 1190 | 1191 | unsigned int ngain, ogain; |
| 1191 | 1192 | u16 gpio; |
| 1192 | 1193 | int change = 0; |
| 1193 | − unsigned long flags; | |
| 1194 | 1194 | u32 source; |
| 1195 | 1195 | /* If the capture source has changed, |
| 1196 | 1196 | * update the capture volume from the cached value |
| @@ -1204,13 +1204,13 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, · 7 unmodified lines | ||
| 1204 | 1204 | change = (emu->i2c_capture_source != source_id); |
| 1205 | 1205 | if (change) { |
| 1206 | 1206 | snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ |
| 1207 | − spin_lock_irqsave(&emu->emu_lock, flags); | |
| 1207 | + spin_lock_irq(&emu->emu_lock); | |
| 1208 | 1208 | gpio = inw(emu->port + A_IOCFG); |
| 1209 | 1209 | if (source_id==0) |
| 1210 | 1210 | outw(gpio | 0x4, emu->port + A_IOCFG); |
| 1211 | 1211 | else |
| 1212 | 1212 | outw(gpio & ~0x4, emu->port + A_IOCFG); |
| 1213 | − spin_unlock_irqrestore(&emu->emu_lock, flags); | |
| 1213 | + spin_unlock_irq(&emu->emu_lock); | |
| 1214 | 1214 | |
| 1215 | 1215 | ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ |
| 1216 | 1216 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ |
| @@ -1354,7 +1354,6 @@ static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, · 137 unmodified lines | ||
| 1354 | 1354 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1355 | 1355 | int change; |
| 1356 | 1356 | unsigned int reg, val, tmp; |
| 1357 | − unsigned long flags; | |
| 1358 | 1357 | |
| 1359 | 1358 | switch(ucontrol->value.enumerated.item[0]) { |
| 1360 | 1359 | case 0: |
| @@ -1372,14 +1371,14 @@ static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, · 11 unmodified lines | ||
| 1372 | 1371 | } |
| 1373 | 1372 | |
| 1374 | 1373 | |
| 1375 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1374 | + spin_lock_irq(&emu->reg_lock); | |
| 1376 | 1375 | reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); |
| 1377 | 1376 | tmp = reg & ~A_SPDIF_RATE_MASK; |
| 1378 | 1377 | tmp |= val; |
| 1379 | 1378 | change = (tmp != reg); |
| 1380 | 1379 | if (change) |
| 1381 | 1380 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); |
| 1382 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1381 | + spin_unlock_irq(&emu->reg_lock); | |
| 1383 | 1382 | return change; |
| 1384 | 1383 | } |
| 1385 | 1384 | |
| @@ -1496,7 +1495,6 @@ static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol, · 110 unmodified lines | ||
| 1496 | 1495 | static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, |
| 1497 | 1496 | struct snd_ctl_elem_value *ucontrol) |
| 1498 | 1497 | { |
| 1499 | − unsigned long flags; | |
| 1500 | 1498 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1501 | 1499 | struct snd_emu10k1_pcm_mixer *mix = |
| 1502 | 1500 | &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; |
| @@ -1504,7 +1502,7 @@ static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, · 1 unmodified line | ||
| 1504 | 1502 | int num_efx = emu->audigy ? 8 : 4; |
| 1505 | 1503 | int mask = emu->audigy ? 0x3f : 0x0f; |
| 1506 | 1504 | |
| 1507 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1505 | + spin_lock_irq(&emu->reg_lock); | |
| 1508 | 1506 | for (voice = 0; voice < 3; voice++) |
| 1509 | 1507 | for (idx = 0; idx < num_efx; idx++) { |
| 1510 | 1508 | val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; |
| @@ -1524,7 +1522,7 @@ static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, · 13 unmodified lines | ||
| 1524 | 1522 | &mix->send_routing[0][0]); |
| 1525 | 1523 | } |
| 1526 | 1524 | } |
| 1527 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1525 | + spin_unlock_irq(&emu->reg_lock); | |
| 1528 | 1526 | return change; |
| 1529 | 1527 | } |
| 1530 | 1528 | |
| @@ -1566,14 +1564,13 @@ static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol, · 35 unmodified lines | ||
| 1566 | 1564 | static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, |
| 1567 | 1565 | struct snd_ctl_elem_value *ucontrol) |
| 1568 | 1566 | { |
| 1569 | − unsigned long flags; | |
| 1570 | 1567 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1571 | 1568 | struct snd_emu10k1_pcm_mixer *mix = |
| 1572 | 1569 | &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; |
| 1573 | 1570 | int change = 0, idx, val; |
| 1574 | 1571 | int num_efx = emu->audigy ? 8 : 4; |
| 1575 | 1572 | |
| 1576 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1573 | + spin_lock_irq(&emu->reg_lock); | |
| 1577 | 1574 | for (idx = 0; idx < 3*num_efx; idx++) { |
| 1578 | 1575 | val = ucontrol->value.integer.value[idx] & 255; |
| 1579 | 1576 | if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { |
| @@ -1592,7 +1589,7 @@ static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, · 12 unmodified lines | ||
| 1592 | 1589 | &mix->send_volume[0][0]); |
| 1593 | 1590 | } |
| 1594 | 1591 | } |
| 1595 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1592 | + spin_unlock_irq(&emu->reg_lock); | |
| 1596 | 1593 | return change; |
| 1597 | 1594 | } |
| 1598 | 1595 | |
| @@ -1632,13 +1629,12 @@ static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, · 33 unmodified lines | ||
| 1632 | 1629 | static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, |
| 1633 | 1630 | struct snd_ctl_elem_value *ucontrol) |
| 1634 | 1631 | { |
| 1635 | − unsigned long flags; | |
| 1636 | 1632 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1637 | 1633 | struct snd_emu10k1_pcm_mixer *mix = |
| 1638 | 1634 | &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; |
| 1639 | 1635 | int change = 0, idx, val; |
| 1640 | 1636 | |
| 1641 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1637 | + spin_lock_irq(&emu->reg_lock); | |
| 1642 | 1638 | for (idx = 0; idx < 3; idx++) { |
| 1643 | 1639 | unsigned uval = ucontrol->value.integer.value[idx] & 0x1ffff; |
| 1644 | 1640 | val = uval * 0x8000U / 0xffffU; |
| @@ -1655,7 +1651,7 @@ static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, · 10 unmodified lines | ||
| 1655 | 1651 | snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); |
| 1656 | 1652 | } |
| 1657 | 1653 | } |
| 1658 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1654 | + spin_unlock_irq(&emu->reg_lock); | |
| 1659 | 1655 | return change; |
| 1660 | 1656 | } |
| 1661 | 1657 | |
| @@ -1701,7 +1697,6 @@ static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, · 39 unmodified lines | ||
| 1701 | 1697 | static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, |
| 1702 | 1698 | struct snd_ctl_elem_value *ucontrol) |
| 1703 | 1699 | { |
| 1704 | − unsigned long flags; | |
| 1705 | 1700 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1706 | 1701 | int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
| 1707 | 1702 | struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; |
| @@ -1709,7 +1704,7 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, · 1 unmodified line | ||
| 1709 | 1704 | int num_efx = emu->audigy ? 8 : 4; |
| 1710 | 1705 | int mask = emu->audigy ? 0x3f : 0x0f; |
| 1711 | 1706 | |
| 1712 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1707 | + spin_lock_irq(&emu->reg_lock); | |
| 1713 | 1708 | for (idx = 0; idx < num_efx; idx++) { |
| 1714 | 1709 | val = ucontrol->value.integer.value[idx] & mask; |
| 1715 | 1710 | if (mix->send_routing[0][idx] != val) { |
| @@ -1724,7 +1719,7 @@ static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, · 8 unmodified lines | ||
| 1724 | 1719 | &mix->send_routing[0][0]); |
| 1725 | 1720 | } |
| 1726 | 1721 | } |
| 1727 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1722 | + spin_unlock_irq(&emu->reg_lock); | |
| 1728 | 1723 | return change; |
| 1729 | 1724 | } |
| 1730 | 1725 | |
| @@ -1766,14 +1761,13 @@ static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, · 35 unmodified lines | ||
| 1766 | 1761 | static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, |
| 1767 | 1762 | struct snd_ctl_elem_value *ucontrol) |
| 1768 | 1763 | { |
| 1769 | − unsigned long flags; | |
| 1770 | 1764 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1771 | 1765 | int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
| 1772 | 1766 | struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; |
| 1773 | 1767 | int change = 0, idx, val; |
| 1774 | 1768 | int num_efx = emu->audigy ? 8 : 4; |
| 1775 | 1769 | |
| 1776 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1770 | + spin_lock_irq(&emu->reg_lock); | |
| 1777 | 1771 | for (idx = 0; idx < num_efx; idx++) { |
| 1778 | 1772 | val = ucontrol->value.integer.value[idx] & 255; |
| 1779 | 1773 | if (mix->send_volume[0][idx] != val) { |
| @@ -1787,7 +1781,7 @@ static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, · 7 unmodified lines | ||
| 1787 | 1781 | &mix->send_volume[0][0]); |
| 1788 | 1782 | } |
| 1789 | 1783 | } |
| 1790 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1784 | + spin_unlock_irq(&emu->reg_lock); | |
| 1791 | 1785 | return change; |
| 1792 | 1786 | } |
| 1793 | 1787 | |
| @@ -1826,14 +1820,13 @@ static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, · 32 unmodified lines | ||
| 1826 | 1820 | static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, |
| 1827 | 1821 | struct snd_ctl_elem_value *ucontrol) |
| 1828 | 1822 | { |
| 1829 | − unsigned long flags; | |
| 1830 | 1823 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1831 | 1824 | int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
| 1832 | 1825 | struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; |
| 1833 | 1826 | int change = 0, val; |
| 1834 | 1827 | unsigned uval; |
| 1835 | 1828 | |
| 1836 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 1829 | + spin_lock_irq(&emu->reg_lock); | |
| 1837 | 1830 | uval = ucontrol->value.integer.value[0] & 0x1ffff; |
| 1838 | 1831 | val = uval * 0x8000U / 0xffffU; |
| 1839 | 1832 | if (mix->attn[0] != val) { |
| @@ -1845,7 +1838,7 @@ static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 1845 | 1838 | snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); |
| 1846 | 1839 | } |
| 1847 | 1840 | } |
| 1848 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 1841 | + spin_unlock_irq(&emu->reg_lock); | |
| 1849 | 1842 | return change; |
| 1850 | 1843 | } |
| 1851 | 1844 | |
| @@ -1881,7 +1874,6 @@ static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, · 29 unmodified lines | ||
| 1881 | 1874 | static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, |
| 1882 | 1875 | struct snd_ctl_elem_value *ucontrol) |
| 1883 | 1876 | { |
| 1884 | − unsigned long flags; | |
| 1885 | 1877 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); |
| 1886 | 1878 | unsigned int reg, val, sw; |
| 1887 | 1879 | int change = 0; |
| @@ -1889,7 +1881,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, · 1 unmodified line | ||
| 1889 | 1881 | sw = ucontrol->value.integer.value[0]; |
| 1890 | 1882 | if (emu->card_capabilities->invert_shared_spdif) |
| 1891 | 1883 | sw = !sw; |
| 1892 | − spin_lock_irqsave(&emu->emu_lock, flags); | |
| 1884 | + spin_lock_irq(&emu->emu_lock); | |
| 1893 | 1885 | if ( emu->card_capabilities->i2c_adc) { |
| 1894 | 1886 | /* Do nothing for Audigy 2 ZS Notebook */ |
| 1895 | 1887 | } else if (emu->audigy) { |
| @@ -1910,7 +1902,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, · 14 unmodified lines | ||
| 1910 | 1902 | reg |= val; |
| 1911 | 1903 | outl(reg | val, emu->port + HCFG); |
| 1912 | 1904 | } |
| 1913 | − spin_unlock_irqrestore(&emu->emu_lock, flags); | |
| 1905 | + spin_unlock_irq(&emu->emu_lock); | |
| 1914 | 1906 | return change; |
| 1915 | 1907 | } |
| 1916 | 1908 | |
| @@ -1990,18 +1982,9 @@ static int remove_ctl(struct snd_card *card, const char *name) · 73 unmodified lines | ||
| 1990 | 1982 | return snd_ctl_remove_id(card, &id); |
| 1991 | 1983 | } |
| 1992 | 1984 | |
| 1993 | −static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) | |
| 1994 | −{ | |
| 1995 | − struct snd_ctl_elem_id sid; | |
| 1996 | − memset(&sid, 0, sizeof(sid)); | |
| 1997 | − strcpy(sid.name, name); | |
| 1998 | − sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 1999 | − return snd_ctl_find_id(card, &sid); | |
| 2000 | −} | |
| 2001 | − | |
| 2002 | 1985 | static int rename_ctl(struct snd_card *card, const char *src, const char *dst) |
| 2003 | 1986 | { |
| 2004 | − struct snd_kcontrol *kctl = ctl_find(card, src); | |
| 1987 | + struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card, src); | |
| 2005 | 1988 | if (kctl) { |
| 2006 | 1989 | snd_ctl_rename(card, kctl, dst); |
| 2007 | 1990 | return 0; |
| @@ -2342,8 +2325,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, · 334 unmodified lines | ||
| 2342 | 2325 | emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); |
| 2343 | 2326 | snd_emu1010_apply_sources(emu); |
| 2344 | 2327 | |
| 2345 | − err = snd_ctl_add(card, | |
| 2346 | − snd_ctl_new1(&snd_emu1010_clock_source, emu)); | |
| 2328 | + kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); | |
| 2329 | + err = snd_ctl_add(card, kctl); | |
| 2347 | 2330 | if (err < 0) |
| 2348 | 2331 | return err; |
| 2349 | 2332 | err = snd_ctl_add(card, |
| @@ -104,10 +104,9 @@ static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int st · 103 unmodified lines | ||
| 104 | 104 | |
| 105 | 105 | static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack) |
| 106 | 106 | { |
| 107 | − unsigned long flags; | |
| 108 | 107 | int timeout, ok; |
| 109 | 108 | |
| 110 | − spin_lock_irqsave(&midi->input_lock, flags); | |
| 109 | + spin_lock_irq(&midi->input_lock); | |
| 111 | 110 | mpu401_write_data(emu, midi, 0x00); |
| 112 | 111 | /* mpu401_clear_rx(emu, midi); */ |
| 113 | 112 | |
| @@ -126,7 +125,7 @@ static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_mid · 12 unmodified lines | ||
| 126 | 125 | } else { |
| 127 | 126 | ok = 1; |
| 128 | 127 | } |
| 129 | − spin_unlock_irqrestore(&midi->input_lock, flags); | |
| 128 | + spin_unlock_irq(&midi->input_lock); | |
| 130 | 129 | if (!ok) { |
| 131 | 130 | dev_err(emu->card->dev, |
| 132 | 131 | "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", |
| @@ -142,22 +141,21 @@ static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) · 9 unmodified lines | ||
| 142 | 141 | { |
| 143 | 142 | struct snd_emu10k1 *emu; |
| 144 | 143 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; |
| 145 | − unsigned long flags; | |
| 146 | 144 | |
| 147 | 145 | emu = midi->emu; |
| 148 | 146 | if (snd_BUG_ON(!emu)) |
| 149 | 147 | return -ENXIO; |
| 150 | − spin_lock_irqsave(&midi->open_lock, flags); | |
| 148 | + spin_lock_irq(&midi->open_lock); | |
| 151 | 149 | midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; |
| 152 | 150 | midi->substream_input = substream; |
| 153 | 151 | if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { |
| 154 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 152 | + spin_unlock_irq(&midi->open_lock); | |
| 155 | 153 | if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) |
| 156 | 154 | goto error_out; |
| 157 | 155 | if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) |
| 158 | 156 | goto error_out; |
| 159 | 157 | } else { |
| 160 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 158 | + spin_unlock_irq(&midi->open_lock); | |
| 161 | 159 | } |
| 162 | 160 | return 0; |
| 163 | 161 | |
| @@ -169,22 +167,21 @@ static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) · 5 unmodified lines | ||
| 169 | 167 | { |
| 170 | 168 | struct snd_emu10k1 *emu; |
| 171 | 169 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; |
| 172 | − unsigned long flags; | |
| 173 | 170 | |
| 174 | 171 | emu = midi->emu; |
| 175 | 172 | if (snd_BUG_ON(!emu)) |
| 176 | 173 | return -ENXIO; |
| 177 | − spin_lock_irqsave(&midi->open_lock, flags); | |
| 174 | + spin_lock_irq(&midi->open_lock); | |
| 178 | 175 | midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; |
| 179 | 176 | midi->substream_output = substream; |
| 180 | 177 | if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { |
| 181 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 178 | + spin_unlock_irq(&midi->open_lock); | |
| 182 | 179 | if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) |
| 183 | 180 | goto error_out; |
| 184 | 181 | if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) |
| 185 | 182 | goto error_out; |
| 186 | 183 | } else { |
| 187 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 184 | + spin_unlock_irq(&midi->open_lock); | |
| 188 | 185 | } |
| 189 | 186 | return 0; |
| 190 | 187 | |
| @@ -196,21 +193,20 @@ static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) · 5 unmodified lines | ||
| 196 | 193 | { |
| 197 | 194 | struct snd_emu10k1 *emu; |
| 198 | 195 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; |
| 199 | − unsigned long flags; | |
| 200 | 196 | int err = 0; |
| 201 | 197 | |
| 202 | 198 | emu = midi->emu; |
| 203 | 199 | if (snd_BUG_ON(!emu)) |
| 204 | 200 | return -ENXIO; |
| 205 | − spin_lock_irqsave(&midi->open_lock, flags); | |
| 201 | + spin_lock_irq(&midi->open_lock); | |
| 206 | 202 | snd_emu10k1_intr_disable(emu, midi->rx_enable); |
| 207 | 203 | midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; |
| 208 | 204 | midi->substream_input = NULL; |
| 209 | 205 | if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { |
| 210 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 206 | + spin_unlock_irq(&midi->open_lock); | |
| 211 | 207 | err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); |
| 212 | 208 | } else { |
| 213 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 209 | + spin_unlock_irq(&midi->open_lock); | |
| 214 | 210 | } |
| 215 | 211 | return err; |
| 216 | 212 | } |
| @@ -219,21 +215,20 @@ static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream · 2 unmodified lines | ||
| 219 | 215 | { |
| 220 | 216 | struct snd_emu10k1 *emu; |
| 221 | 217 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; |
| 222 | − unsigned long flags; | |
| 223 | 218 | int err = 0; |
| 224 | 219 | |
| 225 | 220 | emu = midi->emu; |
| 226 | 221 | if (snd_BUG_ON(!emu)) |
| 227 | 222 | return -ENXIO; |
| 228 | − spin_lock_irqsave(&midi->open_lock, flags); | |
| 223 | + spin_lock_irq(&midi->open_lock); | |
| 229 | 224 | snd_emu10k1_intr_disable(emu, midi->tx_enable); |
| 230 | 225 | midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; |
| 231 | 226 | midi->substream_output = NULL; |
| 232 | 227 | if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { |
| 233 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 228 | + spin_unlock_irq(&midi->open_lock); | |
| 234 | 229 | err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); |
| 235 | 230 | } else { |
| 236 | − spin_unlock_irqrestore(&midi->open_lock, flags); | |
| 231 | + spin_unlock_irq(&midi->open_lock); | |
| 237 | 232 | } |
| 238 | 233 | return err; |
| 239 | 234 | } |
| @@ -256,7 +251,6 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr · 16 unmodified lines | ||
| 256 | 251 | { |
| 257 | 252 | struct snd_emu10k1 *emu; |
| 258 | 253 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; |
| 259 | − unsigned long flags; | |
| 260 | 254 | |
| 261 | 255 | emu = midi->emu; |
| 262 | 256 | if (snd_BUG_ON(!emu)) |
| @@ -267,13 +261,13 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr · 4 unmodified lines | ||
| 267 | 261 | unsigned char byte; |
| 268 | 262 | |
| 269 | 263 | /* try to send some amount of bytes here before interrupts */ |
| 270 | − spin_lock_irqsave(&midi->output_lock, flags); | |
| 264 | + spin_lock_irq(&midi->output_lock); | |
| 271 | 265 | while (max > 0) { |
| 272 | 266 | if (mpu401_output_ready(emu, midi)) { |
| 273 | 267 | if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || |
| 274 | 268 | snd_rawmidi_transmit(substream, &byte, 1) != 1) { |
| 275 | 269 | /* no more data */ |
| 276 | − spin_unlock_irqrestore(&midi->output_lock, flags); | |
| 270 | + spin_unlock_irq(&midi->output_lock); | |
| 277 | 271 | return; |
| 278 | 272 | } |
| 279 | 273 | mpu401_write_data(emu, midi, byte); |
| @@ -282,7 +276,7 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr · 2 unmodified lines | ||
| 282 | 276 | break; |
| 283 | 277 | } |
| 284 | 278 | } |
| 285 | − spin_unlock_irqrestore(&midi->output_lock, flags); | |
| 279 | + spin_unlock_irq(&midi->output_lock); | |
| 286 | 280 | snd_emu10k1_intr_enable(emu, midi->tx_enable); |
| 287 | 281 | } else { |
| 288 | 282 | snd_emu10k1_intr_disable(emu, midi->tx_enable); |
| @@ -1,15 +1,12 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | + * Lee Revell <rlrevell@joe-job.com> | |
| 5 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 6 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 4 | 7 | * Creative Labs, Inc. |
| 5 | − * Routines for control of EMU10K1 chips / PCM routines | |
| 6 | − * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> | |
| 7 | − * | |
| 8 | − * BUGS: | |
| 9 | − * -- | |
| 10 | 8 | * |
| 11 | − * TODO: | |
| 12 | − * -- | |
| 9 | + * Routines for control of EMU10K1 chips / PCM routines | |
| 13 | 10 | */ |
| 14 | 11 | |
| 15 | 12 | #include <linux/pci.h> |
| @@ -343,9 +340,7 @@ static void snd_emu10k1_pcm_init_voices(struct snd_emu10k1 *emu, · 327 unmodified lines | ||
| 343 | 340 | unsigned int end_addr, |
| 344 | 341 | struct snd_emu10k1_pcm_mixer *mix) |
| 345 | 342 | { |
| 346 | − unsigned long flags; | |
| 347 | − | |
| 348 | − spin_lock_irqsave(&emu->reg_lock, flags); | |
| 343 | + spin_lock_irq(&emu->reg_lock); | |
| 349 | 344 | snd_emu10k1_pcm_init_voice(emu, evoice, w_16, stereo, |
| 350 | 345 | start_addr, end_addr, |
| 351 | 346 | &mix->send_routing[stereo][0], |
| @@ -355,7 +350,7 @@ static void snd_emu10k1_pcm_init_voices(struct snd_emu10k1 *emu, · 3 unmodified lines | ||
| 355 | 350 | start_addr, end_addr, |
| 356 | 351 | &mix->send_routing[2][0], |
| 357 | 352 | &mix->send_volume[2][0]); |
| 358 | − spin_unlock_irqrestore(&emu->reg_lock, flags); | |
| 353 | + spin_unlock_irq(&emu->reg_lock); | |
| 359 | 354 | } |
| 360 | 355 | |
| 361 | 356 | static void snd_emu10k1_pcm_init_extra_voice(struct snd_emu10k1 *emu, |
| @@ -1,17 +1,12 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | + * Lee Revell <rlrevell@joe-job.com> | |
| 5 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 6 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 4 | 7 | * Creative Labs, Inc. |
| 5 | − * Routines for control of EMU10K1 chips / proc interface routines | |
| 6 | − * | |
| 7 | − * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> | |
| 8 | − * Added EMU 1010 support. | |
| 9 | 8 | * |
| 10 | − * BUGS: | |
| 11 | − * -- | |
| 12 | − * | |
| 13 | − * TODO: | |
| 14 | − * -- | |
| 9 | + * Routines for control of EMU10K1 chips / proc interface routines | |
| 15 | 10 | */ |
| 16 | 11 | |
| 17 | 12 | #include <linux/slab.h> |
| @@ -536,15 +531,14 @@ static unsigned int snd_ptr_read(struct snd_emu10k1 * emu, · 518 unmodified lines | ||
| 536 | 531 | unsigned int reg, |
| 537 | 532 | unsigned int chn) |
| 538 | 533 | { |
| 539 | − unsigned long flags; | |
| 540 | 534 | unsigned int regptr, val; |
| 541 | 535 | |
| 542 | 536 | regptr = (reg << 16) | chn; |
| 543 | 537 | |
| 544 | − spin_lock_irqsave(&emu->emu_lock, flags); | |
| 538 | + spin_lock_irq(&emu->emu_lock); | |
| 545 | 539 | outl(regptr, emu->port + iobase + PTR); |
| 546 | 540 | val = inl(emu->port + iobase + DATA); |
| 547 | − spin_unlock_irqrestore(&emu->emu_lock, flags); | |
| 541 | + spin_unlock_irq(&emu->emu_lock); | |
| 548 | 542 | return val; |
| 549 | 543 | } |
| 550 | 544 | |
| @@ -555,14 +549,13 @@ static void snd_ptr_write(struct snd_emu10k1 *emu, · 4 unmodified lines | ||
| 555 | 549 | unsigned int data) |
| 556 | 550 | { |
| 557 | 551 | unsigned int regptr; |
| 558 | − unsigned long flags; | |
| 559 | 552 | |
| 560 | 553 | regptr = (reg << 16) | chn; |
| 561 | 554 | |
| 562 | − spin_lock_irqsave(&emu->emu_lock, flags); | |
| 555 | + spin_lock_irq(&emu->emu_lock); | |
| 563 | 556 | outl(regptr, emu->port + iobase + PTR); |
| 564 | 557 | outl(data, emu->port + iobase + DATA); |
| 565 | − spin_unlock_irqrestore(&emu->emu_lock, flags); | |
| 558 | + spin_unlock_irq(&emu->emu_lock); | |
| 566 | 559 | } |
| 567 | 560 | |
| 568 | 561 | |
| @@ -1,14 +1,12 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | + * Lee Revell <rlrevell@joe-job.com> | |
| 5 | + * James Courtier-Dutton <James@superbug.co.uk> | |
| 6 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 4 | 7 | * Creative Labs, Inc. |
| 5 | − * Routines for control of EMU10K1 chips | |
| 6 | − * | |
| 7 | − * BUGS: | |
| 8 | − * -- | |
| 9 | 8 | * |
| 10 | − * TODO: | |
| 11 | − * -- | |
| 9 | + * Routines for control of EMU10K1 chips | |
| 12 | 10 | */ |
| 13 | 11 | |
| 14 | 12 | #include <linux/time.h> |
| @@ -302,6 +300,8 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 * · 287 unmodified lines | ||
| 302 | 300 | { |
| 303 | 301 | // The higest input pin is used as the designated interrupt trigger, |
| 304 | 302 | // so it needs to be masked out. |
| 303 | + // But note that any other input pin change will also cause an IRQ, | |
| 304 | + // so using this function often causes an IRQ as a side effect. | |
| 305 | 305 | u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f; |
| 306 | 306 | if (snd_BUG_ON(reg > 0x3f)) |
| 307 | 307 | return; |
| @@ -3,12 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | 4 | * Creative Labs, Inc. |
| 5 | 5 | * Routines for IRQ control of EMU10K1 chips |
| 6 | − * | |
| 7 | − * BUGS: | |
| 8 | − * -- | |
| 9 | − * | |
| 10 | − * TODO: | |
| 11 | − * -- | |
| 12 | 6 | */ |
| 13 | 7 | |
| 14 | 8 | #include <linux/time.h> |
| @@ -149,6 +143,13 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) · 134 unmodified lines | ||
| 149 | 143 | outl(0, emu->port + INTE2); |
| 150 | 144 | status &= ~IPR_P16V; |
| 151 | 145 | } |
| 146 | + if (status & IPR_A_GPIO) { | |
| 147 | + if (emu->gpio_interrupt) | |
| 148 | + emu->gpio_interrupt(emu); | |
| 149 | + else | |
| 150 | + snd_emu10k1_intr_disable(emu, INTE_A_GPIOENABLE); | |
| 151 | + status &= ~IPR_A_GPIO; | |
| 152 | + } | |
| 152 | 153 | |
| 153 | 154 | if (status) { |
| 154 | 155 | dev_err(emu->card->dev, |
| @@ -2,62 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
| 4 | 4 | * Driver p16v chips |
| 5 | − * Version: 0.21 | |
| 6 | − * | |
| 7 | − * FEATURES currently supported: | |
| 8 | − * Output fixed at S32_LE, 2 channel to hw:0,0 | |
| 9 | − * Rates: 44.1, 48, 96, 192. | |
| 10 | − * | |
| 11 | − * Changelog: | |
| 12 | − * 0.8 | |
| 13 | − * Use separate card based buffer for periods table. | |
| 14 | − * 0.9 | |
| 15 | − * Use 2 channel output streams instead of 8 channel. | |
| 16 | − * (8 channel output streams might be good for ASIO type output) | |
| 17 | − * Corrected speaker output, so Front -> Front etc. | |
| 18 | − * 0.10 | |
| 19 | − * Fixed missed interrupts. | |
| 20 | − * 0.11 | |
| 21 | − * Add Sound card model number and names. | |
| 22 | − * Add Analog volume controls. | |
| 23 | − * 0.12 | |
| 24 | − * Corrected playback interrupts. Now interrupt per period, instead of half period. | |
| 25 | − * 0.13 | |
| 26 | − * Use single trigger for multichannel. | |
| 27 | − * 0.14 | |
| 28 | − * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo. | |
| 29 | − * 0.15 | |
| 30 | − * Force buffer_size / period_size == INTEGER. | |
| 31 | − * 0.16 | |
| 32 | − * Update p16v.c to work with changed alsa api. | |
| 33 | − * 0.17 | |
| 34 | − * Update p16v.c to work with changed alsa api. Removed boot_devs. | |
| 35 | − * 0.18 | |
| 36 | − * Merging with snd-emu10k1 driver. | |
| 37 | − * 0.19 | |
| 38 | − * One stereo channel at 24bit now works. | |
| 39 | − * 0.20 | |
| 40 | − * Added better register defines. | |
| 41 | − * 0.21 | |
| 42 | − * Split from p16v.c | |
| 43 | − * | |
| 44 | − * BUGS: | |
| 45 | − * Some stability problems when unloading the snd-p16v kernel module. | |
| 46 | − * -- | |
| 47 | − * | |
| 48 | − * TODO: | |
| 49 | − * SPDIF out. | |
| 50 | − * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz. | |
| 51 | − * Currently capture fixed at 48000Hz. | |
| 52 | − * | |
| 53 | − * -- | |
| 54 | − * GENERAL INFO: | |
| 55 | − * Model: SB0240 | |
| 56 | − * P16V Chip: CA0151-DBS | |
| 57 | − * Audigy 2 Chip: CA0102-IAT | |
| 58 | − * AC97 Codec: STAC 9721 | |
| 59 | − * ADC: Philips 1361T (Stereo 24bit) | |
| 60 | − * DAC: CS4382-K (8-channel, 24bit, 192Khz) | |
| 61 | 5 | * |
| 62 | 6 | * This code was initially based on code from ALSA's emu10k1x.c which is: |
| 63 | 7 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
| @@ -2,7 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
| 4 | 4 | * Driver p17v chips |
| 5 | − * Version: 0.01 | |
| 6 | 5 | */ |
| 7 | 6 | |
| 8 | 7 | /******************************************************************************/ |
| @@ -2,13 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Lee Revell <rlrevell@joe-job.com> |
| 4 | 4 | * Clemens Ladisch <clemens@ladisch.de> |
| 5 | − * Routines for control of EMU10K1 chips | |
| 6 | − * | |
| 7 | − * BUGS: | |
| 8 | − * -- | |
| 5 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 9 | 6 | * |
| 10 | − * TODO: | |
| 11 | − * -- | |
| 7 | + * Routines for control of EMU10K1 chips | |
| 12 | 8 | */ |
| 13 | 9 | |
| 14 | 10 | #include <linux/time.h> |
| @@ -2,7 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
| 4 | 4 | * Driver tina2 chips |
| 5 | − * Version: 0.1 | |
| 6 | 5 | */ |
| 7 | 6 | |
| 8 | 7 | /********************************************************************************************************/ |
| @@ -1,17 +1,11 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
| 4 | − * Creative Labs, Inc. | |
| 5 | 4 | * Lee Revell <rlrevell@joe-job.com> |
| 6 | − * Routines for control of EMU10K1 chips - voice manager | |
| 7 | − * | |
| 8 | − * Rewrote voice allocator for multichannel support - rlrevell 12/2004 | |
| 9 | − * | |
| 10 | − * BUGS: | |
| 11 | − * -- | |
| 5 | + * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | |
| 6 | + * Creative Labs, Inc. | |
| 12 | 7 | * |
| 13 | − * TODO: | |
| 14 | − * -- | |
| 8 | + * Routines for control of EMU10K1 chips - voice manager | |
| 15 | 9 | */ |
| 16 | 10 | |
| 17 | 11 | #include <linux/time.h> |
| @@ -824,7 +824,7 @@ static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *s · 823 unmodified lines | ||
| 824 | 824 | |
| 825 | 825 | static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, |
| 826 | 826 | int channel, unsigned long pos, |
| 827 | − void __user *dst, unsigned long count) | |
| 827 | + struct iov_iter *dst, unsigned long count) | |
| 828 | 828 | { |
| 829 | 829 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 830 | 830 | struct es1938 *chip = snd_pcm_substream_chip(substream); |
| @@ -832,36 +832,17 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, · 1 unmodified line | ||
| 832 | 832 | if (snd_BUG_ON(pos + count > chip->dma1_size)) |
| 833 | 833 | return -EINVAL; |
| 834 | 834 | if (pos + count < chip->dma1_size) { |
| 835 | − if (copy_to_user(dst, runtime->dma_area + pos + 1, count)) | |
| 835 | + if (copy_to_iter(runtime->dma_area + pos + 1, count, dst) != count) | |
| 836 | 836 | return -EFAULT; |
| 837 | 837 | } else { |
| 838 | − if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) | |
| 838 | + if (copy_to_iter(runtime->dma_area + pos + 1, count - 1, dst) != count - 1) | |
| 839 | 839 | return -EFAULT; |
| 840 | − if (put_user(runtime->dma_area[0], | |
| 841 | − ((unsigned char __user *)dst) + count - 1)) | |
| 840 | + if (copy_to_iter(runtime->dma_area, 1, dst) != 1) | |
| 842 | 841 | return -EFAULT; |
| 843 | 842 | } |
| 844 | 843 | return 0; |
| 845 | 844 | } |
| 846 | 845 | |
| 847 | −static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 848 | − int channel, unsigned long pos, | |
| 849 | − void *dst, unsigned long count) | |
| 850 | −{ | |
| 851 | − struct snd_pcm_runtime *runtime = substream->runtime; | |
| 852 | − struct es1938 *chip = snd_pcm_substream_chip(substream); | |
| 853 | − | |
| 854 | − if (snd_BUG_ON(pos + count > chip->dma1_size)) | |
| 855 | − return -EINVAL; | |
| 856 | − if (pos + count < chip->dma1_size) { | |
| 857 | − memcpy(dst, runtime->dma_area + pos + 1, count); | |
| 858 | − } else { | |
| 859 | − memcpy(dst, runtime->dma_area + pos + 1, count - 1); | |
| 860 | − runtime->dma_area[0] = *((unsigned char *)dst + count - 1); | |
| 861 | − } | |
| 862 | − return 0; | |
| 863 | −} | |
| 864 | − | |
| 865 | 846 | /* ---------------------------------------------------------------------- |
| 866 | 847 | * Audio1 Capture (ADC) |
| 867 | 848 | * ----------------------------------------------------------------------*/ |
| @@ -987,8 +968,7 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = { · 119 unmodified lines | ||
| 987 | 968 | .prepare = snd_es1938_capture_prepare, |
| 988 | 969 | .trigger = snd_es1938_capture_trigger, |
| 989 | 970 | .pointer = snd_es1938_capture_pointer, |
| 990 | − .copy_user = snd_es1938_capture_copy, | |
| 991 | − .copy_kernel = snd_es1938_capture_copy_kernel, | |
| 971 | + .copy = snd_es1938_capture_copy, | |
| 992 | 972 | }; |
| 993 | 973 | |
| 994 | 974 | static int snd_es1938_new_pcm(struct es1938 *chip, int device) |
| @@ -2005,9 +2005,6 @@ snd_es1968_mixer(struct es1968 *chip) · 2004 unmodified lines | ||
| 2005 | 2005 | { |
| 2006 | 2006 | struct snd_ac97_bus *pbus; |
| 2007 | 2007 | struct snd_ac97_template ac97; |
| 2008 | −#ifndef CONFIG_SND_ES1968_INPUT | |
| 2009 | − struct snd_ctl_elem_id elem_id; | |
| 2010 | −#endif | |
| 2011 | 2008 | int err; |
| 2012 | 2009 | static const struct snd_ac97_bus_ops ops = { |
| 2013 | 2010 | .write = snd_es1968_ac97_write, |
| @@ -2027,14 +2024,10 @@ snd_es1968_mixer(struct es1968 *chip) · 13 unmodified lines | ||
| 2027 | 2024 | |
| 2028 | 2025 | #ifndef CONFIG_SND_ES1968_INPUT |
| 2029 | 2026 | /* attach master switch / volumes for h/w volume control */ |
| 2030 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 2031 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2032 | − strcpy(elem_id.name, "Master Playback Switch"); | |
| 2033 | − chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); | |
| 2034 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 2035 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2036 | − strcpy(elem_id.name, "Master Playback Volume"); | |
| 2037 | − chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); | |
| 2027 | + chip->master_switch = snd_ctl_find_id_mixer(chip->card, | |
| 2028 | + "Master Playback Switch"); | |
| 2029 | + chip->master_volume = snd_ctl_find_id_mixer(chip->card, | |
| 2030 | + "Master Playback Volume"); | |
| 2038 | 2031 | #endif |
| 2039 | 2032 | |
| 2040 | 2033 | return 0; |
| @@ -104,6 +104,7 @@ config SND_HDA_SCODEC_CS35L41_I2C · 103 unmodified lines | ||
| 104 | 104 | tristate "Build CS35L41 HD-audio side codec support for I2C Bus" |
| 105 | 105 | depends on I2C |
| 106 | 106 | depends on ACPI |
| 107 | + depends on EFI | |
| 107 | 108 | depends on SND_SOC |
| 108 | 109 | select SND_SOC_CS35L41_LIB |
| 109 | 110 | select SND_HDA_SCODEC_CS35L41 |
| @@ -119,6 +120,7 @@ config SND_HDA_SCODEC_CS35L41_SPI · 9 unmodified lines | ||
| 119 | 120 | tristate "Build CS35L41 HD-audio codec support for SPI Bus" |
| 120 | 121 | depends on SPI_MASTER |
| 121 | 122 | depends on ACPI |
| 123 | + depends on EFI | |
| 122 | 124 | depends on SND_SOC |
| 123 | 125 | select SND_SOC_CS35L41_LIB |
| 124 | 126 | select SND_HDA_SCODEC_CS35L41 |
| @@ -130,6 +132,53 @@ config SND_HDA_SCODEC_CS35L41_SPI · 5 unmodified lines | ||
| 130 | 132 | comment "Set to Y if you want auto-loading the side codec driver" |
| 131 | 133 | depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m |
| 132 | 134 | |
| 135 | +config SND_HDA_SCODEC_CS35L56 | |
| 136 | + tristate | |
| 137 | + | |
| 138 | +config SND_HDA_SCODEC_CS35L56_I2C | |
| 139 | + tristate "Build CS35L56 HD-audio side codec support for I2C Bus" | |
| 140 | + depends on I2C | |
| 141 | + depends on ACPI || COMPILE_TEST | |
| 142 | + depends on SND_SOC | |
| 143 | + select CS_DSP | |
| 144 | + select SND_HDA_GENERIC | |
| 145 | + select SND_SOC_CS35L56_SHARED | |
| 146 | + select SND_HDA_SCODEC_CS35L56 | |
| 147 | + select SND_HDA_CS_DSP_CONTROLS | |
| 148 | + help | |
| 149 | + Say Y or M here to include CS35L56 amplifier support with | |
| 150 | + I2C control. | |
| 151 | + | |
| 152 | +config SND_HDA_SCODEC_CS35L56_SPI | |
| 153 | + tristate "Build CS35L56 HD-audio side codec support for SPI Bus" | |
| 154 | + depends on SPI_MASTER | |
| 155 | + depends on ACPI || COMPILE_TEST | |
| 156 | + depends on SND_SOC | |
| 157 | + select CS_DSP | |
| 158 | + select SND_HDA_GENERIC | |
| 159 | + select SND_SOC_CS35L56_SHARED | |
| 160 | + select SND_HDA_SCODEC_CS35L56 | |
| 161 | + select SND_HDA_CS_DSP_CONTROLS | |
| 162 | + help | |
| 163 | + Say Y or M here to include CS35L56 amplifier support with | |
| 164 | + SPI control. | |
| 165 | + | |
| 166 | +config SND_HDA_SCODEC_TAS2781_I2C | |
| 167 | + tristate "Build TAS2781 HD-audio side codec support for I2C Bus" | |
| 168 | + depends on I2C | |
| 169 | + depends on ACPI | |
| 170 | + depends on EFI | |
| 171 | + depends on SND_SOC | |
| 172 | + select SND_SOC_TAS2781_COMLIB | |
| 173 | + select SND_SOC_TAS2781_FMWLIB | |
| 174 | + select CRC32_SARWATE | |
| 175 | + help | |
| 176 | + Say Y or M here to include TAS2781 I2C HD-audio side codec support | |
| 177 | + in snd-hda-intel driver, such as ALC287. | |
| 178 | + | |
| 179 | +comment "Set to Y if you want auto-loading the side codec driver" | |
| 180 | + depends on SND_HDA=y && SND_HDA_SCODEC_TAS2781_I2C=m | |
| 181 | + | |
| 133 | 182 | config SND_HDA_CODEC_REALTEK |
| 134 | 183 | tristate "Build Realtek HD-audio codec support" |
| 135 | 184 | select SND_HDA_GENERIC |
| @@ -28,10 +28,14 @@ snd-hda-codec-via-objs := patch_via.o · 27 unmodified lines | ||
| 28 | 28 | snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o |
| 29 | 29 | |
| 30 | 30 | # side codecs |
| 31 | −snd-hda-scodec-cs35l41-objs := cs35l41_hda.o | |
| 31 | +snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o | |
| 32 | 32 | snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o |
| 33 | 33 | snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o |
| 34 | +snd-hda-scodec-cs35l56-objs := cs35l56_hda.o | |
| 35 | +snd-hda-scodec-cs35l56-i2c-objs := cs35l56_hda_i2c.o | |
| 36 | +snd-hda-scodec-cs35l56-spi-objs := cs35l56_hda_spi.o | |
| 34 | 37 | snd-hda-cs-dsp-ctls-objs := hda_cs_dsp_ctl.o |
| 38 | +snd-hda-scodec-tas2781-i2c-objs := tas2781_hda_i2c.o | |
| 35 | 39 | |
| 36 | 40 | # common driver |
| 37 | 41 | obj-$(CONFIG_SND_HDA) := snd-hda-codec.o |
| @@ -55,7 +59,11 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o · 17 unmodified lines | ||
| 55 | 59 | obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o |
| 56 | 60 | obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o |
| 57 | 61 | obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o |
| 62 | +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56) += snd-hda-scodec-cs35l56.o | |
| 63 | +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_I2C) += snd-hda-scodec-cs35l56-i2c.o | |
| 64 | +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_SPI) += snd-hda-scodec-cs35l56-spi.o | |
| 58 | 65 | obj-$(CONFIG_SND_HDA_CS_DSP_CONTROLS) += snd-hda-cs-dsp-ctls.o |
| 66 | +obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_I2C) += snd-hda-scodec-tas2781-i2c.o | |
| 59 | 67 | |
| 60 | 68 | # this must be the last entry after codec drivers; |
| 61 | 69 | # otherwise the codec patches won't be hooked before the PCI probe |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "hda_component.h" |
| 20 | 20 | #include "cs35l41_hda.h" |
| 21 | 21 | #include "hda_cs_dsp_ctl.h" |
| 22 | +#include "cs35l41_hda_property.h" | |
| 22 | 23 | |
| 23 | 24 | #define CS35L41_FIRMWARE_ROOT "cirrus/" |
| 24 | 25 | #define CS35L41_PART "cs35l41" |
| @@ -58,8 +59,6 @@ static const struct reg_sequence cs35l41_hda_config[] = { · 33 unmodified lines | ||
| 58 | 59 | { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON |
| 59 | 60 | { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON |
| 60 | 61 | { CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC = ERRVOL |
| 61 | − { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB | |
| 62 | − { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB | |
| 63 | 62 | }; |
| 64 | 63 | |
| 65 | 64 | static const struct reg_sequence cs35l41_hda_config_dsp[] = { |
| @@ -82,6 +81,14 @@ static const struct reg_sequence cs35l41_hda_config_dsp[] = { · 16 unmodified lines | ||
| 82 | 81 | { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON |
| 83 | 82 | { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON |
| 84 | 83 | { CS35L41_DSP1_RX5_SRC, 0x00000029 }, // DSP1RX5 SRC = VBSTMON |
| 84 | +}; | |
| 85 | + | |
| 86 | +static const struct reg_sequence cs35l41_hda_unmute[] = { | |
| 87 | + { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB | |
| 88 | + { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB | |
| 89 | +}; | |
| 90 | + | |
| 91 | +static const struct reg_sequence cs35l41_hda_unmute_dsp[] = { | |
| 85 | 92 | { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB |
| 86 | 93 | { CS35L41_AMP_GAIN_CTRL, 0x00000233 }, // AMP_GAIN_PCM = 17.5dB AMP_GAIN_PDM = 19.5dB |
| 87 | 94 | }; |
| @@ -483,73 +490,159 @@ static void cs35l41_irq_release(struct cs35l41_hda *cs35l41) · 395 unmodified lines | ||
| 483 | 490 | cs35l41->irq_errors = 0; |
| 484 | 491 | } |
| 485 | 492 | |
| 486 | −static void cs35l41_hda_playback_hook(struct device *dev, int action) | |
| 493 | +static void cs35l41_hda_play_start(struct device *dev) | |
| 487 | 494 | { |
| 488 | 495 | struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); |
| 489 | 496 | struct regmap *reg = cs35l41->regmap; |
| 490 | − int ret = 0; | |
| 497 | + | |
| 498 | + dev_dbg(dev, "Play (Start)\n"); | |
| 499 | + | |
| 500 | + if (cs35l41->playback_started) { | |
| 501 | + dev_dbg(dev, "Playback already started."); | |
| 502 | + return; | |
| 503 | + } | |
| 504 | + | |
| 505 | + cs35l41->playback_started = true; | |
| 506 | + | |
| 507 | + if (cs35l41->firmware_running) { | |
| 508 | + regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, | |
| 509 | + ARRAY_SIZE(cs35l41_hda_config_dsp)); | |
| 510 | + regmap_update_bits(reg, CS35L41_PWR_CTRL2, | |
| 511 | + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, | |
| 512 | + 1 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT); | |
| 513 | + cs35l41_set_cspl_mbox_cmd(cs35l41->dev, reg, CSPL_MBOX_CMD_RESUME); | |
| 514 | + } else { | |
| 515 | + regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config)); | |
| 516 | + } | |
| 517 | + regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); | |
| 518 | + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 519 | + regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001); | |
| 520 | + | |
| 521 | +} | |
| 522 | + | |
| 523 | +static void cs35l41_hda_play_done(struct device *dev) | |
| 524 | +{ | |
| 525 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 526 | + struct regmap *reg = cs35l41->regmap; | |
| 527 | + | |
| 528 | + dev_dbg(dev, "Play (Complete)\n"); | |
| 529 | + | |
| 530 | + cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1, NULL, | |
| 531 | + cs35l41->firmware_running); | |
| 532 | + if (cs35l41->firmware_running) { | |
| 533 | + regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp, | |
| 534 | + ARRAY_SIZE(cs35l41_hda_unmute_dsp)); | |
| 535 | + } else { | |
| 536 | + regmap_multi_reg_write(reg, cs35l41_hda_unmute, | |
| 537 | + ARRAY_SIZE(cs35l41_hda_unmute)); | |
| 538 | + } | |
| 539 | +} | |
| 540 | + | |
| 541 | +static void cs35l41_hda_pause_start(struct device *dev) | |
| 542 | +{ | |
| 543 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 544 | + struct regmap *reg = cs35l41->regmap; | |
| 545 | + | |
| 546 | + dev_dbg(dev, "Pause (Start)\n"); | |
| 547 | + | |
| 548 | + regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); | |
| 549 | + cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0, NULL, | |
| 550 | + cs35l41->firmware_running); | |
| 551 | +} | |
| 552 | + | |
| 553 | +static void cs35l41_hda_pause_done(struct device *dev) | |
| 554 | +{ | |
| 555 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 556 | + struct regmap *reg = cs35l41->regmap; | |
| 557 | + | |
| 558 | + dev_dbg(dev, "Pause (Complete)\n"); | |
| 559 | + | |
| 560 | + regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); | |
| 561 | + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 562 | + regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001); | |
| 563 | + if (cs35l41->firmware_running) { | |
| 564 | + cs35l41_set_cspl_mbox_cmd(dev, reg, CSPL_MBOX_CMD_PAUSE); | |
| 565 | + regmap_update_bits(reg, CS35L41_PWR_CTRL2, | |
| 566 | + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, | |
| 567 | + 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); | |
| 568 | + } | |
| 569 | + cs35l41_irq_release(cs35l41); | |
| 570 | + cs35l41->playback_started = false; | |
| 571 | +} | |
| 572 | + | |
| 573 | +static void cs35l41_hda_pre_playback_hook(struct device *dev, int action) | |
| 574 | +{ | |
| 575 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 491 | 576 | |
| 492 | 577 | switch (action) { |
| 493 | − case HDA_GEN_PCM_ACT_OPEN: | |
| 494 | − pm_runtime_get_sync(dev); | |
| 578 | + case HDA_GEN_PCM_ACT_CLEANUP: | |
| 495 | 579 | mutex_lock(&cs35l41->fw_mutex); |
| 496 | − cs35l41->playback_started = true; | |
| 497 | − if (cs35l41->firmware_running) { | |
| 498 | − regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, | |
| 499 | − ARRAY_SIZE(cs35l41_hda_config_dsp)); | |
| 500 | − regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | |
| 501 | − CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, | |
| 502 | − 1 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT); | |
| 503 | − cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, | |
| 504 | − CSPL_MBOX_CMD_RESUME); | |
| 505 | − } else { | |
| 506 | − regmap_multi_reg_write(reg, cs35l41_hda_config, | |
| 507 | − ARRAY_SIZE(cs35l41_hda_config)); | |
| 508 | − } | |
| 509 | − ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, | |
| 510 | − CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); | |
| 511 | − if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 512 | − regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001); | |
| 580 | + cs35l41_hda_pause_start(dev); | |
| 513 | 581 | mutex_unlock(&cs35l41->fw_mutex); |
| 514 | 582 | break; |
| 583 | + default: | |
| 584 | + break; | |
| 585 | + } | |
| 586 | +} | |
| 587 | +static void cs35l41_hda_playback_hook(struct device *dev, int action) | |
| 588 | +{ | |
| 589 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 590 | + | |
| 591 | + switch (action) { | |
| 592 | + case HDA_GEN_PCM_ACT_OPEN: | |
| 593 | + /* | |
| 594 | + * All amps must be resumed before we can start playing back. | |
| 595 | + * This ensures, for external boost, that all amps are in AMP_SAFE mode. | |
| 596 | + * Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the | |
| 597 | + * other actions. | |
| 598 | + */ | |
| 599 | + pm_runtime_get_sync(dev); | |
| 600 | + break; | |
| 515 | 601 | case HDA_GEN_PCM_ACT_PREPARE: |
| 516 | 602 | mutex_lock(&cs35l41->fw_mutex); |
| 517 | − ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1, NULL); | |
| 603 | + cs35l41_hda_play_start(dev); | |
| 518 | 604 | mutex_unlock(&cs35l41->fw_mutex); |
| 519 | 605 | break; |
| 520 | 606 | case HDA_GEN_PCM_ACT_CLEANUP: |
| 521 | 607 | mutex_lock(&cs35l41->fw_mutex); |
| 522 | − regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); | |
| 523 | − ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0, NULL); | |
| 608 | + cs35l41_hda_pause_done(dev); | |
| 524 | 609 | mutex_unlock(&cs35l41->fw_mutex); |
| 525 | 610 | break; |
| 526 | 611 | case HDA_GEN_PCM_ACT_CLOSE: |
| 527 | 612 | mutex_lock(&cs35l41->fw_mutex); |
| 528 | − ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, | |
| 529 | − CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); | |
| 530 | − if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 531 | − regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001); | |
| 532 | − if (cs35l41->firmware_running) { | |
| 533 | − cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, | |
| 534 | − CSPL_MBOX_CMD_PAUSE); | |
| 535 | − regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | |
| 536 | − CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, | |
| 537 | − 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); | |
| 613 | + if (!cs35l41->firmware_running && cs35l41->request_fw_load && | |
| 614 | + !cs35l41->fw_request_ongoing) { | |
| 615 | + dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n"); | |
| 616 | + cs35l41->fw_request_ongoing = true; | |
| 617 | + schedule_work(&cs35l41->fw_load_work); | |
| 538 | 618 | } |
| 539 | − cs35l41_irq_release(cs35l41); | |
| 540 | − cs35l41->playback_started = false; | |
| 541 | 619 | mutex_unlock(&cs35l41->fw_mutex); |
| 542 | 620 | |
| 621 | + /* | |
| 622 | + * Playback must be finished for all amps before we start runtime suspend. | |
| 623 | + * This ensures no amps are playing back when we start putting them to sleep. | |
| 624 | + */ | |
| 543 | 625 | pm_runtime_mark_last_busy(dev); |
| 544 | 626 | pm_runtime_put_autosuspend(dev); |
| 545 | 627 | break; |
| 546 | 628 | default: |
| 547 | − dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action); | |
| 548 | 629 | break; |
| 549 | 630 | } |
| 631 | +} | |
| 550 | 632 | |
| 551 | − if (ret) | |
| 552 | − dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret); | |
| 633 | +static void cs35l41_hda_post_playback_hook(struct device *dev, int action) | |
| 634 | +{ | |
| 635 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 636 | + | |
| 637 | + switch (action) { | |
| 638 | + case HDA_GEN_PCM_ACT_PREPARE: | |
| 639 | + mutex_lock(&cs35l41->fw_mutex); | |
| 640 | + cs35l41_hda_play_done(dev); | |
| 641 | + mutex_unlock(&cs35l41->fw_mutex); | |
| 642 | + break; | |
| 643 | + default: | |
| 644 | + break; | |
| 645 | + } | |
| 553 | 646 | } |
| 554 | 647 | |
| 555 | 648 | static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot, |
| @@ -572,21 +665,62 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi · 16 unmodified lines | ||
| 572 | 665 | rx_slot); |
| 573 | 666 | } |
| 574 | 667 | |
| 575 | −static void cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41) | |
| 668 | +static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41) | |
| 576 | 669 | { |
| 670 | + int ret = 0; | |
| 671 | + | |
| 577 | 672 | mutex_lock(&cs35l41->fw_mutex); |
| 578 | 673 | if (cs35l41->firmware_running) { |
| 579 | 674 | |
| 580 | 675 | regcache_cache_only(cs35l41->regmap, false); |
| 581 | 676 | |
| 582 | − cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); | |
| 677 | + ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); | |
| 678 | + if (ret) { | |
| 679 | + dev_warn(cs35l41->dev, "Unable to exit Hibernate."); | |
| 680 | + goto err; | |
| 681 | + } | |
| 682 | + | |
| 683 | + /* Test key needs to be unlocked to allow the OTP settings to re-apply */ | |
| 684 | + cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap); | |
| 685 | + ret = regcache_sync(cs35l41->regmap); | |
| 686 | + cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap); | |
| 687 | + if (ret) { | |
| 688 | + dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret); | |
| 689 | + goto err; | |
| 690 | + } | |
| 691 | + | |
| 692 | + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 693 | + cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg); | |
| 694 | + | |
| 583 | 695 | cs35l41_shutdown_dsp(cs35l41); |
| 584 | 696 | cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); |
| 697 | + } | |
| 698 | +err: | |
| 699 | + regcache_cache_only(cs35l41->regmap, true); | |
| 700 | + regcache_mark_dirty(cs35l41->regmap); | |
| 701 | + | |
| 702 | + mutex_unlock(&cs35l41->fw_mutex); | |
| 585 | 703 | |
| 586 | − regcache_cache_only(cs35l41->regmap, true); | |
| 587 | − regcache_mark_dirty(cs35l41->regmap); | |
| 704 | + return ret; | |
| 705 | +} | |
| 706 | + | |
| 707 | +static int cs35l41_system_suspend_prep(struct device *dev) | |
| 708 | +{ | |
| 709 | + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); | |
| 710 | + | |
| 711 | + dev_dbg(cs35l41->dev, "System Suspend Prepare\n"); | |
| 712 | + | |
| 713 | + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { | |
| 714 | + dev_err_once(cs35l41->dev, "System Suspend not supported\n"); | |
| 715 | + return 0; /* don't block the whole system suspend */ | |
| 588 | 716 | } |
| 717 | + | |
| 718 | + mutex_lock(&cs35l41->fw_mutex); | |
| 719 | + if (cs35l41->playback_started) | |
| 720 | + cs35l41_hda_pause_start(dev); | |
| 589 | 721 | mutex_unlock(&cs35l41->fw_mutex); |
| 722 | + | |
| 723 | + return 0; | |
| 590 | 724 | } |
| 591 | 725 | |
| 592 | 726 | static int cs35l41_system_suspend(struct device *dev) |
| @@ -601,18 +735,28 @@ static int cs35l41_system_suspend(struct device *dev) · 8 unmodified lines | ||
| 601 | 735 | return 0; /* don't block the whole system suspend */ |
| 602 | 736 | } |
| 603 | 737 | |
| 738 | + mutex_lock(&cs35l41->fw_mutex); | |
| 739 | + if (cs35l41->playback_started) | |
| 740 | + cs35l41_hda_pause_done(dev); | |
| 741 | + mutex_unlock(&cs35l41->fw_mutex); | |
| 742 | + | |
| 604 | 743 | ret = pm_runtime_force_suspend(dev); |
| 605 | − if (ret) | |
| 744 | + if (ret) { | |
| 745 | + dev_err(dev, "System Suspend Failed, unable to runtime suspend: %d\n", ret); | |
| 606 | 746 | return ret; |
| 747 | + } | |
| 607 | 748 | |
| 608 | 749 | /* Shutdown DSP before system suspend */ |
| 609 | − cs35l41_ready_for_reset(cs35l41); | |
| 750 | + ret = cs35l41_ready_for_reset(cs35l41); | |
| 751 | + | |
| 752 | + if (ret) | |
| 753 | + dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret); | |
| 610 | 754 | |
| 611 | 755 | /* |
| 612 | 756 | * Reset GPIO may be shared, so cannot reset here. |
| 613 | 757 | * However beyond this point, amps may be powered down. |
| 614 | 758 | */ |
| 615 | − return 0; | |
| 759 | + return ret; | |
| 616 | 760 | } |
| 617 | 761 | |
| 618 | 762 | static int cs35l41_system_resume(struct device *dev) |
| @@ -635,9 +779,14 @@ static int cs35l41_system_resume(struct device *dev) · 16 unmodified lines | ||
| 635 | 779 | usleep_range(2000, 2100); |
| 636 | 780 | |
| 637 | 781 | ret = pm_runtime_force_resume(dev); |
| 782 | + if (ret) { | |
| 783 | + dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret); | |
| 784 | + return ret; | |
| 785 | + } | |
| 638 | 786 | |
| 639 | 787 | mutex_lock(&cs35l41->fw_mutex); |
| 640 | − if (!ret && cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { | |
| 788 | + | |
| 789 | + if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { | |
| 641 | 790 | cs35l41->fw_request_ongoing = true; |
| 642 | 791 | schedule_work(&cs35l41->fw_load_work); |
| 643 | 792 | } |
| @@ -669,20 +818,6 @@ static int cs35l41_runtime_suspend(struct device *dev) · 25 unmodified lines | ||
| 669 | 818 | |
| 670 | 819 | mutex_lock(&cs35l41->fw_mutex); |
| 671 | 820 | |
| 672 | − if (cs35l41->playback_started) { | |
| 673 | − regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, | |
| 674 | − ARRAY_SIZE(cs35l41_hda_mute)); | |
| 675 | − cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, NULL); | |
| 676 | − regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | |
| 677 | − CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); | |
| 678 | − if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) | |
| 679 | − regmap_write(cs35l41->regmap, CS35L41_GPIO1_CTRL1, 0x00000001); | |
| 680 | − regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, | |
| 681 | − CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, | |
| 682 | − 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); | |
| 683 | − cs35l41->playback_started = false; | |
| 684 | − } | |
| 685 | − | |
| 686 | 821 | if (cs35l41->firmware_running) { |
| 687 | 822 | ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, |
| 688 | 823 | cs35l41->hw_cfg.bst_type); |
| @@ -778,7 +913,12 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) · 89 unmodified lines | ||
| 778 | 913 | goto clean_dsp; |
| 779 | 914 | } |
| 780 | 915 | |
| 781 | − cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE); | |
| 916 | + ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE); | |
| 917 | + if (ret) { | |
| 918 | + dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret); | |
| 919 | + goto clean_dsp; | |
| 920 | + } | |
| 921 | + | |
| 782 | 922 | cs35l41->firmware_running = true; |
| 783 | 923 | |
| 784 | 924 | return 0; |
| @@ -937,6 +1077,7 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas · 152 unmodified lines | ||
| 937 | 1077 | { |
| 938 | 1078 | struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); |
| 939 | 1079 | struct hda_component *comps = master_data; |
| 1080 | + unsigned int sleep_flags; | |
| 940 | 1081 | int ret = 0; |
| 941 | 1082 | |
| 942 | 1083 | if (!comps || cs35l41->index < 0 || cs35l41->index >= HDA_MAX_COMPONENTS) |
| @@ -971,12 +1112,26 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas · 28 unmodified lines | ||
| 971 | 1112 | ret = cs35l41_create_controls(cs35l41); |
| 972 | 1113 | |
| 973 | 1114 | comps->playback_hook = cs35l41_hda_playback_hook; |
| 1115 | + comps->pre_playback_hook = cs35l41_hda_pre_playback_hook; | |
| 1116 | + comps->post_playback_hook = cs35l41_hda_post_playback_hook; | |
| 974 | 1117 | |
| 975 | 1118 | mutex_unlock(&cs35l41->fw_mutex); |
| 976 | 1119 | |
| 1120 | + sleep_flags = lock_system_sleep(); | |
| 1121 | + if (!device_link_add(&comps->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS)) | |
| 1122 | + dev_warn(dev, "Unable to create device link\n"); | |
| 1123 | + unlock_system_sleep(sleep_flags); | |
| 1124 | + | |
| 977 | 1125 | pm_runtime_mark_last_busy(dev); |
| 978 | 1126 | pm_runtime_put_autosuspend(dev); |
| 979 | 1127 | |
| 1128 | + dev_info(cs35l41->dev, | |
| 1129 | + "CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n", | |
| 1130 | + cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type, | |
| 1131 | + cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH, | |
| 1132 | + cs35l41->hw_cfg.spk_pos ? 'R' : 'L', | |
| 1133 | + cs35l41->firmware_running, cs35l41->speaker_id); | |
| 1134 | + | |
| 980 | 1135 | return ret; |
| 981 | 1136 | } |
| 982 | 1137 | |
| @@ -984,9 +1139,14 @@ static void cs35l41_hda_unbind(struct device *dev, struct device *master, void * · 1 unmodified line | ||
| 984 | 1139 | { |
| 985 | 1140 | struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); |
| 986 | 1141 | struct hda_component *comps = master_data; |
| 1142 | + unsigned int sleep_flags; | |
| 987 | 1143 | |
| 988 | − if (comps[cs35l41->index].dev == dev) | |
| 1144 | + if (comps[cs35l41->index].dev == dev) { | |
| 989 | 1145 | memset(&comps[cs35l41->index], 0, sizeof(*comps)); |
| 1146 | + sleep_flags = lock_system_sleep(); | |
| 1147 | + device_link_remove(&comps->codec->core.dev, cs35l41->dev); | |
| 1148 | + unlock_system_sleep(sleep_flags); | |
| 1149 | + } | |
| 990 | 1150 | } |
| 991 | 1151 | |
| 992 | 1152 | static const struct component_ops cs35l41_hda_comp_ops = { |
| @@ -1156,8 +1316,7 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) · 163 unmodified lines | ||
| 1156 | 1316 | return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); |
| 1157 | 1317 | } |
| 1158 | 1318 | |
| 1159 | −static int cs35l41_get_speaker_id(struct device *dev, int amp_index, | |
| 1160 | − int num_amps, int fixed_gpio_id) | |
| 1319 | +int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id) | |
| 1161 | 1320 | { |
| 1162 | 1321 | struct gpio_desc *speaker_id_desc; |
| 1163 | 1322 | int speaker_id = -ENODEV; |
| @@ -1211,49 +1370,6 @@ static int cs35l41_get_speaker_id(struct device *dev, int amp_index, · 47 unmodified lines | ||
| 1211 | 1370 | return speaker_id; |
| 1212 | 1371 | } |
| 1213 | 1372 | |
| 1214 | −/* | |
| 1215 | − * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. | |
| 1216 | − * And devices created by serial-multi-instantiate don't have their device struct | |
| 1217 | − * pointing to the correct fwnode, so acpi_dev must be used here. | |
| 1218 | − * And devm functions expect that the device requesting the resource has the correct | |
| 1219 | − * fwnode. | |
| 1220 | − */ | |
| 1221 | −static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 1222 | − const char *hid) | |
| 1223 | −{ | |
| 1224 | − struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; | |
| 1225 | − | |
| 1226 | − /* check I2C address to assign the index */ | |
| 1227 | − cs35l41->index = id == 0x40 ? 0 : 1; | |
| 1228 | − cs35l41->channel_index = 0; | |
| 1229 | − cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); | |
| 1230 | − cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); | |
| 1231 | − hw_cfg->spk_pos = cs35l41->index; | |
| 1232 | − hw_cfg->gpio2.func = CS35L41_INTERRUPT; | |
| 1233 | − hw_cfg->gpio2.valid = true; | |
| 1234 | − hw_cfg->valid = true; | |
| 1235 | − | |
| 1236 | − if (strncmp(hid, "CLSA0100", 8) == 0) { | |
| 1237 | − hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; | |
| 1238 | − } else if (strncmp(hid, "CLSA0101", 8) == 0) { | |
| 1239 | − hw_cfg->bst_type = CS35L41_EXT_BOOST; | |
| 1240 | − hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; | |
| 1241 | − hw_cfg->gpio1.valid = true; | |
| 1242 | − } else { | |
| 1243 | − /* | |
| 1244 | − * Note: CLSA010(0/1) are special cases which use a slightly different design. | |
| 1245 | − * All other HIDs e.g. CSC3551 require valid ACPI _DSD properties to be supported. | |
| 1246 | − */ | |
| 1247 | − dev_err(cs35l41->dev, "Error: ACPI _DSD Properties are missing for HID %s.\n", hid); | |
| 1248 | − hw_cfg->valid = false; | |
| 1249 | − hw_cfg->gpio1.valid = false; | |
| 1250 | − hw_cfg->gpio2.valid = false; | |
| 1251 | − return -EINVAL; | |
| 1252 | − } | |
| 1253 | − | |
| 1254 | − return 0; | |
| 1255 | −} | |
| 1256 | − | |
| 1257 | 1373 | static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) |
| 1258 | 1374 | { |
| 1259 | 1375 | struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; |
| @@ -1279,12 +1395,17 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i · 19 unmodified lines | ||
| 1279 | 1395 | sub = NULL; |
| 1280 | 1396 | cs35l41->acpi_subsystem_id = sub; |
| 1281 | 1397 | |
| 1398 | + ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid); | |
| 1399 | + if (!ret) { | |
| 1400 | + dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n"); | |
| 1401 | + goto put_physdev; | |
| 1402 | + } | |
| 1403 | + | |
| 1282 | 1404 | property = "cirrus,dev-index"; |
| 1283 | 1405 | ret = device_property_count_u32(physdev, property); |
| 1284 | − if (ret <= 0) { | |
| 1285 | − ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); | |
| 1286 | − goto err_put_physdev; | |
| 1287 | − } | |
| 1406 | + if (ret <= 0) | |
| 1407 | + goto err; | |
| 1408 | + | |
| 1288 | 1409 | if (ret > ARRAY_SIZE(values)) { |
| 1289 | 1410 | ret = -EINVAL; |
| 1290 | 1411 | goto err; |
| @@ -1374,7 +1495,10 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i · 83 unmodified lines | ||
| 1374 | 1495 | |
| 1375 | 1496 | err: |
| 1376 | 1497 | dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); |
| 1377 | −err_put_physdev: | |
| 1498 | + hw_cfg->valid = false; | |
| 1499 | + hw_cfg->gpio1.valid = false; | |
| 1500 | + hw_cfg->gpio2.valid = false; | |
| 1501 | +put_physdev: | |
| 1378 | 1502 | put_device(physdev); |
| 1379 | 1503 | |
| 1380 | 1504 | return ret; |
| @@ -1477,6 +1601,11 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i · 96 unmodified lines | ||
| 1477 | 1601 | if (ret) |
| 1478 | 1602 | goto err; |
| 1479 | 1603 | |
| 1604 | + ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, | |
| 1605 | + ARRAY_SIZE(cs35l41_hda_mute)); | |
| 1606 | + if (ret) | |
| 1607 | + goto err; | |
| 1608 | + | |
| 1480 | 1609 | INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work); |
| 1481 | 1610 | mutex_init(&cs35l41->fw_mutex); |
| 1482 | 1611 | |
| @@ -1542,6 +1671,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); · 59 unmodified lines | ||
| 1542 | 1671 | const struct dev_pm_ops cs35l41_hda_pm_ops = { |
| 1543 | 1672 | RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, |
| 1544 | 1673 | cs35l41_runtime_idle) |
| 1674 | + .prepare = cs35l41_system_suspend_prep, | |
| 1545 | 1675 | SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume) |
| 1546 | 1676 | }; |
| 1547 | 1677 | EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41); |
| @@ -83,5 +83,6 @@ extern const struct dev_pm_ops cs35l41_hda_pm_ops; · 82 unmodified lines | ||
| 83 | 83 | int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, |
| 84 | 84 | struct regmap *regmap); |
| 85 | 85 | void cs35l41_hda_remove(struct device *dev); |
| 86 | +int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id); | |
| 86 | 87 | |
| 87 | 88 | #endif /*__CS35L41_HDA_H__*/ |
| @@ -0,0 +1,105 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +// | |
| 3 | +// CS35L41 ALSA HDA Property driver | |
| 4 | +// | |
| 5 | +// Copyright 2023 Cirrus Logic, Inc. | |
| 6 | +// | |
| 7 | +// Author: Stefan Binding <sbinding@opensource.cirrus.com> | |
| 8 | + | |
| 9 | +#include <linux/gpio/consumer.h> | |
| 10 | +#include <linux/string.h> | |
| 11 | +#include "cs35l41_hda_property.h" | |
| 12 | + | |
| 13 | +/* | |
| 14 | + * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. | |
| 15 | + * And devices created by serial-multi-instantiate don't have their device struct | |
| 16 | + * pointing to the correct fwnode, so acpi_dev must be used here. | |
| 17 | + * And devm functions expect that the device requesting the resource has the correct | |
| 18 | + * fwnode. | |
| 19 | + */ | |
| 20 | +static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 21 | + const char *hid) | |
| 22 | +{ | |
| 23 | + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; | |
| 24 | + | |
| 25 | + /* check I2C address to assign the index */ | |
| 26 | + cs35l41->index = id == 0x40 ? 0 : 1; | |
| 27 | + cs35l41->channel_index = 0; | |
| 28 | + cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); | |
| 29 | + cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); | |
| 30 | + hw_cfg->spk_pos = cs35l41->index; | |
| 31 | + hw_cfg->gpio2.func = CS35L41_INTERRUPT; | |
| 32 | + hw_cfg->gpio2.valid = true; | |
| 33 | + hw_cfg->valid = true; | |
| 34 | + | |
| 35 | + if (strcmp(hid, "CLSA0100") == 0) { | |
| 36 | + hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; | |
| 37 | + } else if (strcmp(hid, "CLSA0101") == 0) { | |
| 38 | + hw_cfg->bst_type = CS35L41_EXT_BOOST; | |
| 39 | + hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; | |
| 40 | + hw_cfg->gpio1.valid = true; | |
| 41 | + } | |
| 42 | + | |
| 43 | + return 0; | |
| 44 | +} | |
| 45 | + | |
| 46 | +/* | |
| 47 | + * Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type. | |
| 48 | + * We can override the _DSD to correct the boost type here. | |
| 49 | + * Since this laptop has valid ACPI, we do not need to handle cs-gpios, since that already exists | |
| 50 | + * in the ACPI. | |
| 51 | + */ | |
| 52 | +static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 53 | + const char *hid) | |
| 54 | +{ | |
| 55 | + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; | |
| 56 | + | |
| 57 | + dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id); | |
| 58 | + | |
| 59 | + cs35l41->index = id; | |
| 60 | + cs35l41->channel_index = 0; | |
| 61 | + cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_HIGH); | |
| 62 | + cs35l41->speaker_id = -ENOENT; | |
| 63 | + hw_cfg->spk_pos = cs35l41->index ? 1 : 0; // right:left | |
| 64 | + hw_cfg->gpio1.func = CS35L41_NOT_USED; | |
| 65 | + hw_cfg->gpio1.valid = true; | |
| 66 | + hw_cfg->gpio2.func = CS35L41_INTERRUPT; | |
| 67 | + hw_cfg->gpio2.valid = true; | |
| 68 | + hw_cfg->bst_type = CS35L41_INT_BOOST; | |
| 69 | + hw_cfg->bst_ind = 1000; | |
| 70 | + hw_cfg->bst_ipk = 4500; | |
| 71 | + hw_cfg->bst_cap = 24; | |
| 72 | + hw_cfg->valid = true; | |
| 73 | + | |
| 74 | + return 0; | |
| 75 | +} | |
| 76 | + | |
| 77 | +struct cs35l41_prop_model { | |
| 78 | + const char *hid; | |
| 79 | + const char *ssid; | |
| 80 | + int (*add_prop)(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 81 | + const char *hid); | |
| 82 | +}; | |
| 83 | + | |
| 84 | +static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { | |
| 85 | + { "CLSA0100", NULL, lenovo_legion_no_acpi }, | |
| 86 | + { "CLSA0101", NULL, lenovo_legion_no_acpi }, | |
| 87 | + { "CSC3551", "103C89C6", hp_vision_acpi_fix }, | |
| 88 | + {} | |
| 89 | +}; | |
| 90 | + | |
| 91 | +int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 92 | + const char *hid) | |
| 93 | +{ | |
| 94 | + const struct cs35l41_prop_model *model; | |
| 95 | + | |
| 96 | + for (model = cs35l41_prop_model_table; model->hid; model++) { | |
| 97 | + if (!strcmp(model->hid, hid) && | |
| 98 | + (!model->ssid || | |
| 99 | + (cs35l41->acpi_subsystem_id && | |
| 100 | + !strcmp(model->ssid, cs35l41->acpi_subsystem_id)))) | |
| 101 | + return model->add_prop(cs35l41, physdev, id, hid); | |
| 102 | + } | |
| 103 | + | |
| 104 | + return -ENOENT; | |
| 105 | +} | |
| @@ -0,0 +1,18 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 | |
| 2 | + * | |
| 3 | + * CS35L41 ALSA HDA Property driver | |
| 4 | + * | |
| 5 | + * Copyright 2023 Cirrus Logic, Inc. | |
| 6 | + * | |
| 7 | + * Author: Stefan Binding <sbinding@opensource.cirrus.com> | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#ifndef CS35L41_HDA_PROP_H | |
| 11 | +#define CS35L41_HDA_PROP_H | |
| 12 | + | |
| 13 | +#include <linux/device.h> | |
| 14 | +#include "cs35l41_hda.h" | |
| 15 | + | |
| 16 | +int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id, | |
| 17 | + const char *hid); | |
| 18 | +#endif /* CS35L41_HDA_PROP_H */ | |
| @@ -0,0 +1,1034 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// HDA audio driver for Cirrus Logic CS35L56 smart amp | |
| 4 | +// | |
| 5 | +// Copyright (C) 2023 Cirrus Logic, Inc. and | |
| 6 | +// Cirrus Logic International Semiconductor Ltd. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#include <linux/acpi.h> | |
| 10 | +#include <linux/debugfs.h> | |
| 11 | +#include <linux/gpio/consumer.h> | |
| 12 | +#include <linux/module.h> | |
| 13 | +#include <linux/pm_runtime.h> | |
| 14 | +#include <linux/regmap.h> | |
| 15 | +#include <linux/slab.h> | |
| 16 | +#include <sound/core.h> | |
| 17 | +#include <sound/hda_codec.h> | |
| 18 | +#include <sound/tlv.h> | |
| 19 | +#include "cs35l56_hda.h" | |
| 20 | +#include "hda_component.h" | |
| 21 | +#include "hda_cs_dsp_ctl.h" | |
| 22 | +#include "hda_generic.h" | |
| 23 | + | |
| 24 | + /* | |
| 25 | + * The cs35l56_hda_dai_config[] reg sequence configures the device as | |
| 26 | + * ASP1_BCLK_FREQ = 3.072 MHz | |
| 27 | + * ASP1_RX_WIDTH = 32 cycles per slot, ASP1_TX_WIDTH = 32 cycles per slot, ASP1_FMT = I2S | |
| 28 | + * ASP1_DOUT_HIZ_CONTROL = Hi-Z during unused timeslots | |
| 29 | + * ASP1_RX_WL = 24 bits per sample | |
| 30 | + * ASP1_TX_WL = 24 bits per sample | |
| 31 | + * ASP1_RXn_EN 1..3 and ASP1_TXn_EN 1..4 disabled | |
| 32 | + */ | |
| 33 | +static const struct reg_sequence cs35l56_hda_dai_config[] = { | |
| 34 | + { CS35L56_ASP1_CONTROL1, 0x00000021 }, | |
| 35 | + { CS35L56_ASP1_CONTROL2, 0x20200200 }, | |
| 36 | + { CS35L56_ASP1_CONTROL3, 0x00000003 }, | |
| 37 | + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, | |
| 38 | + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, | |
| 39 | + { CS35L56_ASP1_ENABLES1, 0x00000000 }, | |
| 40 | +}; | |
| 41 | + | |
| 42 | +static void cs35l56_hda_play(struct cs35l56_hda *cs35l56) | |
| 43 | +{ | |
| 44 | + unsigned int val; | |
| 45 | + int ret; | |
| 46 | + | |
| 47 | + pm_runtime_get_sync(cs35l56->base.dev); | |
| 48 | + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PLAY); | |
| 49 | + if (ret == 0) { | |
| 50 | + /* Wait for firmware to enter PS0 power state */ | |
| 51 | + ret = regmap_read_poll_timeout(cs35l56->base.regmap, | |
| 52 | + CS35L56_TRANSDUCER_ACTUAL_PS, | |
| 53 | + val, (val == CS35L56_PS0), | |
| 54 | + CS35L56_PS0_POLL_US, | |
| 55 | + CS35L56_PS0_TIMEOUT_US); | |
| 56 | + if (ret) | |
| 57 | + dev_warn(cs35l56->base.dev, "PS0 wait failed: %d\n", ret); | |
| 58 | + } | |
| 59 | + regmap_set_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1, | |
| 60 | + BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) | | |
| 61 | + cs35l56->asp_tx_mask); | |
| 62 | + cs35l56->playing = true; | |
| 63 | +} | |
| 64 | + | |
| 65 | +static void cs35l56_hda_pause(struct cs35l56_hda *cs35l56) | |
| 66 | +{ | |
| 67 | + cs35l56->playing = false; | |
| 68 | + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE); | |
| 69 | + regmap_clear_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1, | |
| 70 | + BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) | | |
| 71 | + BIT(CS35L56_ASP_TX1_EN_SHIFT) | BIT(CS35L56_ASP_TX2_EN_SHIFT) | | |
| 72 | + BIT(CS35L56_ASP_TX3_EN_SHIFT) | BIT(CS35L56_ASP_TX4_EN_SHIFT)); | |
| 73 | + | |
| 74 | + pm_runtime_mark_last_busy(cs35l56->base.dev); | |
| 75 | + pm_runtime_put_autosuspend(cs35l56->base.dev); | |
| 76 | +} | |
| 77 | + | |
| 78 | +static void cs35l56_hda_playback_hook(struct device *dev, int action) | |
| 79 | +{ | |
| 80 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 81 | + | |
| 82 | + dev_dbg(cs35l56->base.dev, "%s()%d: action: %d\n", __func__, __LINE__, action); | |
| 83 | + | |
| 84 | + switch (action) { | |
| 85 | + case HDA_GEN_PCM_ACT_PREPARE: | |
| 86 | + if (cs35l56->playing) | |
| 87 | + break; | |
| 88 | + | |
| 89 | + /* If we're suspended: flag that resume should start playback */ | |
| 90 | + if (cs35l56->suspended) { | |
| 91 | + cs35l56->playing = true; | |
| 92 | + break; | |
| 93 | + } | |
| 94 | + | |
| 95 | + cs35l56_hda_play(cs35l56); | |
| 96 | + break; | |
| 97 | + case HDA_GEN_PCM_ACT_CLEANUP: | |
| 98 | + if (!cs35l56->playing) | |
| 99 | + break; | |
| 100 | + | |
| 101 | + cs35l56_hda_pause(cs35l56); | |
| 102 | + break; | |
| 103 | + default: | |
| 104 | + break; | |
| 105 | + } | |
| 106 | +} | |
| 107 | + | |
| 108 | +static int __maybe_unused cs35l56_hda_runtime_suspend(struct device *dev) | |
| 109 | +{ | |
| 110 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 111 | + | |
| 112 | + if (cs35l56->cs_dsp.booted) | |
| 113 | + cs_dsp_stop(&cs35l56->cs_dsp); | |
| 114 | + | |
| 115 | + return cs35l56_runtime_suspend_common(&cs35l56->base); | |
| 116 | +} | |
| 117 | + | |
| 118 | +static int __maybe_unused cs35l56_hda_runtime_resume(struct device *dev) | |
| 119 | +{ | |
| 120 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 121 | + int ret; | |
| 122 | + | |
| 123 | + ret = cs35l56_runtime_resume_common(&cs35l56->base, false); | |
| 124 | + if (ret < 0) | |
| 125 | + return ret; | |
| 126 | + | |
| 127 | + if (cs35l56->cs_dsp.booted) { | |
| 128 | + ret = cs_dsp_run(&cs35l56->cs_dsp); | |
| 129 | + if (ret) { | |
| 130 | + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); | |
| 131 | + goto err; | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 135 | + return 0; | |
| 136 | + | |
| 137 | +err: | |
| 138 | + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); | |
| 139 | + regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, | |
| 140 | + CS35L56_MBOX_CMD_HIBERNATE_NOW); | |
| 141 | + | |
| 142 | + regcache_cache_only(cs35l56->base.regmap, true); | |
| 143 | + | |
| 144 | + return ret; | |
| 145 | +} | |
| 146 | + | |
| 147 | +static int cs35l56_hda_mixer_info(struct snd_kcontrol *kcontrol, | |
| 148 | + struct snd_ctl_elem_info *uinfo) | |
| 149 | +{ | |
| 150 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | |
| 151 | + uinfo->count = 1; | |
| 152 | + uinfo->value.enumerated.items = CS35L56_NUM_INPUT_SRC; | |
| 153 | + if (uinfo->value.enumerated.item >= CS35L56_NUM_INPUT_SRC) | |
| 154 | + uinfo->value.enumerated.item = CS35L56_NUM_INPUT_SRC - 1; | |
| 155 | + strscpy(uinfo->value.enumerated.name, cs35l56_tx_input_texts[uinfo->value.enumerated.item], | |
| 156 | + sizeof(uinfo->value.enumerated.name)); | |
| 157 | + | |
| 158 | + return 0; | |
| 159 | +} | |
| 160 | + | |
| 161 | +static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol, | |
| 162 | + struct snd_ctl_elem_value *ucontrol) | |
| 163 | +{ | |
| 164 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 165 | + unsigned int reg_val; | |
| 166 | + int i; | |
| 167 | + | |
| 168 | + regmap_read(cs35l56->base.regmap, kcontrol->private_value, ®_val); | |
| 169 | + reg_val &= CS35L56_ASP_TXn_SRC_MASK; | |
| 170 | + | |
| 171 | + for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) { | |
| 172 | + if (cs35l56_tx_input_values[i] == reg_val) { | |
| 173 | + ucontrol->value.enumerated.item[0] = i; | |
| 174 | + break; | |
| 175 | + } | |
| 176 | + } | |
| 177 | + | |
| 178 | + return 0; | |
| 179 | +} | |
| 180 | + | |
| 181 | +static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol, | |
| 182 | + struct snd_ctl_elem_value *ucontrol) | |
| 183 | +{ | |
| 184 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 185 | + unsigned int item = ucontrol->value.enumerated.item[0]; | |
| 186 | + bool changed; | |
| 187 | + | |
| 188 | + if (item >= CS35L56_NUM_INPUT_SRC) | |
| 189 | + return -EINVAL; | |
| 190 | + | |
| 191 | + regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value, | |
| 192 | + CS35L56_INPUT_MASK, cs35l56_tx_input_values[item], | |
| 193 | + &changed); | |
| 194 | + | |
| 195 | + return changed; | |
| 196 | +} | |
| 197 | + | |
| 198 | +static int cs35l56_hda_posture_info(struct snd_kcontrol *kcontrol, | |
| 199 | + struct snd_ctl_elem_info *uinfo) | |
| 200 | +{ | |
| 201 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 202 | + uinfo->count = 1; | |
| 203 | + uinfo->value.integer.min = CS35L56_MAIN_POSTURE_MIN; | |
| 204 | + uinfo->value.integer.max = CS35L56_MAIN_POSTURE_MAX; | |
| 205 | + return 0; | |
| 206 | +} | |
| 207 | + | |
| 208 | +static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol, | |
| 209 | + struct snd_ctl_elem_value *ucontrol) | |
| 210 | +{ | |
| 211 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 212 | + unsigned int pos; | |
| 213 | + int ret; | |
| 214 | + | |
| 215 | + ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_POSTURE_NUMBER, &pos); | |
| 216 | + if (ret) | |
| 217 | + return ret; | |
| 218 | + | |
| 219 | + ucontrol->value.integer.value[0] = pos; | |
| 220 | + | |
| 221 | + return ret; | |
| 222 | +} | |
| 223 | + | |
| 224 | +static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol, | |
| 225 | + struct snd_ctl_elem_value *ucontrol) | |
| 226 | +{ | |
| 227 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 228 | + unsigned long pos = ucontrol->value.integer.value[0]; | |
| 229 | + bool changed; | |
| 230 | + int ret; | |
| 231 | + | |
| 232 | + if ((pos < CS35L56_MAIN_POSTURE_MIN) || | |
| 233 | + (pos > CS35L56_MAIN_POSTURE_MAX)) | |
| 234 | + return -EINVAL; | |
| 235 | + | |
| 236 | + ret = regmap_update_bits_check(cs35l56->base.regmap, | |
| 237 | + CS35L56_MAIN_POSTURE_NUMBER, | |
| 238 | + CS35L56_MAIN_POSTURE_MASK, | |
| 239 | + pos, &changed); | |
| 240 | + if (ret) | |
| 241 | + return ret; | |
| 242 | + | |
| 243 | + return changed; | |
| 244 | +} | |
| 245 | + | |
| 246 | +static const struct { | |
| 247 | + const char *name; | |
| 248 | + unsigned int reg; | |
| 249 | +} cs35l56_hda_mixer_controls[] = { | |
| 250 | + { "ASP1 TX1 Source", CS35L56_ASP1TX1_INPUT }, | |
| 251 | + { "ASP1 TX2 Source", CS35L56_ASP1TX2_INPUT }, | |
| 252 | + { "ASP1 TX3 Source", CS35L56_ASP1TX3_INPUT }, | |
| 253 | + { "ASP1 TX4 Source", CS35L56_ASP1TX4_INPUT }, | |
| 254 | +}; | |
| 255 | + | |
| 256 | +static const DECLARE_TLV_DB_SCALE(cs35l56_hda_vol_tlv, -10000, 25, 0); | |
| 257 | + | |
| 258 | +static int cs35l56_hda_vol_info(struct snd_kcontrol *kcontrol, | |
| 259 | + struct snd_ctl_elem_info *uinfo) | |
| 260 | +{ | |
| 261 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 262 | + uinfo->count = 1; | |
| 263 | + uinfo->value.integer.step = 1; | |
| 264 | + uinfo->value.integer.min = 0; | |
| 265 | + uinfo->value.integer.max = CS35L56_MAIN_RENDER_USER_VOLUME_MAX - | |
| 266 | + CS35L56_MAIN_RENDER_USER_VOLUME_MIN; | |
| 267 | + | |
| 268 | + return 0; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol, | |
| 272 | + struct snd_ctl_elem_value *ucontrol) | |
| 273 | +{ | |
| 274 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 275 | + unsigned int raw_vol; | |
| 276 | + int vol; | |
| 277 | + int ret; | |
| 278 | + | |
| 279 | + ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_RENDER_USER_VOLUME, &raw_vol); | |
| 280 | + | |
| 281 | + if (ret) | |
| 282 | + return ret; | |
| 283 | + | |
| 284 | + vol = (s16)(raw_vol & 0xFFFF); | |
| 285 | + vol >>= CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT; | |
| 286 | + | |
| 287 | + if (vol & BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT)) | |
| 288 | + vol |= ~((int)(BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT) - 1)); | |
| 289 | + | |
| 290 | + ucontrol->value.integer.value[0] = vol - CS35L56_MAIN_RENDER_USER_VOLUME_MIN; | |
| 291 | + | |
| 292 | + return 0; | |
| 293 | +} | |
| 294 | + | |
| 295 | +static int cs35l56_hda_vol_put(struct snd_kcontrol *kcontrol, | |
| 296 | + struct snd_ctl_elem_value *ucontrol) | |
| 297 | +{ | |
| 298 | + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; | |
| 299 | + long vol = ucontrol->value.integer.value[0]; | |
| 300 | + unsigned int raw_vol; | |
| 301 | + bool changed; | |
| 302 | + int ret; | |
| 303 | + | |
| 304 | + if ((vol < 0) || (vol > (CS35L56_MAIN_RENDER_USER_VOLUME_MAX - | |
| 305 | + CS35L56_MAIN_RENDER_USER_VOLUME_MIN))) | |
| 306 | + return -EINVAL; | |
| 307 | + | |
| 308 | + raw_vol = (vol + CS35L56_MAIN_RENDER_USER_VOLUME_MIN) << | |
| 309 | + CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT; | |
| 310 | + | |
| 311 | + ret = regmap_update_bits_check(cs35l56->base.regmap, | |
| 312 | + CS35L56_MAIN_RENDER_USER_VOLUME, | |
| 313 | + CS35L56_MAIN_RENDER_USER_VOLUME_MASK, | |
| 314 | + raw_vol, &changed); | |
| 315 | + if (ret) | |
| 316 | + return ret; | |
| 317 | + | |
| 318 | + return changed; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static void cs35l56_hda_create_controls(struct cs35l56_hda *cs35l56) | |
| 322 | +{ | |
| 323 | + struct snd_kcontrol_new ctl_template = { | |
| 324 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
| 325 | + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | |
| 326 | + .info = cs35l56_hda_posture_info, | |
| 327 | + .get = cs35l56_hda_posture_get, | |
| 328 | + .put = cs35l56_hda_posture_put, | |
| 329 | + }; | |
| 330 | + char name[64]; | |
| 331 | + int i; | |
| 332 | + | |
| 333 | + snprintf(name, sizeof(name), "%s Posture Number", cs35l56->amp_name); | |
| 334 | + ctl_template.name = name; | |
| 335 | + cs35l56->posture_ctl = snd_ctl_new1(&ctl_template, cs35l56); | |
| 336 | + if (snd_ctl_add(cs35l56->codec->card, cs35l56->posture_ctl)) | |
| 337 | + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name); | |
| 338 | + | |
| 339 | + /* Mixer controls */ | |
| 340 | + ctl_template.info = cs35l56_hda_mixer_info; | |
| 341 | + ctl_template.get = cs35l56_hda_mixer_get; | |
| 342 | + ctl_template.put = cs35l56_hda_mixer_put; | |
| 343 | + | |
| 344 | + BUILD_BUG_ON(ARRAY_SIZE(cs35l56->mixer_ctl) != ARRAY_SIZE(cs35l56_hda_mixer_controls)); | |
| 345 | + | |
| 346 | + for (i = 0; i < ARRAY_SIZE(cs35l56_hda_mixer_controls); ++i) { | |
| 347 | + snprintf(name, sizeof(name), "%s %s", cs35l56->amp_name, | |
| 348 | + cs35l56_hda_mixer_controls[i].name); | |
| 349 | + ctl_template.private_value = cs35l56_hda_mixer_controls[i].reg; | |
| 350 | + cs35l56->mixer_ctl[i] = snd_ctl_new1(&ctl_template, cs35l56); | |
| 351 | + if (snd_ctl_add(cs35l56->codec->card, cs35l56->mixer_ctl[i])) { | |
| 352 | + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", | |
| 353 | + ctl_template.name); | |
| 354 | + } | |
| 355 | + } | |
| 356 | + | |
| 357 | + ctl_template.info = cs35l56_hda_vol_info; | |
| 358 | + ctl_template.get = cs35l56_hda_vol_get; | |
| 359 | + ctl_template.put = cs35l56_hda_vol_put; | |
| 360 | + ctl_template.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ); | |
| 361 | + ctl_template.tlv.p = cs35l56_hda_vol_tlv; | |
| 362 | + snprintf(name, sizeof(name), "%s Speaker Playback Volume", cs35l56->amp_name); | |
| 363 | + ctl_template.name = name; | |
| 364 | + cs35l56->volume_ctl = snd_ctl_new1(&ctl_template, cs35l56); | |
| 365 | + if (snd_ctl_add(cs35l56->codec->card, cs35l56->volume_ctl)) | |
| 366 | + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name); | |
| 367 | +} | |
| 368 | + | |
| 369 | +static void cs35l56_hda_remove_controls(struct cs35l56_hda *cs35l56) | |
| 370 | +{ | |
| 371 | + int i; | |
| 372 | + | |
| 373 | + for (i = ARRAY_SIZE(cs35l56->mixer_ctl) - 1; i >= 0; i--) | |
| 374 | + snd_ctl_remove(cs35l56->codec->card, cs35l56->mixer_ctl[i]); | |
| 375 | + | |
| 376 | + snd_ctl_remove(cs35l56->codec->card, cs35l56->posture_ctl); | |
| 377 | + snd_ctl_remove(cs35l56->codec->card, cs35l56->volume_ctl); | |
| 378 | +} | |
| 379 | + | |
| 380 | +static const struct cs_dsp_client_ops cs35l56_hda_client_ops = { | |
| 381 | + .control_remove = hda_cs_dsp_control_remove, | |
| 382 | +}; | |
| 383 | + | |
| 384 | +static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, | |
| 385 | + const struct firmware **firmware, char **filename, | |
| 386 | + const char *dir, const char *system_name, | |
| 387 | + const char *amp_name, | |
| 388 | + const char *filetype) | |
| 389 | +{ | |
| 390 | + char *s, c; | |
| 391 | + int ret = 0; | |
| 392 | + | |
| 393 | + if (system_name && amp_name) | |
| 394 | + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s-%s.%s", dir, | |
| 395 | + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 396 | + system_name, amp_name, filetype); | |
| 397 | + else if (system_name) | |
| 398 | + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s.%s", dir, | |
| 399 | + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 400 | + system_name, filetype); | |
| 401 | + else | |
| 402 | + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc.%s", dir, | |
| 403 | + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 404 | + filetype); | |
| 405 | + | |
| 406 | + if (!*filename) | |
| 407 | + return -ENOMEM; | |
| 408 | + | |
| 409 | + /* | |
| 410 | + * Make sure that filename is lower-case and any non alpha-numeric | |
| 411 | + * characters except full stop and forward slash are replaced with | |
| 412 | + * hyphens. | |
| 413 | + */ | |
| 414 | + s = *filename; | |
| 415 | + while (*s) { | |
| 416 | + c = *s; | |
| 417 | + if (isalnum(c)) | |
| 418 | + *s = tolower(c); | |
| 419 | + else if (c != '.' && c != '/') | |
| 420 | + *s = '-'; | |
| 421 | + s++; | |
| 422 | + } | |
| 423 | + | |
| 424 | + ret = firmware_request_nowarn(firmware, *filename, cs35l56->base.dev); | |
| 425 | + if (ret) { | |
| 426 | + dev_dbg(cs35l56->base.dev, "Failed to request '%s'\n", *filename); | |
| 427 | + kfree(*filename); | |
| 428 | + *filename = NULL; | |
| 429 | + return ret; | |
| 430 | + } | |
| 431 | + | |
| 432 | + dev_dbg(cs35l56->base.dev, "Found '%s'\n", *filename); | |
| 433 | + | |
| 434 | + return 0; | |
| 435 | +} | |
| 436 | + | |
| 437 | +static const char cirrus_dir[] = "cirrus/"; | |
| 438 | +static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56, | |
| 439 | + const struct firmware **wmfw_firmware, | |
| 440 | + char **wmfw_filename, | |
| 441 | + const struct firmware **coeff_firmware, | |
| 442 | + char **coeff_filename) | |
| 443 | +{ | |
| 444 | + const char *system_name = cs35l56->system_name; | |
| 445 | + const char *amp_name = cs35l56->amp_name; | |
| 446 | + int ret; | |
| 447 | + | |
| 448 | + if (system_name && amp_name) { | |
| 449 | + if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, | |
| 450 | + cirrus_dir, system_name, amp_name, "wmfw")) { | |
| 451 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 452 | + cirrus_dir, system_name, amp_name, "bin"); | |
| 453 | + return; | |
| 454 | + } | |
| 455 | + } | |
| 456 | + | |
| 457 | + if (system_name) { | |
| 458 | + if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, | |
| 459 | + cirrus_dir, system_name, NULL, "wmfw")) { | |
| 460 | + if (amp_name) | |
| 461 | + cs35l56_hda_request_firmware_file(cs35l56, | |
| 462 | + coeff_firmware, coeff_filename, | |
| 463 | + cirrus_dir, system_name, | |
| 464 | + amp_name, "bin"); | |
| 465 | + if (!*coeff_firmware) | |
| 466 | + cs35l56_hda_request_firmware_file(cs35l56, | |
| 467 | + coeff_firmware, coeff_filename, | |
| 468 | + cirrus_dir, system_name, | |
| 469 | + NULL, "bin"); | |
| 470 | + return; | |
| 471 | + } | |
| 472 | + } | |
| 473 | + | |
| 474 | + ret = cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, | |
| 475 | + cirrus_dir, NULL, NULL, "wmfw"); | |
| 476 | + if (!ret) { | |
| 477 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 478 | + cirrus_dir, NULL, NULL, "bin"); | |
| 479 | + return; | |
| 480 | + } | |
| 481 | + | |
| 482 | + /* When a firmware file is not found must still search for the coeff files */ | |
| 483 | + if (system_name) { | |
| 484 | + if (amp_name) | |
| 485 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 486 | + cirrus_dir, system_name, amp_name, "bin"); | |
| 487 | + if (!*coeff_firmware) | |
| 488 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 489 | + cirrus_dir, system_name, NULL, "bin"); | |
| 490 | + } | |
| 491 | + | |
| 492 | + if (!*coeff_firmware) | |
| 493 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 494 | + cirrus_dir, NULL, NULL, "bin"); | |
| 495 | +} | |
| 496 | + | |
| 497 | +static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmware, | |
| 498 | + char *wmfw_filename, | |
| 499 | + const struct firmware *coeff_firmware, | |
| 500 | + char *coeff_filename) | |
| 501 | +{ | |
| 502 | + if (wmfw_firmware) | |
| 503 | + release_firmware(wmfw_firmware); | |
| 504 | + kfree(wmfw_filename); | |
| 505 | + | |
| 506 | + if (coeff_firmware) | |
| 507 | + release_firmware(coeff_firmware); | |
| 508 | + kfree(coeff_filename); | |
| 509 | +} | |
| 510 | + | |
| 511 | +static void cs35l56_hda_add_dsp_controls(struct cs35l56_hda *cs35l56) | |
| 512 | +{ | |
| 513 | + struct hda_cs_dsp_ctl_info info; | |
| 514 | + | |
| 515 | + info.device_name = cs35l56->amp_name; | |
| 516 | + info.fw_type = HDA_CS_DSP_FW_MISC; | |
| 517 | + info.card = cs35l56->codec->card; | |
| 518 | + | |
| 519 | + hda_cs_dsp_add_controls(&cs35l56->cs_dsp, &info); | |
| 520 | +} | |
| 521 | + | |
| 522 | +static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) | |
| 523 | +{ | |
| 524 | + const struct firmware *coeff_firmware = NULL; | |
| 525 | + const struct firmware *wmfw_firmware = NULL; | |
| 526 | + char *coeff_filename = NULL; | |
| 527 | + char *wmfw_filename = NULL; | |
| 528 | + unsigned int firmware_missing; | |
| 529 | + int ret = 0; | |
| 530 | + | |
| 531 | + /* Prepare for a new DSP power-up */ | |
| 532 | + if (cs35l56->base.fw_patched) | |
| 533 | + cs_dsp_power_down(&cs35l56->cs_dsp); | |
| 534 | + | |
| 535 | + cs35l56->base.fw_patched = false; | |
| 536 | + | |
| 537 | + pm_runtime_get_sync(cs35l56->base.dev); | |
| 538 | + | |
| 539 | + ret = regmap_read(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, &firmware_missing); | |
| 540 | + if (ret) { | |
| 541 | + dev_err(cs35l56->base.dev, "Failed to read PROTECTION_STATUS: %d\n", ret); | |
| 542 | + goto err_pm_put; | |
| 543 | + } | |
| 544 | + | |
| 545 | + firmware_missing &= CS35L56_FIRMWARE_MISSING; | |
| 546 | + | |
| 547 | + /* | |
| 548 | + * Firmware can only be downloaded if the CS35L56 is secured or is | |
| 549 | + * running from the built-in ROM. If it is secured the BIOS will have | |
| 550 | + * downloaded firmware, and the wmfw/bin files will only contain | |
| 551 | + * tunings that are safe to download with the firmware running. | |
| 552 | + */ | |
| 553 | + if (cs35l56->base.secured || firmware_missing) { | |
| 554 | + cs35l56_hda_request_firmware_files(cs35l56, &wmfw_firmware, &wmfw_filename, | |
| 555 | + &coeff_firmware, &coeff_filename); | |
| 556 | + } | |
| 557 | + | |
| 558 | + /* | |
| 559 | + * If the BIOS didn't patch the firmware a bin file is mandatory to | |
| 560 | + * enable the ASP· | |
| 561 | + */ | |
| 562 | + if (!coeff_firmware && firmware_missing) { | |
| 563 | + dev_err(cs35l56->base.dev, ".bin file required but not found\n"); | |
| 564 | + ret = -ENOENT; | |
| 565 | + goto err_fw_release; | |
| 566 | + } | |
| 567 | + | |
| 568 | + mutex_lock(&cs35l56->base.irq_lock); | |
| 569 | + | |
| 570 | + /* | |
| 571 | + * When the device is running in secure mode the firmware files can | |
| 572 | + * only contain insecure tunings and therefore we do not need to | |
| 573 | + * shutdown the firmware to apply them and can use the lower cost | |
| 574 | + * reinit sequence instead. | |
| 575 | + */ | |
| 576 | + if (!cs35l56->base.secured && (wmfw_firmware || coeff_firmware)) { | |
| 577 | + ret = cs35l56_firmware_shutdown(&cs35l56->base); | |
| 578 | + if (ret) | |
| 579 | + goto err; | |
| 580 | + } | |
| 581 | + | |
| 582 | + ret = cs_dsp_power_up(&cs35l56->cs_dsp, wmfw_firmware, wmfw_filename, | |
| 583 | + coeff_firmware, coeff_filename, "misc"); | |
| 584 | + if (ret) { | |
| 585 | + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_power_up ret %d\n", __func__, ret); | |
| 586 | + goto err; | |
| 587 | + } | |
| 588 | + | |
| 589 | + if (wmfw_filename) | |
| 590 | + dev_dbg(cs35l56->base.dev, "Loaded WMFW Firmware: %s\n", wmfw_filename); | |
| 591 | + | |
| 592 | + if (coeff_filename) | |
| 593 | + dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename); | |
| 594 | + | |
| 595 | + if (cs35l56->base.secured) { | |
| 596 | + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); | |
| 597 | + if (ret) | |
| 598 | + goto err_powered_up; | |
| 599 | + } else if (wmfw_firmware || coeff_firmware) { | |
| 600 | + /* If we downloaded firmware, reset the device and wait for it to boot */ | |
| 601 | + cs35l56_system_reset(&cs35l56->base, false); | |
| 602 | + regcache_mark_dirty(cs35l56->base.regmap); | |
| 603 | + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); | |
| 604 | + if (ret) | |
| 605 | + goto err_powered_up; | |
| 606 | + } | |
| 607 | + | |
| 608 | + /* Disable auto-hibernate so that runtime_pm has control */ | |
| 609 | + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); | |
| 610 | + if (ret) | |
| 611 | + goto err_powered_up; | |
| 612 | + | |
| 613 | + regcache_sync(cs35l56->base.regmap); | |
| 614 | + | |
| 615 | + regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, | |
| 616 | + CS35L56_FIRMWARE_MISSING); | |
| 617 | + cs35l56->base.fw_patched = true; | |
| 618 | + | |
| 619 | + ret = cs_dsp_run(&cs35l56->cs_dsp); | |
| 620 | + if (ret) | |
| 621 | + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); | |
| 622 | + | |
| 623 | +err_powered_up: | |
| 624 | + if (!cs35l56->base.fw_patched) | |
| 625 | + cs_dsp_power_down(&cs35l56->cs_dsp); | |
| 626 | +err: | |
| 627 | + mutex_unlock(&cs35l56->base.irq_lock); | |
| 628 | +err_fw_release: | |
| 629 | + cs35l56_hda_release_firmware_files(wmfw_firmware, wmfw_filename, | |
| 630 | + coeff_firmware, coeff_filename); | |
| 631 | +err_pm_put: | |
| 632 | + pm_runtime_put(cs35l56->base.dev); | |
| 633 | + | |
| 634 | + return ret; | |
| 635 | +} | |
| 636 | + | |
| 637 | +static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data) | |
| 638 | +{ | |
| 639 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 640 | + struct hda_component *comps = master_data; | |
| 641 | + int ret; | |
| 642 | + | |
| 643 | + if (!comps || cs35l56->index < 0 || cs35l56->index >= HDA_MAX_COMPONENTS) | |
| 644 | + return -EINVAL; | |
| 645 | + | |
| 646 | + comps = &comps[cs35l56->index]; | |
| 647 | + if (comps->dev) | |
| 648 | + return -EBUSY; | |
| 649 | + | |
| 650 | + comps->dev = dev; | |
| 651 | + cs35l56->codec = comps->codec; | |
| 652 | + strscpy(comps->name, dev_name(dev), sizeof(comps->name)); | |
| 653 | + comps->playback_hook = cs35l56_hda_playback_hook; | |
| 654 | + | |
| 655 | + ret = cs35l56_hda_fw_load(cs35l56); | |
| 656 | + if (ret) | |
| 657 | + return ret; | |
| 658 | + | |
| 659 | + cs35l56_hda_create_controls(cs35l56); | |
| 660 | + cs35l56_hda_add_dsp_controls(cs35l56); | |
| 661 | + | |
| 662 | +#if IS_ENABLED(CONFIG_SND_DEBUG) | |
| 663 | + cs35l56->debugfs_root = debugfs_create_dir(dev_name(cs35l56->base.dev), sound_debugfs_root); | |
| 664 | + cs_dsp_init_debugfs(&cs35l56->cs_dsp, cs35l56->debugfs_root); | |
| 665 | +#endif | |
| 666 | + | |
| 667 | + dev_dbg(cs35l56->base.dev, "Bound\n"); | |
| 668 | + | |
| 669 | + return 0; | |
| 670 | +} | |
| 671 | + | |
| 672 | +static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *master_data) | |
| 673 | +{ | |
| 674 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 675 | + struct hda_component *comps = master_data; | |
| 676 | + | |
| 677 | + cs35l56_hda_remove_controls(cs35l56); | |
| 678 | + | |
| 679 | +#if IS_ENABLED(CONFIG_SND_DEBUG) | |
| 680 | + cs_dsp_cleanup_debugfs(&cs35l56->cs_dsp); | |
| 681 | + debugfs_remove_recursive(cs35l56->debugfs_root); | |
| 682 | +#endif | |
| 683 | + | |
| 684 | + if (cs35l56->base.fw_patched) | |
| 685 | + cs_dsp_power_down(&cs35l56->cs_dsp); | |
| 686 | + | |
| 687 | + cs_dsp_remove(&cs35l56->cs_dsp); | |
| 688 | + | |
| 689 | + if (comps[cs35l56->index].dev == dev) | |
| 690 | + memset(&comps[cs35l56->index], 0, sizeof(*comps)); | |
| 691 | + | |
| 692 | + dev_dbg(cs35l56->base.dev, "Unbound\n"); | |
| 693 | +} | |
| 694 | + | |
| 695 | +static const struct component_ops cs35l56_hda_comp_ops = { | |
| 696 | + .bind = cs35l56_hda_bind, | |
| 697 | + .unbind = cs35l56_hda_unbind, | |
| 698 | +}; | |
| 699 | + | |
| 700 | +static int cs35l56_hda_system_suspend(struct device *dev) | |
| 701 | +{ | |
| 702 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 703 | + | |
| 704 | + if (cs35l56->playing) | |
| 705 | + cs35l56_hda_pause(cs35l56); | |
| 706 | + | |
| 707 | + cs35l56->suspended = true; | |
| 708 | + | |
| 709 | + /* | |
| 710 | + * The interrupt line is normally shared, but after we start suspending | |
| 711 | + * we can't check if our device is the source of an interrupt, and can't | |
| 712 | + * clear it. Prevent this race by temporarily disabling the parent irq | |
| 713 | + * until we reach _no_irq. | |
| 714 | + */ | |
| 715 | + if (cs35l56->base.irq) | |
| 716 | + disable_irq(cs35l56->base.irq); | |
| 717 | + | |
| 718 | + return pm_runtime_force_suspend(dev); | |
| 719 | +} | |
| 720 | + | |
| 721 | +static int cs35l56_hda_system_suspend_late(struct device *dev) | |
| 722 | +{ | |
| 723 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 724 | + | |
| 725 | + /* | |
| 726 | + * RESET is usually shared by all amps so it must not be asserted until | |
| 727 | + * all driver instances have done their suspend() stage. | |
| 728 | + */ | |
| 729 | + if (cs35l56->base.reset_gpio) { | |
| 730 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); | |
| 731 | + cs35l56_wait_min_reset_pulse(); | |
| 732 | + } | |
| 733 | + | |
| 734 | + return 0; | |
| 735 | +} | |
| 736 | + | |
| 737 | +static int cs35l56_hda_system_suspend_no_irq(struct device *dev) | |
| 738 | +{ | |
| 739 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 740 | + | |
| 741 | + /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */ | |
| 742 | + if (cs35l56->base.irq) | |
| 743 | + enable_irq(cs35l56->base.irq); | |
| 744 | + | |
| 745 | + return 0; | |
| 746 | +} | |
| 747 | + | |
| 748 | +static int cs35l56_hda_system_resume_no_irq(struct device *dev) | |
| 749 | +{ | |
| 750 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 751 | + | |
| 752 | + /* | |
| 753 | + * WAKE interrupts unmask if the CS35L56 hibernates, which can cause | |
| 754 | + * spurious interrupts, and the interrupt line is normally shared. | |
| 755 | + * We can't check if our device is the source of an interrupt, and can't | |
| 756 | + * clear it, until it has fully resumed. Prevent this race by temporarily | |
| 757 | + * disabling the parent irq until we complete resume(). | |
| 758 | + */ | |
| 759 | + if (cs35l56->base.irq) | |
| 760 | + disable_irq(cs35l56->base.irq); | |
| 761 | + | |
| 762 | + return 0; | |
| 763 | +} | |
| 764 | + | |
| 765 | +static int cs35l56_hda_system_resume_early(struct device *dev) | |
| 766 | +{ | |
| 767 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 768 | + | |
| 769 | + /* Ensure a spec-compliant RESET pulse. */ | |
| 770 | + if (cs35l56->base.reset_gpio) { | |
| 771 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); | |
| 772 | + cs35l56_wait_min_reset_pulse(); | |
| 773 | + | |
| 774 | + /* Release shared RESET before drivers start resume(). */ | |
| 775 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); | |
| 776 | + cs35l56_wait_control_port_ready(); | |
| 777 | + } | |
| 778 | + | |
| 779 | + return 0; | |
| 780 | +} | |
| 781 | + | |
| 782 | +static int cs35l56_hda_system_resume(struct device *dev) | |
| 783 | +{ | |
| 784 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 785 | + int ret; | |
| 786 | + | |
| 787 | + /* Undo pm_runtime_force_suspend() before re-enabling the irq */ | |
| 788 | + ret = pm_runtime_force_resume(dev); | |
| 789 | + if (cs35l56->base.irq) | |
| 790 | + enable_irq(cs35l56->base.irq); | |
| 791 | + | |
| 792 | + if (ret) | |
| 793 | + return ret; | |
| 794 | + | |
| 795 | + cs35l56->suspended = false; | |
| 796 | + | |
| 797 | + ret = cs35l56_is_fw_reload_needed(&cs35l56->base); | |
| 798 | + dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); | |
| 799 | + if (ret > 0) { | |
| 800 | + ret = cs35l56_hda_fw_load(cs35l56); | |
| 801 | + if (ret) | |
| 802 | + return ret; | |
| 803 | + } | |
| 804 | + | |
| 805 | + if (cs35l56->playing) | |
| 806 | + cs35l56_hda_play(cs35l56); | |
| 807 | + | |
| 808 | + return 0; | |
| 809 | +} | |
| 810 | + | |
| 811 | +static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id) | |
| 812 | +{ | |
| 813 | + u32 values[HDA_MAX_COMPONENTS]; | |
| 814 | + struct acpi_device *adev; | |
| 815 | + const char *property, *sub; | |
| 816 | + size_t nval; | |
| 817 | + int i, ret; | |
| 818 | + | |
| 819 | + /* | |
| 820 | + * ACPI_COMPANION isn't available when this driver was instantiated by | |
| 821 | + * the serial-multi-instantiate driver, so lookup the node by HID | |
| 822 | + */ | |
| 823 | + if (!ACPI_COMPANION(cs35l56->base.dev)) { | |
| 824 | + adev = acpi_dev_get_first_match_dev("CSC3556", NULL, -1); | |
| 825 | + if (!adev) { | |
| 826 | + dev_err(cs35l56->base.dev, "Failed to find an ACPI device for %s\n", | |
| 827 | + dev_name(cs35l56->base.dev)); | |
| 828 | + return -ENODEV; | |
| 829 | + } | |
| 830 | + ACPI_COMPANION_SET(cs35l56->base.dev, adev); | |
| 831 | + } | |
| 832 | + | |
| 833 | + property = "cirrus,dev-index"; | |
| 834 | + ret = device_property_count_u32(cs35l56->base.dev, property); | |
| 835 | + if (ret <= 0) | |
| 836 | + goto err; | |
| 837 | + | |
| 838 | + if (ret > ARRAY_SIZE(values)) { | |
| 839 | + ret = -EINVAL; | |
| 840 | + goto err; | |
| 841 | + } | |
| 842 | + nval = ret; | |
| 843 | + | |
| 844 | + ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval); | |
| 845 | + if (ret) | |
| 846 | + goto err; | |
| 847 | + | |
| 848 | + cs35l56->index = -1; | |
| 849 | + for (i = 0; i < nval; i++) { | |
| 850 | + if (values[i] == id) { | |
| 851 | + cs35l56->index = i; | |
| 852 | + break; | |
| 853 | + } | |
| 854 | + } | |
| 855 | + /* | |
| 856 | + * It's not an error for the ID to be missing: for I2C there can be | |
| 857 | + * an alias address that is not a real device. So reject silently. | |
| 858 | + */ | |
| 859 | + if (cs35l56->index == -1) { | |
| 860 | + dev_dbg(cs35l56->base.dev, "No index found in %s\n", property); | |
| 861 | + ret = -ENODEV; | |
| 862 | + goto err; | |
| 863 | + } | |
| 864 | + | |
| 865 | + sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev)); | |
| 866 | + | |
| 867 | + if (IS_ERR(sub)) { | |
| 868 | + /* If no ACPI SUB, return 0 and fallback to legacy firmware path, otherwise fail */ | |
| 869 | + if (PTR_ERR(sub) == -ENODATA) | |
| 870 | + return 0; | |
| 871 | + else | |
| 872 | + return PTR_ERR(sub); | |
| 873 | + } | |
| 874 | + | |
| 875 | + cs35l56->system_name = sub; | |
| 876 | + | |
| 877 | + cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev, | |
| 878 | + "reset", | |
| 879 | + cs35l56->index, | |
| 880 | + GPIOD_OUT_LOW); | |
| 881 | + if (IS_ERR(cs35l56->base.reset_gpio)) { | |
| 882 | + ret = PTR_ERR(cs35l56->base.reset_gpio); | |
| 883 | + | |
| 884 | + /* | |
| 885 | + * If RESET is shared the first amp to probe will grab the reset | |
| 886 | + * line and reset all the amps | |
| 887 | + */ | |
| 888 | + if (ret != -EBUSY) | |
| 889 | + return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n"); | |
| 890 | + | |
| 891 | + dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n"); | |
| 892 | + cs35l56->base.reset_gpio = NULL; | |
| 893 | + } | |
| 894 | + | |
| 895 | + return 0; | |
| 896 | + | |
| 897 | +err: | |
| 898 | + if (ret != -ENODEV) | |
| 899 | + dev_err(cs35l56->base.dev, "Failed property %s: %d\n", property, ret); | |
| 900 | + | |
| 901 | + return ret; | |
| 902 | +} | |
| 903 | + | |
| 904 | +int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id) | |
| 905 | +{ | |
| 906 | + int ret; | |
| 907 | + | |
| 908 | + mutex_init(&cs35l56->base.irq_lock); | |
| 909 | + dev_set_drvdata(cs35l56->base.dev, cs35l56); | |
| 910 | + | |
| 911 | + ret = cs35l56_hda_read_acpi(cs35l56, id); | |
| 912 | + if (ret) | |
| 913 | + goto err; | |
| 914 | + | |
| 915 | + cs35l56->amp_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "AMP%d", | |
| 916 | + cs35l56->index + 1); | |
| 917 | + if (!cs35l56->amp_name) { | |
| 918 | + ret = -ENOMEM; | |
| 919 | + goto err; | |
| 920 | + } | |
| 921 | + | |
| 922 | + cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); | |
| 923 | + cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops; | |
| 924 | + | |
| 925 | + if (cs35l56->base.reset_gpio) { | |
| 926 | + dev_dbg(cs35l56->base.dev, "Hard reset\n"); | |
| 927 | + | |
| 928 | + /* | |
| 929 | + * The GPIOD_OUT_LOW to *_gpiod_get_*() will be ignored if the | |
| 930 | + * ACPI defines a different default state. So explicitly set low. | |
| 931 | + */ | |
| 932 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); | |
| 933 | + cs35l56_wait_min_reset_pulse(); | |
| 934 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); | |
| 935 | + } | |
| 936 | + | |
| 937 | + ret = cs35l56_hw_init(&cs35l56->base); | |
| 938 | + if (ret < 0) | |
| 939 | + goto err; | |
| 940 | + | |
| 941 | + /* Reset the device and wait for it to boot */ | |
| 942 | + cs35l56_system_reset(&cs35l56->base, false); | |
| 943 | + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); | |
| 944 | + if (ret) | |
| 945 | + goto err; | |
| 946 | + | |
| 947 | + ret = cs35l56_set_patch(&cs35l56->base); | |
| 948 | + if (ret) | |
| 949 | + goto err; | |
| 950 | + | |
| 951 | + regcache_mark_dirty(cs35l56->base.regmap); | |
| 952 | + regcache_sync(cs35l56->base.regmap); | |
| 953 | + | |
| 954 | + /* Disable auto-hibernate so that runtime_pm has control */ | |
| 955 | + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); | |
| 956 | + if (ret) | |
| 957 | + goto err; | |
| 958 | + | |
| 959 | + ret = cs_dsp_halo_init(&cs35l56->cs_dsp); | |
| 960 | + if (ret) { | |
| 961 | + dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n"); | |
| 962 | + goto err; | |
| 963 | + } | |
| 964 | + | |
| 965 | + dev_dbg(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n", | |
| 966 | + cs35l56->system_name, cs35l56->amp_name); | |
| 967 | + | |
| 968 | + regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config, | |
| 969 | + ARRAY_SIZE(cs35l56_hda_dai_config)); | |
| 970 | + | |
| 971 | + /* | |
| 972 | + * By default only enable one ASP1TXn, where n=amplifier index, | |
| 973 | + * This prevents multiple amps trying to drive the same slot. | |
| 974 | + */ | |
| 975 | + cs35l56->asp_tx_mask = BIT(cs35l56->index); | |
| 976 | + | |
| 977 | + pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 3000); | |
| 978 | + pm_runtime_use_autosuspend(cs35l56->base.dev); | |
| 979 | + pm_runtime_set_active(cs35l56->base.dev); | |
| 980 | + pm_runtime_mark_last_busy(cs35l56->base.dev); | |
| 981 | + pm_runtime_enable(cs35l56->base.dev); | |
| 982 | + | |
| 983 | + ret = component_add(cs35l56->base.dev, &cs35l56_hda_comp_ops); | |
| 984 | + if (ret) { | |
| 985 | + dev_err(cs35l56->base.dev, "Register component failed: %d\n", ret); | |
| 986 | + goto pm_err; | |
| 987 | + } | |
| 988 | + | |
| 989 | + cs35l56->base.init_done = true; | |
| 990 | + | |
| 991 | + return 0; | |
| 992 | + | |
| 993 | +pm_err: | |
| 994 | + pm_runtime_disable(cs35l56->base.dev); | |
| 995 | +err: | |
| 996 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); | |
| 997 | + | |
| 998 | + return ret; | |
| 999 | +} | |
| 1000 | +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, SND_HDA_SCODEC_CS35L56); | |
| 1001 | + | |
| 1002 | +void cs35l56_hda_remove(struct device *dev) | |
| 1003 | +{ | |
| 1004 | + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); | |
| 1005 | + | |
| 1006 | + pm_runtime_get_sync(cs35l56->base.dev); | |
| 1007 | + pm_runtime_disable(cs35l56->base.dev); | |
| 1008 | + | |
| 1009 | + component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops); | |
| 1010 | + | |
| 1011 | + kfree(cs35l56->system_name); | |
| 1012 | + pm_runtime_put_noidle(cs35l56->base.dev); | |
| 1013 | + | |
| 1014 | + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); | |
| 1015 | +} | |
| 1016 | +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, SND_HDA_SCODEC_CS35L56); | |
| 1017 | + | |
| 1018 | +const struct dev_pm_ops cs35l56_hda_pm_ops = { | |
| 1019 | + SET_RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL) | |
| 1020 | + SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend, cs35l56_hda_system_resume) | |
| 1021 | + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_late, | |
| 1022 | + cs35l56_hda_system_resume_early) | |
| 1023 | + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_no_irq, | |
| 1024 | + cs35l56_hda_system_resume_no_irq) | |
| 1025 | +}; | |
| 1026 | +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56); | |
| 1027 | + | |
| 1028 | +MODULE_DESCRIPTION("CS35L56 HDA Driver"); | |
| 1029 | +MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); | |
| 1030 | +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | |
| 1031 | +MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | |
| 1032 | +MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | |
| 1033 | +MODULE_LICENSE("GPL"); | |
| 1034 | +MODULE_IMPORT_NS(FW_CS_DSP); | |
| @@ -0,0 +1,48 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + * | |
| 3 | + * HDA audio driver for Cirrus Logic CS35L56 smart amp | |
| 4 | + * | |
| 5 | + * Copyright (C) 2023 Cirrus Logic, Inc. and | |
| 6 | + * Cirrus Logic International Semiconductor Ltd. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef __CS35L56_HDA_H__ | |
| 10 | +#define __CS35L56_HDA_H__ | |
| 11 | + | |
| 12 | +#include <linux/device.h> | |
| 13 | +#include <linux/gpio/consumer.h> | |
| 14 | +#include <linux/firmware/cirrus/cs_dsp.h> | |
| 15 | +#include <linux/firmware/cirrus/wmfw.h> | |
| 16 | +#include <linux/regulator/consumer.h> | |
| 17 | +#include <sound/cs35l56.h> | |
| 18 | + | |
| 19 | +struct dentry; | |
| 20 | + | |
| 21 | +struct cs35l56_hda { | |
| 22 | + struct cs35l56_base base; | |
| 23 | + struct hda_codec *codec; | |
| 24 | + | |
| 25 | + int index; | |
| 26 | + const char *system_name; | |
| 27 | + const char *amp_name; | |
| 28 | + | |
| 29 | + struct cs_dsp cs_dsp; | |
| 30 | + bool playing; | |
| 31 | + bool suspended; | |
| 32 | + u8 asp_tx_mask; | |
| 33 | + | |
| 34 | + struct snd_kcontrol *posture_ctl; | |
| 35 | + struct snd_kcontrol *volume_ctl; | |
| 36 | + struct snd_kcontrol *mixer_ctl[4]; | |
| 37 | + | |
| 38 | +#if IS_ENABLED(CONFIG_SND_DEBUG) | |
| 39 | + struct dentry *debugfs_root; | |
| 40 | +#endif | |
| 41 | +}; | |
| 42 | + | |
| 43 | +extern const struct dev_pm_ops cs35l56_hda_pm_ops; | |
| 44 | + | |
| 45 | +int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id); | |
| 46 | +void cs35l56_hda_remove(struct device *dev); | |
| 47 | + | |
| 48 | +#endif /*__CS35L56_HDA_H__*/ | |
| @@ -0,0 +1,69 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// CS35L56 HDA audio driver I2C binding | |
| 4 | +// | |
| 5 | +// Copyright (C) 2023 Cirrus Logic, Inc. and | |
| 6 | +// Cirrus Logic International Semiconductor Ltd. | |
| 7 | + | |
| 8 | +#include <linux/i2c.h> | |
| 9 | +#include <linux/module.h> | |
| 10 | +#include <linux/regmap.h> | |
| 11 | + | |
| 12 | +#include "cs35l56_hda.h" | |
| 13 | + | |
| 14 | +static int cs35l56_hda_i2c_probe(struct i2c_client *clt) | |
| 15 | +{ | |
| 16 | + struct cs35l56_hda *cs35l56; | |
| 17 | + int ret; | |
| 18 | + | |
| 19 | + cs35l56 = devm_kzalloc(&clt->dev, sizeof(*cs35l56), GFP_KERNEL); | |
| 20 | + if (!cs35l56) | |
| 21 | + return -ENOMEM; | |
| 22 | + | |
| 23 | + cs35l56->base.dev = &clt->dev; | |
| 24 | + cs35l56->base.can_hibernate = true; | |
| 25 | + cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c); | |
| 26 | + if (IS_ERR(cs35l56->base.regmap)) { | |
| 27 | + ret = PTR_ERR(cs35l56->base.regmap); | |
| 28 | + dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n", | |
| 29 | + ret); | |
| 30 | + return ret; | |
| 31 | + } | |
| 32 | + | |
| 33 | + ret = cs35l56_hda_common_probe(cs35l56, clt->addr); | |
| 34 | + if (ret) | |
| 35 | + return ret; | |
| 36 | + ret = cs35l56_irq_request(&cs35l56->base, clt->irq); | |
| 37 | + if (ret < 0) | |
| 38 | + cs35l56_hda_remove(cs35l56->base.dev); | |
| 39 | + | |
| 40 | + return ret; | |
| 41 | +} | |
| 42 | + | |
| 43 | +static void cs35l56_hda_i2c_remove(struct i2c_client *clt) | |
| 44 | +{ | |
| 45 | + cs35l56_hda_remove(&clt->dev); | |
| 46 | +} | |
| 47 | + | |
| 48 | +static const struct i2c_device_id cs35l56_hda_i2c_id[] = { | |
| 49 | + { "cs35l56-hda", 0 }, | |
| 50 | + {} | |
| 51 | +}; | |
| 52 | + | |
| 53 | +static struct i2c_driver cs35l56_hda_i2c_driver = { | |
| 54 | + .driver = { | |
| 55 | + .name = "cs35l56-hda", | |
| 56 | + .pm = &cs35l56_hda_pm_ops, | |
| 57 | + }, | |
| 58 | + .id_table = cs35l56_hda_i2c_id, | |
| 59 | + .probe = cs35l56_hda_i2c_probe, | |
| 60 | + .remove = cs35l56_hda_i2c_remove, | |
| 61 | +}; | |
| 62 | +module_i2c_driver(cs35l56_hda_i2c_driver); | |
| 63 | + | |
| 64 | +MODULE_DESCRIPTION("HDA CS35L56 I2C driver"); | |
| 65 | +MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56); | |
| 66 | +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | |
| 67 | +MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | |
| 68 | +MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | |
| 69 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,68 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// CS35L56 HDA audio driver SPI binding | |
| 4 | +// | |
| 5 | +// Copyright (C) 2023 Cirrus Logic, Inc. and | |
| 6 | +// Cirrus Logic International Semiconductor Ltd. | |
| 7 | + | |
| 8 | +#include <linux/module.h> | |
| 9 | +#include <linux/regmap.h> | |
| 10 | +#include <linux/spi/spi.h> | |
| 11 | + | |
| 12 | +#include "cs35l56_hda.h" | |
| 13 | + | |
| 14 | +static int cs35l56_hda_spi_probe(struct spi_device *spi) | |
| 15 | +{ | |
| 16 | + struct cs35l56_hda *cs35l56; | |
| 17 | + int ret; | |
| 18 | + | |
| 19 | + cs35l56 = devm_kzalloc(&spi->dev, sizeof(*cs35l56), GFP_KERNEL); | |
| 20 | + if (!cs35l56) | |
| 21 | + return -ENOMEM; | |
| 22 | + | |
| 23 | + cs35l56->base.dev = &spi->dev; | |
| 24 | + cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi); | |
| 25 | + if (IS_ERR(cs35l56->base.regmap)) { | |
| 26 | + ret = PTR_ERR(cs35l56->base.regmap); | |
| 27 | + dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n", | |
| 28 | + ret); | |
| 29 | + return ret; | |
| 30 | + } | |
| 31 | + | |
| 32 | + ret = cs35l56_hda_common_probe(cs35l56, spi->chip_select); | |
| 33 | + if (ret) | |
| 34 | + return ret; | |
| 35 | + ret = cs35l56_irq_request(&cs35l56->base, spi->irq); | |
| 36 | + if (ret < 0) | |
| 37 | + cs35l56_hda_remove(cs35l56->base.dev); | |
| 38 | + | |
| 39 | + return ret; | |
| 40 | +} | |
| 41 | + | |
| 42 | +static void cs35l56_hda_spi_remove(struct spi_device *spi) | |
| 43 | +{ | |
| 44 | + cs35l56_hda_remove(&spi->dev); | |
| 45 | +} | |
| 46 | + | |
| 47 | +static const struct spi_device_id cs35l56_hda_spi_id[] = { | |
| 48 | + { "cs35l56-hda", 0 }, | |
| 49 | + {} | |
| 50 | +}; | |
| 51 | + | |
| 52 | +static struct spi_driver cs35l56_hda_spi_driver = { | |
| 53 | + .driver = { | |
| 54 | + .name = "cs35l56-hda", | |
| 55 | + .pm = &cs35l56_hda_pm_ops, | |
| 56 | + }, | |
| 57 | + .id_table = cs35l56_hda_spi_id, | |
| 58 | + .probe = cs35l56_hda_spi_probe, | |
| 59 | + .remove = cs35l56_hda_spi_remove, | |
| 60 | +}; | |
| 61 | +module_spi_driver(cs35l56_hda_spi_driver); | |
| 62 | + | |
| 63 | +MODULE_DESCRIPTION("HDA CS35L56 SPI driver"); | |
| 64 | +MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56); | |
| 65 | +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | |
| 66 | +MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | |
| 67 | +MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); | |
| 68 | +MODULE_LICENSE("GPL"); | |
| @@ -8,6 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef __SOUND_HDA_AUTO_PARSER_H |
| 9 | 9 | #define __SOUND_HDA_AUTO_PARSER_H |
| 10 | 10 | |
| 11 | +#include "hda_local.h" | |
| 12 | + | |
| 11 | 13 | /* |
| 12 | 14 | * Helper for automatic pin configuration |
| 13 | 15 | */ |
| @@ -1769,10 +1769,8 @@ void snd_hda_ctls_clear(struct hda_codec *codec) · 1768 unmodified lines | ||
| 1769 | 1769 | int i; |
| 1770 | 1770 | struct hda_nid_item *items = codec->mixers.list; |
| 1771 | 1771 | |
| 1772 | − down_write(&codec->card->controls_rwsem); | |
| 1773 | 1772 | for (i = 0; i < codec->mixers.used; i++) |
| 1774 | 1773 | snd_ctl_remove(codec->card, items[i].kctl); |
| 1775 | − up_write(&codec->card->controls_rwsem); | |
| 1776 | 1774 | snd_array_free(&codec->mixers); |
| 1777 | 1775 | snd_array_free(&codec->nids); |
| 1778 | 1776 | } |
| @@ -15,5 +15,7 @@ struct hda_component { · 14 unmodified lines | ||
| 15 | 15 | struct device *dev; |
| 16 | 16 | char name[HDA_MAX_NAME_SIZE]; |
| 17 | 17 | struct hda_codec *codec; |
| 18 | + void (*pre_playback_hook)(struct device *dev, int action); | |
| 18 | 19 | void (*playback_hook)(struct device *dev, int action); |
| 20 | + void (*post_playback_hook)(struct device *dev, int action); | |
| 19 | 21 | }; |
| @@ -9,6 +9,9 @@ · 8 unmodified lines | ||
| 9 | 9 | #define __SOUND_HDA_GENERIC_H |
| 10 | 10 | |
| 11 | 11 | #include <linux/leds.h> |
| 12 | +#include "hda_auto_parser.h" | |
| 13 | + | |
| 14 | +struct hda_jack_callback; | |
| 12 | 15 | |
| 13 | 16 | /* table entry for multi-io paths */ |
| 14 | 17 | struct hda_multi_io { |
| @@ -114,8 +114,8 @@ int snd_hda_create_hwdep(struct hda_codec *codec) · 113 unmodified lines | ||
| 114 | 114 | #endif |
| 115 | 115 | |
| 116 | 116 | /* for sysfs */ |
| 117 | − hwdep->dev.groups = snd_hda_dev_attr_groups; | |
| 118 | − dev_set_drvdata(&hwdep->dev, codec); | |
| 117 | + hwdep->dev->groups = snd_hda_dev_attr_groups; | |
| 118 | + dev_set_drvdata(hwdep->dev, codec); | |
| 119 | 119 | |
| 120 | 120 | return 0; |
| 121 | 121 | } |
| @@ -330,18 +330,6 @@ enum { · 329 unmodified lines | ||
| 330 | 330 | #define needs_eld_notify_link(chip) false |
| 331 | 331 | #endif |
| 332 | 332 | |
| 333 | −#define CONTROLLER_IN_GPU(pci) (((pci)->vendor == 0x8086) && \ | |
| 334 | − (((pci)->device == 0x0a0c) || \ | |
| 335 | − ((pci)->device == 0x0c0c) || \ | |
| 336 | − ((pci)->device == 0x0d0c) || \ | |
| 337 | − ((pci)->device == 0x160c) || \ | |
| 338 | − ((pci)->device == 0x490d) || \ | |
| 339 | − ((pci)->device == 0x4f90) || \ | |
| 340 | − ((pci)->device == 0x4f91) || \ | |
| 341 | − ((pci)->device == 0x4f92))) | |
| 342 | − | |
| 343 | −#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) | |
| 344 | − | |
| 345 | 333 | static const char * const driver_short_names[] = { |
| 346 | 334 | [AZX_DRIVER_ICH] = "HDA Intel", |
| 347 | 335 | [AZX_DRIVER_PCH] = "HDA Intel PCH", |
| @@ -573,7 +561,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) · 225 unmodified lines | ||
| 573 | 561 | snd_hdac_set_codec_wakeup(bus, false); |
| 574 | 562 | |
| 575 | 563 | /* reduce dma latency to avoid noise */ |
| 576 | − if (IS_BXT(pci)) | |
| 564 | + if (HDA_CONTROLLER_IS_APL(pci)) | |
| 577 | 565 | bxt_reduce_dma_latency(chip); |
| 578 | 566 | |
| 579 | 567 | if (bus->mlcap != NULL) |
| @@ -2175,7 +2163,7 @@ static int azx_probe(struct pci_dev *pci, · 1595 unmodified lines | ||
| 2175 | 2163 | #endif /* CONFIG_SND_HDA_PATCH_LOADER */ |
| 2176 | 2164 | |
| 2177 | 2165 | #ifndef CONFIG_SND_HDA_I915 |
| 2178 | − if (CONTROLLER_IN_GPU(pci)) | |
| 2166 | + if (HDA_CONTROLLER_IN_GPU(pci)) | |
| 2179 | 2167 | dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n"); |
| 2180 | 2168 | #endif |
| 2181 | 2169 | |
| @@ -2283,7 +2271,7 @@ static int azx_probe_continue(struct azx *chip) · 101 unmodified lines | ||
| 2283 | 2271 | * for other chips, still continue probing as other |
| 2284 | 2272 | * codecs can be on the same link. |
| 2285 | 2273 | */ |
| 2286 | − if (CONTROLLER_IN_GPU(pci)) { | |
| 2274 | + if (HDA_CONTROLLER_IN_GPU(pci)) { | |
| 2287 | 2275 | dev_err(chip->card->dev, |
| 2288 | 2276 | "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); |
| 2289 | 2277 | goto out_free; |
| @@ -2294,7 +2282,7 @@ static int azx_probe_continue(struct azx *chip) · 4 unmodified lines | ||
| 2294 | 2282 | } |
| 2295 | 2283 | |
| 2296 | 2284 | /* HSW/BDW controllers need this power */ |
| 2297 | − if (CONTROLLER_IN_GPU(pci)) | |
| 2285 | + if (HDA_CONTROLLER_IN_GPU(pci)) | |
| 2298 | 2286 | hda->need_i915_power = true; |
| 2299 | 2287 | } |
| 2300 | 2288 | |
| @@ -2428,333 +2416,262 @@ static void azx_shutdown(struct pci_dev *pci) · 127 unmodified lines | ||
| 2428 | 2416 | /* PCI IDs */ |
| 2429 | 2417 | static const struct pci_device_id azx_ids[] = { |
| 2430 | 2418 | /* CPT */ |
| 2431 | − { PCI_DEVICE(0x8086, 0x1c20), | |
| 2432 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | |
| 2419 | + { PCI_DEVICE_DATA(INTEL, HDA_CPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) }, | |
| 2433 | 2420 | /* PBG */ |
| 2434 | − { PCI_DEVICE(0x8086, 0x1d20), | |
| 2435 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | |
| 2421 | + { PCI_DEVICE_DATA(INTEL, HDA_PBG, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) }, | |
| 2436 | 2422 | /* Panther Point */ |
| 2437 | − { PCI_DEVICE(0x8086, 0x1e20), | |
| 2438 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | |
| 2423 | + { PCI_DEVICE_DATA(INTEL, HDA_PPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) }, | |
| 2439 | 2424 | /* Lynx Point */ |
| 2440 | − { PCI_DEVICE(0x8086, 0x8c20), | |
| 2441 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2425 | + { PCI_DEVICE_DATA(INTEL, HDA_LPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2442 | 2426 | /* 9 Series */ |
| 2443 | − { PCI_DEVICE(0x8086, 0x8ca0), | |
| 2444 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2427 | + { PCI_DEVICE_DATA(INTEL, HDA_9_SERIES, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2445 | 2428 | /* Wellsburg */ |
| 2446 | − { PCI_DEVICE(0x8086, 0x8d20), | |
| 2447 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2448 | − { PCI_DEVICE(0x8086, 0x8d21), | |
| 2449 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2429 | + { PCI_DEVICE_DATA(INTEL, HDA_WBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2430 | + { PCI_DEVICE_DATA(INTEL, HDA_WBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2450 | 2431 | /* Lewisburg */ |
| 2451 | − { PCI_DEVICE(0x8086, 0xa1f0), | |
| 2452 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2453 | − { PCI_DEVICE(0x8086, 0xa270), | |
| 2454 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2432 | + { PCI_DEVICE_DATA(INTEL, HDA_LBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2433 | + { PCI_DEVICE_DATA(INTEL, HDA_LBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2455 | 2434 | /* Lynx Point-LP */ |
| 2456 | − { PCI_DEVICE(0x8086, 0x9c20), | |
| 2457 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2435 | + { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2458 | 2436 | /* Lynx Point-LP */ |
| 2459 | − { PCI_DEVICE(0x8086, 0x9c21), | |
| 2460 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2437 | + { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2461 | 2438 | /* Wildcat Point-LP */ |
| 2462 | − { PCI_DEVICE(0x8086, 0x9ca0), | |
| 2463 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | |
| 2464 | − /* Sunrise Point */ | |
| 2465 | − { PCI_DEVICE(0x8086, 0xa170), | |
| 2466 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2467 | − /* Sunrise Point-LP */ | |
| 2468 | − { PCI_DEVICE(0x8086, 0x9d70), | |
| 2469 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2439 | + { PCI_DEVICE_DATA(INTEL, HDA_WPT_LP, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) }, | |
| 2440 | + /* Skylake (Sunrise Point) */ | |
| 2441 | + { PCI_DEVICE_DATA(INTEL, HDA_SKL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2442 | + /* Skylake-LP (Sunrise Point-LP) */ | |
| 2443 | + { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2470 | 2444 | /* Kabylake */ |
| 2471 | − { PCI_DEVICE(0x8086, 0xa171), | |
| 2472 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2445 | + { PCI_DEVICE_DATA(INTEL, HDA_KBL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2473 | 2446 | /* Kabylake-LP */ |
| 2474 | − { PCI_DEVICE(0x8086, 0x9d71), | |
| 2475 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2447 | + { PCI_DEVICE_DATA(INTEL, HDA_KBL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2476 | 2448 | /* Kabylake-H */ |
| 2477 | − { PCI_DEVICE(0x8086, 0xa2f0), | |
| 2478 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, | |
| 2449 | + { PCI_DEVICE_DATA(INTEL, HDA_KBL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2479 | 2450 | /* Coffelake */ |
| 2480 | − { PCI_DEVICE(0x8086, 0xa348), | |
| 2481 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2451 | + { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2482 | 2452 | /* Cannonlake */ |
| 2483 | − { PCI_DEVICE(0x8086, 0x9dc8), | |
| 2484 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2453 | + { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2485 | 2454 | /* CometLake-LP */ |
| 2486 | − { PCI_DEVICE(0x8086, 0x02C8), | |
| 2487 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2455 | + { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2488 | 2456 | /* CometLake-H */ |
| 2489 | − { PCI_DEVICE(0x8086, 0x06C8), | |
| 2490 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2491 | − { PCI_DEVICE(0x8086, 0xf1c8), | |
| 2492 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2457 | + { PCI_DEVICE_DATA(INTEL, HDA_CML_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2458 | + { PCI_DEVICE_DATA(INTEL, HDA_RKL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2493 | 2459 | /* CometLake-S */ |
| 2494 | − { PCI_DEVICE(0x8086, 0xa3f0), | |
| 2495 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2460 | + { PCI_DEVICE_DATA(INTEL, HDA_CML_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2496 | 2461 | /* CometLake-R */ |
| 2497 | − { PCI_DEVICE(0x8086, 0xf0c8), | |
| 2498 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2462 | + { PCI_DEVICE_DATA(INTEL, HDA_CML_R, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2499 | 2463 | /* Icelake */ |
| 2500 | − { PCI_DEVICE(0x8086, 0x34c8), | |
| 2501 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2464 | + { PCI_DEVICE_DATA(INTEL, HDA_ICL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2502 | 2465 | /* Icelake-H */ |
| 2503 | − { PCI_DEVICE(0x8086, 0x3dc8), | |
| 2504 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2466 | + { PCI_DEVICE_DATA(INTEL, HDA_ICL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2505 | 2467 | /* Jasperlake */ |
| 2506 | − { PCI_DEVICE(0x8086, 0x38c8), | |
| 2507 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2508 | − { PCI_DEVICE(0x8086, 0x4dc8), | |
| 2509 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2468 | + { PCI_DEVICE_DATA(INTEL, HDA_ICL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2469 | + { PCI_DEVICE_DATA(INTEL, HDA_JSL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2510 | 2470 | /* Tigerlake */ |
| 2511 | − { PCI_DEVICE(0x8086, 0xa0c8), | |
| 2512 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2471 | + { PCI_DEVICE_DATA(INTEL, HDA_TGL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2513 | 2472 | /* Tigerlake-H */ |
| 2514 | − { PCI_DEVICE(0x8086, 0x43c8), | |
| 2515 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2473 | + { PCI_DEVICE_DATA(INTEL, HDA_TGL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2516 | 2474 | /* DG1 */ |
| 2517 | − { PCI_DEVICE(0x8086, 0x490d), | |
| 2518 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2475 | + { PCI_DEVICE_DATA(INTEL, HDA_DG1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2519 | 2476 | /* DG2 */ |
| 2520 | − { PCI_DEVICE(0x8086, 0x4f90), | |
| 2521 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2522 | − { PCI_DEVICE(0x8086, 0x4f91), | |
| 2523 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2524 | − { PCI_DEVICE(0x8086, 0x4f92), | |
| 2525 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2477 | + { PCI_DEVICE_DATA(INTEL, HDA_DG2_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2478 | + { PCI_DEVICE_DATA(INTEL, HDA_DG2_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2479 | + { PCI_DEVICE_DATA(INTEL, HDA_DG2_2, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2526 | 2480 | /* Alderlake-S */ |
| 2527 | − { PCI_DEVICE(0x8086, 0x7ad0), | |
| 2528 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2481 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2529 | 2482 | /* Alderlake-P */ |
| 2530 | − { PCI_DEVICE(0x8086, 0x51c8), | |
| 2531 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2532 | − { PCI_DEVICE(0x8086, 0x51c9), | |
| 2533 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2534 | − { PCI_DEVICE(0x8086, 0x51cd), | |
| 2535 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2483 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2484 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_PS, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2485 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2536 | 2486 | /* Alderlake-M */ |
| 2537 | − { PCI_DEVICE(0x8086, 0x51cc), | |
| 2538 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2487 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2539 | 2488 | /* Alderlake-N */ |
| 2540 | − { PCI_DEVICE(0x8086, 0x54c8), | |
| 2541 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2489 | + { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2542 | 2490 | /* Elkhart Lake */ |
| 2543 | − { PCI_DEVICE(0x8086, 0x4b55), | |
| 2544 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2545 | − { PCI_DEVICE(0x8086, 0x4b58), | |
| 2546 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2491 | + { PCI_DEVICE_DATA(INTEL, HDA_EHL_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2492 | + { PCI_DEVICE_DATA(INTEL, HDA_EHL_3, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2547 | 2493 | /* Raptor Lake */ |
| 2548 | − { PCI_DEVICE(0x8086, 0x7a50), | |
| 2549 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2550 | − { PCI_DEVICE(0x8086, 0x51ca), | |
| 2551 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2552 | − { PCI_DEVICE(0x8086, 0x51cb), | |
| 2553 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2554 | − { PCI_DEVICE(0x8086, 0x51ce), | |
| 2555 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2556 | − { PCI_DEVICE(0x8086, 0x51cf), | |
| 2557 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2558 | − /* Meteorlake-P */ | |
| 2559 | − { PCI_DEVICE(0x8086, 0x7e28), | |
| 2560 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2494 | + { PCI_DEVICE_DATA(INTEL, HDA_RPL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2495 | + { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2496 | + { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2497 | + { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2498 | + { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2499 | + { PCI_DEVICE_DATA(INTEL, HDA_MTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2561 | 2500 | /* Lunarlake-P */ |
| 2562 | − { PCI_DEVICE(0x8086, 0xa828), | |
| 2563 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2564 | − /* Broxton-P(Apollolake) */ | |
| 2565 | − { PCI_DEVICE(0x8086, 0x5a98), | |
| 2566 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, | |
| 2567 | − /* Broxton-T */ | |
| 2568 | − { PCI_DEVICE(0x8086, 0x1a98), | |
| 2569 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, | |
| 2501 | + { PCI_DEVICE_DATA(INTEL, HDA_LNL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2502 | + /* Arrow Lake-S */ | |
| 2503 | + { PCI_DEVICE_DATA(INTEL, HDA_ARL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, | |
| 2504 | + /* Apollolake (Broxton-P) */ | |
| 2505 | + { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, | |
| 2570 | 2506 | /* Gemini-Lake */ |
| 2571 | − { PCI_DEVICE(0x8086, 0x3198), | |
| 2572 | − .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, | |
| 2507 | + { PCI_DEVICE_DATA(INTEL, HDA_GML, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, | |
| 2573 | 2508 | /* Haswell */ |
| 2574 | − { PCI_DEVICE(0x8086, 0x0a0c), | |
| 2575 | − .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | |
| 2576 | − { PCI_DEVICE(0x8086, 0x0c0c), | |
| 2577 | − .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | |
| 2578 | − { PCI_DEVICE(0x8086, 0x0d0c), | |
| 2579 | − .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | |
| 2509 | + { PCI_DEVICE_DATA(INTEL, HDA_HSW_0, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) }, | |
| 2510 | + { PCI_DEVICE_DATA(INTEL, HDA_HSW_2, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) }, | |
| 2511 | + { PCI_DEVICE_DATA(INTEL, HDA_HSW_3, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) }, | |
| 2580 | 2512 | /* Broadwell */ |
| 2581 | − { PCI_DEVICE(0x8086, 0x160c), | |
| 2582 | − .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_BROADWELL }, | |
| 2513 | + { PCI_DEVICE_DATA(INTEL, HDA_BDW, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_BROADWELL) }, | |
| 2583 | 2514 | /* 5 Series/3400 */ |
| 2584 | − { PCI_DEVICE(0x8086, 0x3b56), | |
| 2585 | − .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, | |
| 2586 | − { PCI_DEVICE(0x8086, 0x3b57), | |
| 2587 | − .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, | |
| 2515 | + { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_0, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) }, | |
| 2516 | + { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_1, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) }, | |
| 2588 | 2517 | /* Poulsbo */ |
| 2589 | − { PCI_DEVICE(0x8086, 0x811b), | |
| 2590 | − .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE | | |
| 2591 | − AZX_DCAPS_POSFIX_LPIB }, | |
| 2518 | + { PCI_DEVICE_DATA(INTEL, HDA_POULSBO, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE | | |
| 2519 | + AZX_DCAPS_POSFIX_LPIB) }, | |
| 2592 | 2520 | /* Oaktrail */ |
| 2593 | − { PCI_DEVICE(0x8086, 0x080a), | |
| 2594 | − .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, | |
| 2521 | + { PCI_DEVICE_DATA(INTEL, HDA_OAKTRAIL, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE) }, | |
| 2595 | 2522 | /* BayTrail */ |
| 2596 | − { PCI_DEVICE(0x8086, 0x0f04), | |
| 2597 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL }, | |
| 2523 | + { PCI_DEVICE_DATA(INTEL, HDA_BYT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL) }, | |
| 2598 | 2524 | /* Braswell */ |
| 2599 | − { PCI_DEVICE(0x8086, 0x2284), | |
| 2600 | − .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BRASWELL }, | |
| 2525 | + { PCI_DEVICE_DATA(INTEL, HDA_BSW, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BRASWELL) }, | |
| 2601 | 2526 | /* ICH6 */ |
| 2602 | − { PCI_DEVICE(0x8086, 0x2668), | |
| 2603 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2527 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH6, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2604 | 2528 | /* ICH7 */ |
| 2605 | − { PCI_DEVICE(0x8086, 0x27d8), | |
| 2606 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2529 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH7, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2607 | 2530 | /* ESB2 */ |
| 2608 | − { PCI_DEVICE(0x8086, 0x269a), | |
| 2609 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2531 | + { PCI_DEVICE_DATA(INTEL, HDA_ESB2, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2610 | 2532 | /* ICH8 */ |
| 2611 | − { PCI_DEVICE(0x8086, 0x284b), | |
| 2612 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2533 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH8, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2613 | 2534 | /* ICH9 */ |
| 2614 | − { PCI_DEVICE(0x8086, 0x293e), | |
| 2615 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2535 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH9_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2616 | 2536 | /* ICH9 */ |
| 2617 | − { PCI_DEVICE(0x8086, 0x293f), | |
| 2618 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2537 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH9_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2619 | 2538 | /* ICH10 */ |
| 2620 | − { PCI_DEVICE(0x8086, 0x3a3e), | |
| 2621 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2539 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH10_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2622 | 2540 | /* ICH10 */ |
| 2623 | − { PCI_DEVICE(0x8086, 0x3a6e), | |
| 2624 | − .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH }, | |
| 2541 | + { PCI_DEVICE_DATA(INTEL, HDA_ICH10_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) }, | |
| 2625 | 2542 | /* Generic Intel */ |
| 2626 | 2543 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), |
| 2627 | 2544 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
| 2628 | 2545 | .class_mask = 0xffffff, |
| 2629 | 2546 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_NO_ALIGN_BUFSIZE }, |
| 2630 | 2547 | /* ATI SB 450/600/700/800/900 */ |
| 2631 | − { PCI_DEVICE(0x1002, 0x437b), | |
| 2548 | + { PCI_VDEVICE(ATI, 0x437b), | |
| 2632 | 2549 | .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, |
| 2633 | − { PCI_DEVICE(0x1002, 0x4383), | |
| 2550 | + { PCI_VDEVICE(ATI, 0x4383), | |
| 2634 | 2551 | .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, |
| 2635 | 2552 | /* AMD Hudson */ |
| 2636 | − { PCI_DEVICE(0x1022, 0x780d), | |
| 2553 | + { PCI_VDEVICE(AMD, 0x780d), | |
| 2637 | 2554 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, |
| 2638 | 2555 | /* AMD, X370 & co */ |
| 2639 | − { PCI_DEVICE(0x1022, 0x1457), | |
| 2556 | + { PCI_VDEVICE(AMD, 0x1457), | |
| 2640 | 2557 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB }, |
| 2641 | 2558 | /* AMD, X570 & co */ |
| 2642 | − { PCI_DEVICE(0x1022, 0x1487), | |
| 2559 | + { PCI_VDEVICE(AMD, 0x1487), | |
| 2643 | 2560 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB }, |
| 2644 | 2561 | /* AMD Stoney */ |
| 2645 | − { PCI_DEVICE(0x1022, 0x157a), | |
| 2562 | + { PCI_VDEVICE(AMD, 0x157a), | |
| 2646 | 2563 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | |
| 2647 | 2564 | AZX_DCAPS_PM_RUNTIME }, |
| 2648 | 2565 | /* AMD Raven */ |
| 2649 | − { PCI_DEVICE(0x1022, 0x15e3), | |
| 2566 | + { PCI_VDEVICE(AMD, 0x15e3), | |
| 2650 | 2567 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB }, |
| 2651 | 2568 | /* ATI HDMI */ |
| 2652 | − { PCI_DEVICE(0x1002, 0x0002), | |
| 2569 | + { PCI_VDEVICE(ATI, 0x0002), | |
| 2653 | 2570 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2654 | 2571 | AZX_DCAPS_PM_RUNTIME }, |
| 2655 | − { PCI_DEVICE(0x1002, 0x1308), | |
| 2572 | + { PCI_VDEVICE(ATI, 0x1308), | |
| 2656 | 2573 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2657 | − { PCI_DEVICE(0x1002, 0x157a), | |
| 2574 | + { PCI_VDEVICE(ATI, 0x157a), | |
| 2658 | 2575 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2659 | − { PCI_DEVICE(0x1002, 0x15b3), | |
| 2576 | + { PCI_VDEVICE(ATI, 0x15b3), | |
| 2660 | 2577 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2661 | − { PCI_DEVICE(0x1002, 0x793b), | |
| 2578 | + { PCI_VDEVICE(ATI, 0x793b), | |
| 2662 | 2579 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2663 | − { PCI_DEVICE(0x1002, 0x7919), | |
| 2580 | + { PCI_VDEVICE(ATI, 0x7919), | |
| 2664 | 2581 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2665 | − { PCI_DEVICE(0x1002, 0x960f), | |
| 2582 | + { PCI_VDEVICE(ATI, 0x960f), | |
| 2666 | 2583 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2667 | − { PCI_DEVICE(0x1002, 0x970f), | |
| 2584 | + { PCI_VDEVICE(ATI, 0x970f), | |
| 2668 | 2585 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2669 | − { PCI_DEVICE(0x1002, 0x9840), | |
| 2586 | + { PCI_VDEVICE(ATI, 0x9840), | |
| 2670 | 2587 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2671 | − { PCI_DEVICE(0x1002, 0xaa00), | |
| 2588 | + { PCI_VDEVICE(ATI, 0xaa00), | |
| 2672 | 2589 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2673 | − { PCI_DEVICE(0x1002, 0xaa08), | |
| 2590 | + { PCI_VDEVICE(ATI, 0xaa08), | |
| 2674 | 2591 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2675 | − { PCI_DEVICE(0x1002, 0xaa10), | |
| 2592 | + { PCI_VDEVICE(ATI, 0xaa10), | |
| 2676 | 2593 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2677 | − { PCI_DEVICE(0x1002, 0xaa18), | |
| 2594 | + { PCI_VDEVICE(ATI, 0xaa18), | |
| 2678 | 2595 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2679 | − { PCI_DEVICE(0x1002, 0xaa20), | |
| 2596 | + { PCI_VDEVICE(ATI, 0xaa20), | |
| 2680 | 2597 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2681 | − { PCI_DEVICE(0x1002, 0xaa28), | |
| 2598 | + { PCI_VDEVICE(ATI, 0xaa28), | |
| 2682 | 2599 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2683 | − { PCI_DEVICE(0x1002, 0xaa30), | |
| 2600 | + { PCI_VDEVICE(ATI, 0xaa30), | |
| 2684 | 2601 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2685 | − { PCI_DEVICE(0x1002, 0xaa38), | |
| 2602 | + { PCI_VDEVICE(ATI, 0xaa38), | |
| 2686 | 2603 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2687 | − { PCI_DEVICE(0x1002, 0xaa40), | |
| 2604 | + { PCI_VDEVICE(ATI, 0xaa40), | |
| 2688 | 2605 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2689 | − { PCI_DEVICE(0x1002, 0xaa48), | |
| 2606 | + { PCI_VDEVICE(ATI, 0xaa48), | |
| 2690 | 2607 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2691 | − { PCI_DEVICE(0x1002, 0xaa50), | |
| 2608 | + { PCI_VDEVICE(ATI, 0xaa50), | |
| 2692 | 2609 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2693 | − { PCI_DEVICE(0x1002, 0xaa58), | |
| 2610 | + { PCI_VDEVICE(ATI, 0xaa58), | |
| 2694 | 2611 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2695 | − { PCI_DEVICE(0x1002, 0xaa60), | |
| 2612 | + { PCI_VDEVICE(ATI, 0xaa60), | |
| 2696 | 2613 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2697 | − { PCI_DEVICE(0x1002, 0xaa68), | |
| 2614 | + { PCI_VDEVICE(ATI, 0xaa68), | |
| 2698 | 2615 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2699 | − { PCI_DEVICE(0x1002, 0xaa80), | |
| 2616 | + { PCI_VDEVICE(ATI, 0xaa80), | |
| 2700 | 2617 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2701 | − { PCI_DEVICE(0x1002, 0xaa88), | |
| 2618 | + { PCI_VDEVICE(ATI, 0xaa88), | |
| 2702 | 2619 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2703 | − { PCI_DEVICE(0x1002, 0xaa90), | |
| 2620 | + { PCI_VDEVICE(ATI, 0xaa90), | |
| 2704 | 2621 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2705 | − { PCI_DEVICE(0x1002, 0xaa98), | |
| 2622 | + { PCI_VDEVICE(ATI, 0xaa98), | |
| 2706 | 2623 | .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2707 | − { PCI_DEVICE(0x1002, 0x9902), | |
| 2624 | + { PCI_VDEVICE(ATI, 0x9902), | |
| 2708 | 2625 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2709 | − { PCI_DEVICE(0x1002, 0xaaa0), | |
| 2626 | + { PCI_VDEVICE(ATI, 0xaaa0), | |
| 2710 | 2627 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2711 | − { PCI_DEVICE(0x1002, 0xaaa8), | |
| 2628 | + { PCI_VDEVICE(ATI, 0xaaa8), | |
| 2712 | 2629 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2713 | − { PCI_DEVICE(0x1002, 0xaab0), | |
| 2630 | + { PCI_VDEVICE(ATI, 0xaab0), | |
| 2714 | 2631 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2715 | − { PCI_DEVICE(0x1002, 0xaac0), | |
| 2632 | + { PCI_VDEVICE(ATI, 0xaac0), | |
| 2716 | 2633 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2717 | 2634 | AZX_DCAPS_PM_RUNTIME }, |
| 2718 | − { PCI_DEVICE(0x1002, 0xaac8), | |
| 2635 | + { PCI_VDEVICE(ATI, 0xaac8), | |
| 2719 | 2636 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2720 | 2637 | AZX_DCAPS_PM_RUNTIME }, |
| 2721 | − { PCI_DEVICE(0x1002, 0xaad8), | |
| 2638 | + { PCI_VDEVICE(ATI, 0xaad8), | |
| 2722 | 2639 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2723 | 2640 | AZX_DCAPS_PM_RUNTIME }, |
| 2724 | − { PCI_DEVICE(0x1002, 0xaae0), | |
| 2641 | + { PCI_VDEVICE(ATI, 0xaae0), | |
| 2725 | 2642 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2726 | 2643 | AZX_DCAPS_PM_RUNTIME }, |
| 2727 | − { PCI_DEVICE(0x1002, 0xaae8), | |
| 2644 | + { PCI_VDEVICE(ATI, 0xaae8), | |
| 2728 | 2645 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2729 | 2646 | AZX_DCAPS_PM_RUNTIME }, |
| 2730 | − { PCI_DEVICE(0x1002, 0xaaf0), | |
| 2647 | + { PCI_VDEVICE(ATI, 0xaaf0), | |
| 2731 | 2648 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2732 | 2649 | AZX_DCAPS_PM_RUNTIME }, |
| 2733 | − { PCI_DEVICE(0x1002, 0xaaf8), | |
| 2650 | + { PCI_VDEVICE(ATI, 0xaaf8), | |
| 2734 | 2651 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2735 | 2652 | AZX_DCAPS_PM_RUNTIME }, |
| 2736 | − { PCI_DEVICE(0x1002, 0xab00), | |
| 2653 | + { PCI_VDEVICE(ATI, 0xab00), | |
| 2737 | 2654 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2738 | 2655 | AZX_DCAPS_PM_RUNTIME }, |
| 2739 | − { PCI_DEVICE(0x1002, 0xab08), | |
| 2656 | + { PCI_VDEVICE(ATI, 0xab08), | |
| 2740 | 2657 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2741 | 2658 | AZX_DCAPS_PM_RUNTIME }, |
| 2742 | − { PCI_DEVICE(0x1002, 0xab10), | |
| 2659 | + { PCI_VDEVICE(ATI, 0xab10), | |
| 2743 | 2660 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2744 | 2661 | AZX_DCAPS_PM_RUNTIME }, |
| 2745 | − { PCI_DEVICE(0x1002, 0xab18), | |
| 2662 | + { PCI_VDEVICE(ATI, 0xab18), | |
| 2746 | 2663 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2747 | 2664 | AZX_DCAPS_PM_RUNTIME }, |
| 2748 | − { PCI_DEVICE(0x1002, 0xab20), | |
| 2665 | + { PCI_VDEVICE(ATI, 0xab20), | |
| 2749 | 2666 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2750 | 2667 | AZX_DCAPS_PM_RUNTIME }, |
| 2751 | − { PCI_DEVICE(0x1002, 0xab28), | |
| 2668 | + { PCI_VDEVICE(ATI, 0xab28), | |
| 2752 | 2669 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2753 | 2670 | AZX_DCAPS_PM_RUNTIME }, |
| 2754 | − { PCI_DEVICE(0x1002, 0xab30), | |
| 2671 | + { PCI_VDEVICE(ATI, 0xab30), | |
| 2755 | 2672 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2756 | 2673 | AZX_DCAPS_PM_RUNTIME }, |
| 2757 | − { PCI_DEVICE(0x1002, 0xab38), | |
| 2674 | + { PCI_VDEVICE(ATI, 0xab38), | |
| 2758 | 2675 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | |
| 2759 | 2676 | AZX_DCAPS_PM_RUNTIME }, |
| 2760 | 2677 | /* GLENFLY */ |
| @@ -2764,15 +2681,15 @@ static const struct pci_device_id azx_ids[] = { · 3 unmodified lines | ||
| 2764 | 2681 | .driver_data = AZX_DRIVER_GFHDMI | AZX_DCAPS_POSFIX_LPIB | |
| 2765 | 2682 | AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT }, |
| 2766 | 2683 | /* VIA VT8251/VT8237A */ |
| 2767 | − { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, | |
| 2684 | + { PCI_VDEVICE(VIA, 0x3288), .driver_data = AZX_DRIVER_VIA }, | |
| 2768 | 2685 | /* VIA GFX VT7122/VX900 */ |
| 2769 | − { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2686 | + { PCI_VDEVICE(VIA, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2770 | 2687 | /* VIA GFX VT6122/VX11 */ |
| 2771 | − { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2688 | + { PCI_VDEVICE(VIA, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2772 | 2689 | /* SIS966 */ |
| 2773 | − { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, | |
| 2690 | + { PCI_VDEVICE(SI, 0x7502), .driver_data = AZX_DRIVER_SIS }, | |
| 2774 | 2691 | /* ULI M5461 */ |
| 2775 | − { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, | |
| 2692 | + { PCI_VDEVICE(AL, 0x5461), .driver_data = AZX_DRIVER_ULI }, | |
| 2776 | 2693 | /* NVIDIA MCP */ |
| 2777 | 2694 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), |
| 2778 | 2695 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
| @@ -2785,9 +2702,9 @@ static const struct pci_device_id azx_ids[] = { · 6 unmodified lines | ||
| 2785 | 2702 | .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, |
| 2786 | 2703 | /* Creative X-Fi (CA0110-IBG) */ |
| 2787 | 2704 | /* CTHDA chips */ |
| 2788 | − { PCI_DEVICE(0x1102, 0x0010), | |
| 2705 | + { PCI_VDEVICE(CREATIVE, 0x0010), | |
| 2789 | 2706 | .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, |
| 2790 | − { PCI_DEVICE(0x1102, 0x0012), | |
| 2707 | + { PCI_VDEVICE(CREATIVE, 0x0012), | |
| 2791 | 2708 | .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, |
| 2792 | 2709 | #if !IS_ENABLED(CONFIG_SND_CTXFI) |
| 2793 | 2710 | /* the following entry conflicts with snd-ctxfi driver, |
| @@ -2801,18 +2718,18 @@ static const struct pci_device_id azx_ids[] = { · 7 unmodified lines | ||
| 2801 | 2718 | AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB }, |
| 2802 | 2719 | #else |
| 2803 | 2720 | /* this entry seems still valid -- i.e. without emu20kx chip */ |
| 2804 | − { PCI_DEVICE(0x1102, 0x0009), | |
| 2721 | + { PCI_VDEVICE(CREATIVE, 0x0009), | |
| 2805 | 2722 | .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | |
| 2806 | 2723 | AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB }, |
| 2807 | 2724 | #endif |
| 2808 | 2725 | /* CM8888 */ |
| 2809 | − { PCI_DEVICE(0x13f6, 0x5011), | |
| 2726 | + { PCI_VDEVICE(CMEDIA, 0x5011), | |
| 2810 | 2727 | .driver_data = AZX_DRIVER_CMEDIA | |
| 2811 | 2728 | AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_SNOOP_OFF }, |
| 2812 | 2729 | /* Vortex86MX */ |
| 2813 | − { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2730 | + { PCI_VDEVICE(RDC, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2814 | 2731 | /* VMware HDAudio */ |
| 2815 | − { PCI_DEVICE(0x15ad, 0x1977), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2732 | + { PCI_VDEVICE(VMWARE, 0x1977), .driver_data = AZX_DRIVER_GENERIC }, | |
| 2816 | 2733 | /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ |
| 2817 | 2734 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), |
| 2818 | 2735 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
| @@ -2823,11 +2740,11 @@ static const struct pci_device_id azx_ids[] = { · 4 unmodified lines | ||
| 2823 | 2740 | .class_mask = 0xffffff, |
| 2824 | 2741 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, |
| 2825 | 2742 | /* Zhaoxin */ |
| 2826 | − { PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, | |
| 2743 | + { PCI_VDEVICE(ZHAOXIN, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, | |
| 2827 | 2744 | /* Loongson HDAudio*/ |
| 2828 | − {PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_HDA), | |
| 2745 | + { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDA), | |
| 2829 | 2746 | .driver_data = AZX_DRIVER_LOONGSON }, |
| 2830 | − {PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_HDMI), | |
| 2747 | + { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDMI), | |
| 2831 | 2748 | .driver_data = AZX_DRIVER_LOONGSON }, |
| 2832 | 2749 | { 0, } |
| 2833 | 2750 | }; |
| @@ -16,7 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/module.h> |
| 17 | 17 | #include <linux/moduleparam.h> |
| 18 | 18 | #include <linux/mutex.h> |
| 19 | −#include <linux/of_device.h> | |
| 19 | +#include <linux/of.h> | |
| 20 | +#include <linux/platform_device.h> | |
| 20 | 21 | #include <linux/reset.h> |
| 21 | 22 | #include <linux/slab.h> |
| 22 | 23 | #include <linux/time.h> |
| @@ -378,14 +379,14 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) · 355 unmodified lines | ||
| 378 | 379 | } |
| 379 | 380 | |
| 380 | 381 | /* driver name */ |
| 381 | − strncpy(card->driver, drv_name, sizeof(card->driver)); | |
| 382 | + strscpy(card->driver, drv_name, sizeof(card->driver)); | |
| 382 | 383 | /* shortname for card */ |
| 383 | 384 | sname = of_get_property(np, "nvidia,model", NULL); |
| 384 | 385 | if (!sname) |
| 385 | 386 | sname = drv_name; |
| 386 | 387 | if (strlen(sname) > sizeof(card->shortname)) |
| 387 | 388 | dev_info(card->dev, "truncating shortname for card\n"); |
| 388 | − strncpy(card->shortname, sname, sizeof(card->shortname)); | |
| 389 | + strscpy(card->shortname, sname, sizeof(card->shortname)); | |
| 389 | 390 | |
| 390 | 391 | /* longname for card */ |
| 391 | 392 | snprintf(card->longname, sizeof(card->longname), |
| @@ -4632,8 +4632,9 @@ HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi), · 4631 unmodified lines | ||
| 4632 | 4632 | HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), |
| 4633 | 4633 | HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), |
| 4634 | 4634 | HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_adlp_hdmi), |
| 4635 | −HDA_CODEC_ENTRY(0x8086281f, "Raptorlake-P HDMI", patch_i915_adlp_hdmi), | |
| 4636 | −HDA_CODEC_ENTRY(0x8086281d, "Meteorlake HDMI", patch_i915_adlp_hdmi), | |
| 4635 | +HDA_CODEC_ENTRY(0x8086281d, "Meteor Lake HDMI", patch_i915_adlp_hdmi), | |
| 4636 | +HDA_CODEC_ENTRY(0x8086281f, "Raptor Lake P HDMI", patch_i915_adlp_hdmi), | |
| 4637 | +HDA_CODEC_ENTRY(0x80862820, "Lunar Lake HDMI", patch_i915_adlp_hdmi), | |
| 4637 | 4638 | HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), |
| 4638 | 4639 | HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), |
| 4639 | 4640 | HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), |
| @@ -4639,6 +4639,22 @@ static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec, · 4638 unmodified lines | ||
| 4639 | 4639 | } |
| 4640 | 4640 | } |
| 4641 | 4641 | |
| 4642 | +static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec, | |
| 4643 | + const struct hda_fixup *fix, | |
| 4644 | + int action) | |
| 4645 | +{ | |
| 4646 | + struct alc_spec *spec = codec->spec; | |
| 4647 | + | |
| 4648 | + if (action == HDA_FIXUP_ACT_PRE_PROBE) { | |
| 4649 | + spec->mute_led_polarity = 0; | |
| 4650 | + spec->mute_led_coef.idx = 0x0b; | |
| 4651 | + spec->mute_led_coef.mask = 3 << 2; | |
| 4652 | + spec->mute_led_coef.on = 2 << 2; | |
| 4653 | + spec->mute_led_coef.off = 1 << 2; | |
| 4654 | + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); | |
| 4655 | + } | |
| 4656 | +} | |
| 4657 | + | |
| 4642 | 4658 | /* turn on/off mic-mute LED per capture hook by coef bit */ |
| 4643 | 4659 | static int coef_micmute_led_set(struct led_classdev *led_cdev, |
| 4644 | 4660 | enum led_brightness brightness) |
| @@ -6716,12 +6732,20 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_ · 2071 unmodified lines | ||
| 6716 | 6732 | int i; |
| 6717 | 6733 | |
| 6718 | 6734 | for (i = 0; i < HDA_MAX_COMPONENTS; i++) { |
| 6719 | − if (spec->comps[i].dev) | |
| 6735 | + if (spec->comps[i].dev && spec->comps[i].pre_playback_hook) | |
| 6736 | + spec->comps[i].pre_playback_hook(spec->comps[i].dev, action); | |
| 6737 | + } | |
| 6738 | + for (i = 0; i < HDA_MAX_COMPONENTS; i++) { | |
| 6739 | + if (spec->comps[i].dev && spec->comps[i].playback_hook) | |
| 6720 | 6740 | spec->comps[i].playback_hook(spec->comps[i].dev, action); |
| 6721 | 6741 | } |
| 6742 | + for (i = 0; i < HDA_MAX_COMPONENTS; i++) { | |
| 6743 | + if (spec->comps[i].dev && spec->comps[i].post_playback_hook) | |
| 6744 | + spec->comps[i].post_playback_hook(spec->comps[i].dev, action); | |
| 6745 | + } | |
| 6722 | 6746 | } |
| 6723 | 6747 | |
| 6724 | −struct cs35l41_dev_name { | |
| 6748 | +struct scodec_dev_name { | |
| 6725 | 6749 | const char *bus; |
| 6726 | 6750 | const char *hid; |
| 6727 | 6751 | int index; |
| @@ -6730,7 +6754,7 @@ struct cs35l41_dev_name { · 2 unmodified lines | ||
| 6730 | 6754 | /* match the device name in a slightly relaxed manner */ |
| 6731 | 6755 | static int comp_match_cs35l41_dev_name(struct device *dev, void *data) |
| 6732 | 6756 | { |
| 6733 | − struct cs35l41_dev_name *p = data; | |
| 6757 | + struct scodec_dev_name *p = data; | |
| 6734 | 6758 | const char *d = dev_name(dev); |
| 6735 | 6759 | int n = strlen(p->bus); |
| 6736 | 6760 | char tmp[32]; |
| @@ -6746,12 +6770,32 @@ static int comp_match_cs35l41_dev_name(struct device *dev, void *data) · 9 unmodified lines | ||
| 6746 | 6770 | return !strcmp(d + n, tmp); |
| 6747 | 6771 | } |
| 6748 | 6772 | |
| 6773 | +static int comp_match_tas2781_dev_name(struct device *dev, | |
| 6774 | + void *data) | |
| 6775 | +{ | |
| 6776 | + struct scodec_dev_name *p = data; | |
| 6777 | + const char *d = dev_name(dev); | |
| 6778 | + int n = strlen(p->bus); | |
| 6779 | + char tmp[32]; | |
| 6780 | + | |
| 6781 | + /* check the bus name */ | |
| 6782 | + if (strncmp(d, p->bus, n)) | |
| 6783 | + return 0; | |
| 6784 | + /* skip the bus number */ | |
| 6785 | + if (isdigit(d[n])) | |
| 6786 | + n++; | |
| 6787 | + /* the rest must be exact matching */ | |
| 6788 | + snprintf(tmp, sizeof(tmp), "-%s:00", p->hid); | |
| 6789 | + | |
| 6790 | + return !strcmp(d + n, tmp); | |
| 6791 | +} | |
| 6792 | + | |
| 6749 | 6793 | static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus, |
| 6750 | 6794 | const char *hid, int count) |
| 6751 | 6795 | { |
| 6752 | 6796 | struct device *dev = hda_codec_dev(cdc); |
| 6753 | 6797 | struct alc_spec *spec = cdc->spec; |
| 6754 | − struct cs35l41_dev_name *rec; | |
| 6798 | + struct scodec_dev_name *rec; | |
| 6755 | 6799 | int ret, i; |
| 6756 | 6800 | |
| 6757 | 6801 | switch (action) { |
| @@ -6779,6 +6823,41 @@ static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char · 21 unmodified lines | ||
| 6779 | 6823 | } |
| 6780 | 6824 | } |
| 6781 | 6825 | |
| 6826 | +static void tas2781_generic_fixup(struct hda_codec *cdc, int action, | |
| 6827 | + const char *bus, const char *hid) | |
| 6828 | +{ | |
| 6829 | + struct device *dev = hda_codec_dev(cdc); | |
| 6830 | + struct alc_spec *spec = cdc->spec; | |
| 6831 | + struct scodec_dev_name *rec; | |
| 6832 | + int ret; | |
| 6833 | + | |
| 6834 | + switch (action) { | |
| 6835 | + case HDA_FIXUP_ACT_PRE_PROBE: | |
| 6836 | + rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL); | |
| 6837 | + if (!rec) | |
| 6838 | + return; | |
| 6839 | + rec->bus = bus; | |
| 6840 | + rec->hid = hid; | |
| 6841 | + rec->index = 0; | |
| 6842 | + spec->comps[0].codec = cdc; | |
| 6843 | + component_match_add(dev, &spec->match, | |
| 6844 | + comp_match_tas2781_dev_name, rec); | |
| 6845 | + ret = component_master_add_with_match(dev, &comp_master_ops, | |
| 6846 | + spec->match); | |
| 6847 | + if (ret) | |
| 6848 | + codec_err(cdc, | |
| 6849 | + "Fail to register component aggregator %d\n", | |
| 6850 | + ret); | |
| 6851 | + else | |
| 6852 | + spec->gen.pcm_playback_hook = | |
| 6853 | + comp_generic_playback_hook; | |
| 6854 | + break; | |
| 6855 | + case HDA_FIXUP_ACT_FREE: | |
| 6856 | + component_master_del(dev, &comp_master_ops); | |
| 6857 | + break; | |
| 6858 | + } | |
| 6859 | +} | |
| 6860 | + | |
| 6782 | 6861 | static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action) |
| 6783 | 6862 | { |
| 6784 | 6863 | cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2); |
| @@ -6806,6 +6885,12 @@ static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const st · 21 unmodified lines | ||
| 6806 | 6885 | cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0101", 2); |
| 6807 | 6886 | } |
| 6808 | 6887 | |
| 6888 | +static void tas2781_fixup_i2c(struct hda_codec *cdc, | |
| 6889 | + const struct hda_fixup *fix, int action) | |
| 6890 | +{ | |
| 6891 | + tas2781_generic_fixup(cdc, action, "i2c", "TIAS2781"); | |
| 6892 | +} | |
| 6893 | + | |
| 6809 | 6894 | /* for alc295_fixup_hp_top_speakers */ |
| 6810 | 6895 | #include "hp_x360_helper.c" |
| 6811 | 6896 | |
| @@ -7231,6 +7316,9 @@ enum { · 419 unmodified lines | ||
| 7231 | 7316 | ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS, |
| 7232 | 7317 | ALC236_FIXUP_DELL_DUAL_CODECS, |
| 7233 | 7318 | ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI, |
| 7319 | + ALC287_FIXUP_TAS2781_I2C, | |
| 7320 | + ALC245_FIXUP_HP_MUTE_LED_COEFBIT, | |
| 7321 | + ALC245_FIXUP_HP_X360_MUTE_LEDS, | |
| 7234 | 7322 | }; |
| 7235 | 7323 | |
| 7236 | 7324 | /* A special fixup for Lenovo C940 and Yoga Duet 7; |
| @@ -9309,6 +9397,22 @@ static const struct hda_fixup alc269_fixups[] = { · 2072 unmodified lines | ||
| 9309 | 9397 | .chained = true, |
| 9310 | 9398 | .chain_id = ALC269_FIXUP_THINKPAD_ACPI, |
| 9311 | 9399 | }, |
| 9400 | + [ALC287_FIXUP_TAS2781_I2C] = { | |
| 9401 | + .type = HDA_FIXUP_FUNC, | |
| 9402 | + .v.func = tas2781_fixup_i2c, | |
| 9403 | + .chained = true, | |
| 9404 | + .chain_id = ALC269_FIXUP_THINKPAD_ACPI, | |
| 9405 | + }, | |
| 9406 | + [ALC245_FIXUP_HP_MUTE_LED_COEFBIT] = { | |
| 9407 | + .type = HDA_FIXUP_FUNC, | |
| 9408 | + .v.func = alc245_fixup_hp_mute_led_coefbit, | |
| 9409 | + }, | |
| 9410 | + [ALC245_FIXUP_HP_X360_MUTE_LEDS] = { | |
| 9411 | + .type = HDA_FIXUP_FUNC, | |
| 9412 | + .v.func = alc245_fixup_hp_mute_led_coefbit, | |
| 9413 | + .chained = true, | |
| 9414 | + .chain_id = ALC245_FIXUP_HP_GPIO_LED | |
| 9415 | + }, | |
| 9312 | 9416 | }; |
| 9313 | 9417 | |
| 9314 | 9418 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| @@ -9551,6 +9655,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 236 unmodified lines | ||
| 9551 | 9655 | SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), |
| 9552 | 9656 | SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), |
| 9553 | 9657 | SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), |
| 9658 | + SND_PCI_QUIRK(0x103c, 0x888a, "HP ENVY x360 Convertible 15-eu0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS), | |
| 9554 | 9659 | SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED), |
| 9555 | 9660 | SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED), |
| 9556 | 9661 | SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), |
| @@ -9582,6 +9687,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 25 unmodified lines | ||
| 9582 | 9687 | SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9583 | 9688 | SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9584 | 9689 | SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9690 | + SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), | |
| 9585 | 9691 | SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), |
| 9586 | 9692 | SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED), |
| 9587 | 9693 | SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), |
| @@ -9889,6 +9995,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 301 unmodified lines | ||
| 9889 | 9995 | SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), |
| 9890 | 9996 | SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), |
| 9891 | 9997 | SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), |
| 9998 | + SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C), | |
| 9999 | + SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C), | |
| 10000 | + SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C), | |
| 10001 | + SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C), | |
| 10002 | + SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C), | |
| 10003 | + SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C), | |
| 10004 | + SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C), | |
| 10005 | + SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C), | |
| 10006 | + SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C), | |
| 10007 | + SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C), | |
| 10008 | + SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C), | |
| 10009 | + SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C), | |
| 10010 | + SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C), | |
| 10011 | + SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C), | |
| 9892 | 10012 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| 9893 | 10013 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), |
| 9894 | 10014 | SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| @@ -0,0 +1,856 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +// | |
| 3 | +// TAS2781 HDA I2C driver | |
| 4 | +// | |
| 5 | +// Copyright 2023 Texas Instruments, Inc. | |
| 6 | +// | |
| 7 | +// Author: Shenghao Ding <shenghao-ding@ti.com> | |
| 8 | + | |
| 9 | +#include <linux/acpi.h> | |
| 10 | +#include <linux/crc8.h> | |
| 11 | +#include <linux/crc32.h> | |
| 12 | +#include <linux/efi.h> | |
| 13 | +#include <linux/firmware.h> | |
| 14 | +#include <linux/i2c.h> | |
| 15 | +#include <linux/mod_devicetable.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/pm_runtime.h> | |
| 18 | +#include <linux/regmap.h> | |
| 19 | +#include <sound/hda_codec.h> | |
| 20 | +#include <sound/soc.h> | |
| 21 | +#include <sound/tas2781.h> | |
| 22 | +#include <sound/tlv.h> | |
| 23 | +#include <sound/tas2781-tlv.h> | |
| 24 | + | |
| 25 | +#include "hda_local.h" | |
| 26 | +#include "hda_auto_parser.h" | |
| 27 | +#include "hda_component.h" | |
| 28 | +#include "hda_jack.h" | |
| 29 | +#include "hda_generic.h" | |
| 30 | + | |
| 31 | +#define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20 | |
| 32 | + | |
| 33 | +/* No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD | |
| 34 | + * Define two controls, one is Volume control callbacks, the other is | |
| 35 | + * flag setting control callbacks. | |
| 36 | + */ | |
| 37 | + | |
| 38 | +/* Volume control callbacks for tas2781 */ | |
| 39 | +#define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ | |
| 40 | + xhandler_get, xhandler_put, tlv_array) \ | |
| 41 | +{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname),\ | |
| 42 | + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | |
| 43 | + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | |
| 44 | + .tlv.p = (tlv_array), \ | |
| 45 | + .info = snd_soc_info_volsw_range, \ | |
| 46 | + .get = xhandler_get, .put = xhandler_put, \ | |
| 47 | + .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
| 48 | + {.reg = xreg, .rreg = xreg, .shift = xshift, \ | |
| 49 | + .rshift = xshift, .min = xmin, .max = xmax, \ | |
| 50 | + .invert = xinvert} } | |
| 51 | + | |
| 52 | +/* Flag control callbacks for tas2781 */ | |
| 53 | +#define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ | |
| 54 | +{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, \ | |
| 55 | + .info = snd_ctl_boolean_mono_info, \ | |
| 56 | + .get = xhandler_get, .put = xhandler_put, \ | |
| 57 | + .private_value = xdata } | |
| 58 | + | |
| 59 | +enum calib_data { | |
| 60 | + R0_VAL = 0, | |
| 61 | + INV_R0, | |
| 62 | + R0LOW, | |
| 63 | + POWER, | |
| 64 | + TLIM, | |
| 65 | + CALIB_MAX | |
| 66 | +}; | |
| 67 | + | |
| 68 | +static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) | |
| 69 | +{ | |
| 70 | + struct tasdevice_priv *tas_priv = data; | |
| 71 | + struct acpi_resource_i2c_serialbus *sb; | |
| 72 | + | |
| 73 | + if (i2c_acpi_get_i2c_resource(ares, &sb)) { | |
| 74 | + if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS && | |
| 75 | + sb->slave_address != TAS2781_GLOBAL_ADDR) { | |
| 76 | + tas_priv->tasdevice[tas_priv->ndev].dev_addr = | |
| 77 | + (unsigned int)sb->slave_address; | |
| 78 | + tas_priv->ndev++; | |
| 79 | + } | |
| 80 | + } | |
| 81 | + return 1; | |
| 82 | +} | |
| 83 | + | |
| 84 | +static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) | |
| 85 | +{ | |
| 86 | + struct acpi_device *adev; | |
| 87 | + struct device *physdev; | |
| 88 | + LIST_HEAD(resources); | |
| 89 | + const char *sub; | |
| 90 | + int ret; | |
| 91 | + | |
| 92 | + adev = acpi_dev_get_first_match_dev(hid, NULL, -1); | |
| 93 | + if (!adev) { | |
| 94 | + dev_err(p->dev, | |
| 95 | + "Failed to find an ACPI device for %s\n", hid); | |
| 96 | + return -ENODEV; | |
| 97 | + } | |
| 98 | + | |
| 99 | + ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p); | |
| 100 | + if (ret < 0) | |
| 101 | + goto err; | |
| 102 | + | |
| 103 | + acpi_dev_free_resource_list(&resources); | |
| 104 | + strscpy(p->dev_name, hid, sizeof(p->dev_name)); | |
| 105 | + physdev = get_device(acpi_get_first_physical_node(adev)); | |
| 106 | + acpi_dev_put(adev); | |
| 107 | + | |
| 108 | + /* No side-effect to the playback even if subsystem_id is NULL*/ | |
| 109 | + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); | |
| 110 | + if (IS_ERR(sub)) | |
| 111 | + sub = NULL; | |
| 112 | + | |
| 113 | + p->acpi_subsystem_id = sub; | |
| 114 | + | |
| 115 | + put_device(physdev); | |
| 116 | + | |
| 117 | + return 0; | |
| 118 | + | |
| 119 | +err: | |
| 120 | + dev_err(p->dev, "read acpi error, ret: %d\n", ret); | |
| 121 | + acpi_dev_put(adev); | |
| 122 | + | |
| 123 | + return ret; | |
| 124 | +} | |
| 125 | + | |
| 126 | +static void tas2781_hda_playback_hook(struct device *dev, int action) | |
| 127 | +{ | |
| 128 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 129 | + | |
| 130 | + dev_dbg(tas_priv->dev, "%s: action = %d\n", __func__, action); | |
| 131 | + switch (action) { | |
| 132 | + case HDA_GEN_PCM_ACT_OPEN: | |
| 133 | + pm_runtime_get_sync(dev); | |
| 134 | + mutex_lock(&tas_priv->codec_lock); | |
| 135 | + tasdevice_tuning_switch(tas_priv, 0); | |
| 136 | + mutex_unlock(&tas_priv->codec_lock); | |
| 137 | + break; | |
| 138 | + case HDA_GEN_PCM_ACT_CLOSE: | |
| 139 | + mutex_lock(&tas_priv->codec_lock); | |
| 140 | + tasdevice_tuning_switch(tas_priv, 1); | |
| 141 | + mutex_unlock(&tas_priv->codec_lock); | |
| 142 | + | |
| 143 | + pm_runtime_mark_last_busy(dev); | |
| 144 | + pm_runtime_put_autosuspend(dev); | |
| 145 | + break; | |
| 146 | + default: | |
| 147 | + dev_dbg(tas_priv->dev, "Playback action not supported: %d\n", | |
| 148 | + action); | |
| 149 | + break; | |
| 150 | + } | |
| 151 | +} | |
| 152 | + | |
| 153 | +static int tasdevice_info_profile(struct snd_kcontrol *kcontrol, | |
| 154 | + struct snd_ctl_elem_info *uinfo) | |
| 155 | +{ | |
| 156 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 157 | + | |
| 158 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 159 | + uinfo->count = 1; | |
| 160 | + uinfo->value.integer.min = 0; | |
| 161 | + uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1; | |
| 162 | + | |
| 163 | + return 0; | |
| 164 | +} | |
| 165 | + | |
| 166 | +static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol, | |
| 167 | + struct snd_ctl_elem_value *ucontrol) | |
| 168 | +{ | |
| 169 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 170 | + | |
| 171 | + ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id; | |
| 172 | + | |
| 173 | + return 0; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static int tasdevice_hda_clamp(int val, int max) | |
| 177 | +{ | |
| 178 | + if (val > max) | |
| 179 | + val = max; | |
| 180 | + | |
| 181 | + if (val < 0) | |
| 182 | + val = 0; | |
| 183 | + return val; | |
| 184 | +} | |
| 185 | + | |
| 186 | +static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol, | |
| 187 | + struct snd_ctl_elem_value *ucontrol) | |
| 188 | +{ | |
| 189 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 190 | + int nr_profile = ucontrol->value.integer.value[0]; | |
| 191 | + int max = tas_priv->rcabin.ncfgs - 1; | |
| 192 | + int val, ret = 0; | |
| 193 | + | |
| 194 | + val = tasdevice_hda_clamp(nr_profile, max); | |
| 195 | + | |
| 196 | + if (tas_priv->rcabin.profile_cfg_id != val) { | |
| 197 | + tas_priv->rcabin.profile_cfg_id = val; | |
| 198 | + ret = 1; | |
| 199 | + } | |
| 200 | + | |
| 201 | + return ret; | |
| 202 | +} | |
| 203 | + | |
| 204 | +static int tasdevice_info_programs(struct snd_kcontrol *kcontrol, | |
| 205 | + struct snd_ctl_elem_info *uinfo) | |
| 206 | +{ | |
| 207 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 208 | + struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
| 209 | + | |
| 210 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 211 | + uinfo->count = 1; | |
| 212 | + uinfo->value.integer.min = 0; | |
| 213 | + uinfo->value.integer.max = tas_fw->nr_programs - 1; | |
| 214 | + | |
| 215 | + return 0; | |
| 216 | +} | |
| 217 | + | |
| 218 | +static int tasdevice_info_config(struct snd_kcontrol *kcontrol, | |
| 219 | + struct snd_ctl_elem_info *uinfo) | |
| 220 | +{ | |
| 221 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 222 | + struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
| 223 | + | |
| 224 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 225 | + uinfo->count = 1; | |
| 226 | + uinfo->value.integer.min = 0; | |
| 227 | + uinfo->value.integer.max = tas_fw->nr_configurations - 1; | |
| 228 | + | |
| 229 | + return 0; | |
| 230 | +} | |
| 231 | + | |
| 232 | +static int tasdevice_program_get(struct snd_kcontrol *kcontrol, | |
| 233 | + struct snd_ctl_elem_value *ucontrol) | |
| 234 | +{ | |
| 235 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 236 | + | |
| 237 | + ucontrol->value.integer.value[0] = tas_priv->cur_prog; | |
| 238 | + | |
| 239 | + return 0; | |
| 240 | +} | |
| 241 | + | |
| 242 | +static int tasdevice_program_put(struct snd_kcontrol *kcontrol, | |
| 243 | + struct snd_ctl_elem_value *ucontrol) | |
| 244 | +{ | |
| 245 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 246 | + struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
| 247 | + int nr_program = ucontrol->value.integer.value[0]; | |
| 248 | + int max = tas_fw->nr_programs - 1; | |
| 249 | + int val, ret = 0; | |
| 250 | + | |
| 251 | + val = tasdevice_hda_clamp(nr_program, max); | |
| 252 | + | |
| 253 | + if (tas_priv->cur_prog != val) { | |
| 254 | + tas_priv->cur_prog = val; | |
| 255 | + ret = 1; | |
| 256 | + } | |
| 257 | + | |
| 258 | + return ret; | |
| 259 | +} | |
| 260 | + | |
| 261 | +static int tasdevice_config_get(struct snd_kcontrol *kcontrol, | |
| 262 | + struct snd_ctl_elem_value *ucontrol) | |
| 263 | +{ | |
| 264 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 265 | + | |
| 266 | + ucontrol->value.integer.value[0] = tas_priv->cur_conf; | |
| 267 | + | |
| 268 | + return 0; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static int tasdevice_config_put(struct snd_kcontrol *kcontrol, | |
| 272 | + struct snd_ctl_elem_value *ucontrol) | |
| 273 | +{ | |
| 274 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 275 | + struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
| 276 | + int nr_config = ucontrol->value.integer.value[0]; | |
| 277 | + int max = tas_fw->nr_configurations - 1; | |
| 278 | + int val, ret = 0; | |
| 279 | + | |
| 280 | + val = tasdevice_hda_clamp(nr_config, max); | |
| 281 | + | |
| 282 | + if (tas_priv->cur_conf != val) { | |
| 283 | + tas_priv->cur_conf = val; | |
| 284 | + ret = 1; | |
| 285 | + } | |
| 286 | + | |
| 287 | + return ret; | |
| 288 | +} | |
| 289 | + | |
| 290 | +/* | |
| 291 | + * tas2781_digital_getvol - get the volum control | |
| 292 | + * @kcontrol: control pointer | |
| 293 | + * @ucontrol: User data | |
| 294 | + * Customer Kcontrol for tas2781 is primarily for regmap booking, paging | |
| 295 | + * depends on internal regmap mechanism. | |
| 296 | + * tas2781 contains book and page two-level register map, especially | |
| 297 | + * book switching will set the register BXXP00R7F, after switching to the | |
| 298 | + * correct book, then leverage the mechanism for paging to access the | |
| 299 | + * register. | |
| 300 | + */ | |
| 301 | +static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol, | |
| 302 | + struct snd_ctl_elem_value *ucontrol) | |
| 303 | +{ | |
| 304 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 305 | + struct soc_mixer_control *mc = | |
| 306 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 307 | + | |
| 308 | + return tasdevice_digital_getvol(tas_priv, ucontrol, mc); | |
| 309 | +} | |
| 310 | + | |
| 311 | +static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol, | |
| 312 | + struct snd_ctl_elem_value *ucontrol) | |
| 313 | +{ | |
| 314 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 315 | + struct soc_mixer_control *mc = | |
| 316 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 317 | + | |
| 318 | + return tasdevice_amp_getvol(tas_priv, ucontrol, mc); | |
| 319 | +} | |
| 320 | + | |
| 321 | +static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol, | |
| 322 | + struct snd_ctl_elem_value *ucontrol) | |
| 323 | +{ | |
| 324 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 325 | + struct soc_mixer_control *mc = | |
| 326 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 327 | + | |
| 328 | + /* The check of the given value is in tasdevice_digital_putvol. */ | |
| 329 | + return tasdevice_digital_putvol(tas_priv, ucontrol, mc); | |
| 330 | +} | |
| 331 | + | |
| 332 | +static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol, | |
| 333 | + struct snd_ctl_elem_value *ucontrol) | |
| 334 | +{ | |
| 335 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 336 | + struct soc_mixer_control *mc = | |
| 337 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 338 | + | |
| 339 | + /* The check of the given value is in tasdevice_amp_putvol. */ | |
| 340 | + return tasdevice_amp_putvol(tas_priv, ucontrol, mc); | |
| 341 | +} | |
| 342 | + | |
| 343 | +static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, | |
| 344 | + struct snd_ctl_elem_value *ucontrol) | |
| 345 | +{ | |
| 346 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 347 | + | |
| 348 | + ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status; | |
| 349 | + dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__, | |
| 350 | + tas_priv->force_fwload_status ? "ON" : "OFF"); | |
| 351 | + | |
| 352 | + return 0; | |
| 353 | +} | |
| 354 | + | |
| 355 | +static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, | |
| 356 | + struct snd_ctl_elem_value *ucontrol) | |
| 357 | +{ | |
| 358 | + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
| 359 | + bool change, val = (bool)ucontrol->value.integer.value[0]; | |
| 360 | + | |
| 361 | + if (tas_priv->force_fwload_status == val) | |
| 362 | + change = false; | |
| 363 | + else { | |
| 364 | + change = true; | |
| 365 | + tas_priv->force_fwload_status = val; | |
| 366 | + } | |
| 367 | + dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__, | |
| 368 | + tas_priv->force_fwload_status ? "ON" : "OFF"); | |
| 369 | + | |
| 370 | + return change; | |
| 371 | +} | |
| 372 | + | |
| 373 | +static const struct snd_kcontrol_new tas2781_snd_controls[] = { | |
| 374 | + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL, | |
| 375 | + 1, 0, 20, 0, tas2781_amp_getvol, | |
| 376 | + tas2781_amp_putvol, amp_vol_tlv), | |
| 377 | + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL, | |
| 378 | + 0, 0, 200, 1, tas2781_digital_getvol, | |
| 379 | + tas2781_digital_putvol, dvc_tlv), | |
| 380 | + ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, | |
| 381 | + tas2781_force_fwload_get, tas2781_force_fwload_put), | |
| 382 | +}; | |
| 383 | + | |
| 384 | +static const struct snd_kcontrol_new tas2781_prof_ctrl = { | |
| 385 | + .name = "Speaker Profile Id", | |
| 386 | + .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
| 387 | + .info = tasdevice_info_profile, | |
| 388 | + .get = tasdevice_get_profile_id, | |
| 389 | + .put = tasdevice_set_profile_id, | |
| 390 | +}; | |
| 391 | + | |
| 392 | +static const struct snd_kcontrol_new tas2781_dsp_prog_ctrl = { | |
| 393 | + .name = "Speaker Program Id", | |
| 394 | + .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
| 395 | + .info = tasdevice_info_programs, | |
| 396 | + .get = tasdevice_program_get, | |
| 397 | + .put = tasdevice_program_put, | |
| 398 | +}; | |
| 399 | + | |
| 400 | +static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = { | |
| 401 | + .name = "Speaker Config Id", | |
| 402 | + .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
| 403 | + .info = tasdevice_info_config, | |
| 404 | + .get = tasdevice_config_get, | |
| 405 | + .put = tasdevice_config_put, | |
| 406 | +}; | |
| 407 | + | |
| 408 | +static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) | |
| 409 | +{ | |
| 410 | + static const unsigned char page_array[CALIB_MAX] = { | |
| 411 | + 0x17, 0x18, 0x18, 0x0d, 0x18 | |
| 412 | + }; | |
| 413 | + static const unsigned char rgno_array[CALIB_MAX] = { | |
| 414 | + 0x74, 0x0c, 0x14, 0x3c, 0x7c | |
| 415 | + }; | |
| 416 | + unsigned char *data; | |
| 417 | + int i, j, rc; | |
| 418 | + | |
| 419 | + for (i = 0; i < tas_priv->ndev; i++) { | |
| 420 | + data = tas_priv->cali_data.data + | |
| 421 | + i * TASDEVICE_SPEAKER_CALIBRATION_SIZE; | |
| 422 | + for (j = 0; j < CALIB_MAX; j++) { | |
| 423 | + rc = tasdevice_dev_bulk_write(tas_priv, i, | |
| 424 | + TASDEVICE_REG(0, page_array[j], rgno_array[j]), | |
| 425 | + &(data[4 * j]), 4); | |
| 426 | + if (rc < 0) | |
| 427 | + dev_err(tas_priv->dev, | |
| 428 | + "chn %d calib %d bulk_wr err = %d\n", | |
| 429 | + i, j, rc); | |
| 430 | + } | |
| 431 | + } | |
| 432 | +} | |
| 433 | + | |
| 434 | +/* Update the calibrate data, including speaker impedance, f0, etc, into algo. | |
| 435 | + * Calibrate data is done by manufacturer in the factory. These data are used | |
| 436 | + * by Algo for calucating the speaker temperature, speaker membrance excursion | |
| 437 | + * and f0 in real time during playback. | |
| 438 | + */ | |
| 439 | +static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) | |
| 440 | +{ | |
| 441 | + efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, | |
| 442 | + 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); | |
| 443 | + static efi_char16_t efi_name[] = L"CALI_DATA"; | |
| 444 | + struct tm *tm = &tas_priv->tm; | |
| 445 | + unsigned int attr, crc; | |
| 446 | + unsigned int *tmp_val; | |
| 447 | + efi_status_t status; | |
| 448 | + | |
| 449 | + /* Lenovo devices */ | |
| 450 | + if (tas_priv->catlog_id == LENOVO) | |
| 451 | + efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, | |
| 452 | + 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); | |
| 453 | + | |
| 454 | + tas_priv->cali_data.total_sz = 0; | |
| 455 | + /* Get real size of UEFI variable */ | |
| 456 | + status = efi.get_variable(efi_name, &efi_guid, &attr, | |
| 457 | + &tas_priv->cali_data.total_sz, tas_priv->cali_data.data); | |
| 458 | + if (status == EFI_BUFFER_TOO_SMALL) { | |
| 459 | + /* Allocate data buffer of data_size bytes */ | |
| 460 | + tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, | |
| 461 | + tas_priv->cali_data.total_sz, GFP_KERNEL); | |
| 462 | + if (!tas_priv->cali_data.data) | |
| 463 | + return -ENOMEM; | |
| 464 | + /* Get variable contents into buffer */ | |
| 465 | + status = efi.get_variable(efi_name, &efi_guid, &attr, | |
| 466 | + &tas_priv->cali_data.total_sz, | |
| 467 | + tas_priv->cali_data.data); | |
| 468 | + if (status != EFI_SUCCESS) | |
| 469 | + return -EINVAL; | |
| 470 | + } | |
| 471 | + | |
| 472 | + tmp_val = (unsigned int *)tas_priv->cali_data.data; | |
| 473 | + | |
| 474 | + crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0; | |
| 475 | + dev_dbg(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n", | |
| 476 | + crc, tmp_val[21]); | |
| 477 | + | |
| 478 | + if (crc == tmp_val[21]) { | |
| 479 | + time64_to_tm(tmp_val[20], 0, tm); | |
| 480 | + dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n", | |
| 481 | + tm->tm_year, tm->tm_mon, tm->tm_mday, | |
| 482 | + tm->tm_hour, tm->tm_min, tm->tm_sec); | |
| 483 | + tas2781_apply_calib(tas_priv); | |
| 484 | + } else | |
| 485 | + tas_priv->cali_data.total_sz = 0; | |
| 486 | + | |
| 487 | + return 0; | |
| 488 | +} | |
| 489 | + | |
| 490 | +static void tasdev_fw_ready(const struct firmware *fmw, void *context) | |
| 491 | +{ | |
| 492 | + struct tasdevice_priv *tas_priv = context; | |
| 493 | + struct hda_codec *codec = tas_priv->codec; | |
| 494 | + int i, ret; | |
| 495 | + | |
| 496 | + pm_runtime_get_sync(tas_priv->dev); | |
| 497 | + mutex_lock(&tas_priv->codec_lock); | |
| 498 | + | |
| 499 | + ret = tasdevice_rca_parser(tas_priv, fmw); | |
| 500 | + if (ret) | |
| 501 | + goto out; | |
| 502 | + | |
| 503 | + ret = snd_ctl_add(codec->card, | |
| 504 | + snd_ctl_new1(&tas2781_prof_ctrl, tas_priv)); | |
| 505 | + if (ret) { | |
| 506 | + dev_err(tas_priv->dev, | |
| 507 | + "Failed to add KControl %s = %d\n", | |
| 508 | + tas2781_prof_ctrl.name, ret); | |
| 509 | + goto out; | |
| 510 | + } | |
| 511 | + | |
| 512 | + for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) { | |
| 513 | + ret = snd_ctl_add(codec->card, | |
| 514 | + snd_ctl_new1(&tas2781_snd_controls[i], tas_priv)); | |
| 515 | + if (ret) { | |
| 516 | + dev_err(tas_priv->dev, | |
| 517 | + "Failed to add KControl %s = %d\n", | |
| 518 | + tas2781_snd_controls[i].name, ret); | |
| 519 | + goto out; | |
| 520 | + } | |
| 521 | + } | |
| 522 | + | |
| 523 | + tasdevice_dsp_remove(tas_priv); | |
| 524 | + | |
| 525 | + tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; | |
| 526 | + scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X.bin", | |
| 527 | + codec->core.subsystem_id & 0xffff); | |
| 528 | + ret = tasdevice_dsp_parser(tas_priv); | |
| 529 | + if (ret) { | |
| 530 | + dev_err(tas_priv->dev, "dspfw load %s error\n", | |
| 531 | + tas_priv->coef_binaryname); | |
| 532 | + tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL; | |
| 533 | + goto out; | |
| 534 | + } | |
| 535 | + | |
| 536 | + ret = snd_ctl_add(codec->card, | |
| 537 | + snd_ctl_new1(&tas2781_dsp_prog_ctrl, tas_priv)); | |
| 538 | + if (ret) { | |
| 539 | + dev_err(tas_priv->dev, | |
| 540 | + "Failed to add KControl %s = %d\n", | |
| 541 | + tas2781_dsp_prog_ctrl.name, ret); | |
| 542 | + goto out; | |
| 543 | + } | |
| 544 | + | |
| 545 | + ret = snd_ctl_add(codec->card, | |
| 546 | + snd_ctl_new1(&tas2781_dsp_conf_ctrl, tas_priv)); | |
| 547 | + if (ret) { | |
| 548 | + dev_err(tas_priv->dev, | |
| 549 | + "Failed to add KControl %s = %d\n", | |
| 550 | + tas2781_dsp_conf_ctrl.name, ret); | |
| 551 | + goto out; | |
| 552 | + } | |
| 553 | + | |
| 554 | + tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; | |
| 555 | + tasdevice_prmg_load(tas_priv, 0); | |
| 556 | + | |
| 557 | + /* If calibrated data occurs error, dsp will still works with default | |
| 558 | + * calibrated data inside algo. | |
| 559 | + */ | |
| 560 | + tas2781_save_calibration(tas_priv); | |
| 561 | + | |
| 562 | +out: | |
| 563 | + if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) { | |
| 564 | + /*If DSP FW fail, kcontrol won't be created */ | |
| 565 | + tasdevice_config_info_remove(tas_priv); | |
| 566 | + tasdevice_dsp_remove(tas_priv); | |
| 567 | + } | |
| 568 | + mutex_unlock(&tas_priv->codec_lock); | |
| 569 | + if (fmw) | |
| 570 | + release_firmware(fmw); | |
| 571 | + pm_runtime_mark_last_busy(tas_priv->dev); | |
| 572 | + pm_runtime_put_autosuspend(tas_priv->dev); | |
| 573 | +} | |
| 574 | + | |
| 575 | +static int tas2781_hda_bind(struct device *dev, struct device *master, | |
| 576 | + void *master_data) | |
| 577 | +{ | |
| 578 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 579 | + struct hda_component *comps = master_data; | |
| 580 | + struct hda_codec *codec; | |
| 581 | + unsigned int subid; | |
| 582 | + int ret; | |
| 583 | + | |
| 584 | + if (!comps || tas_priv->index < 0 || | |
| 585 | + tas_priv->index >= HDA_MAX_COMPONENTS) | |
| 586 | + return -EINVAL; | |
| 587 | + | |
| 588 | + comps = &comps[tas_priv->index]; | |
| 589 | + if (comps->dev) | |
| 590 | + return -EBUSY; | |
| 591 | + | |
| 592 | + codec = comps->codec; | |
| 593 | + subid = codec->core.subsystem_id >> 16; | |
| 594 | + | |
| 595 | + switch (subid) { | |
| 596 | + case 0x17aa: | |
| 597 | + tas_priv->catlog_id = LENOVO; | |
| 598 | + break; | |
| 599 | + default: | |
| 600 | + tas_priv->catlog_id = OTHERS; | |
| 601 | + break; | |
| 602 | + } | |
| 603 | + | |
| 604 | + pm_runtime_get_sync(dev); | |
| 605 | + | |
| 606 | + comps->dev = dev; | |
| 607 | + | |
| 608 | + strscpy(comps->name, dev_name(dev), sizeof(comps->name)); | |
| 609 | + | |
| 610 | + ret = tascodec_init(tas_priv, codec, tasdev_fw_ready); | |
| 611 | + if (!ret) | |
| 612 | + comps->playback_hook = tas2781_hda_playback_hook; | |
| 613 | + | |
| 614 | + pm_runtime_mark_last_busy(dev); | |
| 615 | + pm_runtime_put_autosuspend(dev); | |
| 616 | + | |
| 617 | + return ret; | |
| 618 | +} | |
| 619 | + | |
| 620 | +static void tas2781_hda_unbind(struct device *dev, | |
| 621 | + struct device *master, void *master_data) | |
| 622 | +{ | |
| 623 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 624 | + struct hda_component *comps = master_data; | |
| 625 | + | |
| 626 | + if (comps[tas_priv->index].dev == dev) | |
| 627 | + memset(&comps[tas_priv->index], 0, sizeof(*comps)); | |
| 628 | + | |
| 629 | + tasdevice_config_info_remove(tas_priv); | |
| 630 | + tasdevice_dsp_remove(tas_priv); | |
| 631 | + | |
| 632 | + tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; | |
| 633 | +} | |
| 634 | + | |
| 635 | +static const struct component_ops tas2781_hda_comp_ops = { | |
| 636 | + .bind = tas2781_hda_bind, | |
| 637 | + .unbind = tas2781_hda_unbind, | |
| 638 | +}; | |
| 639 | + | |
| 640 | +static void tas2781_hda_remove(struct device *dev) | |
| 641 | +{ | |
| 642 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 643 | + | |
| 644 | + pm_runtime_get_sync(tas_priv->dev); | |
| 645 | + pm_runtime_disable(tas_priv->dev); | |
| 646 | + | |
| 647 | + component_del(tas_priv->dev, &tas2781_hda_comp_ops); | |
| 648 | + | |
| 649 | + pm_runtime_put_noidle(tas_priv->dev); | |
| 650 | + | |
| 651 | + tasdevice_remove(tas_priv); | |
| 652 | +} | |
| 653 | + | |
| 654 | +static int tas2781_hda_i2c_probe(struct i2c_client *clt) | |
| 655 | +{ | |
| 656 | + struct tasdevice_priv *tas_priv; | |
| 657 | + const char *device_name; | |
| 658 | + int ret; | |
| 659 | + | |
| 660 | + if (strstr(dev_name(&clt->dev), "TIAS2781")) | |
| 661 | + device_name = "TIAS2781"; | |
| 662 | + else | |
| 663 | + return -ENODEV; | |
| 664 | + | |
| 665 | + tas_priv = tasdevice_kzalloc(clt); | |
| 666 | + if (!tas_priv) | |
| 667 | + return -ENOMEM; | |
| 668 | + | |
| 669 | + tas_priv->irq_info.irq = clt->irq; | |
| 670 | + ret = tas2781_read_acpi(tas_priv, device_name); | |
| 671 | + if (ret) | |
| 672 | + return dev_err_probe(tas_priv->dev, ret, | |
| 673 | + "Platform not supported\n"); | |
| 674 | + | |
| 675 | + ret = tasdevice_init(tas_priv); | |
| 676 | + if (ret) | |
| 677 | + goto err; | |
| 678 | + | |
| 679 | + pm_runtime_set_autosuspend_delay(tas_priv->dev, 3000); | |
| 680 | + pm_runtime_use_autosuspend(tas_priv->dev); | |
| 681 | + pm_runtime_mark_last_busy(tas_priv->dev); | |
| 682 | + pm_runtime_set_active(tas_priv->dev); | |
| 683 | + pm_runtime_get_noresume(tas_priv->dev); | |
| 684 | + pm_runtime_enable(tas_priv->dev); | |
| 685 | + | |
| 686 | + pm_runtime_put_autosuspend(tas_priv->dev); | |
| 687 | + | |
| 688 | + ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops); | |
| 689 | + if (ret) { | |
| 690 | + dev_err(tas_priv->dev, "Register component failed: %d\n", ret); | |
| 691 | + pm_runtime_disable(tas_priv->dev); | |
| 692 | + goto err; | |
| 693 | + } | |
| 694 | + | |
| 695 | + tas2781_reset(tas_priv); | |
| 696 | +err: | |
| 697 | + if (ret) | |
| 698 | + tas2781_hda_remove(&clt->dev); | |
| 699 | + return ret; | |
| 700 | +} | |
| 701 | + | |
| 702 | +static void tas2781_hda_i2c_remove(struct i2c_client *clt) | |
| 703 | +{ | |
| 704 | + tas2781_hda_remove(&clt->dev); | |
| 705 | +} | |
| 706 | + | |
| 707 | +static int tas2781_runtime_suspend(struct device *dev) | |
| 708 | +{ | |
| 709 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 710 | + int i; | |
| 711 | + | |
| 712 | + dev_dbg(tas_priv->dev, "Runtime Suspend\n"); | |
| 713 | + | |
| 714 | + mutex_lock(&tas_priv->codec_lock); | |
| 715 | + | |
| 716 | + if (tas_priv->playback_started) { | |
| 717 | + tasdevice_tuning_switch(tas_priv, 1); | |
| 718 | + tas_priv->playback_started = false; | |
| 719 | + } | |
| 720 | + | |
| 721 | + for (i = 0; i < tas_priv->ndev; i++) { | |
| 722 | + tas_priv->tasdevice[i].cur_book = -1; | |
| 723 | + tas_priv->tasdevice[i].cur_prog = -1; | |
| 724 | + tas_priv->tasdevice[i].cur_conf = -1; | |
| 725 | + } | |
| 726 | + | |
| 727 | + regcache_cache_only(tas_priv->regmap, true); | |
| 728 | + regcache_mark_dirty(tas_priv->regmap); | |
| 729 | + | |
| 730 | + mutex_unlock(&tas_priv->codec_lock); | |
| 731 | + | |
| 732 | + return 0; | |
| 733 | +} | |
| 734 | + | |
| 735 | +static int tas2781_runtime_resume(struct device *dev) | |
| 736 | +{ | |
| 737 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 738 | + unsigned long calib_data_sz = | |
| 739 | + tas_priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE; | |
| 740 | + int ret; | |
| 741 | + | |
| 742 | + dev_dbg(tas_priv->dev, "Runtime Resume\n"); | |
| 743 | + | |
| 744 | + mutex_lock(&tas_priv->codec_lock); | |
| 745 | + | |
| 746 | + regcache_cache_only(tas_priv->regmap, false); | |
| 747 | + ret = regcache_sync(tas_priv->regmap); | |
| 748 | + if (ret) { | |
| 749 | + dev_err(tas_priv->dev, | |
| 750 | + "Failed to restore register cache: %d\n", ret); | |
| 751 | + goto out; | |
| 752 | + } | |
| 753 | + | |
| 754 | + tasdevice_prmg_load(tas_priv, tas_priv->cur_prog); | |
| 755 | + | |
| 756 | + /* If calibrated data occurs error, dsp will still works with default | |
| 757 | + * calibrated data inside algo. | |
| 758 | + */ | |
| 759 | + if (tas_priv->cali_data.total_sz > calib_data_sz) | |
| 760 | + tas2781_apply_calib(tas_priv); | |
| 761 | + | |
| 762 | +out: | |
| 763 | + mutex_unlock(&tas_priv->codec_lock); | |
| 764 | + | |
| 765 | + return ret; | |
| 766 | +} | |
| 767 | + | |
| 768 | +static int tas2781_system_suspend(struct device *dev) | |
| 769 | +{ | |
| 770 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 771 | + int ret; | |
| 772 | + | |
| 773 | + dev_dbg(tas_priv->dev, "System Suspend\n"); | |
| 774 | + | |
| 775 | + ret = pm_runtime_force_suspend(dev); | |
| 776 | + if (ret) | |
| 777 | + return ret; | |
| 778 | + | |
| 779 | + /* Shutdown chip before system suspend */ | |
| 780 | + regcache_cache_only(tas_priv->regmap, false); | |
| 781 | + tasdevice_tuning_switch(tas_priv, 1); | |
| 782 | + regcache_cache_only(tas_priv->regmap, true); | |
| 783 | + regcache_mark_dirty(tas_priv->regmap); | |
| 784 | + | |
| 785 | + /* | |
| 786 | + * Reset GPIO may be shared, so cannot reset here. | |
| 787 | + * However beyond this point, amps may be powered down. | |
| 788 | + */ | |
| 789 | + return 0; | |
| 790 | +} | |
| 791 | + | |
| 792 | +static int tas2781_system_resume(struct device *dev) | |
| 793 | +{ | |
| 794 | + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); | |
| 795 | + unsigned long calib_data_sz = | |
| 796 | + tas_priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE; | |
| 797 | + int i, ret; | |
| 798 | + | |
| 799 | + dev_dbg(tas_priv->dev, "System Resume\n"); | |
| 800 | + | |
| 801 | + ret = pm_runtime_force_resume(dev); | |
| 802 | + if (ret) | |
| 803 | + return ret; | |
| 804 | + | |
| 805 | + mutex_lock(&tas_priv->codec_lock); | |
| 806 | + | |
| 807 | + for (i = 0; i < tas_priv->ndev; i++) { | |
| 808 | + tas_priv->tasdevice[i].cur_book = -1; | |
| 809 | + tas_priv->tasdevice[i].cur_prog = -1; | |
| 810 | + tas_priv->tasdevice[i].cur_conf = -1; | |
| 811 | + } | |
| 812 | + tas2781_reset(tas_priv); | |
| 813 | + tasdevice_prmg_load(tas_priv, tas_priv->cur_prog); | |
| 814 | + | |
| 815 | + /* If calibrated data occurs error, dsp will still work with default | |
| 816 | + * calibrated data inside algo. | |
| 817 | + */ | |
| 818 | + if (tas_priv->cali_data.total_sz > calib_data_sz) | |
| 819 | + tas2781_apply_calib(tas_priv); | |
| 820 | + mutex_unlock(&tas_priv->codec_lock); | |
| 821 | + | |
| 822 | + return 0; | |
| 823 | +} | |
| 824 | + | |
| 825 | +static const struct dev_pm_ops tas2781_hda_pm_ops = { | |
| 826 | + RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL) | |
| 827 | + SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume) | |
| 828 | +}; | |
| 829 | + | |
| 830 | +static const struct i2c_device_id tas2781_hda_i2c_id[] = { | |
| 831 | + { "tas2781-hda", 0 }, | |
| 832 | + {} | |
| 833 | +}; | |
| 834 | + | |
| 835 | +static const struct acpi_device_id tas2781_acpi_hda_match[] = { | |
| 836 | + {"TIAS2781", 0 }, | |
| 837 | + {} | |
| 838 | +}; | |
| 839 | +MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); | |
| 840 | + | |
| 841 | +static struct i2c_driver tas2781_hda_i2c_driver = { | |
| 842 | + .driver = { | |
| 843 | + .name = "tas2781-hda", | |
| 844 | + .acpi_match_table = tas2781_acpi_hda_match, | |
| 845 | + .pm = &tas2781_hda_pm_ops, | |
| 846 | + }, | |
| 847 | + .id_table = tas2781_hda_i2c_id, | |
| 848 | + .probe = tas2781_hda_i2c_probe, | |
| 849 | + .remove = tas2781_hda_i2c_remove, | |
| 850 | +}; | |
| 851 | +module_i2c_driver(tas2781_hda_i2c_driver); | |
| 852 | + | |
| 853 | +MODULE_DESCRIPTION("TAS2781 HDA Driver"); | |
| 854 | +MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>"); | |
| 855 | +MODULE_LICENSE("GPL"); | |
| 856 | +MODULE_IMPORT_NS(SND_SOC_TAS2781_FMWLIB); | |
| @@ -408,30 +408,6 @@ static const char * const follower_vols[] = { · 407 unmodified lines | ||
| 408 | 408 | static |
| 409 | 409 | DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1); |
| 410 | 410 | |
| 411 | −static struct snd_kcontrol *ctl_find(struct snd_card *card, | |
| 412 | − const char *name) | |
| 413 | −{ | |
| 414 | − struct snd_ctl_elem_id sid = {0}; | |
| 415 | − | |
| 416 | − strscpy(sid.name, name, sizeof(sid.name)); | |
| 417 | − sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 418 | − return snd_ctl_find_id(card, &sid); | |
| 419 | −} | |
| 420 | − | |
| 421 | −static void add_followers(struct snd_card *card, | |
| 422 | − struct snd_kcontrol *master, | |
| 423 | − const char * const *list) | |
| 424 | −{ | |
| 425 | − for (; *list; list++) { | |
| 426 | − struct snd_kcontrol *follower = ctl_find(card, *list); | |
| 427 | − /* dev_dbg(card->dev, "add_followers - %s\n", *list); */ | |
| 428 | − if (follower) { | |
| 429 | − /* dev_dbg(card->dev, "follower %s found\n", *list); */ | |
| 430 | − snd_ctl_add_follower(master, follower); | |
| 431 | − } | |
| 432 | − } | |
| 433 | −} | |
| 434 | − | |
| 435 | 411 | static int juli_add_controls(struct snd_ice1712 *ice) |
| 436 | 412 | { |
| 437 | 413 | struct juli_spec *spec = ice->spec; |
| @@ -454,8 +430,10 @@ static int juli_add_controls(struct snd_ice1712 *ice) · 16 unmodified lines | ||
| 454 | 430 | juli_master_db_scale); |
| 455 | 431 | if (!vmaster) |
| 456 | 432 | return -ENOMEM; |
| 457 | − add_followers(ice->card, vmaster, follower_vols); | |
| 458 | 433 | err = snd_ctl_add(ice->card, vmaster); |
| 434 | + if (err < 0) | |
| 435 | + return err; | |
| 436 | + err = snd_ctl_add_followers(ice->card, vmaster, follower_vols); | |
| 459 | 437 | if (err < 0) |
| 460 | 438 | return err; |
| 461 | 439 | |
| @@ -177,7 +177,6 @@ static bool psc724_get_master_switch(struct snd_ice1712 *ice) · 176 unmodified lines | ||
| 177 | 177 | static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected) |
| 178 | 178 | { |
| 179 | 179 | struct psc724_spec *spec = ice->spec; |
| 180 | − struct snd_ctl_elem_id elem_id; | |
| 181 | 180 | struct snd_kcontrol *kctl; |
| 182 | 181 | u16 power = spec->wm8776.regs[WM8776_REG_PWRDOWN] & ~WM8776_PWR_HPPD; |
| 183 | 182 | |
| @@ -187,17 +186,15 @@ static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected) · 3 unmodified lines | ||
| 187 | 186 | snd_wm8776_set_power(&spec->wm8776, power); |
| 188 | 187 | spec->hp_connected = hp_connected; |
| 189 | 188 | /* notify about master speaker mute change */ |
| 190 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 191 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 192 | − strscpy(elem_id.name, "Master Speakers Playback Switch", | |
| 193 | − sizeof(elem_id.name)); | |
| 194 | − kctl = snd_ctl_find_id(ice->card, &elem_id); | |
| 195 | − snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); | |
| 189 | + kctl = snd_ctl_find_id_mixer(ice->card, | |
| 190 | + "Master Speakers Playback Switch"); | |
| 191 | + if (kctl) | |
| 192 | + snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); | |
| 196 | 193 | /* and headphone mute change */ |
| 197 | − strscpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name, | |
| 198 | − sizeof(elem_id.name)); | |
| 199 | − kctl = snd_ctl_find_id(ice->card, &elem_id); | |
| 200 | − snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); | |
| 194 | + kctl = snd_ctl_find_id_mixer(ice->card, | |
| 195 | + spec->wm8776.ctl[WM8776_CTL_HP_SW].name); | |
| 196 | + if (kctl) | |
| 197 | + snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); | |
| 201 | 198 | } |
| 202 | 199 | |
| 203 | 200 | static void psc724_update_hp_jack_state(struct work_struct *work) |
| @@ -766,26 +766,6 @@ static const char * const follower_vols[] = { · 765 unmodified lines | ||
| 766 | 766 | static |
| 767 | 767 | DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); |
| 768 | 768 | |
| 769 | −static struct snd_kcontrol *ctl_find(struct snd_card *card, | |
| 770 | − const char *name) | |
| 771 | −{ | |
| 772 | − struct snd_ctl_elem_id sid = {0}; | |
| 773 | − | |
| 774 | − strscpy(sid.name, name, sizeof(sid.name)); | |
| 775 | − sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 776 | − return snd_ctl_find_id(card, &sid); | |
| 777 | −} | |
| 778 | − | |
| 779 | −static void add_followers(struct snd_card *card, | |
| 780 | − struct snd_kcontrol *master, const char * const *list) | |
| 781 | −{ | |
| 782 | − for (; *list; list++) { | |
| 783 | − struct snd_kcontrol *follower = ctl_find(card, *list); | |
| 784 | − if (follower) | |
| 785 | − snd_ctl_add_follower(master, follower); | |
| 786 | − } | |
| 787 | −} | |
| 788 | − | |
| 789 | 769 | static int qtet_add_controls(struct snd_ice1712 *ice) |
| 790 | 770 | { |
| 791 | 771 | struct qtet_spec *spec = ice->spec; |
| @@ -806,8 +786,10 @@ static int qtet_add_controls(struct snd_ice1712 *ice) · 14 unmodified lines | ||
| 806 | 786 | qtet_master_db_scale); |
| 807 | 787 | if (!vmaster) |
| 808 | 788 | return -ENOMEM; |
| 809 | − add_followers(ice->card, vmaster, follower_vols); | |
| 810 | 789 | err = snd_ctl_add(ice->card, vmaster); |
| 790 | + if (err < 0) | |
| 791 | + return err; | |
| 792 | + err = snd_ctl_add_followers(ice->card, vmaster, follower_vols); | |
| 811 | 793 | if (err < 0) |
| 812 | 794 | return err; |
| 813 | 795 | /* only capture SPDIF over AK4113 */ |
| @@ -34,13 +34,9 @@ static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm, · 33 unmodified lines | ||
| 34 | 34 | struct snd_card *card = wm->card; |
| 35 | 35 | struct snd_kcontrol *kctl; |
| 36 | 36 | struct snd_kcontrol_volatile *vd; |
| 37 | − struct snd_ctl_elem_id elem_id; | |
| 38 | 37 | unsigned int index_offset; |
| 39 | 38 | |
| 40 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 41 | − strscpy(elem_id.name, ctl_name, sizeof(elem_id.name)); | |
| 42 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 43 | − kctl = snd_ctl_find_id(card, &elem_id); | |
| 39 | + kctl = snd_ctl_find_id_mixer(card, ctl_name); | |
| 44 | 40 | if (!kctl) |
| 45 | 41 | return; |
| 46 | 42 | index_offset = snd_ctl_get_ioff(kctl, &kctl->id); |
| @@ -1285,8 +1285,7 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun · 1284 unmodified lines | ||
| 1285 | 1285 | } |
| 1286 | 1286 | |
| 1287 | 1287 | static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, |
| 1288 | − void __user *dst, int pos, int count, | |
| 1289 | − bool in_kernel) | |
| 1288 | + struct iov_iter *dst, int pos, int count) | |
| 1290 | 1289 | { |
| 1291 | 1290 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1292 | 1291 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); |
| @@ -1306,24 +1305,20 @@ static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, · 13 unmodified lines | ||
| 1306 | 1305 | #if K1212_DEBUG_LEVEL > 0 |
| 1307 | 1306 | if ( (void *) src < (void *) korg1212->recordDataBufsPtr || |
| 1308 | 1307 | (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { |
| 1309 | − printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); | |
| 1308 | + printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst->kvec.iov_base, i); | |
| 1310 | 1309 | return -EFAULT; |
| 1311 | 1310 | } |
| 1312 | 1311 | #endif |
| 1313 | − if (in_kernel) | |
| 1314 | − memcpy((__force void *)dst, src, size); | |
| 1315 | − else if (copy_to_user(dst, src, size)) | |
| 1312 | + if (copy_to_iter(src, size, dst) != size) | |
| 1316 | 1313 | return -EFAULT; |
| 1317 | 1314 | src++; |
| 1318 | − dst += size; | |
| 1319 | 1315 | } |
| 1320 | 1316 | |
| 1321 | 1317 | return 0; |
| 1322 | 1318 | } |
| 1323 | 1319 | |
| 1324 | 1320 | static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, |
| 1325 | − void __user *src, int pos, int count, | |
| 1326 | − bool in_kernel) | |
| 1321 | + struct iov_iter *src, int pos, int count) | |
| 1327 | 1322 | { |
| 1328 | 1323 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1329 | 1324 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); |
| @@ -1345,16 +1340,13 @@ static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, · 15 unmodified lines | ||
| 1345 | 1340 | #if K1212_DEBUG_LEVEL > 0 |
| 1346 | 1341 | if ( (void *) dst < (void *) korg1212->playDataBufsPtr || |
| 1347 | 1342 | (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { |
| 1348 | − printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); | |
| 1343 | + printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src->kvec.iov_base, dst, i); | |
| 1349 | 1344 | return -EFAULT; |
| 1350 | 1345 | } |
| 1351 | 1346 | #endif |
| 1352 | − if (in_kernel) | |
| 1353 | − memcpy(dst, (__force void *)src, size); | |
| 1354 | − else if (copy_from_user(dst, src, size)) | |
| 1347 | + if (copy_from_iter(dst, size, src) != size) | |
| 1355 | 1348 | return -EFAULT; |
| 1356 | 1349 | dst++; |
| 1357 | − src += size; | |
| 1358 | 1350 | } |
| 1359 | 1351 | |
| 1360 | 1352 | return 0; |
| @@ -1642,17 +1634,9 @@ static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream * · 281 unmodified lines | ||
| 1642 | 1634 | |
| 1643 | 1635 | static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, |
| 1644 | 1636 | int channel, unsigned long pos, |
| 1645 | − void __user *src, unsigned long count) | |
| 1637 | + struct iov_iter *src, unsigned long count) | |
| 1646 | 1638 | { |
| 1647 | − return snd_korg1212_copy_from(substream, src, pos, count, false); | |
| 1648 | −} | |
| 1649 | − | |
| 1650 | −static int snd_korg1212_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 1651 | − int channel, unsigned long pos, | |
| 1652 | − void *src, unsigned long count) | |
| 1653 | −{ | |
| 1654 | − return snd_korg1212_copy_from(substream, (void __user *)src, | |
| 1655 | − pos, count, true); | |
| 1639 | + return snd_korg1212_copy_from(substream, src, pos, count); | |
| 1656 | 1640 | } |
| 1657 | 1641 | |
| 1658 | 1642 | static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, |
| @@ -1670,17 +1654,9 @@ static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, · 11 unmodified lines | ||
| 1670 | 1654 | |
| 1671 | 1655 | static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, |
| 1672 | 1656 | int channel, unsigned long pos, |
| 1673 | − void __user *dst, unsigned long count) | |
| 1674 | −{ | |
| 1675 | − return snd_korg1212_copy_to(substream, dst, pos, count, false); | |
| 1676 | −} | |
| 1677 | − | |
| 1678 | −static int snd_korg1212_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 1679 | − int channel, unsigned long pos, | |
| 1680 | − void *dst, unsigned long count) | |
| 1657 | + struct iov_iter *dst, unsigned long count) | |
| 1681 | 1658 | { |
| 1682 | − return snd_korg1212_copy_to(substream, (void __user *)dst, | |
| 1683 | − pos, count, true); | |
| 1659 | + return snd_korg1212_copy_to(substream, dst, pos, count); | |
| 1684 | 1660 | } |
| 1685 | 1661 | |
| 1686 | 1662 | static const struct snd_pcm_ops snd_korg1212_playback_ops = { |
| @@ -1691,8 +1667,7 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = { · 4 unmodified lines | ||
| 1691 | 1667 | .prepare = snd_korg1212_prepare, |
| 1692 | 1668 | .trigger = snd_korg1212_trigger, |
| 1693 | 1669 | .pointer = snd_korg1212_playback_pointer, |
| 1694 | − .copy_user = snd_korg1212_playback_copy, | |
| 1695 | − .copy_kernel = snd_korg1212_playback_copy_kernel, | |
| 1670 | + .copy = snd_korg1212_playback_copy, | |
| 1696 | 1671 | .fill_silence = snd_korg1212_playback_silence, |
| 1697 | 1672 | }; |
| 1698 | 1673 | |
| @@ -1704,8 +1679,7 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = { · 5 unmodified lines | ||
| 1704 | 1679 | .prepare = snd_korg1212_prepare, |
| 1705 | 1680 | .trigger = snd_korg1212_trigger, |
| 1706 | 1681 | .pointer = snd_korg1212_capture_pointer, |
| 1707 | − .copy_user = snd_korg1212_capture_copy, | |
| 1708 | − .copy_kernel = snd_korg1212_capture_copy_kernel, | |
| 1682 | + .copy = snd_korg1212_capture_copy, | |
| 1709 | 1683 | }; |
| 1710 | 1684 | |
| 1711 | 1685 | /* |
| @@ -2029,9 +2029,6 @@ static int snd_m3_mixer(struct snd_m3 *chip) · 2028 unmodified lines | ||
| 2029 | 2029 | { |
| 2030 | 2030 | struct snd_ac97_bus *pbus; |
| 2031 | 2031 | struct snd_ac97_template ac97; |
| 2032 | −#ifndef CONFIG_SND_MAESTRO3_INPUT | |
| 2033 | − struct snd_ctl_elem_id elem_id; | |
| 2034 | −#endif | |
| 2035 | 2032 | int err; |
| 2036 | 2033 | static const struct snd_ac97_bus_ops ops = { |
| 2037 | 2034 | .write = snd_m3_ac97_write, |
| @@ -2054,14 +2051,10 @@ static int snd_m3_mixer(struct snd_m3 *chip) · 16 unmodified lines | ||
| 2054 | 2051 | snd_ac97_write(chip->ac97, AC97_PCM, 0); |
| 2055 | 2052 | |
| 2056 | 2053 | #ifndef CONFIG_SND_MAESTRO3_INPUT |
| 2057 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 2058 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2059 | − strcpy(elem_id.name, "Master Playback Switch"); | |
| 2060 | − chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); | |
| 2061 | − memset(&elem_id, 0, sizeof(elem_id)); | |
| 2062 | − elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 2063 | − strcpy(elem_id.name, "Master Playback Volume"); | |
| 2064 | − chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); | |
| 2054 | + chip->master_switch = snd_ctl_find_id_mixer(chip->card, | |
| 2055 | + "Master Playback Switch"); | |
| 2056 | + chip->master_volume = snd_ctl_find_id_mixer(chip->card, | |
| 2057 | + "Master Playback Volume"); | |
| 2065 | 2058 | #endif |
| 2066 | 2059 | |
| 2067 | 2060 | return 0; |
| @@ -691,26 +691,12 @@ snd_nm256_playback_silence(struct snd_pcm_substream *substream, · 690 unmodified lines | ||
| 691 | 691 | static int |
| 692 | 692 | snd_nm256_playback_copy(struct snd_pcm_substream *substream, |
| 693 | 693 | int channel, unsigned long pos, |
| 694 | − void __user *src, unsigned long count) | |
| 694 | + struct iov_iter *src, unsigned long count) | |
| 695 | 695 | { |
| 696 | 696 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 697 | 697 | struct nm256_stream *s = runtime->private_data; |
| 698 | 698 | |
| 699 | − if (copy_from_user_toio(s->bufptr + pos, src, count)) | |
| 700 | − return -EFAULT; | |
| 701 | − return 0; | |
| 702 | −} | |
| 703 | − | |
| 704 | −static int | |
| 705 | −snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 706 | − int channel, unsigned long pos, | |
| 707 | − void *src, unsigned long count) | |
| 708 | −{ | |
| 709 | − struct snd_pcm_runtime *runtime = substream->runtime; | |
| 710 | − struct nm256_stream *s = runtime->private_data; | |
| 711 | − | |
| 712 | − memcpy_toio(s->bufptr + pos, src, count); | |
| 713 | − return 0; | |
| 699 | + return copy_from_iter_toio(s->bufptr + pos, src, count); | |
| 714 | 700 | } |
| 715 | 701 | |
| 716 | 702 | /* |
| @@ -719,26 +705,12 @@ snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream, · 2 unmodified lines | ||
| 719 | 705 | static int |
| 720 | 706 | snd_nm256_capture_copy(struct snd_pcm_substream *substream, |
| 721 | 707 | int channel, unsigned long pos, |
| 722 | − void __user *dst, unsigned long count) | |
| 708 | + struct iov_iter *dst, unsigned long count) | |
| 723 | 709 | { |
| 724 | 710 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 725 | 711 | struct nm256_stream *s = runtime->private_data; |
| 726 | 712 | |
| 727 | − if (copy_to_user_fromio(dst, s->bufptr + pos, count)) | |
| 728 | − return -EFAULT; | |
| 729 | − return 0; | |
| 730 | −} | |
| 731 | − | |
| 732 | −static int | |
| 733 | −snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 734 | − int channel, unsigned long pos, | |
| 735 | − void *dst, unsigned long count) | |
| 736 | −{ | |
| 737 | − struct snd_pcm_runtime *runtime = substream->runtime; | |
| 738 | − struct nm256_stream *s = runtime->private_data; | |
| 739 | − | |
| 740 | − memcpy_fromio(dst, s->bufptr + pos, count); | |
| 741 | − return 0; | |
| 713 | + return copy_to_iter_fromio(dst, s->bufptr + pos, count); | |
| 742 | 714 | } |
| 743 | 715 | |
| 744 | 716 | #endif /* !__i386__ */ |
| @@ -909,8 +881,7 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = { · 164 unmodified lines | ||
| 909 | 881 | .trigger = snd_nm256_playback_trigger, |
| 910 | 882 | .pointer = snd_nm256_playback_pointer, |
| 911 | 883 | #ifndef __i386__ |
| 912 | − .copy_user = snd_nm256_playback_copy, | |
| 913 | − .copy_kernel = snd_nm256_playback_copy_kernel, | |
| 884 | + .copy = snd_nm256_playback_copy, | |
| 914 | 885 | .fill_silence = snd_nm256_playback_silence, |
| 915 | 886 | #endif |
| 916 | 887 | .mmap = snd_pcm_lib_mmap_iomem, |
| @@ -924,8 +895,7 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = { · 7 unmodified lines | ||
| 924 | 895 | .trigger = snd_nm256_capture_trigger, |
| 925 | 896 | .pointer = snd_nm256_capture_pointer, |
| 926 | 897 | #ifndef __i386__ |
| 927 | − .copy_user = snd_nm256_capture_copy, | |
| 928 | − .copy_kernel = snd_nm256_capture_copy_kernel, | |
| 898 | + .copy = snd_nm256_capture_copy, | |
| 929 | 899 | #endif |
| 930 | 900 | .mmap = snd_pcm_lib_mmap_iomem, |
| 931 | 901 | }; |
| @@ -252,48 +252,24 @@ static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, · 251 unmodified lines | ||
| 252 | 252 | /* copy callback for halfduplex mode */ |
| 253 | 253 | static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, |
| 254 | 254 | int channel, unsigned long pos, |
| 255 | − void __user *src, unsigned long count) | |
| 255 | + struct iov_iter *src, unsigned long count) | |
| 256 | 256 | { |
| 257 | 257 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
| 258 | 258 | |
| 259 | − if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, | |
| 260 | − src, count)) | |
| 261 | − return -EFAULT; | |
| 262 | − return 0; | |
| 263 | −} | |
| 264 | − | |
| 265 | −static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 266 | − int channel, unsigned long pos, | |
| 267 | − void *src, unsigned long count) | |
| 268 | −{ | |
| 269 | − struct rme32 *rme32 = snd_pcm_substream_chip(substream); | |
| 270 | − | |
| 271 | − memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count); | |
| 272 | − return 0; | |
| 259 | + return copy_from_iter_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, | |
| 260 | + src, count); | |
| 273 | 261 | } |
| 274 | 262 | |
| 275 | 263 | /* copy callback for halfduplex mode */ |
| 276 | 264 | static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, |
| 277 | 265 | int channel, unsigned long pos, |
| 278 | − void __user *dst, unsigned long count) | |
| 266 | + struct iov_iter *dst, unsigned long count) | |
| 279 | 267 | { |
| 280 | 268 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
| 281 | 269 | |
| 282 | − if (copy_to_user_fromio(dst, | |
| 283 | − rme32->iobase + RME32_IO_DATA_BUFFER + pos, | |
| 284 | − count)) | |
| 285 | − return -EFAULT; | |
| 286 | − return 0; | |
| 287 | −} | |
| 288 | − | |
| 289 | −static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 290 | − int channel, unsigned long pos, | |
| 291 | − void *dst, unsigned long count) | |
| 292 | −{ | |
| 293 | − struct rme32 *rme32 = snd_pcm_substream_chip(substream); | |
| 294 | − | |
| 295 | − memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count); | |
| 296 | − return 0; | |
| 270 | + return copy_to_iter_fromio(dst, | |
| 271 | + rme32->iobase + RME32_IO_DATA_BUFFER + pos, | |
| 272 | + count); | |
| 297 | 273 | } |
| 298 | 274 | |
| 299 | 275 | /* |
| @@ -1194,8 +1170,7 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { · 894 unmodified lines | ||
| 1194 | 1170 | .prepare = snd_rme32_playback_prepare, |
| 1195 | 1171 | .trigger = snd_rme32_pcm_trigger, |
| 1196 | 1172 | .pointer = snd_rme32_playback_pointer, |
| 1197 | − .copy_user = snd_rme32_playback_copy, | |
| 1198 | − .copy_kernel = snd_rme32_playback_copy_kernel, | |
| 1173 | + .copy = snd_rme32_playback_copy, | |
| 1199 | 1174 | .fill_silence = snd_rme32_playback_silence, |
| 1200 | 1175 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1201 | 1176 | }; |
| @@ -1207,8 +1182,7 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { · 5 unmodified lines | ||
| 1207 | 1182 | .prepare = snd_rme32_capture_prepare, |
| 1208 | 1183 | .trigger = snd_rme32_pcm_trigger, |
| 1209 | 1184 | .pointer = snd_rme32_capture_pointer, |
| 1210 | − .copy_user = snd_rme32_capture_copy, | |
| 1211 | − .copy_kernel = snd_rme32_capture_copy_kernel, | |
| 1185 | + .copy = snd_rme32_capture_copy, | |
| 1212 | 1186 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1213 | 1187 | }; |
| 1214 | 1188 | |
| @@ -1219,8 +1193,7 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { · 4 unmodified lines | ||
| 1219 | 1193 | .prepare = snd_rme32_playback_prepare, |
| 1220 | 1194 | .trigger = snd_rme32_pcm_trigger, |
| 1221 | 1195 | .pointer = snd_rme32_playback_pointer, |
| 1222 | − .copy_user = snd_rme32_playback_copy, | |
| 1223 | − .copy_kernel = snd_rme32_playback_copy_kernel, | |
| 1196 | + .copy = snd_rme32_playback_copy, | |
| 1224 | 1197 | .fill_silence = snd_rme32_playback_silence, |
| 1225 | 1198 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1226 | 1199 | }; |
| @@ -1232,8 +1205,7 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { · 5 unmodified lines | ||
| 1232 | 1205 | .prepare = snd_rme32_capture_prepare, |
| 1233 | 1206 | .trigger = snd_rme32_pcm_trigger, |
| 1234 | 1207 | .pointer = snd_rme32_capture_pointer, |
| 1235 | − .copy_user = snd_rme32_capture_copy, | |
| 1236 | − .copy_kernel = snd_rme32_capture_copy_kernel, | |
| 1208 | + .copy = snd_rme32_capture_copy, | |
| 1237 | 1209 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1238 | 1210 | }; |
| 1239 | 1211 | |
| @@ -320,48 +320,26 @@ snd_rme96_playback_silence(struct snd_pcm_substream *substream, · 319 unmodified lines | ||
| 320 | 320 | static int |
| 321 | 321 | snd_rme96_playback_copy(struct snd_pcm_substream *substream, |
| 322 | 322 | int channel, unsigned long pos, |
| 323 | − void __user *src, unsigned long count) | |
| 323 | + struct iov_iter *src, unsigned long count) | |
| 324 | 324 | { |
| 325 | 325 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
| 326 | 326 | |
| 327 | − return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, | |
| 327 | + return copy_from_iter_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, | |
| 328 | 328 | src, count); |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | −static int | |
| 332 | −snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 333 | − int channel, unsigned long pos, | |
| 334 | − void *src, unsigned long count) | |
| 335 | −{ | |
| 336 | − struct rme96 *rme96 = snd_pcm_substream_chip(substream); | |
| 337 | − | |
| 338 | − memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count); | |
| 339 | − return 0; | |
| 340 | −} | |
| 341 | − | |
| 342 | 331 | static int |
| 343 | 332 | snd_rme96_capture_copy(struct snd_pcm_substream *substream, |
| 344 | 333 | int channel, unsigned long pos, |
| 345 | − void __user *dst, unsigned long count) | |
| 334 | + struct iov_iter *dst, unsigned long count) | |
| 346 | 335 | { |
| 347 | 336 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
| 348 | 337 | |
| 349 | − return copy_to_user_fromio(dst, | |
| 338 | + return copy_to_iter_fromio(dst, | |
| 350 | 339 | rme96->iobase + RME96_IO_REC_BUFFER + pos, |
| 351 | 340 | count); |
| 352 | 341 | } |
| 353 | 342 | |
| 354 | −static int | |
| 355 | −snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 356 | − int channel, unsigned long pos, | |
| 357 | − void *dst, unsigned long count) | |
| 358 | −{ | |
| 359 | − struct rme96 *rme96 = snd_pcm_substream_chip(substream); | |
| 360 | − | |
| 361 | − memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count); | |
| 362 | − return 0; | |
| 363 | −} | |
| 364 | − | |
| 365 | 343 | /* |
| 366 | 344 | * Digital output capabilities (S/PDIF) |
| 367 | 345 | */ |
| @@ -1518,8 +1496,7 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { · 1150 unmodified lines | ||
| 1518 | 1496 | .prepare = snd_rme96_playback_prepare, |
| 1519 | 1497 | .trigger = snd_rme96_playback_trigger, |
| 1520 | 1498 | .pointer = snd_rme96_playback_pointer, |
| 1521 | − .copy_user = snd_rme96_playback_copy, | |
| 1522 | − .copy_kernel = snd_rme96_playback_copy_kernel, | |
| 1499 | + .copy = snd_rme96_playback_copy, | |
| 1523 | 1500 | .fill_silence = snd_rme96_playback_silence, |
| 1524 | 1501 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1525 | 1502 | }; |
| @@ -1531,8 +1508,7 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { · 5 unmodified lines | ||
| 1531 | 1508 | .prepare = snd_rme96_capture_prepare, |
| 1532 | 1509 | .trigger = snd_rme96_capture_trigger, |
| 1533 | 1510 | .pointer = snd_rme96_capture_pointer, |
| 1534 | − .copy_user = snd_rme96_capture_copy, | |
| 1535 | − .copy_kernel = snd_rme96_capture_copy_kernel, | |
| 1511 | + .copy = snd_rme96_capture_copy, | |
| 1536 | 1512 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1537 | 1513 | }; |
| 1538 | 1514 | |
| @@ -1543,8 +1519,7 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { · 4 unmodified lines | ||
| 1543 | 1519 | .prepare = snd_rme96_playback_prepare, |
| 1544 | 1520 | .trigger = snd_rme96_playback_trigger, |
| 1545 | 1521 | .pointer = snd_rme96_playback_pointer, |
| 1546 | − .copy_user = snd_rme96_playback_copy, | |
| 1547 | − .copy_kernel = snd_rme96_playback_copy_kernel, | |
| 1522 | + .copy = snd_rme96_playback_copy, | |
| 1548 | 1523 | .fill_silence = snd_rme96_playback_silence, |
| 1549 | 1524 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1550 | 1525 | }; |
| @@ -1556,8 +1531,7 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { · 5 unmodified lines | ||
| 1556 | 1531 | .prepare = snd_rme96_capture_prepare, |
| 1557 | 1532 | .trigger = snd_rme96_capture_trigger, |
| 1558 | 1533 | .pointer = snd_rme96_capture_pointer, |
| 1559 | − .copy_user = snd_rme96_capture_copy, | |
| 1560 | − .copy_kernel = snd_rme96_capture_copy_kernel, | |
| 1534 | + .copy = snd_rme96_capture_copy, | |
| 1561 | 1535 | .mmap = snd_pcm_lib_mmap_iomem, |
| 1562 | 1536 | }; |
| 1563 | 1537 | |
| @@ -3961,7 +3961,7 @@ static signed char *hdsp_channel_buffer_location(struct hdsp *hdsp, · 3960 unmodified lines | ||
| 3961 | 3961 | |
| 3962 | 3962 | static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, |
| 3963 | 3963 | int channel, unsigned long pos, |
| 3964 | − void __user *src, unsigned long count) | |
| 3964 | + struct iov_iter *src, unsigned long count) | |
| 3965 | 3965 | { |
| 3966 | 3966 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
| 3967 | 3967 | signed char *channel_buf; |
| @@ -3972,28 +3972,14 @@ static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, · 4 unmodified lines | ||
| 3972 | 3972 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); |
| 3973 | 3973 | if (snd_BUG_ON(!channel_buf)) |
| 3974 | 3974 | return -EIO; |
| 3975 | − if (copy_from_user(channel_buf + pos, src, count)) | |
| 3975 | + if (copy_from_iter(channel_buf + pos, count, src) != count) | |
| 3976 | 3976 | return -EFAULT; |
| 3977 | 3977 | return 0; |
| 3978 | 3978 | } |
| 3979 | 3979 | |
| 3980 | −static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 3981 | − int channel, unsigned long pos, | |
| 3982 | − void *src, unsigned long count) | |
| 3983 | −{ | |
| 3984 | − struct hdsp *hdsp = snd_pcm_substream_chip(substream); | |
| 3985 | − signed char *channel_buf; | |
| 3986 | − | |
| 3987 | − channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); | |
| 3988 | − if (snd_BUG_ON(!channel_buf)) | |
| 3989 | − return -EIO; | |
| 3990 | − memcpy(channel_buf + pos, src, count); | |
| 3991 | − return 0; | |
| 3992 | −} | |
| 3993 | − | |
| 3994 | 3980 | static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, |
| 3995 | 3981 | int channel, unsigned long pos, |
| 3996 | − void __user *dst, unsigned long count) | |
| 3982 | + struct iov_iter *dst, unsigned long count) | |
| 3997 | 3983 | { |
| 3998 | 3984 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
| 3999 | 3985 | signed char *channel_buf; |
| @@ -4004,25 +3990,11 @@ static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, · 4 unmodified lines | ||
| 4004 | 3990 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); |
| 4005 | 3991 | if (snd_BUG_ON(!channel_buf)) |
| 4006 | 3992 | return -EIO; |
| 4007 | − if (copy_to_user(dst, channel_buf + pos, count)) | |
| 3993 | + if (copy_to_iter(channel_buf + pos, count, dst) != count) | |
| 4008 | 3994 | return -EFAULT; |
| 4009 | 3995 | return 0; |
| 4010 | 3996 | } |
| 4011 | 3997 | |
| 4012 | −static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 4013 | − int channel, unsigned long pos, | |
| 4014 | − void *dst, unsigned long count) | |
| 4015 | −{ | |
| 4016 | − struct hdsp *hdsp = snd_pcm_substream_chip(substream); | |
| 4017 | − signed char *channel_buf; | |
| 4018 | − | |
| 4019 | − channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); | |
| 4020 | − if (snd_BUG_ON(!channel_buf)) | |
| 4021 | − return -EIO; | |
| 4022 | − memcpy(dst, channel_buf + pos, count); | |
| 4023 | − return 0; | |
| 4024 | −} | |
| 4025 | − | |
| 4026 | 3998 | static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, |
| 4027 | 3999 | int channel, unsigned long pos, |
| 4028 | 4000 | unsigned long count) |
| @@ -4950,8 +4922,7 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = { · 921 unmodified lines | ||
| 4950 | 4922 | .prepare = snd_hdsp_prepare, |
| 4951 | 4923 | .trigger = snd_hdsp_trigger, |
| 4952 | 4924 | .pointer = snd_hdsp_hw_pointer, |
| 4953 | − .copy_user = snd_hdsp_playback_copy, | |
| 4954 | − .copy_kernel = snd_hdsp_playback_copy_kernel, | |
| 4925 | + .copy = snd_hdsp_playback_copy, | |
| 4955 | 4926 | .fill_silence = snd_hdsp_hw_silence, |
| 4956 | 4927 | }; |
| 4957 | 4928 | |
| @@ -4963,8 +4934,7 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = { · 5 unmodified lines | ||
| 4963 | 4934 | .prepare = snd_hdsp_prepare, |
| 4964 | 4935 | .trigger = snd_hdsp_trigger, |
| 4965 | 4936 | .pointer = snd_hdsp_hw_pointer, |
| 4966 | − .copy_user = snd_hdsp_capture_copy, | |
| 4967 | − .copy_kernel = snd_hdsp_capture_copy_kernel, | |
| 4937 | + .copy = snd_hdsp_capture_copy, | |
| 4968 | 4938 | }; |
| 4969 | 4939 | |
| 4970 | 4940 | static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) |
| @@ -1844,7 +1844,7 @@ static signed char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, · 1843 unmodified lines | ||
| 1844 | 1844 | |
| 1845 | 1845 | static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, |
| 1846 | 1846 | int channel, unsigned long pos, |
| 1847 | − void __user *src, unsigned long count) | |
| 1847 | + struct iov_iter *src, unsigned long count) | |
| 1848 | 1848 | { |
| 1849 | 1849 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); |
| 1850 | 1850 | signed char *channel_buf; |
| @@ -1857,30 +1857,14 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, · 6 unmodified lines | ||
| 1857 | 1857 | channel); |
| 1858 | 1858 | if (snd_BUG_ON(!channel_buf)) |
| 1859 | 1859 | return -EIO; |
| 1860 | − if (copy_from_user(channel_buf + pos, src, count)) | |
| 1860 | + if (copy_from_iter(channel_buf + pos, count, src) != count) | |
| 1861 | 1861 | return -EFAULT; |
| 1862 | 1862 | return 0; |
| 1863 | 1863 | } |
| 1864 | 1864 | |
| 1865 | −static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream *substream, | |
| 1866 | − int channel, unsigned long pos, | |
| 1867 | − void *src, unsigned long count) | |
| 1868 | −{ | |
| 1869 | − struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | |
| 1870 | − signed char *channel_buf; | |
| 1871 | − | |
| 1872 | − channel_buf = rme9652_channel_buffer_location(rme9652, | |
| 1873 | − substream->pstr->stream, | |
| 1874 | − channel); | |
| 1875 | − if (snd_BUG_ON(!channel_buf)) | |
| 1876 | − return -EIO; | |
| 1877 | − memcpy(channel_buf + pos, src, count); | |
| 1878 | − return 0; | |
| 1879 | −} | |
| 1880 | − | |
| 1881 | 1865 | static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, |
| 1882 | 1866 | int channel, unsigned long pos, |
| 1883 | − void __user *dst, unsigned long count) | |
| 1867 | + struct iov_iter *dst, unsigned long count) | |
| 1884 | 1868 | { |
| 1885 | 1869 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); |
| 1886 | 1870 | signed char *channel_buf; |
| @@ -1893,27 +1877,11 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, · 6 unmodified lines | ||
| 1893 | 1877 | channel); |
| 1894 | 1878 | if (snd_BUG_ON(!channel_buf)) |
| 1895 | 1879 | return -EIO; |
| 1896 | − if (copy_to_user(dst, channel_buf + pos, count)) | |
| 1880 | + if (copy_to_iter(channel_buf + pos, count, dst) != count) | |
| 1897 | 1881 | return -EFAULT; |
| 1898 | 1882 | return 0; |
| 1899 | 1883 | } |
| 1900 | 1884 | |
| 1901 | −static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream, | |
| 1902 | − int channel, unsigned long pos, | |
| 1903 | − void *dst, unsigned long count) | |
| 1904 | −{ | |
| 1905 | − struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | |
| 1906 | − signed char *channel_buf; | |
| 1907 | − | |
| 1908 | − channel_buf = rme9652_channel_buffer_location(rme9652, | |
| 1909 | − substream->pstr->stream, | |
| 1910 | − channel); | |
| 1911 | − if (snd_BUG_ON(!channel_buf)) | |
| 1912 | − return -EIO; | |
| 1913 | − memcpy(dst, channel_buf + pos, count); | |
| 1914 | − return 0; | |
| 1915 | −} | |
| 1916 | − | |
| 1917 | 1885 | static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, |
| 1918 | 1886 | int channel, unsigned long pos, |
| 1919 | 1887 | unsigned long count) |
| @@ -2370,8 +2338,7 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops = { · 450 unmodified lines | ||
| 2370 | 2338 | .prepare = snd_rme9652_prepare, |
| 2371 | 2339 | .trigger = snd_rme9652_trigger, |
| 2372 | 2340 | .pointer = snd_rme9652_hw_pointer, |
| 2373 | − .copy_user = snd_rme9652_playback_copy, | |
| 2374 | − .copy_kernel = snd_rme9652_playback_copy_kernel, | |
| 2341 | + .copy = snd_rme9652_playback_copy, | |
| 2375 | 2342 | .fill_silence = snd_rme9652_hw_silence, |
| 2376 | 2343 | }; |
| 2377 | 2344 | |
| @@ -2383,8 +2350,7 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = { · 5 unmodified lines | ||
| 2383 | 2350 | .prepare = snd_rme9652_prepare, |
| 2384 | 2351 | .trigger = snd_rme9652_trigger, |
| 2385 | 2352 | .pointer = snd_rme9652_hw_pointer, |
| 2386 | − .copy_user = snd_rme9652_capture_copy, | |
| 2387 | − .copy_kernel = snd_rme9652_capture_copy_kernel, | |
| 2353 | + .copy = snd_rme9652_capture_copy, | |
| 2388 | 2354 | }; |
| 2389 | 2355 | |
| 2390 | 2356 | static int snd_rme9652_create_pcm(struct snd_card *card, |
| @@ -1984,11 +1984,7 @@ static int snd_via8233_init_misc(struct via82xx *chip) · 1983 unmodified lines | ||
| 1984 | 1984 | /* when no h/w PCM volume control is found, use DXS volume control |
| 1985 | 1985 | * as the PCM vol control |
| 1986 | 1986 | */ |
| 1987 | − struct snd_ctl_elem_id sid; | |
| 1988 | − memset(&sid, 0, sizeof(sid)); | |
| 1989 | − strcpy(sid.name, "PCM Playback Volume"); | |
| 1990 | − sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | |
| 1991 | − if (! snd_ctl_find_id(chip->card, &sid)) { | |
| 1987 | + if (!snd_ctl_find_id_mixer(chip->card, "PCM Playback Volume")) { | |
| 1992 | 1988 | dev_info(chip->card->dev, |
| 1993 | 1989 | "Using DXS as PCM Playback\n"); |
| 1994 | 1990 | err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip)); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <asm/nvram.h> |
| 12 | 12 | #include <linux/init.h> |
| 13 | 13 | #include <linux/delay.h> |
| 14 | +#include <linux/of.h> | |
| 14 | 15 | #include <linux/slab.h> |
| 15 | 16 | #include <sound/core.h> |
| 16 | 17 | #include "pmac.h" |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/io.h> |
| 10 | 10 | #include <linux/init.h> |
| 11 | 11 | #include <linux/delay.h> |
| 12 | +#include <linux/of.h> | |
| 12 | 13 | #include <sound/core.h> |
| 13 | 14 | #include "pmac.h" |
| 14 | 15 | #include "burgundy.h" |
| @@ -158,12 +158,12 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) · 157 unmodified lines | ||
| 158 | 158 | |
| 159 | 159 | static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, |
| 160 | 160 | int channel, unsigned long pos, |
| 161 | − void __user *src, unsigned long count) | |
| 161 | + struct iov_iter *src, unsigned long count) | |
| 162 | 162 | { |
| 163 | 163 | /* channel is not used (interleaved data) */ |
| 164 | 164 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); |
| 165 | 165 | |
| 166 | − if (copy_from_user_toio(chip->data_buffer + pos, src, count)) | |
| 166 | + if (copy_from_iter_toio(chip->data_buffer + pos, src, count)) | |
| 167 | 167 | return -EFAULT; |
| 168 | 168 | chip->buffer_end = chip->data_buffer + pos + count; |
| 169 | 169 | |
| @@ -175,24 +175,6 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, · 5 unmodified lines | ||
| 175 | 175 | return 0; |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | −static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream, | |
| 179 | − int channel, unsigned long pos, | |
| 180 | − void *src, unsigned long count) | |
| 181 | −{ | |
| 182 | − /* channel is not used (interleaved data) */ | |
| 183 | − struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); | |
| 184 | − | |
| 185 | − memcpy_toio(chip->data_buffer + pos, src, count); | |
| 186 | − chip->buffer_end = chip->data_buffer + pos + count; | |
| 187 | − | |
| 188 | − if (chip->empty) { | |
| 189 | − chip->empty = 0; | |
| 190 | − dac_audio_start_timer(chip); | |
| 191 | − } | |
| 192 | − | |
| 193 | − return 0; | |
| 194 | −} | |
| 195 | − | |
| 196 | 178 | static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, |
| 197 | 179 | int channel, unsigned long pos, |
| 198 | 180 | unsigned long count) |
| @@ -227,8 +209,7 @@ static const struct snd_pcm_ops snd_sh_dac_pcm_ops = { · 28 unmodified lines | ||
| 227 | 209 | .prepare = snd_sh_dac_pcm_prepare, |
| 228 | 210 | .trigger = snd_sh_dac_pcm_trigger, |
| 229 | 211 | .pointer = snd_sh_dac_pcm_pointer, |
| 230 | − .copy_user = snd_sh_dac_pcm_copy, | |
| 231 | − .copy_kernel = snd_sh_dac_pcm_copy_kernel, | |
| 212 | + .copy = snd_sh_dac_pcm_copy, | |
| 232 | 213 | .fill_silence = snd_sh_dac_pcm_silence, |
| 233 | 214 | .mmap = snd_pcm_lib_mmap_iomem, |
| 234 | 215 | }; |
| @@ -38,6 +38,17 @@ config SND_SOC_TOPOLOGY · 37 unmodified lines | ||
| 38 | 38 | bool |
| 39 | 39 | select SND_DYNAMIC_MINORS |
| 40 | 40 | |
| 41 | +config SND_SOC_TOPOLOGY_BUILD | |
| 42 | + bool "Build topology core" | |
| 43 | + select SND_SOC_TOPOLOGY | |
| 44 | + depends on KUNIT | |
| 45 | + help | |
| 46 | + This option exists to facilitate running the KUnit tests for | |
| 47 | + the topology core, KUnit is frequently tested in virtual | |
| 48 | + environments with minimal drivers enabled but the topology | |
| 49 | + core is usually selected by drivers. There is little reason | |
| 50 | + to enable it if not doing a KUnit build. | |
| 51 | + | |
| 41 | 52 | config SND_SOC_TOPOLOGY_KUNIT_TEST |
| 42 | 53 | tristate "KUnit tests for SoC topology" |
| 43 | 54 | depends on KUNIT |
| @@ -147,6 +147,7 @@ static int axi_i2s_dai_probe(struct snd_soc_dai *dai) · 146 unmodified lines | ||
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | static const struct snd_soc_dai_ops axi_i2s_dai_ops = { |
| 150 | + .probe = axi_i2s_dai_probe, | |
| 150 | 151 | .startup = axi_i2s_startup, |
| 151 | 152 | .shutdown = axi_i2s_shutdown, |
| 152 | 153 | .trigger = axi_i2s_trigger, |
| @@ -154,7 +155,6 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = { · 1 unmodified line | ||
| 154 | 155 | }; |
| 155 | 156 | |
| 156 | 157 | static struct snd_soc_dai_driver axi_i2s_dai = { |
| 157 | − .probe = axi_i2s_dai_probe, | |
| 158 | 158 | .ops = &axi_i2s_dai_ops, |
| 159 | 159 | .symmetric_rate = 1, |
| 160 | 160 | }; |
| @@ -148,6 +148,7 @@ static void axi_spdif_shutdown(struct snd_pcm_substream *substream, · 147 unmodified lines | ||
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | static const struct snd_soc_dai_ops axi_spdif_dai_ops = { |
| 151 | + .probe = axi_spdif_dai_probe, | |
| 151 | 152 | .startup = axi_spdif_startup, |
| 152 | 153 | .shutdown = axi_spdif_shutdown, |
| 153 | 154 | .trigger = axi_spdif_trigger, |
| @@ -155,7 +156,6 @@ static const struct snd_soc_dai_ops axi_spdif_dai_ops = { · 1 unmodified line | ||
| 155 | 156 | }; |
| 156 | 157 | |
| 157 | 158 | static struct snd_soc_dai_driver axi_spdif_dai = { |
| 158 | − .probe = axi_spdif_dai_probe, | |
| 159 | 159 | .playback = { |
| 160 | 160 | .channels_min = 2, |
| 161 | 161 | .channels_max = 2, |
| @@ -79,14 +79,15 @@ config SND_SOC_AMD_ACP5x · 78 unmodified lines | ||
| 79 | 79 | ACP DMA driver, CPU DAI driver. |
| 80 | 80 | |
| 81 | 81 | config SND_SOC_AMD_VANGOGH_MACH |
| 82 | − tristate "AMD Vangogh support for NAU8821 CS35L41" | |
| 82 | + tristate "AMD Vangogh support for NAU8821/CS35L41/MAX98388" | |
| 83 | 83 | select SND_SOC_NAU8821 |
| 84 | 84 | select SND_SOC_CS35L41_SPI |
| 85 | + select SND_SOC_MAX98388 | |
| 85 | 86 | select SND_AMD_ACP_CONFIG |
| 86 | 87 | depends on SND_SOC_AMD_ACP5x && I2C && SPI_MASTER |
| 87 | 88 | help |
| 88 | 89 | This option enables machine driver for Vangogh platform |
| 89 | − using NAU8821 and CS35L41 codecs. | |
| 90 | + using NAU8821 and either CS35L41 or MAX98388 codecs. | |
| 90 | 91 | Say m if you have such a device. |
| 91 | 92 | If unsure select "N". |
| 92 | 93 | |
| @@ -47,6 +47,20 @@ static const struct config_entry config_table[] = { · 46 unmodified lines | ||
| 47 | 47 | {} |
| 48 | 48 | }, |
| 49 | 49 | }, |
| 50 | + { | |
| 51 | + .flags = FLAG_AMD_SOF, | |
| 52 | + .device = ACP_PCI_DEV_ID, | |
| 53 | + .dmi_table = (const struct dmi_system_id []) { | |
| 54 | + { | |
| 55 | + .matches = { | |
| 56 | + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), | |
| 57 | + DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"), | |
| 58 | + DMI_MATCH(DMI_PRODUCT_FAMILY, "Sephiroth"), | |
| 59 | + }, | |
| 60 | + }, | |
| 61 | + {} | |
| 62 | + }, | |
| 63 | + }, | |
| 50 | 64 | }; |
| 51 | 65 | |
| 52 | 66 | int snd_amd_acp_find_config(struct pci_dev *pci) |
| @@ -82,6 +96,11 @@ static struct snd_soc_acpi_codecs amp_max = { · 29 unmodified lines | ||
| 82 | 96 | .codecs = {"MX98360A"} |
| 83 | 97 | }; |
| 84 | 98 | |
| 99 | +static struct snd_soc_acpi_codecs amp_max98388 = { | |
| 100 | + .num_codecs = 1, | |
| 101 | + .codecs = {"ADS8388"} | |
| 102 | +}; | |
| 103 | + | |
| 85 | 104 | struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[] = { |
| 86 | 105 | { |
| 87 | 106 | .id = "10EC5682", |
| @@ -130,6 +149,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[] = { · 42 unmodified lines | ||
| 130 | 149 | }; |
| 131 | 150 | EXPORT_SYMBOL(snd_soc_acpi_amd_sof_machines); |
| 132 | 151 | |
| 152 | +struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[] = { | |
| 153 | + { | |
| 154 | + .id = "NVTN2020", | |
| 155 | + .drv_name = "nau8821-max", | |
| 156 | + .pdata = &acp_quirk_data, | |
| 157 | + .machine_quirk = snd_soc_acpi_codec_list, | |
| 158 | + .quirk_data = &_max98388, | |
| 159 | + .fw_filename = "sof-vangogh.ri", | |
| 160 | + .sof_tplg_filename = "sof-vangogh-nau8821-max.tplg", | |
| 161 | + }, | |
| 162 | + {}, | |
| 163 | +}; | |
| 164 | +EXPORT_SYMBOL(snd_soc_acpi_amd_vangogh_sof_machines); | |
| 165 | + | |
| 133 | 166 | struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = { |
| 134 | 167 | { |
| 135 | 168 | .id = "AMDI1019", |
| @@ -28,6 +28,21 @@ · 27 unmodified lines | ||
| 28 | 28 | #define RT5682_PLL_FREQ (48000 * 512) |
| 29 | 29 | |
| 30 | 30 | static struct snd_soc_jack cz_jack; |
| 31 | +static struct snd_soc_jack_pin cz_jack_pins[] = { | |
| 32 | + { | |
| 33 | + .pin = "Headphone Jack", | |
| 34 | + .mask = SND_JACK_HEADPHONE, | |
| 35 | + }, | |
| 36 | + { | |
| 37 | + .pin = "Headset Mic", | |
| 38 | + .mask = SND_JACK_MICROPHONE, | |
| 39 | + }, | |
| 40 | + { | |
| 41 | + .pin = "Line Out", | |
| 42 | + .mask = SND_JACK_LINEOUT, | |
| 43 | + }, | |
| 44 | +}; | |
| 45 | + | |
| 31 | 46 | static struct clk *da7219_dai_wclk; |
| 32 | 47 | static struct clk *da7219_dai_bclk; |
| 33 | 48 | static struct clk *rt5682_dai_wclk; |
| @@ -66,11 +81,13 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) · 32 unmodified lines | ||
| 66 | 81 | if (IS_ERR(da7219_dai_bclk)) |
| 67 | 82 | return PTR_ERR(da7219_dai_bclk); |
| 68 | 83 | |
| 69 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 70 | − SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 71 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 72 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 73 | − &cz_jack); | |
| 84 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 85 | + SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 86 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 87 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 88 | + &cz_jack, | |
| 89 | + cz_jack_pins, | |
| 90 | + ARRAY_SIZE(cz_jack_pins)); | |
| 74 | 91 | if (ret) { |
| 75 | 92 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 76 | 93 | return ret; |
| @@ -146,11 +163,13 @@ static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd) · 69 unmodified lines | ||
| 146 | 163 | if (IS_ERR(rt5682_dai_bclk)) |
| 147 | 164 | return PTR_ERR(rt5682_dai_bclk); |
| 148 | 165 | |
| 149 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 150 | − SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 151 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 152 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 153 | − &cz_jack); | |
| 166 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 167 | + SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 168 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 169 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 170 | + &cz_jack, | |
| 171 | + cz_jack_pins, | |
| 172 | + ARRAY_SIZE(cz_jack_pins)); | |
| 154 | 173 | if (ret) { |
| 155 | 174 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 156 | 175 | return ret; |
| @@ -631,6 +650,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = { · 474 unmodified lines | ||
| 631 | 650 | static const struct snd_soc_dapm_widget cz_widgets[] = { |
| 632 | 651 | SND_SOC_DAPM_HP("Headphones", NULL), |
| 633 | 652 | SND_SOC_DAPM_SPK("Speakers", NULL), |
| 653 | + SND_SOC_DAPM_LINE("Line Out", NULL), | |
| 634 | 654 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
| 635 | 655 | SND_SOC_DAPM_MIC("Int Mic", NULL), |
| 636 | 656 | }; |
| @@ -654,6 +674,7 @@ static const struct snd_soc_dapm_route cz_rt5682_audio_route[] = { · 17 unmodified lines | ||
| 654 | 674 | static const struct snd_kcontrol_new cz_mc_controls[] = { |
| 655 | 675 | SOC_DAPM_PIN_SWITCH("Headphones"), |
| 656 | 676 | SOC_DAPM_PIN_SWITCH("Speakers"), |
| 677 | + SOC_DAPM_PIN_SWITCH("Line Out"), | |
| 657 | 678 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
| 658 | 679 | SOC_DAPM_PIN_SWITCH("Int Mic"), |
| 659 | 680 | }; |
| @@ -42,6 +42,16 @@ · 41 unmodified lines | ||
| 42 | 42 | #define CZ_PLAT_CLK 24000000 |
| 43 | 43 | |
| 44 | 44 | static struct snd_soc_jack cz_jack; |
| 45 | +static struct snd_soc_jack_pin cz_jack_pins[] = { | |
| 46 | + { | |
| 47 | + .pin = "Headphones", | |
| 48 | + .mask = SND_JACK_HEADPHONE, | |
| 49 | + }, | |
| 50 | + { | |
| 51 | + .pin = "Headset Mic", | |
| 52 | + .mask = SND_JACK_MICROPHONE, | |
| 53 | + }, | |
| 54 | +}; | |
| 45 | 55 | |
| 46 | 56 | static int cz_aif1_hw_params(struct snd_pcm_substream *substream, |
| 47 | 57 | struct snd_pcm_hw_params *params) |
| @@ -76,11 +86,13 @@ static int cz_init(struct snd_soc_pcm_runtime *rtd) · 28 unmodified lines | ||
| 76 | 86 | codec = asoc_rtd_to_codec(rtd, 0)->component; |
| 77 | 87 | card = rtd->card; |
| 78 | 88 | |
| 79 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 80 | − SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | |
| 81 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 82 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 83 | − &cz_jack); | |
| 89 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 90 | + SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | |
| 91 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 92 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 93 | + &cz_jack, | |
| 94 | + cz_jack_pins, | |
| 95 | + ARRAY_SIZE(cz_jack_pins)); | |
| 84 | 96 | if (ret) { |
| 85 | 97 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 86 | 98 | return ret; |
| @@ -18,6 +18,9 @@ if SND_SOC_AMD_ACP_COMMON · 17 unmodified lines | ||
| 18 | 18 | config SND_SOC_AMD_ACP_PDM |
| 19 | 19 | tristate |
| 20 | 20 | |
| 21 | +config SND_SOC_AMD_ACP_LEGACY_COMMON | |
| 22 | + tristate | |
| 23 | + | |
| 21 | 24 | config SND_SOC_AMD_ACP_I2S |
| 22 | 25 | tristate |
| 23 | 26 | |
| @@ -27,6 +30,7 @@ config SND_SOC_AMD_ACP_PCM · 3 unmodified lines | ||
| 27 | 30 | |
| 28 | 31 | config SND_SOC_AMD_ACP_PCI |
| 29 | 32 | tristate "AMD ACP PCI Driver Support" |
| 33 | + select SND_SOC_AMD_ACP_LEGACY_COMMON | |
| 30 | 34 | depends on X86 && PCI |
| 31 | 35 | help |
| 32 | 36 | This options enables generic PCI driver for ACP device. |
| @@ -36,6 +40,7 @@ config SND_AMD_ASOC_RENOIR · 3 unmodified lines | ||
| 36 | 40 | select SND_SOC_AMD_ACP_PCM |
| 37 | 41 | select SND_SOC_AMD_ACP_I2S |
| 38 | 42 | select SND_SOC_AMD_ACP_PDM |
| 43 | + select SND_SOC_AMD_ACP_LEGACY_COMMON | |
| 39 | 44 | depends on X86 && PCI |
| 40 | 45 | help |
| 41 | 46 | This option enables Renoir I2S support on AMD platform. |
| @@ -45,6 +50,7 @@ config SND_AMD_ASOC_REMBRANDT · 3 unmodified lines | ||
| 45 | 50 | select SND_SOC_AMD_ACP_PCM |
| 46 | 51 | select SND_SOC_AMD_ACP_I2S |
| 47 | 52 | select SND_SOC_AMD_ACP_PDM |
| 53 | + select SND_SOC_AMD_ACP_LEGACY_COMMON | |
| 48 | 54 | depends on X86 && PCI |
| 49 | 55 | help |
| 50 | 56 | This option enables Rembrandt I2S support on AMD platform. |
| @@ -61,6 +67,8 @@ config SND_SOC_AMD_MACH_COMMON · 10 unmodified lines | ||
| 61 | 67 | select SND_SOC_MAX98357A |
| 62 | 68 | select SND_SOC_RT5682S |
| 63 | 69 | select SND_SOC_NAU8825 |
| 70 | + select SND_SOC_NAU8821 | |
| 71 | + select SND_SOC_MAX98388 | |
| 64 | 72 | help |
| 65 | 73 | This option enables common Machine driver module for ACP. |
| 66 | 74 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | snd-acp-pcm-objs := acp-platform.o |
| 9 | 9 | snd-acp-i2s-objs := acp-i2s.o |
| 10 | 10 | snd-acp-pdm-objs := acp-pdm.o |
| 11 | +snd-acp-legacy-common-objs := acp-legacy-common.o | |
| 11 | 12 | snd-acp-pci-objs := acp-pci.o |
| 12 | 13 | |
| 13 | 14 | #platform specific driver |
| @@ -22,6 +23,7 @@ snd-acp-sof-mach-objs := acp-sof-mach.o · 8 unmodified lines | ||
| 22 | 23 | obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o |
| 23 | 24 | obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o |
| 24 | 25 | obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o |
| 26 | +obj-$(CONFIG_SND_SOC_AMD_ACP_LEGACY_COMMON) += snd-acp-legacy-common.o | |
| 25 | 27 | obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o |
| 26 | 28 | |
| 27 | 29 | obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o |
| @@ -149,6 +149,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ · 148 unmodified lines | ||
| 149 | 149 | dev_err(dev, "Invalid dai id %x\n", dai->driver->id); |
| 150 | 150 | return -EINVAL; |
| 151 | 151 | } |
| 152 | + adata->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution; | |
| 152 | 153 | } else { |
| 153 | 154 | switch (dai->driver->id) { |
| 154 | 155 | case I2S_BT_INSTANCE: |
| @@ -167,6 +168,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ · 12 unmodified lines | ||
| 167 | 168 | dev_err(dev, "Invalid dai id %x\n", dai->driver->id); |
| 168 | 169 | return -EINVAL; |
| 169 | 170 | } |
| 171 | + adata->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution; | |
| 170 | 172 | } |
| 171 | 173 | |
| 172 | 174 | val = readl(adata->acp_base + reg_val); |
| @@ -537,17 +539,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d · 364 unmodified lines | ||
| 537 | 539 | return 0; |
| 538 | 540 | } |
| 539 | 541 | |
| 540 | −const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { | |
| 541 | − .startup = acp_i2s_startup, | |
| 542 | − .hw_params = acp_i2s_hwparams, | |
| 543 | − .prepare = acp_i2s_prepare, | |
| 544 | − .trigger = acp_i2s_trigger, | |
| 545 | − .set_fmt = acp_i2s_set_fmt, | |
| 546 | − .set_tdm_slot = acp_i2s_set_tdm_slot, | |
| 547 | −}; | |
| 548 | −EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON); | |
| 549 | − | |
| 550 | −int asoc_acp_i2s_probe(struct snd_soc_dai *dai) | |
| 542 | +static int acp_i2s_probe(struct snd_soc_dai *dai) | |
| 551 | 543 | { |
| 552 | 544 | struct device *dev = dai->component->dev; |
| 553 | 545 | struct acp_dev_data *adata = dev_get_drvdata(dev); |
| @@ -567,7 +559,17 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai) · 13 unmodified lines | ||
| 567 | 559 | |
| 568 | 560 | return 0; |
| 569 | 561 | } |
| 570 | −EXPORT_SYMBOL_NS_GPL(asoc_acp_i2s_probe, SND_SOC_ACP_COMMON); | |
| 562 | + | |
| 563 | +const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { | |
| 564 | + .probe = acp_i2s_probe, | |
| 565 | + .startup = acp_i2s_startup, | |
| 566 | + .hw_params = acp_i2s_hwparams, | |
| 567 | + .prepare = acp_i2s_prepare, | |
| 568 | + .trigger = acp_i2s_trigger, | |
| 569 | + .set_fmt = acp_i2s_set_fmt, | |
| 570 | + .set_tdm_slot = acp_i2s_set_tdm_slot, | |
| 571 | +}; | |
| 572 | +EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON); | |
| 571 | 573 | |
| 572 | 574 | MODULE_LICENSE("Dual BSD/GPL"); |
| 573 | 575 | MODULE_ALIAS(DRV_NAME); |
| @@ -0,0 +1,347 @@ | ||
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) | |
| 2 | +// | |
| 3 | +// This file is provided under a dual BSD/GPLv2 license. When using or | |
| 4 | +// redistributing this file, you may do so under either license. | |
| 5 | +// | |
| 6 | +// Copyright(c) 2023 Advanced Micro Devices, Inc. | |
| 7 | +// | |
| 8 | +// Authors: Syed Saba Kareem <Syed.SabaKareem@amd.com> | |
| 9 | +// | |
| 10 | + | |
| 11 | +/* | |
| 12 | + * Common file to be used by amd platforms | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include "amd.h" | |
| 16 | +#include <linux/pci.h> | |
| 17 | +#include <linux/export.h> | |
| 18 | + | |
| 19 | +void acp_enable_interrupts(struct acp_dev_data *adata) | |
| 20 | +{ | |
| 21 | + struct acp_resource *rsrc = adata->rsrc; | |
| 22 | + u32 ext_intr_ctrl; | |
| 23 | + | |
| 24 | + writel(0x01, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 25 | + ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 26 | + ext_intr_ctrl |= ACP_ERROR_MASK; | |
| 27 | + writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 28 | +} | |
| 29 | +EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, SND_SOC_ACP_COMMON); | |
| 30 | + | |
| 31 | +void acp_disable_interrupts(struct acp_dev_data *adata) | |
| 32 | +{ | |
| 33 | + struct acp_resource *rsrc = adata->rsrc; | |
| 34 | + | |
| 35 | + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); | |
| 36 | + writel(0x00, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 37 | +} | |
| 38 | +EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, SND_SOC_ACP_COMMON); | |
| 39 | + | |
| 40 | +static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream, | |
| 41 | + struct snd_soc_dai *dai) | |
| 42 | +{ | |
| 43 | + struct snd_pcm_runtime *runtime = substream->runtime; | |
| 44 | + struct acp_stream *stream = runtime->private_data; | |
| 45 | + struct device *dev = dai->component->dev; | |
| 46 | + struct acp_dev_data *adata = dev_get_drvdata(dev); | |
| 47 | + | |
| 48 | + u32 physical_addr, pdm_size, period_bytes; | |
| 49 | + | |
| 50 | + period_bytes = frames_to_bytes(runtime, runtime->period_size); | |
| 51 | + pdm_size = frames_to_bytes(runtime, runtime->buffer_size); | |
| 52 | + physical_addr = stream->reg_offset + MEM_WINDOW_START; | |
| 53 | + | |
| 54 | + /* Init ACP PDM Ring buffer */ | |
| 55 | + writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR); | |
| 56 | + writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE); | |
| 57 | + writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); | |
| 58 | + writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); | |
| 59 | +} | |
| 60 | + | |
| 61 | +static void set_acp_pdm_clk(struct snd_pcm_substream *substream, | |
| 62 | + struct snd_soc_dai *dai) | |
| 63 | +{ | |
| 64 | + struct device *dev = dai->component->dev; | |
| 65 | + struct acp_dev_data *adata = dev_get_drvdata(dev); | |
| 66 | + unsigned int pdm_ctrl; | |
| 67 | + | |
| 68 | + /* Enable default ACP PDM clk */ | |
| 69 | + writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL); | |
| 70 | + pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL); | |
| 71 | + pdm_ctrl |= PDM_MISC_CTRL_MASK; | |
| 72 | + writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL); | |
| 73 | + set_acp_pdm_ring_buffer(substream, dai); | |
| 74 | +} | |
| 75 | + | |
| 76 | +void restore_acp_pdm_params(struct snd_pcm_substream *substream, | |
| 77 | + struct acp_dev_data *adata) | |
| 78 | +{ | |
| 79 | + struct snd_soc_dai *dai; | |
| 80 | + struct snd_soc_pcm_runtime *soc_runtime; | |
| 81 | + u32 ext_int_ctrl; | |
| 82 | + | |
| 83 | + soc_runtime = asoc_substream_to_rtd(substream); | |
| 84 | + dai = asoc_rtd_to_cpu(soc_runtime, 0); | |
| 85 | + /* Programming channel mask and sampling rate */ | |
| 86 | + writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); | |
| 87 | + writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR); | |
| 88 | + | |
| 89 | + /* Enabling ACP Pdm interuppts */ | |
| 90 | + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0)); | |
| 91 | + ext_int_ctrl |= PDM_DMA_INTR_MASK; | |
| 92 | + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0)); | |
| 93 | + set_acp_pdm_clk(substream, dai); | |
| 94 | +} | |
| 95 | +EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, SND_SOC_ACP_COMMON); | |
| 96 | + | |
| 97 | +static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, | |
| 98 | + struct snd_soc_dai *dai) | |
| 99 | +{ | |
| 100 | + struct device *dev = dai->component->dev; | |
| 101 | + struct acp_dev_data *adata = dev_get_drvdata(dev); | |
| 102 | + struct acp_resource *rsrc = adata->rsrc; | |
| 103 | + struct acp_stream *stream = substream->runtime->private_data; | |
| 104 | + u32 reg_dma_size, reg_fifo_size, reg_fifo_addr; | |
| 105 | + u32 phy_addr, acp_fifo_addr, ext_int_ctrl; | |
| 106 | + unsigned int dir = substream->stream; | |
| 107 | + | |
| 108 | + switch (dai->driver->id) { | |
| 109 | + case I2S_SP_INSTANCE: | |
| 110 | + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 111 | + reg_dma_size = ACP_I2S_TX_DMA_SIZE; | |
| 112 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 113 | + SP_PB_FIFO_ADDR_OFFSET; | |
| 114 | + reg_fifo_addr = ACP_I2S_TX_FIFOADDR; | |
| 115 | + reg_fifo_size = ACP_I2S_TX_FIFOSIZE; | |
| 116 | + phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; | |
| 117 | + writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); | |
| 118 | + } else { | |
| 119 | + reg_dma_size = ACP_I2S_RX_DMA_SIZE; | |
| 120 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 121 | + SP_CAPT_FIFO_ADDR_OFFSET; | |
| 122 | + reg_fifo_addr = ACP_I2S_RX_FIFOADDR; | |
| 123 | + reg_fifo_size = ACP_I2S_RX_FIFOSIZE; | |
| 124 | + phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; | |
| 125 | + writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); | |
| 126 | + } | |
| 127 | + break; | |
| 128 | + case I2S_BT_INSTANCE: | |
| 129 | + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 130 | + reg_dma_size = ACP_BT_TX_DMA_SIZE; | |
| 131 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 132 | + BT_PB_FIFO_ADDR_OFFSET; | |
| 133 | + reg_fifo_addr = ACP_BT_TX_FIFOADDR; | |
| 134 | + reg_fifo_size = ACP_BT_TX_FIFOSIZE; | |
| 135 | + phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; | |
| 136 | + writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); | |
| 137 | + } else { | |
| 138 | + reg_dma_size = ACP_BT_RX_DMA_SIZE; | |
| 139 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 140 | + BT_CAPT_FIFO_ADDR_OFFSET; | |
| 141 | + reg_fifo_addr = ACP_BT_RX_FIFOADDR; | |
| 142 | + reg_fifo_size = ACP_BT_RX_FIFOSIZE; | |
| 143 | + phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; | |
| 144 | + writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); | |
| 145 | + } | |
| 146 | + break; | |
| 147 | + case I2S_HS_INSTANCE: | |
| 148 | + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 149 | + reg_dma_size = ACP_HS_TX_DMA_SIZE; | |
| 150 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 151 | + HS_PB_FIFO_ADDR_OFFSET; | |
| 152 | + reg_fifo_addr = ACP_HS_TX_FIFOADDR; | |
| 153 | + reg_fifo_size = ACP_HS_TX_FIFOSIZE; | |
| 154 | + phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; | |
| 155 | + writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR); | |
| 156 | + } else { | |
| 157 | + reg_dma_size = ACP_HS_RX_DMA_SIZE; | |
| 158 | + acp_fifo_addr = rsrc->sram_pte_offset + | |
| 159 | + HS_CAPT_FIFO_ADDR_OFFSET; | |
| 160 | + reg_fifo_addr = ACP_HS_RX_FIFOADDR; | |
| 161 | + reg_fifo_size = ACP_HS_RX_FIFOSIZE; | |
| 162 | + phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; | |
| 163 | + writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR); | |
| 164 | + } | |
| 165 | + break; | |
| 166 | + default: | |
| 167 | + dev_err(dev, "Invalid dai id %x\n", dai->driver->id); | |
| 168 | + return -EINVAL; | |
| 169 | + } | |
| 170 | + | |
| 171 | + writel(DMA_SIZE, adata->acp_base + reg_dma_size); | |
| 172 | + writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); | |
| 173 | + writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); | |
| 174 | + | |
| 175 | + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 176 | + ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | | |
| 177 | + BIT(BT_RX_THRESHOLD(rsrc->offset)) | | |
| 178 | + BIT(I2S_TX_THRESHOLD(rsrc->offset)) | | |
| 179 | + BIT(BT_TX_THRESHOLD(rsrc->offset)) | | |
| 180 | + BIT(HS_RX_THRESHOLD(rsrc->offset)) | | |
| 181 | + BIT(HS_TX_THRESHOLD(rsrc->offset)); | |
| 182 | + | |
| 183 | + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 184 | + return 0; | |
| 185 | +} | |
| 186 | + | |
| 187 | +int restore_acp_i2s_params(struct snd_pcm_substream *substream, | |
| 188 | + struct acp_dev_data *adata, | |
| 189 | + struct acp_stream *stream) | |
| 190 | +{ | |
| 191 | + struct snd_soc_dai *dai; | |
| 192 | + struct snd_soc_pcm_runtime *soc_runtime; | |
| 193 | + u32 tdm_fmt, reg_val, fmt_reg, val; | |
| 194 | + | |
| 195 | + soc_runtime = asoc_substream_to_rtd(substream); | |
| 196 | + dai = asoc_rtd_to_cpu(soc_runtime, 0); | |
| 197 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 198 | + tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1]; | |
| 199 | + switch (stream->dai_id) { | |
| 200 | + case I2S_BT_INSTANCE: | |
| 201 | + reg_val = ACP_BTTDM_ITER; | |
| 202 | + fmt_reg = ACP_BTTDM_TXFRMT; | |
| 203 | + break; | |
| 204 | + case I2S_SP_INSTANCE: | |
| 205 | + reg_val = ACP_I2STDM_ITER; | |
| 206 | + fmt_reg = ACP_I2STDM_TXFRMT; | |
| 207 | + break; | |
| 208 | + case I2S_HS_INSTANCE: | |
| 209 | + reg_val = ACP_HSTDM_ITER; | |
| 210 | + fmt_reg = ACP_HSTDM_TXFRMT; | |
| 211 | + break; | |
| 212 | + default: | |
| 213 | + pr_err("Invalid dai id %x\n", stream->dai_id); | |
| 214 | + return -EINVAL; | |
| 215 | + } | |
| 216 | + val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3; | |
| 217 | + } else { | |
| 218 | + tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1]; | |
| 219 | + switch (stream->dai_id) { | |
| 220 | + case I2S_BT_INSTANCE: | |
| 221 | + reg_val = ACP_BTTDM_IRER; | |
| 222 | + fmt_reg = ACP_BTTDM_RXFRMT; | |
| 223 | + break; | |
| 224 | + case I2S_SP_INSTANCE: | |
| 225 | + reg_val = ACP_I2STDM_IRER; | |
| 226 | + fmt_reg = ACP_I2STDM_RXFRMT; | |
| 227 | + break; | |
| 228 | + case I2S_HS_INSTANCE: | |
| 229 | + reg_val = ACP_HSTDM_IRER; | |
| 230 | + fmt_reg = ACP_HSTDM_RXFRMT; | |
| 231 | + break; | |
| 232 | + default: | |
| 233 | + pr_err("Invalid dai id %x\n", stream->dai_id); | |
| 234 | + return -EINVAL; | |
| 235 | + } | |
| 236 | + val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3; | |
| 237 | + } | |
| 238 | + writel(val, adata->acp_base + reg_val); | |
| 239 | + if (adata->tdm_mode == TDM_ENABLE) { | |
| 240 | + writel(tdm_fmt, adata->acp_base + fmt_reg); | |
| 241 | + val = readl(adata->acp_base + reg_val); | |
| 242 | + writel(val | 0x2, adata->acp_base + reg_val); | |
| 243 | + } | |
| 244 | + return set_acp_i2s_dma_fifo(substream, dai); | |
| 245 | +} | |
| 246 | +EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, SND_SOC_ACP_COMMON); | |
| 247 | + | |
| 248 | +static int acp_power_on(struct acp_chip_info *chip) | |
| 249 | +{ | |
| 250 | + u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg; | |
| 251 | + void __iomem *base; | |
| 252 | + | |
| 253 | + base = chip->base; | |
| 254 | + switch (chip->acp_rev) { | |
| 255 | + case ACP3X_DEV: | |
| 256 | + acp_pgfsm_stat_reg = ACP_PGFSM_STATUS; | |
| 257 | + acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL; | |
| 258 | + break; | |
| 259 | + case ACP6X_DEV: | |
| 260 | + acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS; | |
| 261 | + acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL; | |
| 262 | + break; | |
| 263 | + default: | |
| 264 | + return -EINVAL; | |
| 265 | + } | |
| 266 | + | |
| 267 | + val = readl(base + acp_pgfsm_stat_reg); | |
| 268 | + if (val == ACP_POWERED_ON) | |
| 269 | + return 0; | |
| 270 | + | |
| 271 | + if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) | |
| 272 | + writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg); | |
| 273 | + | |
| 274 | + return readl_poll_timeout(base + acp_pgfsm_stat_reg, val, | |
| 275 | + !val, DELAY_US, ACP_TIMEOUT); | |
| 276 | +} | |
| 277 | + | |
| 278 | +static int acp_reset(void __iomem *base) | |
| 279 | +{ | |
| 280 | + u32 val; | |
| 281 | + int ret; | |
| 282 | + | |
| 283 | + writel(1, base + ACP_SOFT_RESET); | |
| 284 | + ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK, | |
| 285 | + DELAY_US, ACP_TIMEOUT); | |
| 286 | + if (ret) | |
| 287 | + return ret; | |
| 288 | + | |
| 289 | + writel(0, base + ACP_SOFT_RESET); | |
| 290 | + return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); | |
| 291 | +} | |
| 292 | + | |
| 293 | +int acp_init(struct acp_chip_info *chip) | |
| 294 | +{ | |
| 295 | + int ret; | |
| 296 | + | |
| 297 | + /* power on */ | |
| 298 | + ret = acp_power_on(chip); | |
| 299 | + if (ret) { | |
| 300 | + pr_err("ACP power on failed\n"); | |
| 301 | + return ret; | |
| 302 | + } | |
| 303 | + writel(0x01, chip->base + ACP_CONTROL); | |
| 304 | + | |
| 305 | + /* Reset */ | |
| 306 | + ret = acp_reset(chip->base); | |
| 307 | + if (ret) { | |
| 308 | + pr_err("ACP reset failed\n"); | |
| 309 | + return ret; | |
| 310 | + } | |
| 311 | + return 0; | |
| 312 | +} | |
| 313 | +EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON); | |
| 314 | + | |
| 315 | +int acp_deinit(void __iomem *base) | |
| 316 | +{ | |
| 317 | + int ret; | |
| 318 | + | |
| 319 | + /* Reset */ | |
| 320 | + ret = acp_reset(base); | |
| 321 | + if (ret) | |
| 322 | + return ret; | |
| 323 | + | |
| 324 | + writel(0, base + ACP_CONTROL); | |
| 325 | + return 0; | |
| 326 | +} | |
| 327 | +EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON); | |
| 328 | + | |
| 329 | +int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data) | |
| 330 | +{ | |
| 331 | + pci_write_config_dword(dev, 0x60, smn_addr); | |
| 332 | + pci_write_config_dword(dev, 0x64, data); | |
| 333 | + return 0; | |
| 334 | +} | |
| 335 | +EXPORT_SYMBOL_NS_GPL(smn_write, SND_SOC_ACP_COMMON); | |
| 336 | + | |
| 337 | +int smn_read(struct pci_dev *dev, u32 smn_addr) | |
| 338 | +{ | |
| 339 | + u32 data; | |
| 340 | + | |
| 341 | + pci_write_config_dword(dev, 0x60, smn_addr); | |
| 342 | + pci_read_config_dword(dev, 0x64, &data); | |
| 343 | + return data; | |
| 344 | +} | |
| 345 | +EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON); | |
| 346 | + | |
| 347 | +MODULE_LICENSE("Dual BSD/GPL"); | |
| @@ -75,23 +75,6 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { · 74 unmodified lines | ||
| 75 | 75 | .tdm_mode = false, |
| 76 | 76 | }; |
| 77 | 77 | |
| 78 | −static const struct snd_kcontrol_new acp_controls[] = { | |
| 79 | − SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 80 | − SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 81 | − SOC_DAPM_PIN_SWITCH("Spk"), | |
| 82 | − SOC_DAPM_PIN_SWITCH("Left Spk"), | |
| 83 | − SOC_DAPM_PIN_SWITCH("Right Spk"), | |
| 84 | − | |
| 85 | −}; | |
| 86 | − | |
| 87 | −static const struct snd_soc_dapm_widget acp_widgets[] = { | |
| 88 | − SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 89 | − SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 90 | − SND_SOC_DAPM_SPK("Spk", NULL), | |
| 91 | − SND_SOC_DAPM_SPK("Left Spk", NULL), | |
| 92 | − SND_SOC_DAPM_SPK("Right Spk", NULL), | |
| 93 | −}; | |
| 94 | − | |
| 95 | 78 | static int acp_asoc_probe(struct platform_device *pdev) |
| 96 | 79 | { |
| 97 | 80 | struct snd_soc_card *card = NULL; |
| @@ -110,11 +93,8 @@ static int acp_asoc_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 110 | 93 | card->dev = dev; |
| 111 | 94 | card->owner = THIS_MODULE; |
| 112 | 95 | card->name = pdev->id_entry->name; |
| 113 | − card->dapm_widgets = acp_widgets; | |
| 114 | − card->num_dapm_widgets = ARRAY_SIZE(acp_widgets); | |
| 115 | − card->controls = acp_controls; | |
| 116 | − card->num_controls = ARRAY_SIZE(acp_controls); | |
| 117 | 96 | card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; |
| 97 | + /* Widgets and controls added per-codec in acp-mach-common.c */ | |
| 118 | 98 | |
| 119 | 99 | acp_card_drvdata = card->drvdata; |
| 120 | 100 | dmi_id = dmi_first_match(acp_quirk_table); |
| @@ -25,12 +25,17 @@ · 24 unmodified lines | ||
| 25 | 25 | #include "../../codecs/rt1019.h" |
| 26 | 26 | #include "../../codecs/rt5682s.h" |
| 27 | 27 | #include "../../codecs/nau8825.h" |
| 28 | +#include "../../codecs/nau8821.h" | |
| 28 | 29 | #include "acp-mach.h" |
| 29 | 30 | |
| 30 | 31 | #define PCO_PLAT_CLK 48000000 |
| 31 | 32 | #define RT5682_PLL_FREQ (48000 * 512) |
| 32 | 33 | #define DUAL_CHANNEL 2 |
| 33 | 34 | #define FOUR_CHANNEL 4 |
| 35 | +#define NAU8821_CODEC_DAI "nau8821-hifi" | |
| 36 | +#define NAU8821_BCLK 1536000 | |
| 37 | +#define NAU8821_FREQ_OUT 12288000 | |
| 38 | +#define MAX98388_CODEC_DAI "max98388-aif1" | |
| 34 | 39 | |
| 35 | 40 | #define TDM_MODE_ENABLE 1 |
| 36 | 41 | |
| @@ -46,8 +51,6 @@ const struct dmi_system_id acp_quirk_table[] = { · 9 unmodified lines | ||
| 46 | 51 | }; |
| 47 | 52 | EXPORT_SYMBOL_GPL(acp_quirk_table); |
| 48 | 53 | |
| 49 | −static struct snd_soc_jack pco_jack; | |
| 50 | − | |
| 51 | 54 | static const unsigned int channels[] = { |
| 52 | 55 | DUAL_CHANNEL, |
| 53 | 56 | }; |
| @@ -81,6 +84,28 @@ static int acp_clk_enable(struct acp_card_drvdata *drvdata, · 27 unmodified lines | ||
| 81 | 84 | SND_SOC_DAILINK_DEF(rt5682, |
| 82 | 85 | DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); |
| 83 | 86 | |
| 87 | +static struct snd_soc_jack rt5682_jack; | |
| 88 | +static struct snd_soc_jack_pin rt5682_jack_pins[] = { | |
| 89 | + { | |
| 90 | + .pin = "Headphone Jack", | |
| 91 | + .mask = SND_JACK_HEADPHONE, | |
| 92 | + }, | |
| 93 | + { | |
| 94 | + .pin = "Headset Mic", | |
| 95 | + .mask = SND_JACK_MICROPHONE, | |
| 96 | + }, | |
| 97 | +}; | |
| 98 | + | |
| 99 | +static const struct snd_kcontrol_new rt5682_controls[] = { | |
| 100 | + SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 101 | + SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 102 | +}; | |
| 103 | + | |
| 104 | +static const struct snd_soc_dapm_widget rt5682_widgets[] = { | |
| 105 | + SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 106 | + SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 107 | +}; | |
| 108 | + | |
| 84 | 109 | static const struct snd_soc_dapm_route rt5682_map[] = { |
| 85 | 110 | { "Headphone Jack", NULL, "HPOL" }, |
| 86 | 111 | { "Headphone Jack", NULL, "HPOR" }, |
| @@ -104,22 +129,38 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd) · 17 unmodified lines | ||
| 104 | 129 | drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); |
| 105 | 130 | drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); |
| 106 | 131 | |
| 107 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 108 | − SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 109 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 110 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 111 | − &pco_jack); | |
| 132 | + ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets, | |
| 133 | + ARRAY_SIZE(rt5682_widgets)); | |
| 134 | + if (ret) { | |
| 135 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 136 | + return ret; | |
| 137 | + } | |
| 138 | + | |
| 139 | + ret = snd_soc_add_card_controls(card, rt5682_controls, | |
| 140 | + ARRAY_SIZE(rt5682_controls)); | |
| 141 | + if (ret) { | |
| 142 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 143 | + return ret; | |
| 144 | + } | |
| 145 | + | |
| 146 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 147 | + SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 148 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 149 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 150 | + &rt5682_jack, | |
| 151 | + rt5682_jack_pins, | |
| 152 | + ARRAY_SIZE(rt5682_jack_pins)); | |
| 112 | 153 | if (ret) { |
| 113 | 154 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 114 | 155 | return ret; |
| 115 | 156 | } |
| 116 | 157 | |
| 117 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 118 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 119 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 120 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 158 | + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 159 | + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 160 | + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 161 | + snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 121 | 162 | |
| 122 | − ret = snd_soc_component_set_jack(component, &pco_jack, NULL); | |
| 163 | + ret = snd_soc_component_set_jack(component, &rt5682_jack, NULL); | |
| 123 | 164 | if (ret) { |
| 124 | 165 | dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); |
| 125 | 166 | return ret; |
| @@ -269,6 +310,28 @@ static const struct snd_soc_ops acp_card_rt5682_ops = { · 143 unmodified lines | ||
| 269 | 310 | SND_SOC_DAILINK_DEF(rt5682s, |
| 270 | 311 | DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1"))); |
| 271 | 312 | |
| 313 | +static struct snd_soc_jack rt5682s_jack; | |
| 314 | +static struct snd_soc_jack_pin rt5682s_jack_pins[] = { | |
| 315 | + { | |
| 316 | + .pin = "Headphone Jack", | |
| 317 | + .mask = SND_JACK_HEADPHONE, | |
| 318 | + }, | |
| 319 | + { | |
| 320 | + .pin = "Headset Mic", | |
| 321 | + .mask = SND_JACK_MICROPHONE, | |
| 322 | + }, | |
| 323 | +}; | |
| 324 | + | |
| 325 | +static const struct snd_kcontrol_new rt5682s_controls[] = { | |
| 326 | + SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 327 | + SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 328 | +}; | |
| 329 | + | |
| 330 | +static const struct snd_soc_dapm_widget rt5682s_widgets[] = { | |
| 331 | + SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 332 | + SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 333 | +}; | |
| 334 | + | |
| 272 | 335 | static const struct snd_soc_dapm_route rt5682s_map[] = { |
| 273 | 336 | { "Headphone Jack", NULL, "HPOL" }, |
| 274 | 337 | { "Headphone Jack", NULL, "HPOR" }, |
| @@ -293,22 +356,38 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) · 18 unmodified lines | ||
| 293 | 356 | drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); |
| 294 | 357 | } |
| 295 | 358 | |
| 296 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 297 | − SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 298 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 299 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 300 | − &pco_jack); | |
| 359 | + ret = snd_soc_dapm_new_controls(&card->dapm, rt5682s_widgets, | |
| 360 | + ARRAY_SIZE(rt5682s_widgets)); | |
| 361 | + if (ret) { | |
| 362 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 363 | + return ret; | |
| 364 | + } | |
| 365 | + | |
| 366 | + ret = snd_soc_add_card_controls(card, rt5682s_controls, | |
| 367 | + ARRAY_SIZE(rt5682s_controls)); | |
| 368 | + if (ret) { | |
| 369 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 370 | + return ret; | |
| 371 | + } | |
| 372 | + | |
| 373 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 374 | + SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 375 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 376 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 377 | + &rt5682s_jack, | |
| 378 | + rt5682s_jack_pins, | |
| 379 | + ARRAY_SIZE(rt5682s_jack_pins)); | |
| 301 | 380 | if (ret) { |
| 302 | 381 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 303 | 382 | return ret; |
| 304 | 383 | } |
| 305 | 384 | |
| 306 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 307 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 308 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 309 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 385 | + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 386 | + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 387 | + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 388 | + snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 310 | 389 | |
| 311 | − ret = snd_soc_component_set_jack(component, &pco_jack, NULL); | |
| 390 | + ret = snd_soc_component_set_jack(component, &rt5682s_jack, NULL); | |
| 312 | 391 | if (ret) { |
| 313 | 392 | dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); |
| 314 | 393 | return ret; |
| @@ -434,6 +513,16 @@ SND_SOC_DAILINK_DEF(rt1019, · 119 unmodified lines | ||
| 434 | 513 | DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"), |
| 435 | 514 | COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"))); |
| 436 | 515 | |
| 516 | +static const struct snd_kcontrol_new rt1019_controls[] = { | |
| 517 | + SOC_DAPM_PIN_SWITCH("Left Spk"), | |
| 518 | + SOC_DAPM_PIN_SWITCH("Right Spk"), | |
| 519 | +}; | |
| 520 | + | |
| 521 | +static const struct snd_soc_dapm_widget rt1019_widgets[] = { | |
| 522 | + SND_SOC_DAPM_SPK("Left Spk", NULL), | |
| 523 | + SND_SOC_DAPM_SPK("Right Spk", NULL), | |
| 524 | +}; | |
| 525 | + | |
| 437 | 526 | static const struct snd_soc_dapm_route rt1019_map_lr[] = { |
| 438 | 527 | { "Left Spk", NULL, "Left SPO" }, |
| 439 | 528 | { "Right Spk", NULL, "Right SPO" }, |
| @@ -454,10 +543,25 @@ static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) · 14 unmodified lines | ||
| 454 | 543 | { |
| 455 | 544 | struct snd_soc_card *card = rtd->card; |
| 456 | 545 | struct acp_card_drvdata *drvdata = card->drvdata; |
| 546 | + int ret; | |
| 457 | 547 | |
| 458 | 548 | if (drvdata->amp_codec_id != RT1019) |
| 459 | 549 | return -EINVAL; |
| 460 | 550 | |
| 551 | + ret = snd_soc_dapm_new_controls(&card->dapm, rt1019_widgets, | |
| 552 | + ARRAY_SIZE(rt1019_widgets)); | |
| 553 | + if (ret) { | |
| 554 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 555 | + return ret; | |
| 556 | + } | |
| 557 | + | |
| 558 | + ret = snd_soc_add_card_controls(card, rt1019_controls, | |
| 559 | + ARRAY_SIZE(rt1019_controls)); | |
| 560 | + if (ret) { | |
| 561 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 562 | + return ret; | |
| 563 | + } | |
| 564 | + | |
| 461 | 565 | return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr, |
| 462 | 566 | ARRAY_SIZE(rt1019_map_lr)); |
| 463 | 567 | } |
| @@ -588,6 +692,14 @@ static const struct snd_soc_ops acp_card_rt1019_ops = { · 124 unmodified lines | ||
| 588 | 692 | SND_SOC_DAILINK_DEF(max98360a, |
| 589 | 693 | DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); |
| 590 | 694 | |
| 695 | +static const struct snd_kcontrol_new max98360a_controls[] = { | |
| 696 | + SOC_DAPM_PIN_SWITCH("Spk"), | |
| 697 | +}; | |
| 698 | + | |
| 699 | +static const struct snd_soc_dapm_widget max98360a_widgets[] = { | |
| 700 | + SND_SOC_DAPM_SPK("Spk", NULL), | |
| 701 | +}; | |
| 702 | + | |
| 591 | 703 | static const struct snd_soc_dapm_route max98360a_map[] = { |
| 592 | 704 | {"Spk", NULL, "Speaker"}, |
| 593 | 705 | }; |
| @@ -596,10 +708,25 @@ static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd) · 2 unmodified lines | ||
| 596 | 708 | { |
| 597 | 709 | struct snd_soc_card *card = rtd->card; |
| 598 | 710 | struct acp_card_drvdata *drvdata = card->drvdata; |
| 711 | + int ret; | |
| 599 | 712 | |
| 600 | 713 | if (drvdata->amp_codec_id != MAX98360A) |
| 601 | 714 | return -EINVAL; |
| 602 | 715 | |
| 716 | + ret = snd_soc_dapm_new_controls(&card->dapm, max98360a_widgets, | |
| 717 | + ARRAY_SIZE(max98360a_widgets)); | |
| 718 | + if (ret) { | |
| 719 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 720 | + return ret; | |
| 721 | + } | |
| 722 | + | |
| 723 | + ret = snd_soc_add_card_controls(card, max98360a_controls, | |
| 724 | + ARRAY_SIZE(max98360a_controls)); | |
| 725 | + if (ret) { | |
| 726 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 727 | + return ret; | |
| 728 | + } | |
| 729 | + | |
| 603 | 730 | return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map, |
| 604 | 731 | ARRAY_SIZE(max98360a_map)); |
| 605 | 732 | } |
| @@ -661,10 +788,137 @@ static const struct snd_soc_ops acp_card_maxim_ops = { · 55 unmodified lines | ||
| 661 | 788 | .hw_params = acp_card_maxim_hw_params, |
| 662 | 789 | }; |
| 663 | 790 | |
| 791 | +SND_SOC_DAILINK_DEF(max98388, | |
| 792 | + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ADS8388:00", "max98388-aif1"), | |
| 793 | + COMP_CODEC("i2c-ADS8388:01", "max98388-aif1"))); | |
| 794 | + | |
| 795 | +static const struct snd_kcontrol_new max98388_controls[] = { | |
| 796 | + SOC_DAPM_PIN_SWITCH("Left Spk"), | |
| 797 | + SOC_DAPM_PIN_SWITCH("Right Spk"), | |
| 798 | +}; | |
| 799 | + | |
| 800 | +static const struct snd_soc_dapm_widget max98388_widgets[] = { | |
| 801 | + SND_SOC_DAPM_SPK("Left Spk", NULL), | |
| 802 | + SND_SOC_DAPM_SPK("Right Spk", NULL), | |
| 803 | +}; | |
| 804 | + | |
| 805 | +static const struct snd_soc_dapm_route max98388_map[] = { | |
| 806 | + { "Left Spk", NULL, "Left BE_OUT" }, | |
| 807 | + { "Right Spk", NULL, "Right BE_OUT" }, | |
| 808 | +}; | |
| 809 | + | |
| 810 | +static struct snd_soc_codec_conf max98388_conf[] = { | |
| 811 | + { | |
| 812 | + .dlc = COMP_CODEC_CONF("i2c-ADS8388:00"), | |
| 813 | + .name_prefix = "Left", | |
| 814 | + }, | |
| 815 | + { | |
| 816 | + .dlc = COMP_CODEC_CONF("i2c-ADS8388:01"), | |
| 817 | + .name_prefix = "Right", | |
| 818 | + }, | |
| 819 | +}; | |
| 820 | + | |
| 821 | +static const unsigned int max98388_format[] = {16}; | |
| 822 | + | |
| 823 | +static struct snd_pcm_hw_constraint_list constraints_sample_bits_max = { | |
| 824 | + .list = max98388_format, | |
| 825 | + .count = ARRAY_SIZE(max98388_format), | |
| 826 | +}; | |
| 827 | + | |
| 828 | +static int acp_card_max98388_startup(struct snd_pcm_substream *substream) | |
| 829 | +{ | |
| 830 | + struct snd_pcm_runtime *runtime = substream->runtime; | |
| 831 | + | |
| 832 | + runtime->hw.channels_max = DUAL_CHANNEL; | |
| 833 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | |
| 834 | + &constraints_channels); | |
| 835 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | |
| 836 | + &constraints_rates); | |
| 837 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | |
| 838 | + &constraints_sample_bits_max); | |
| 839 | + | |
| 840 | + return 0; | |
| 841 | +} | |
| 842 | + | |
| 843 | +static int acp_card_max98388_init(struct snd_soc_pcm_runtime *rtd) | |
| 844 | +{ | |
| 845 | + struct snd_soc_card *card = rtd->card; | |
| 846 | + struct acp_card_drvdata *drvdata = card->drvdata; | |
| 847 | + int ret; | |
| 848 | + | |
| 849 | + if (drvdata->amp_codec_id != MAX98388) | |
| 850 | + return -EINVAL; | |
| 851 | + | |
| 852 | + ret = snd_soc_dapm_new_controls(&card->dapm, max98388_widgets, | |
| 853 | + ARRAY_SIZE(max98388_widgets)); | |
| 854 | + | |
| 855 | + if (ret) { | |
| 856 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 857 | + /* Don't need to add routes if widget addition failed */ | |
| 858 | + return ret; | |
| 859 | + } | |
| 860 | + | |
| 861 | + ret = snd_soc_add_card_controls(card, max98388_controls, | |
| 862 | + ARRAY_SIZE(max98388_controls)); | |
| 863 | + if (ret) { | |
| 864 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 865 | + return ret; | |
| 866 | + } | |
| 867 | + | |
| 868 | + return snd_soc_dapm_add_routes(&rtd->card->dapm, max98388_map, | |
| 869 | + ARRAY_SIZE(max98388_map)); | |
| 870 | +} | |
| 871 | + | |
| 872 | +static int acp_max98388_hw_params(struct snd_pcm_substream *substream, | |
| 873 | + struct snd_pcm_hw_params *params) | |
| 874 | +{ | |
| 875 | + struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
| 876 | + struct snd_soc_card *card = rtd->card; | |
| 877 | + struct snd_soc_dai *codec_dai = | |
| 878 | + snd_soc_card_get_codec_dai(card, | |
| 879 | + MAX98388_CODEC_DAI); | |
| 880 | + int ret; | |
| 881 | + | |
| 882 | + ret = snd_soc_dai_set_fmt(codec_dai, | |
| 883 | + SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | | |
| 884 | + SND_SOC_DAIFMT_NB_NF); | |
| 885 | + if (ret < 0) | |
| 886 | + return ret; | |
| 887 | + | |
| 888 | + return ret; | |
| 889 | +} | |
| 890 | + | |
| 891 | +static const struct snd_soc_ops acp_max98388_ops = { | |
| 892 | + .startup = acp_card_max98388_startup, | |
| 893 | + .hw_params = acp_max98388_hw_params, | |
| 894 | +}; | |
| 895 | + | |
| 664 | 896 | /* Declare nau8825 codec components */ |
| 665 | 897 | SND_SOC_DAILINK_DEF(nau8825, |
| 666 | 898 | DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi"))); |
| 667 | 899 | |
| 900 | +static struct snd_soc_jack nau8825_jack; | |
| 901 | +static struct snd_soc_jack_pin nau8825_jack_pins[] = { | |
| 902 | + { | |
| 903 | + .pin = "Headphone Jack", | |
| 904 | + .mask = SND_JACK_HEADPHONE, | |
| 905 | + }, | |
| 906 | + { | |
| 907 | + .pin = "Headset Mic", | |
| 908 | + .mask = SND_JACK_MICROPHONE, | |
| 909 | + }, | |
| 910 | +}; | |
| 911 | + | |
| 912 | +static const struct snd_kcontrol_new nau8825_controls[] = { | |
| 913 | + SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 914 | + SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 915 | +}; | |
| 916 | + | |
| 917 | +static const struct snd_soc_dapm_widget nau8825_widgets[] = { | |
| 918 | + SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 919 | + SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 920 | +}; | |
| 921 | + | |
| 668 | 922 | static const struct snd_soc_dapm_route nau8825_map[] = { |
| 669 | 923 | { "Headphone Jack", NULL, "HPOL" }, |
| 670 | 924 | { "Headphone Jack", NULL, "HPOR" }, |
| @@ -683,22 +937,38 @@ static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd) · 12 unmodified lines | ||
| 683 | 937 | if (drvdata->hs_codec_id != NAU8825) |
| 684 | 938 | return -EINVAL; |
| 685 | 939 | |
| 686 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 940 | + ret = snd_soc_dapm_new_controls(&card->dapm, nau8825_widgets, | |
| 941 | + ARRAY_SIZE(nau8825_widgets)); | |
| 942 | + if (ret) { | |
| 943 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 944 | + return ret; | |
| 945 | + } | |
| 946 | + | |
| 947 | + ret = snd_soc_add_card_controls(card, nau8825_controls, | |
| 948 | + ARRAY_SIZE(nau8825_controls)); | |
| 949 | + if (ret) { | |
| 950 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 951 | + return ret; | |
| 952 | + } | |
| 953 | + | |
| 954 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 687 | 955 | SND_JACK_HEADSET | SND_JACK_LINEOUT | |
| 688 | 956 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
| 689 | 957 | SND_JACK_BTN_2 | SND_JACK_BTN_3, |
| 690 | − &pco_jack); | |
| 958 | + &nau8825_jack, | |
| 959 | + nau8825_jack_pins, | |
| 960 | + ARRAY_SIZE(nau8825_jack_pins)); | |
| 691 | 961 | if (ret) { |
| 692 | 962 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 693 | 963 | return ret; |
| 694 | 964 | } |
| 695 | 965 | |
| 696 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 697 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 698 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 699 | − snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 966 | + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 967 | + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 968 | + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 969 | + snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 700 | 970 | |
| 701 | − ret = snd_soc_component_set_jack(component, &pco_jack, NULL); | |
| 971 | + ret = snd_soc_component_set_jack(component, &nau8825_jack, NULL); | |
| 702 | 972 | if (ret) { |
| 703 | 973 | dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); |
| 704 | 974 | return ret; |
| @@ -790,6 +1060,189 @@ static const struct snd_soc_ops acp_card_nau8825_ops = { · 85 unmodified lines | ||
| 790 | 1060 | .hw_params = acp_nau8825_hw_params, |
| 791 | 1061 | }; |
| 792 | 1062 | |
| 1063 | +static int platform_clock_control(struct snd_soc_dapm_widget *w, | |
| 1064 | + struct snd_kcontrol *k, int event) | |
| 1065 | +{ | |
| 1066 | + struct snd_soc_dapm_context *dapm = w->dapm; | |
| 1067 | + struct snd_soc_card *card = dapm->card; | |
| 1068 | + struct snd_soc_dai *codec_dai; | |
| 1069 | + int ret = 0; | |
| 1070 | + | |
| 1071 | + codec_dai = snd_soc_card_get_codec_dai(card, NAU8821_CODEC_DAI); | |
| 1072 | + if (!codec_dai) { | |
| 1073 | + dev_err(card->dev, "Codec dai not found\n"); | |
| 1074 | + return -EIO; | |
| 1075 | + } | |
| 1076 | + | |
| 1077 | + if (SND_SOC_DAPM_EVENT_OFF(event)) { | |
| 1078 | + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL, | |
| 1079 | + 0, SND_SOC_CLOCK_IN); | |
| 1080 | + if (ret < 0) { | |
| 1081 | + dev_err(card->dev, "set sysclk err = %d\n", ret); | |
| 1082 | + return -EIO; | |
| 1083 | + } | |
| 1084 | + } else { | |
| 1085 | + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, | |
| 1086 | + SND_SOC_CLOCK_IN); | |
| 1087 | + if (ret < 0) | |
| 1088 | + dev_err(codec_dai->dev, "can't set FS clock %d\n", ret); | |
| 1089 | + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, NAU8821_BCLK, | |
| 1090 | + NAU8821_FREQ_OUT); | |
| 1091 | + if (ret < 0) | |
| 1092 | + dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); | |
| 1093 | + } | |
| 1094 | + return ret; | |
| 1095 | +} | |
| 1096 | + | |
| 1097 | +static struct snd_soc_jack nau8821_jack; | |
| 1098 | +static struct snd_soc_jack_pin nau8821_jack_pins[] = { | |
| 1099 | + { | |
| 1100 | + .pin = "Headphone Jack", | |
| 1101 | + .mask = SND_JACK_HEADPHONE, | |
| 1102 | + }, | |
| 1103 | + { | |
| 1104 | + .pin = "Headset Mic", | |
| 1105 | + .mask = SND_JACK_MICROPHONE, | |
| 1106 | + }, | |
| 1107 | +}; | |
| 1108 | + | |
| 1109 | +static const struct snd_kcontrol_new nau8821_controls[] = { | |
| 1110 | + SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 1111 | + SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 1112 | +}; | |
| 1113 | + | |
| 1114 | +static const struct snd_soc_dapm_widget nau8821_widgets[] = { | |
| 1115 | + SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 1116 | + SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 1117 | + SND_SOC_DAPM_MIC("Int Mic", NULL), | |
| 1118 | + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | |
| 1119 | + platform_clock_control, SND_SOC_DAPM_PRE_PMU | | |
| 1120 | + SND_SOC_DAPM_POST_PMD), | |
| 1121 | +}; | |
| 1122 | + | |
| 1123 | +static const struct snd_soc_dapm_route nau8821_audio_route[] = { | |
| 1124 | + /* HP jack connectors - unknown if we have jack detection */ | |
| 1125 | + { "Headphone Jack", NULL, "HPOL" }, | |
| 1126 | + { "Headphone Jack", NULL, "HPOR" }, | |
| 1127 | + { "MICL", NULL, "Headset Mic" }, | |
| 1128 | + { "MICR", NULL, "Headset Mic" }, | |
| 1129 | + { "DMIC", NULL, "Int Mic" }, | |
| 1130 | + { "Headphone Jack", NULL, "Platform Clock" }, | |
| 1131 | + { "Headset Mic", NULL, "Platform Clock" }, | |
| 1132 | + { "Int Mic", NULL, "Platform Clock" }, | |
| 1133 | +}; | |
| 1134 | + | |
| 1135 | +static const unsigned int nau8821_format[] = {16}; | |
| 1136 | + | |
| 1137 | +static struct snd_pcm_hw_constraint_list constraints_sample_bits = { | |
| 1138 | + .list = nau8821_format, | |
| 1139 | + .count = ARRAY_SIZE(nau8821_format), | |
| 1140 | +}; | |
| 1141 | + | |
| 1142 | +static int acp_8821_init(struct snd_soc_pcm_runtime *rtd) | |
| 1143 | +{ | |
| 1144 | + struct snd_soc_card *card = rtd->card; | |
| 1145 | + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); | |
| 1146 | + struct snd_soc_component *component = codec_dai->component; | |
| 1147 | + int ret; | |
| 1148 | + | |
| 1149 | + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); | |
| 1150 | + | |
| 1151 | + ret = snd_soc_dapm_new_controls(&card->dapm, nau8821_widgets, | |
| 1152 | + ARRAY_SIZE(nau8821_widgets)); | |
| 1153 | + if (ret) { | |
| 1154 | + dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret); | |
| 1155 | + // Don't need to add routes if widget addition failed | |
| 1156 | + return ret; | |
| 1157 | + } | |
| 1158 | + | |
| 1159 | + ret = snd_soc_add_card_controls(card, nau8821_controls, | |
| 1160 | + ARRAY_SIZE(nau8821_controls)); | |
| 1161 | + if (ret) { | |
| 1162 | + dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); | |
| 1163 | + return ret; | |
| 1164 | + } | |
| 1165 | + | |
| 1166 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 1167 | + SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 1168 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 1169 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 1170 | + &nau8821_jack, | |
| 1171 | + nau8821_jack_pins, | |
| 1172 | + ARRAY_SIZE(nau8821_jack_pins)); | |
| 1173 | + if (ret) { | |
| 1174 | + dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | |
| 1175 | + return ret; | |
| 1176 | + } | |
| 1177 | + | |
| 1178 | + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
| 1179 | + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
| 1180 | + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
| 1181 | + snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
| 1182 | + | |
| 1183 | + nau8821_enable_jack_detect(component, &nau8821_jack); | |
| 1184 | + | |
| 1185 | + return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8821_audio_route, | |
| 1186 | + ARRAY_SIZE(nau8821_audio_route)); | |
| 1187 | +} | |
| 1188 | + | |
| 1189 | +static int acp_8821_startup(struct snd_pcm_substream *substream) | |
| 1190 | +{ | |
| 1191 | + struct snd_pcm_runtime *runtime = substream->runtime; | |
| 1192 | + | |
| 1193 | + runtime->hw.channels_max = DUAL_CHANNEL; | |
| 1194 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | |
| 1195 | + &constraints_channels); | |
| 1196 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | |
| 1197 | + &constraints_rates); | |
| 1198 | + snd_pcm_hw_constraint_list(substream->runtime, 0, | |
| 1199 | + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | |
| 1200 | + &constraints_sample_bits); | |
| 1201 | + return 0; | |
| 1202 | +} | |
| 1203 | + | |
| 1204 | +static int acp_nau8821_hw_params(struct snd_pcm_substream *substream, | |
| 1205 | + struct snd_pcm_hw_params *params) | |
| 1206 | +{ | |
| 1207 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | |
| 1208 | + struct snd_soc_card *card = rtd->card; | |
| 1209 | + struct acp_card_drvdata *drvdata = card->drvdata; | |
| 1210 | + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); | |
| 1211 | + int ret; | |
| 1212 | + unsigned int fmt; | |
| 1213 | + | |
| 1214 | + if (drvdata->soc_mclk) | |
| 1215 | + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; | |
| 1216 | + else | |
| 1217 | + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; | |
| 1218 | + | |
| 1219 | + ret = snd_soc_dai_set_fmt(codec_dai, fmt); | |
| 1220 | + if (ret < 0) { | |
| 1221 | + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); | |
| 1222 | + return ret; | |
| 1223 | + } | |
| 1224 | + | |
| 1225 | + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, | |
| 1226 | + SND_SOC_CLOCK_IN); | |
| 1227 | + if (ret < 0) | |
| 1228 | + dev_err(card->dev, "can't set FS clock %d\n", ret); | |
| 1229 | + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params), | |
| 1230 | + params_rate(params) * 256); | |
| 1231 | + if (ret < 0) | |
| 1232 | + dev_err(card->dev, "can't set FLL: %d\n", ret); | |
| 1233 | + | |
| 1234 | + return ret; | |
| 1235 | +} | |
| 1236 | + | |
| 1237 | +static const struct snd_soc_ops acp_8821_ops = { | |
| 1238 | + .startup = acp_8821_startup, | |
| 1239 | + .hw_params = acp_nau8821_hw_params, | |
| 1240 | +}; | |
| 1241 | + | |
| 1242 | +SND_SOC_DAILINK_DEF(nau8821, | |
| 1243 | + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", | |
| 1244 | + "nau8821-hifi"))); | |
| 1245 | + | |
| 793 | 1246 | /* Declare DMIC codec components */ |
| 794 | 1247 | SND_SOC_DAILINK_DEF(dmic_codec, |
| 795 | 1248 | DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); |
| @@ -920,6 +1373,12 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) · 124 unmodified lines | ||
| 920 | 1373 | links[i].init = acp_card_rt5682s_init; |
| 921 | 1374 | links[i].ops = &acp_card_rt5682s_ops; |
| 922 | 1375 | } |
| 1376 | + if (drv_data->hs_codec_id == NAU8821) { | |
| 1377 | + links[i].codecs = nau8821; | |
| 1378 | + links[i].num_codecs = ARRAY_SIZE(nau8821); | |
| 1379 | + links[i].init = acp_8821_init; | |
| 1380 | + links[i].ops = &acp_8821_ops; | |
| 1381 | + } | |
| 923 | 1382 | i++; |
| 924 | 1383 | } |
| 925 | 1384 | |
| @@ -1007,6 +1466,14 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) · 81 unmodified lines | ||
| 1007 | 1466 | links[i].ops = &acp_card_maxim_ops; |
| 1008 | 1467 | links[i].init = acp_card_maxim_init; |
| 1009 | 1468 | } |
| 1469 | + if (drv_data->amp_codec_id == MAX98388) { | |
| 1470 | + links[i].codecs = max98388; | |
| 1471 | + links[i].num_codecs = ARRAY_SIZE(max98388); | |
| 1472 | + links[i].ops = &acp_max98388_ops; | |
| 1473 | + links[i].init = acp_card_max98388_init; | |
| 1474 | + card->codec_conf = max98388_conf; | |
| 1475 | + card->num_configs = ARRAY_SIZE(max98388_conf); | |
| 1476 | + } | |
| 1010 | 1477 | if (drv_data->amp_codec_id == RT1019) { |
| 1011 | 1478 | links[i].codecs = rt1019; |
| 1012 | 1479 | links[i].num_codecs = ARRAY_SIZE(rt1019); |
| @@ -41,6 +41,8 @@ enum codec_endpoints { · 40 unmodified lines | ||
| 41 | 41 | MAX98360A, |
| 42 | 42 | RT5682S, |
| 43 | 43 | NAU8825, |
| 44 | + NAU8821, | |
| 45 | + MAX98388, | |
| 44 | 46 | }; |
| 45 | 47 | |
| 46 | 48 | enum platform_end_point { |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/pci.h> |
| 17 | 17 | #include <linux/platform_device.h> |
| 18 | 18 | #include <linux/module.h> |
| 19 | +#include <linux/pm_runtime.h> | |
| 19 | 20 | |
| 20 | 21 | #include "amd.h" |
| 21 | 22 | #include "../mach-config.h" |
| @@ -106,6 +107,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id · 84 unmodified lines | ||
| 106 | 107 | goto unregister_dmic_dev; |
| 107 | 108 | } |
| 108 | 109 | |
| 110 | + acp_init(chip); | |
| 109 | 111 | res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL); |
| 110 | 112 | if (!res) { |
| 111 | 113 | ret = -ENOMEM; |
| @@ -139,7 +141,12 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id · 27 unmodified lines | ||
| 139 | 141 | ret = PTR_ERR(pdev); |
| 140 | 142 | goto unregister_dmic_dev; |
| 141 | 143 | } |
| 142 | − | |
| 144 | + chip->chip_pdev = pdev; | |
| 145 | + dev_set_drvdata(&pci->dev, chip); | |
| 146 | + pm_runtime_set_autosuspend_delay(&pci->dev, 2000); | |
| 147 | + pm_runtime_use_autosuspend(&pci->dev); | |
| 148 | + pm_runtime_put_noidle(&pci->dev); | |
| 149 | + pm_runtime_allow(&pci->dev); | |
| 143 | 150 | return ret; |
| 144 | 151 | |
| 145 | 152 | unregister_dmic_dev: |
| @@ -152,12 +159,56 @@ disable_pci: · 6 unmodified lines | ||
| 152 | 159 | return ret; |
| 153 | 160 | }; |
| 154 | 161 | |
| 162 | +static int __maybe_unused snd_acp_suspend(struct device *dev) | |
| 163 | +{ | |
| 164 | + struct acp_chip_info *chip; | |
| 165 | + int ret; | |
| 166 | + | |
| 167 | + chip = dev_get_drvdata(dev); | |
| 168 | + ret = acp_deinit(chip->base); | |
| 169 | + if (ret) | |
| 170 | + dev_err(dev, "ACP de-init failed\n"); | |
| 171 | + return ret; | |
| 172 | +} | |
| 173 | + | |
| 174 | +static int __maybe_unused snd_acp_resume(struct device *dev) | |
| 175 | +{ | |
| 176 | + struct acp_chip_info *chip; | |
| 177 | + struct acp_dev_data *adata; | |
| 178 | + struct device child; | |
| 179 | + int ret; | |
| 180 | + | |
| 181 | + chip = dev_get_drvdata(dev); | |
| 182 | + ret = acp_init(chip); | |
| 183 | + if (ret) | |
| 184 | + dev_err(dev, "ACP init failed\n"); | |
| 185 | + child = chip->chip_pdev->dev; | |
| 186 | + adata = dev_get_drvdata(&child); | |
| 187 | + if (adata) | |
| 188 | + acp_enable_interrupts(adata); | |
| 189 | + return ret; | |
| 190 | +} | |
| 191 | + | |
| 192 | +static const struct dev_pm_ops acp_pm_ops = { | |
| 193 | + SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL) | |
| 194 | + SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) | |
| 195 | +}; | |
| 196 | + | |
| 155 | 197 | static void acp_pci_remove(struct pci_dev *pci) |
| 156 | 198 | { |
| 199 | + struct acp_chip_info *chip; | |
| 200 | + int ret; | |
| 201 | + | |
| 202 | + chip = pci_get_drvdata(pci); | |
| 203 | + pm_runtime_forbid(&pci->dev); | |
| 204 | + pm_runtime_get_noresume(&pci->dev); | |
| 157 | 205 | if (dmic_dev) |
| 158 | 206 | platform_device_unregister(dmic_dev); |
| 159 | 207 | if (pdev) |
| 160 | 208 | platform_device_unregister(pdev); |
| 209 | + ret = acp_deinit(chip->base); | |
| 210 | + if (ret) | |
| 211 | + dev_err(&pci->dev, "ACP de-init failed\n"); | |
| 161 | 212 | } |
| 162 | 213 | |
| 163 | 214 | /* PCI IDs */ |
| @@ -173,8 +224,12 @@ static struct pci_driver snd_amd_acp_pci_driver = { · 9 unmodified lines | ||
| 173 | 224 | .id_table = acp_pci_ids, |
| 174 | 225 | .probe = acp_pci_probe, |
| 175 | 226 | .remove = acp_pci_remove, |
| 227 | + .driver = { | |
| 228 | + .pm = &acp_pm_ops, | |
| 229 | + }, | |
| 176 | 230 | }; |
| 177 | 231 | module_pci_driver(snd_amd_acp_pci_driver); |
| 178 | 232 | |
| 179 | 233 | MODULE_LICENSE("Dual BSD/GPL"); |
| 234 | +MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); | |
| 180 | 235 | MODULE_ALIAS(DRV_NAME); |
| @@ -25,18 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #define DRV_NAME "acp-pdm" |
| 27 | 27 | |
| 28 | −#define PDM_DMA_STAT 0x10 | |
| 29 | −#define PDM_DMA_INTR_MASK 0x10000 | |
| 30 | −#define PDM_DEC_64 0x2 | |
| 31 | −#define PDM_CLK_FREQ_MASK 0x07 | |
| 32 | −#define PDM_MISC_CTRL_MASK 0x10 | |
| 33 | −#define PDM_ENABLE 0x01 | |
| 34 | −#define PDM_DISABLE 0x00 | |
| 35 | −#define DMA_EN_MASK 0x02 | |
| 36 | −#define DELAY_US 5 | |
| 37 | −#define PDM_TIMEOUT 1000 | |
| 38 | −#define ACP_REGION2_OFFSET 0x02000000 | |
| 39 | − | |
| 40 | 28 | static int acp_dmic_prepare(struct snd_pcm_substream *substream, |
| 41 | 29 | struct snd_soc_dai *dai) |
| 42 | 30 | { |
| @@ -135,6 +123,7 @@ static int acp_dmic_hwparams(struct snd_pcm_substream *substream, · 92 unmodified lines | ||
| 135 | 123 | return -EINVAL; |
| 136 | 124 | } |
| 137 | 125 | |
| 126 | + adata->ch_mask = ch_mask; | |
| 138 | 127 | if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) { |
| 139 | 128 | dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams)); |
| 140 | 129 | return -EINVAL; |
| @@ -127,7 +127,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data) · 126 unmodified lines | ||
| 127 | 127 | return IRQ_NONE; |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | −static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream) | |
| 130 | +void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream) | |
| 131 | 131 | { |
| 132 | 132 | struct acp_resource *rsrc = adata->rsrc; |
| 133 | 133 | u32 pte_reg, pte_size, reg_val; |
| @@ -143,8 +143,9 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream · 9 unmodified lines | ||
| 143 | 143 | writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + pte_size); |
| 144 | 144 | writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); |
| 145 | 145 | } |
| 146 | +EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON); | |
| 146 | 147 | |
| 147 | −static void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size) | |
| 148 | +void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size) | |
| 148 | 149 | { |
| 149 | 150 | struct snd_pcm_substream *substream = stream->substream; |
| 150 | 151 | struct acp_resource *rsrc = adata->rsrc; |
| @@ -168,6 +169,7 @@ static void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream · 17 unmodified lines | ||
| 168 | 169 | addr += PAGE_SIZE; |
| 169 | 170 | } |
| 170 | 171 | } |
| 172 | +EXPORT_SYMBOL_NS_GPL(config_acp_dma, SND_SOC_ACP_COMMON); | |
| 171 | 173 | |
| 172 | 174 | static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) |
| 173 | 175 | { |
| @@ -19,30 +19,17 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <sound/soc.h> |
| 20 | 20 | #include <sound/soc-dai.h> |
| 21 | 21 | #include <linux/dma-mapping.h> |
| 22 | +#include <linux/pci.h> | |
| 23 | +#include <linux/pm_runtime.h> | |
| 22 | 24 | |
| 23 | 25 | #include "amd.h" |
| 24 | 26 | |
| 25 | 27 | #define DRV_NAME "acp_asoc_rembrandt" |
| 26 | 28 | |
| 27 | −#define ACP6X_PGFSM_CONTROL 0x1024 | |
| 28 | −#define ACP6X_PGFSM_STATUS 0x1028 | |
| 29 | − | |
| 30 | −#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 | |
| 31 | − | |
| 32 | −#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 | |
| 33 | −#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 | |
| 34 | −#define ACP_PGFSM_STATUS_MASK 0x03 | |
| 35 | −#define ACP_POWERED_ON 0x00 | |
| 36 | −#define ACP_POWER_ON_IN_PROGRESS 0x01 | |
| 37 | −#define ACP_POWERED_OFF 0x02 | |
| 38 | −#define ACP_POWER_OFF_IN_PROGRESS 0x03 | |
| 39 | − | |
| 40 | −#define ACP_ERROR_MASK 0x20000000 | |
| 41 | −#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF | |
| 42 | − | |
| 43 | − | |
| 44 | −static int rmb_acp_init(void __iomem *base); | |
| 45 | −static int rmb_acp_deinit(void __iomem *base); | |
| 29 | +#define MP1_C2PMSG_69 0x3B10A14 | |
| 30 | +#define MP1_C2PMSG_85 0x3B10A54 | |
| 31 | +#define MP1_C2PMSG_93 0x3B10A74 | |
| 32 | +#define HOST_BRIDGE_ID 0x14B5 | |
| 46 | 33 | |
| 47 | 34 | static struct acp_resource rsrc = { |
| 48 | 35 | .offset = 0, |
| @@ -111,7 +98,6 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = { · 62 unmodified lines | ||
| 111 | 98 | .rate_max = 48000, |
| 112 | 99 | }, |
| 113 | 100 | .ops = &asoc_acp_cpu_dai_ops, |
| 114 | − .probe = &asoc_acp_i2s_probe, | |
| 115 | 101 | }, |
| 116 | 102 | { |
| 117 | 103 | .name = "acp-i2s-bt", |
| @@ -137,7 +123,6 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = { · 19 unmodified lines | ||
| 137 | 123 | .rate_max = 48000, |
| 138 | 124 | }, |
| 139 | 125 | .ops = &asoc_acp_cpu_dai_ops, |
| 140 | − .probe = &asoc_acp_i2s_probe, | |
| 141 | 126 | }, |
| 142 | 127 | { |
| 143 | 128 | .name = "acp-i2s-hs", |
| @@ -163,7 +148,6 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = { · 19 unmodified lines | ||
| 163 | 148 | .rate_max = 48000, |
| 164 | 149 | }, |
| 165 | 150 | .ops = &asoc_acp_cpu_dai_ops, |
| 166 | − .probe = &asoc_acp_i2s_probe, | |
| 167 | 151 | }, |
| 168 | 152 | { |
| 169 | 153 | .name = "acp-pdm-dmic", |
| @@ -180,108 +164,22 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = { · 10 unmodified lines | ||
| 180 | 164 | }, |
| 181 | 165 | }; |
| 182 | 166 | |
| 183 | −static int acp6x_power_on(void __iomem *base) | |
| 184 | −{ | |
| 185 | − u32 val; | |
| 186 | − int timeout; | |
| 187 | − | |
| 188 | − val = readl(base + ACP6X_PGFSM_STATUS); | |
| 189 | − | |
| 190 | − if (val == ACP_POWERED_ON) | |
| 191 | − return 0; | |
| 192 | − | |
| 193 | − if ((val & ACP_PGFSM_STATUS_MASK) != | |
| 194 | − ACP_POWER_ON_IN_PROGRESS) | |
| 195 | − writel(ACP_PGFSM_CNTL_POWER_ON_MASK, | |
| 196 | − base + ACP6X_PGFSM_CONTROL); | |
| 197 | − timeout = 0; | |
| 198 | − while (++timeout < 500) { | |
| 199 | − val = readl(base + ACP6X_PGFSM_STATUS); | |
| 200 | − if (!val) | |
| 201 | − return 0; | |
| 202 | − udelay(1); | |
| 203 | − } | |
| 204 | − return -ETIMEDOUT; | |
| 205 | −} | |
| 206 | − | |
| 207 | −static int acp6x_reset(void __iomem *base) | |
| 167 | +static int acp6x_master_clock_generate(struct device *dev) | |
| 208 | 168 | { |
| 209 | − u32 val; | |
| 210 | − int timeout; | |
| 211 | − | |
| 212 | − writel(1, base + ACP_SOFT_RESET); | |
| 213 | − timeout = 0; | |
| 214 | − while (++timeout < 500) { | |
| 215 | − val = readl(base + ACP_SOFT_RESET); | |
| 216 | − if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) | |
| 217 | − break; | |
| 218 | − cpu_relax(); | |
| 219 | − } | |
| 220 | − writel(0, base + ACP_SOFT_RESET); | |
| 221 | − timeout = 0; | |
| 222 | − while (++timeout < 500) { | |
| 223 | − val = readl(base + ACP_SOFT_RESET); | |
| 224 | − if (!val) | |
| 225 | − return 0; | |
| 226 | − cpu_relax(); | |
| 227 | − } | |
| 228 | − return -ETIMEDOUT; | |
| 229 | −} | |
| 230 | − | |
| 231 | −static void acp6x_enable_interrupts(struct acp_dev_data *adata) | |
| 232 | −{ | |
| 233 | − struct acp_resource *rsrc = adata->rsrc; | |
| 234 | − u32 ext_intr_ctrl; | |
| 235 | − | |
| 236 | − writel(0x01, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 237 | − ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 238 | − ext_intr_ctrl |= ACP_ERROR_MASK; | |
| 239 | − writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 240 | −} | |
| 241 | − | |
| 242 | −static void acp6x_disable_interrupts(struct acp_dev_data *adata) | |
| 243 | −{ | |
| 244 | − struct acp_resource *rsrc = adata->rsrc; | |
| 245 | − | |
| 246 | − writel(ACP_EXT_INTR_STAT_CLEAR_MASK, | |
| 247 | − ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); | |
| 248 | − writel(0x00, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 249 | −} | |
| 169 | + int data = 0; | |
| 170 | + struct pci_dev *smn_dev; | |
| 250 | 171 | |
| 251 | −static int rmb_acp_init(void __iomem *base) | |
| 252 | −{ | |
| 253 | − int ret; | |
| 254 | − | |
| 255 | − /* power on */ | |
| 256 | − ret = acp6x_power_on(base); | |
| 257 | − if (ret) { | |
| 258 | − pr_err("ACP power on failed\n"); | |
| 259 | − return ret; | |
| 260 | − } | |
| 261 | − writel(0x01, base + ACP_CONTROL); | |
| 262 | − | |
| 263 | − /* Reset */ | |
| 264 | − ret = acp6x_reset(base); | |
| 265 | − if (ret) { | |
| 266 | − pr_err("ACP reset failed\n"); | |
| 267 | − return ret; | |
| 268 | − } | |
| 269 | − | |
| 270 | − return 0; | |
| 271 | −} | |
| 272 | − | |
| 273 | −static int rmb_acp_deinit(void __iomem *base) | |
| 274 | −{ | |
| 275 | − int ret = 0; | |
| 276 | − | |
| 277 | − /* Reset */ | |
| 278 | − ret = acp6x_reset(base); | |
| 279 | − if (ret) { | |
| 280 | − pr_err("ACP reset failed\n"); | |
| 281 | − return ret; | |
| 172 | + smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL); | |
| 173 | + if (!smn_dev) { | |
| 174 | + dev_err(dev, "Failed to get host bridge device\n"); | |
| 175 | + return -ENODEV; | |
| 282 | 176 | } |
| 283 | 177 | |
| 284 | − writel(0x00, base + ACP_CONTROL); | |
| 178 | + smn_write(smn_dev, MP1_C2PMSG_93, 0); | |
| 179 | + smn_write(smn_dev, MP1_C2PMSG_85, 0xC4); | |
| 180 | + smn_write(smn_dev, MP1_C2PMSG_69, 0x4); | |
| 181 | + read_poll_timeout(smn_read, data, data, DELAY_US, | |
| 182 | + ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93); | |
| 285 | 183 | return 0; |
| 286 | 184 | } |
| 287 | 185 | |
| @@ -303,8 +201,6 @@ static int rembrandt_audio_probe(struct platform_device *pdev) · 15 unmodified lines | ||
| 303 | 201 | return -ENODEV; |
| 304 | 202 | } |
| 305 | 203 | |
| 306 | − rmb_acp_init(chip->base); | |
| 307 | − | |
| 308 | 204 | adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); |
| 309 | 205 | if (!adata) |
| 310 | 206 | return -ENOMEM; |
| @@ -335,9 +231,14 @@ static int rembrandt_audio_probe(struct platform_device *pdev) · 24 unmodified lines | ||
| 335 | 231 | acp_machine_select(adata); |
| 336 | 232 | |
| 337 | 233 | dev_set_drvdata(dev, adata); |
| 338 | − acp6x_enable_interrupts(adata); | |
| 234 | + acp6x_master_clock_generate(dev); | |
| 235 | + acp_enable_interrupts(adata); | |
| 339 | 236 | acp_platform_register(dev); |
| 340 | − | |
| 237 | + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); | |
| 238 | + pm_runtime_use_autosuspend(&pdev->dev); | |
| 239 | + pm_runtime_mark_last_busy(&pdev->dev); | |
| 240 | + pm_runtime_set_active(&pdev->dev); | |
| 241 | + pm_runtime_enable(&pdev->dev); | |
| 341 | 242 | return 0; |
| 342 | 243 | } |
| 343 | 244 | |
| @@ -345,19 +246,49 @@ static void rembrandt_audio_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 345 | 246 | { |
| 346 | 247 | struct device *dev = &pdev->dev; |
| 347 | 248 | struct acp_dev_data *adata = dev_get_drvdata(dev); |
| 348 | − struct acp_chip_info *chip = dev_get_platdata(dev); | |
| 349 | − | |
| 350 | − rmb_acp_deinit(chip->base); | |
| 351 | 249 | |
| 352 | − acp6x_disable_interrupts(adata); | |
| 250 | + acp_disable_interrupts(adata); | |
| 353 | 251 | acp_platform_unregister(dev); |
| 252 | + pm_runtime_disable(&pdev->dev); | |
| 354 | 253 | } |
| 355 | 254 | |
| 255 | +static int __maybe_unused rmb_pcm_resume(struct device *dev) | |
| 256 | +{ | |
| 257 | + struct acp_dev_data *adata = dev_get_drvdata(dev); | |
| 258 | + struct acp_stream *stream; | |
| 259 | + struct snd_pcm_substream *substream; | |
| 260 | + snd_pcm_uframes_t buf_in_frames; | |
| 261 | + u64 buf_size; | |
| 262 | + | |
| 263 | + acp6x_master_clock_generate(dev); | |
| 264 | + spin_lock(&adata->acp_lock); | |
| 265 | + list_for_each_entry(stream, &adata->stream_list, list) { | |
| 266 | + substream = stream->substream; | |
| 267 | + if (substream && substream->runtime) { | |
| 268 | + buf_in_frames = (substream->runtime->buffer_size); | |
| 269 | + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); | |
| 270 | + config_pte_for_stream(adata, stream); | |
| 271 | + config_acp_dma(adata, stream, buf_size); | |
| 272 | + if (stream->dai_id) | |
| 273 | + restore_acp_i2s_params(substream, adata, stream); | |
| 274 | + else | |
| 275 | + restore_acp_pdm_params(substream, adata); | |
| 276 | + } | |
| 277 | + } | |
| 278 | + spin_unlock(&adata->acp_lock); | |
| 279 | + return 0; | |
| 280 | +} | |
| 281 | + | |
| 282 | +static const struct dev_pm_ops rmb_dma_pm_ops = { | |
| 283 | + SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume) | |
| 284 | +}; | |
| 285 | + | |
| 356 | 286 | static struct platform_driver rembrandt_driver = { |
| 357 | 287 | .probe = rembrandt_audio_probe, |
| 358 | 288 | .remove_new = rembrandt_audio_remove, |
| 359 | 289 | .driver = { |
| 360 | 290 | .name = "acp_asoc_rembrandt", |
| 291 | + .pm = &rmb_dma_pm_ops, | |
| 361 | 292 | }, |
| 362 | 293 | }; |
| 363 | 294 | |
| @@ -25,20 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #define DRV_NAME "acp_asoc_renoir" |
| 27 | 27 | |
| 28 | −#define ACP_SOFT_RST_DONE_MASK 0x00010001 | |
| 29 | − | |
| 30 | −#define ACP_PWR_ON_MASK 0x01 | |
| 31 | −#define ACP_PWR_OFF_MASK 0x00 | |
| 32 | −#define ACP_PGFSM_STAT_MASK 0x03 | |
| 33 | −#define ACP_POWERED_ON 0x00 | |
| 34 | −#define ACP_PWR_ON_IN_PROGRESS 0x01 | |
| 35 | −#define ACP_POWERED_OFF 0x02 | |
| 36 | −#define DELAY_US 5 | |
| 37 | −#define ACP_TIMEOUT 500 | |
| 38 | − | |
| 39 | −#define ACP_ERROR_MASK 0x20000000 | |
| 40 | −#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF | |
| 41 | − | |
| 42 | 28 | static struct acp_resource rsrc = { |
| 43 | 29 | .offset = 20, |
| 44 | 30 | .no_of_ctrls = 1, |
| @@ -111,7 +97,6 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = { · 66 unmodified lines | ||
| 111 | 97 | .rate_max = 48000, |
| 112 | 98 | }, |
| 113 | 99 | .ops = &asoc_acp_cpu_dai_ops, |
| 114 | − .probe = &asoc_acp_i2s_probe, | |
| 115 | 100 | }, |
| 116 | 101 | { |
| 117 | 102 | .name = "acp-i2s-bt", |
| @@ -137,7 +122,6 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = { · 19 unmodified lines | ||
| 137 | 122 | .rate_max = 48000, |
| 138 | 123 | }, |
| 139 | 124 | .ops = &asoc_acp_cpu_dai_ops, |
| 140 | − .probe = &asoc_acp_i2s_probe, | |
| 141 | 125 | }, |
| 142 | 126 | { |
| 143 | 127 | .name = "acp-pdm-dmic", |
| @@ -154,89 +138,7 @@ static struct snd_soc_dai_driver acp_renoir_dai[] = { · 10 unmodified lines | ||
| 154 | 138 | }, |
| 155 | 139 | }; |
| 156 | 140 | |
| 157 | −static int acp3x_power_on(void __iomem *base) | |
| 158 | −{ | |
| 159 | − u32 val; | |
| 160 | − | |
| 161 | − val = readl(base + ACP_PGFSM_STATUS); | |
| 162 | − | |
| 163 | − if (val == ACP_POWERED_ON) | |
| 164 | − return 0; | |
| 165 | − | |
| 166 | − if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS) | |
| 167 | − writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL); | |
| 168 | − | |
| 169 | − return readl_poll_timeout(base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP_TIMEOUT); | |
| 170 | −} | |
| 171 | − | |
| 172 | −static int acp3x_reset(void __iomem *base) | |
| 173 | −{ | |
| 174 | − u32 val; | |
| 175 | − int ret; | |
| 176 | − | |
| 177 | − writel(1, base + ACP_SOFT_RESET); | |
| 178 | − | |
| 179 | − ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK, | |
| 180 | − DELAY_US, ACP_TIMEOUT); | |
| 181 | − if (ret) | |
| 182 | − return ret; | |
| 183 | − | |
| 184 | − writel(0, base + ACP_SOFT_RESET); | |
| 185 | − | |
| 186 | − return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); | |
| 187 | −} | |
| 188 | − | |
| 189 | −static void acp3x_enable_interrupts(struct acp_dev_data *adata) | |
| 190 | −{ | |
| 191 | − struct acp_resource *rsrc = adata->rsrc; | |
| 192 | − u32 ext_intr_ctrl; | |
| 193 | − | |
| 194 | − writel(0x01, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 195 | − ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 196 | − ext_intr_ctrl |= ACP_ERROR_MASK; | |
| 197 | − writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); | |
| 198 | −} | |
| 199 | − | |
| 200 | −static void acp3x_disable_interrupts(struct acp_dev_data *adata) | |
| 201 | −{ | |
| 202 | − struct acp_resource *rsrc = adata->rsrc; | |
| 203 | − | |
| 204 | − writel(ACP_EXT_INTR_STAT_CLEAR_MASK, | |
| 205 | − ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); | |
| 206 | − writel(0x00, ACP_EXTERNAL_INTR_ENB(adata)); | |
| 207 | −} | |
| 208 | 141 | |
| 209 | −static int rn_acp_init(void __iomem *base) | |
| 210 | −{ | |
| 211 | − int ret; | |
| 212 | − | |
| 213 | − /* power on */ | |
| 214 | − ret = acp3x_power_on(base); | |
| 215 | − if (ret) | |
| 216 | − return ret; | |
| 217 | − | |
| 218 | − writel(0x01, base + ACP_CONTROL); | |
| 219 | − | |
| 220 | − /* Reset */ | |
| 221 | − ret = acp3x_reset(base); | |
| 222 | − if (ret) | |
| 223 | − return ret; | |
| 224 | − | |
| 225 | − return 0; | |
| 226 | −} | |
| 227 | − | |
| 228 | −static int rn_acp_deinit(void __iomem *base) | |
| 229 | −{ | |
| 230 | − int ret = 0; | |
| 231 | − | |
| 232 | − /* Reset */ | |
| 233 | − ret = acp3x_reset(base); | |
| 234 | − if (ret) | |
| 235 | − return ret; | |
| 236 | − | |
| 237 | − writel(0x00, base + ACP_CONTROL); | |
| 238 | − return 0; | |
| 239 | −} | |
| 240 | 142 | static int renoir_audio_probe(struct platform_device *pdev) |
| 241 | 143 | { |
| 242 | 144 | struct device *dev = &pdev->dev; |
| @@ -256,12 +158,6 @@ static int renoir_audio_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 256 | 158 | return -ENODEV; |
| 257 | 159 | } |
| 258 | 160 | |
| 259 | − ret = rn_acp_init(chip->base); | |
| 260 | − if (ret) { | |
| 261 | − dev_err(&pdev->dev, "ACP Init failed\n"); | |
| 262 | − return -EINVAL; | |
| 263 | − } | |
| 264 | − | |
| 265 | 161 | adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); |
| 266 | 162 | if (!adata) |
| 267 | 163 | return -ENOMEM; |
| @@ -290,7 +186,7 @@ static int renoir_audio_probe(struct platform_device *pdev) · 22 unmodified lines | ||
| 290 | 186 | acp_machine_select(adata); |
| 291 | 187 | |
| 292 | 188 | dev_set_drvdata(dev, adata); |
| 293 | − acp3x_enable_interrupts(adata); | |
| 189 | + acp_enable_interrupts(adata); | |
| 294 | 190 | acp_platform_register(dev); |
| 295 | 191 | |
| 296 | 192 | return 0; |
| @@ -300,17 +196,8 @@ static void renoir_audio_remove(struct platform_device *pdev) · 3 unmodified lines | ||
| 300 | 196 | { |
| 301 | 197 | struct device *dev = &pdev->dev; |
| 302 | 198 | struct acp_dev_data *adata = dev_get_drvdata(dev); |
| 303 | − struct acp_chip_info *chip; | |
| 304 | − int ret; | |
| 305 | − | |
| 306 | − chip = dev_get_platdata(&pdev->dev); | |
| 307 | − | |
| 308 | − acp3x_disable_interrupts(adata); | |
| 309 | − | |
| 310 | − ret = rn_acp_deinit(chip->base); | |
| 311 | − if (ret) | |
| 312 | − dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); | |
| 313 | 199 | |
| 200 | + acp_disable_interrupts(adata); | |
| 314 | 201 | acp_platform_unregister(dev); |
| 315 | 202 | } |
| 316 | 203 | |
| @@ -83,20 +83,15 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { · 82 unmodified lines | ||
| 83 | 83 | .tdm_mode = false, |
| 84 | 84 | }; |
| 85 | 85 | |
| 86 | −static const struct snd_kcontrol_new acp_controls[] = { | |
| 87 | − SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
| 88 | − SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
| 89 | − SOC_DAPM_PIN_SWITCH("Spk"), | |
| 90 | − SOC_DAPM_PIN_SWITCH("Left Spk"), | |
| 91 | − SOC_DAPM_PIN_SWITCH("Right Spk"), | |
| 92 | −}; | |
| 93 | − | |
| 94 | −static const struct snd_soc_dapm_widget acp_widgets[] = { | |
| 95 | − SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
| 96 | − SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 97 | − SND_SOC_DAPM_SPK("Spk", NULL), | |
| 98 | − SND_SOC_DAPM_SPK("Left Spk", NULL), | |
| 99 | − SND_SOC_DAPM_SPK("Right Spk", NULL), | |
| 86 | +static struct acp_card_drvdata sof_nau8821_max98388_data = { | |
| 87 | + .hs_cpu_id = I2S_SP, | |
| 88 | + .amp_cpu_id = I2S_HS, | |
| 89 | + .dmic_cpu_id = NONE, | |
| 90 | + .hs_codec_id = NAU8821, | |
| 91 | + .amp_codec_id = MAX98388, | |
| 92 | + .dmic_codec_id = NONE, | |
| 93 | + .soc_mclk = true, | |
| 94 | + .tdm_mode = false, | |
| 100 | 95 | }; |
| 101 | 96 | |
| 102 | 97 | static int acp_sof_probe(struct platform_device *pdev) |
| @@ -117,11 +112,8 @@ static int acp_sof_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 117 | 112 | card->dev = dev; |
| 118 | 113 | card->owner = THIS_MODULE; |
| 119 | 114 | card->name = pdev->id_entry->name; |
| 120 | − card->dapm_widgets = acp_widgets; | |
| 121 | − card->num_dapm_widgets = ARRAY_SIZE(acp_widgets); | |
| 122 | − card->controls = acp_controls; | |
| 123 | − card->num_controls = ARRAY_SIZE(acp_controls); | |
| 124 | 115 | card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; |
| 116 | + /* Widgets and controls added per-codec in acp-mach-common.c */ | |
| 125 | 117 | |
| 126 | 118 | acp_card_drvdata = card->drvdata; |
| 127 | 119 | dmi_id = dmi_first_match(acp_quirk_table); |
| @@ -166,6 +158,10 @@ static const struct platform_device_id board_ids[] = { · 38 unmodified lines | ||
| 166 | 158 | .name = "rt5682s-hs-rt1019", |
| 167 | 159 | .driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data |
| 168 | 160 | }, |
| 161 | + { | |
| 162 | + .name = "nau8821-max", | |
| 163 | + .driver_data = (kernel_ulong_t)&sof_nau8821_max98388_data | |
| 164 | + }, | |
| 169 | 165 | { } |
| 170 | 166 | }; |
| 171 | 167 | static struct platform_driver acp_asoc_audio = { |
| @@ -187,4 +183,5 @@ MODULE_ALIAS("platform:rt5682s-max"); · 15 unmodified lines | ||
| 187 | 183 | MODULE_ALIAS("platform:rt5682s-rt1019"); |
| 188 | 184 | MODULE_ALIAS("platform:nau8825-max"); |
| 189 | 185 | MODULE_ALIAS("platform:rt5682s-hs-rt1019"); |
| 186 | +MODULE_ALIAS("platform:nau8821-max"); | |
| 190 | 187 | MODULE_LICENSE("GPL v2"); |
| @@ -92,10 +92,43 @@ · 91 unmodified lines | ||
| 92 | 92 | #define SLOT_WIDTH_24 0x18 |
| 93 | 93 | #define SLOT_WIDTH_32 0x20 |
| 94 | 94 | |
| 95 | +#define ACP6X_PGFSM_CONTROL 0x1024 | |
| 96 | +#define ACP6X_PGFSM_STATUS 0x1028 | |
| 97 | + | |
| 98 | +#define ACP_SOFT_RST_DONE_MASK 0x00010001 | |
| 99 | + | |
| 100 | +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 | |
| 101 | +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 | |
| 102 | +#define ACP_PGFSM_STATUS_MASK 0x03 | |
| 103 | +#define ACP_POWERED_ON 0x00 | |
| 104 | +#define ACP_POWER_ON_IN_PROGRESS 0x01 | |
| 105 | +#define ACP_POWERED_OFF 0x02 | |
| 106 | +#define ACP_POWER_OFF_IN_PROGRESS 0x03 | |
| 107 | + | |
| 108 | +#define ACP_ERROR_MASK 0x20000000 | |
| 109 | +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xffffffff | |
| 110 | + | |
| 111 | +#define ACP_TIMEOUT 500 | |
| 112 | +#define DELAY_US 5 | |
| 113 | +#define ACP_SUSPEND_DELAY_MS 2000 | |
| 114 | + | |
| 115 | +#define PDM_DMA_STAT 0x10 | |
| 116 | +#define PDM_DMA_INTR_MASK 0x10000 | |
| 117 | +#define PDM_DEC_64 0x2 | |
| 118 | +#define PDM_CLK_FREQ_MASK 0x07 | |
| 119 | +#define PDM_MISC_CTRL_MASK 0x10 | |
| 120 | +#define PDM_ENABLE 0x01 | |
| 121 | +#define PDM_DISABLE 0x00 | |
| 122 | +#define DMA_EN_MASK 0x02 | |
| 123 | +#define DELAY_US 5 | |
| 124 | +#define PDM_TIMEOUT 1000 | |
| 125 | +#define ACP_REGION2_OFFSET 0x02000000 | |
| 126 | + | |
| 95 | 127 | struct acp_chip_info { |
| 96 | 128 | char *name; /* Platform name */ |
| 97 | 129 | unsigned int acp_rev; /* ACP Revision id */ |
| 98 | 130 | void __iomem *base; /* ACP memory PCI base */ |
| 131 | + struct platform_device *chip_pdev; | |
| 99 | 132 | }; |
| 100 | 133 | |
| 101 | 134 | struct acp_stream { |
| @@ -144,8 +177,11 @@ struct acp_dev_data { · 42 unmodified lines | ||
| 144 | 177 | u32 lrclk_div; |
| 145 | 178 | |
| 146 | 179 | struct acp_resource *rsrc; |
| 180 | + u32 ch_mask; | |
| 147 | 181 | u32 tdm_tx_fmt[3]; |
| 148 | 182 | u32 tdm_rx_fmt[3]; |
| 183 | + u32 xfer_tx_resolution[3]; | |
| 184 | + u32 xfer_rx_resolution[3]; | |
| 149 | 185 | }; |
| 150 | 186 | |
| 151 | 187 | union acp_i2stdm_mstrclkgen { |
| @@ -162,15 +198,29 @@ union acp_i2stdm_mstrclkgen { · 10 unmodified lines | ||
| 162 | 198 | extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; |
| 163 | 199 | extern const struct snd_soc_dai_ops acp_dmic_dai_ops; |
| 164 | 200 | |
| 165 | −int asoc_acp_i2s_probe(struct snd_soc_dai *dai); | |
| 166 | 201 | int acp_platform_register(struct device *dev); |
| 167 | 202 | int acp_platform_unregister(struct device *dev); |
| 168 | 203 | |
| 169 | 204 | int acp_machine_select(struct acp_dev_data *adata); |
| 170 | 205 | |
| 206 | +int smn_read(struct pci_dev *dev, u32 smn_addr); | |
| 207 | +int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data); | |
| 208 | + | |
| 209 | +int acp_init(struct acp_chip_info *chip); | |
| 210 | +int acp_deinit(void __iomem *base); | |
| 211 | +void acp_enable_interrupts(struct acp_dev_data *adata); | |
| 212 | +void acp_disable_interrupts(struct acp_dev_data *adata); | |
| 171 | 213 | /* Machine configuration */ |
| 172 | 214 | int snd_amd_acp_find_config(struct pci_dev *pci); |
| 173 | 215 | |
| 216 | +void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream); | |
| 217 | +void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size); | |
| 218 | +void restore_acp_pdm_params(struct snd_pcm_substream *substream, | |
| 219 | + struct acp_dev_data *adata); | |
| 220 | + | |
| 221 | +int restore_acp_i2s_params(struct snd_pcm_substream *substream, | |
| 222 | + struct acp_dev_data *adata, struct acp_stream *stream); | |
| 223 | + | |
| 174 | 224 | static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction) |
| 175 | 225 | { |
| 176 | 226 | u64 byte_count = 0, low = 0, high = 0; |
| @@ -28,6 +28,17 @@ · 27 unmodified lines | ||
| 28 | 28 | #define DUAL_CHANNEL 2 |
| 29 | 29 | |
| 30 | 30 | static struct snd_soc_jack pco_jack; |
| 31 | +static struct snd_soc_jack_pin pco_jack_pins[] = { | |
| 32 | + { | |
| 33 | + .pin = "Headphone Jack", | |
| 34 | + .mask = SND_JACK_HEADPHONE, | |
| 35 | + }, | |
| 36 | + { | |
| 37 | + .pin = "Headset Mic", | |
| 38 | + .mask = SND_JACK_MICROPHONE, | |
| 39 | + }, | |
| 40 | +}; | |
| 41 | + | |
| 31 | 42 | static struct clk *rt5682_dai_wclk; |
| 32 | 43 | static struct clk *rt5682_dai_bclk; |
| 33 | 44 | static struct gpio_desc *dmic_sel; |
| @@ -86,11 +97,13 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) · 52 unmodified lines | ||
| 86 | 97 | rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk"); |
| 87 | 98 | rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk"); |
| 88 | 99 | |
| 89 | − ret = snd_soc_card_jack_new(card, "Headset Jack", | |
| 90 | − SND_JACK_HEADSET | SND_JACK_LINEOUT | | |
| 91 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 92 | − SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 93 | − &pco_jack); | |
| 100 | + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | |
| 101 | + SND_JACK_HEADSET | | |
| 102 | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 103 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, | |
| 104 | + &pco_jack, | |
| 105 | + pco_jack_pins, | |
| 106 | + ARRAY_SIZE(pco_jack_pins)); | |
| 94 | 107 | if (ret) { |
| 95 | 108 | dev_err(card->dev, "HP jack creation failed %d\n", ret); |
| 96 | 109 | return ret; |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; |
| 22 | 22 | extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; |
| 23 | +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; | |
| 23 | 24 | |
| 24 | 25 | struct config_entry { |
| 25 | 26 | u32 flags; |
| @@ -488,10 +488,9 @@ static int acp63_sdw_platform_probe(struct platform_device *pdev) · 487 unmodified lines | ||
| 488 | 488 | return 0; |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | −static int acp63_sdw_platform_remove(struct platform_device *pdev) | |
| 491 | +static void acp63_sdw_platform_remove(struct platform_device *pdev) | |
| 492 | 492 | { |
| 493 | 493 | pm_runtime_disable(&pdev->dev); |
| 494 | − return 0; | |
| 495 | 494 | } |
| 496 | 495 | |
| 497 | 496 | static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) |
| @@ -552,7 +551,7 @@ static const struct dev_pm_ops acp63_pm_ops = { · 54 unmodified lines | ||
| 552 | 551 | |
| 553 | 552 | static struct platform_driver acp63_sdw_dma_driver = { |
| 554 | 553 | .probe = acp63_sdw_platform_probe, |
| 555 | − .remove = acp63_sdw_platform_remove, | |
| 554 | + .remove_new = acp63_sdw_platform_remove, | |
| 556 | 555 | .driver = { |
| 557 | 556 | .name = "amd_ps_sdw_dma", |
| 558 | 557 | .pm = &acp63_pm_ops, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | 2 | /* |
| 3 | − * Machine driver for AMD Vangogh platform using NAU8821 & CS35L41 | |
| 4 | − * codecs. | |
| 3 | + * Machine driver for AMD Vangogh platform using either | |
| 4 | + * NAU8821 & CS35L41 or NAU8821 & MAX98388 codecs. | |
| 5 | 5 | * |
| 6 | 6 | * Copyright 2021 Advanced Micro Devices, Inc. |
| 7 | 7 | */ |
| @@ -22,7 +22,6 @@ · 14 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | #define DRV_NAME "acp5x_mach" |
| 24 | 24 | #define DUAL_CHANNEL 2 |
| 25 | −#define VG_JUPITER 1 | |
| 26 | 25 | #define ACP5X_NAU8821_BCLK 3072000 |
| 27 | 26 | #define ACP5X_NAU8821_FREQ_OUT 12288000 |
| 28 | 27 | #define ACP5X_NAU8821_COMP_NAME "i2c-NVTN2020:00" |
| @@ -30,8 +29,10 @@ · 1 unmodified line | ||
| 30 | 29 | #define ACP5X_CS35L41_COMP_LNAME "spi-VLV1776:00" |
| 31 | 30 | #define ACP5X_CS35L41_COMP_RNAME "spi-VLV1776:01" |
| 32 | 31 | #define ACP5X_CS35L41_DAI_NAME "cs35l41-pcm" |
| 32 | +#define ACP5X_MAX98388_COMP_LNAME "i2c-ADS8388:00" | |
| 33 | +#define ACP5X_MAX98388_COMP_RNAME "i2c-ADS8388:01" | |
| 34 | +#define ACP5X_MAX98388_DAI_NAME "max98388-aif1" | |
| 33 | 35 | |
| 34 | −static unsigned long acp5x_machine_id; | |
| 35 | 36 | static struct snd_soc_jack vg_headset; |
| 36 | 37 | |
| 37 | 38 | SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); |
| @@ -169,6 +170,9 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, · 131 unmodified lines | ||
| 169 | 170 | struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); |
| 170 | 171 | int ret, bclk; |
| 171 | 172 | |
| 173 | + if (!dai) | |
| 174 | + return -EINVAL; | |
| 175 | + | |
| 172 | 176 | ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); |
| 173 | 177 | if (ret < 0) |
| 174 | 178 | dev_err(card->dev, "can't set FS clock %d\n", ret); |
| @@ -242,7 +246,6 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, · 67 unmodified lines | ||
| 242 | 246 | } |
| 243 | 247 | |
| 244 | 248 | return 0; |
| 245 | − | |
| 246 | 249 | } |
| 247 | 250 | |
| 248 | 251 | static const struct snd_soc_ops acp5x_cs35l41_play_ops = { |
| @@ -292,8 +295,6 @@ static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { · 43 unmodified lines | ||
| 292 | 295 | }, |
| 293 | 296 | }; |
| 294 | 297 | |
| 295 | − | |
| 296 | − | |
| 297 | 298 | static const struct snd_soc_dapm_widget acp5x_8821_35l41_widgets[] = { |
| 298 | 299 | SND_SOC_DAPM_HP("Headphone", NULL), |
| 299 | 300 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
| @@ -331,16 +332,110 @@ static struct snd_soc_card acp5x_8821_35l41_card = { · 31 unmodified lines | ||
| 331 | 332 | .num_controls = ARRAY_SIZE(acp5x_8821_controls), |
| 332 | 333 | }; |
| 333 | 334 | |
| 334 | −static int acp5x_vg_quirk_cb(const struct dmi_system_id *id) | |
| 335 | +static int acp5x_max98388_startup(struct snd_pcm_substream *substream) | |
| 335 | 336 | { |
| 336 | − acp5x_machine_id = VG_JUPITER; | |
| 337 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | |
| 338 | + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); | |
| 339 | + struct snd_pcm_runtime *runtime = substream->runtime; | |
| 340 | + | |
| 341 | + machine->play_i2s_instance = I2S_HS_INSTANCE; | |
| 337 | 342 | |
| 338 | − return 1; | |
| 343 | + runtime->hw.channels_max = DUAL_CHANNEL; | |
| 344 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | |
| 345 | + &constraints_channels); | |
| 346 | + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | |
| 347 | + &constraints_rates); | |
| 348 | + return 0; | |
| 339 | 349 | } |
| 340 | 350 | |
| 351 | +static const struct snd_soc_ops acp5x_max98388_play_ops = { | |
| 352 | + .startup = acp5x_max98388_startup, | |
| 353 | +}; | |
| 354 | + | |
| 355 | +static struct snd_soc_codec_conf acp5x_max98388_conf[] = { | |
| 356 | + { | |
| 357 | + .dlc = COMP_CODEC_CONF(ACP5X_MAX98388_COMP_LNAME), | |
| 358 | + .name_prefix = "Left", | |
| 359 | + }, | |
| 360 | + { | |
| 361 | + .dlc = COMP_CODEC_CONF(ACP5X_MAX98388_COMP_RNAME), | |
| 362 | + .name_prefix = "Right", | |
| 363 | + }, | |
| 364 | +}; | |
| 365 | + | |
| 366 | +SND_SOC_DAILINK_DEF(max98388, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_MAX98388_COMP_LNAME, | |
| 367 | + ACP5X_MAX98388_DAI_NAME), | |
| 368 | + COMP_CODEC(ACP5X_MAX98388_COMP_RNAME, | |
| 369 | + ACP5X_MAX98388_DAI_NAME))); | |
| 370 | + | |
| 371 | +static struct snd_soc_dai_link acp5x_8821_98388_dai[] = { | |
| 372 | + { | |
| 373 | + .name = "acp5x-8821-play", | |
| 374 | + .stream_name = "Playback/Capture", | |
| 375 | + .dai_fmt = SND_SOC_DAIFMT_I2S | | |
| 376 | + SND_SOC_DAIFMT_NB_NF | | |
| 377 | + SND_SOC_DAIFMT_CBC_CFC, | |
| 378 | + .dpcm_playback = 1, | |
| 379 | + .dpcm_capture = 1, | |
| 380 | + .ops = &acp5x_8821_ops, | |
| 381 | + .init = acp5x_8821_init, | |
| 382 | + SND_SOC_DAILINK_REG(acp5x_i2s, nau8821, platform), | |
| 383 | + }, | |
| 384 | + { | |
| 385 | + .name = "acp5x-max98388-play", | |
| 386 | + .stream_name = "MAX98388 Playback", | |
| 387 | + .dai_fmt = SND_SOC_DAIFMT_I2S | | |
| 388 | + SND_SOC_DAIFMT_NB_NF | | |
| 389 | + SND_SOC_DAIFMT_CBC_CFC, | |
| 390 | + .dpcm_playback = 1, | |
| 391 | + .playback_only = 1, | |
| 392 | + .ops = &acp5x_max98388_play_ops, | |
| 393 | + SND_SOC_DAILINK_REG(acp5x_bt, max98388, platform), | |
| 394 | + }, | |
| 395 | +}; | |
| 396 | + | |
| 397 | +static const struct snd_soc_dapm_widget acp5x_8821_98388_widgets[] = { | |
| 398 | + SND_SOC_DAPM_HP("Headphone", NULL), | |
| 399 | + SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
| 400 | + SND_SOC_DAPM_MIC("Int Mic", NULL), | |
| 401 | + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | |
| 402 | + platform_clock_control, | |
| 403 | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 404 | + SND_SOC_DAPM_SPK("SPK", NULL), | |
| 405 | +}; | |
| 406 | + | |
| 407 | +static const struct snd_soc_dapm_route acp5x_8821_98388_route[] = { | |
| 408 | + { "Headphone", NULL, "HPOL" }, | |
| 409 | + { "Headphone", NULL, "HPOR" }, | |
| 410 | + { "MICL", NULL, "Headset Mic" }, | |
| 411 | + { "MICR", NULL, "Headset Mic" }, | |
| 412 | + { "DMIC", NULL, "Int Mic" }, | |
| 413 | + | |
| 414 | + { "Headphone", NULL, "Platform Clock" }, | |
| 415 | + { "Headset Mic", NULL, "Platform Clock" }, | |
| 416 | + { "Int Mic", NULL, "Platform Clock" }, | |
| 417 | + | |
| 418 | + { "SPK", NULL, "Left BE_OUT" }, | |
| 419 | + { "SPK", NULL, "Right BE_OUT" }, | |
| 420 | +}; | |
| 421 | + | |
| 422 | +static struct snd_soc_card acp5x_8821_98388_card = { | |
| 423 | + .name = "acp5x-max98388", | |
| 424 | + .owner = THIS_MODULE, | |
| 425 | + .dai_link = acp5x_8821_98388_dai, | |
| 426 | + .num_links = ARRAY_SIZE(acp5x_8821_98388_dai), | |
| 427 | + .dapm_widgets = acp5x_8821_98388_widgets, | |
| 428 | + .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_98388_widgets), | |
| 429 | + .dapm_routes = acp5x_8821_98388_route, | |
| 430 | + .num_dapm_routes = ARRAY_SIZE(acp5x_8821_98388_route), | |
| 431 | + .codec_conf = acp5x_max98388_conf, | |
| 432 | + .num_configs = ARRAY_SIZE(acp5x_max98388_conf), | |
| 433 | + .controls = acp5x_8821_controls, | |
| 434 | + .num_controls = ARRAY_SIZE(acp5x_8821_controls), | |
| 435 | +}; | |
| 436 | + | |
| 341 | 437 | static const struct dmi_system_id acp5x_vg_quirk_table[] = { |
| 342 | 438 | { |
| 343 | − .callback = acp5x_vg_quirk_cb, | |
| 344 | 439 | .matches = { |
| 345 | 440 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Valve"), |
| 346 | 441 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), |
| @@ -351,23 +446,31 @@ static const struct dmi_system_id acp5x_vg_quirk_table[] = { · 4 unmodified lines | ||
| 351 | 446 | |
| 352 | 447 | static int acp5x_probe(struct platform_device *pdev) |
| 353 | 448 | { |
| 449 | + const struct dmi_system_id *dmi_id; | |
| 354 | 450 | struct acp5x_platform_info *machine; |
| 355 | 451 | struct device *dev = &pdev->dev; |
| 356 | 452 | struct snd_soc_card *card; |
| 357 | 453 | int ret; |
| 358 | 454 | |
| 455 | + card = (struct snd_soc_card *)device_get_match_data(dev); | |
| 456 | + if (!card) { | |
| 457 | + /* | |
| 458 | + * This is normally the result of directly probing the driver | |
| 459 | + * in pci-acp5x through platform_device_register_full(), which | |
| 460 | + * is necessary for the CS35L41 variant, as it doesn't support | |
| 461 | + * ACPI probing and relies on DMI quirks. | |
| 462 | + */ | |
| 463 | + dmi_id = dmi_first_match(acp5x_vg_quirk_table); | |
| 464 | + if (!dmi_id) | |
| 465 | + return -ENODEV; | |
| 466 | + | |
| 467 | + card = &acp5x_8821_35l41_card; | |
| 468 | + } | |
| 469 | + | |
| 359 | 470 | machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL); |
| 360 | 471 | if (!machine) |
| 361 | 472 | return -ENOMEM; |
| 362 | 473 | |
| 363 | − dmi_check_system(acp5x_vg_quirk_table); | |
| 364 | − switch (acp5x_machine_id) { | |
| 365 | − case VG_JUPITER: | |
| 366 | − card = &acp5x_8821_35l41_card; | |
| 367 | − break; | |
| 368 | − default: | |
| 369 | − return -ENODEV; | |
| 370 | − } | |
| 371 | 474 | card->dev = dev; |
| 372 | 475 | platform_set_drvdata(pdev, card); |
| 373 | 476 | snd_soc_card_set_drvdata(card, machine); |
| @@ -379,10 +482,17 @@ static int acp5x_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 379 | 482 | return 0; |
| 380 | 483 | } |
| 381 | 484 | |
| 485 | +static const struct acpi_device_id acp5x_acpi_match[] = { | |
| 486 | + { "AMDI8821", (kernel_ulong_t)&acp5x_8821_98388_card }, | |
| 487 | + {}, | |
| 488 | +}; | |
| 489 | +MODULE_DEVICE_TABLE(acpi, acp5x_acpi_match); | |
| 490 | + | |
| 382 | 491 | static struct platform_driver acp5x_mach_driver = { |
| 383 | 492 | .driver = { |
| 384 | − .name = "acp5x_mach", | |
| 493 | + .name = DRV_NAME, | |
| 385 | 494 | .pm = &snd_soc_pm_ops, |
| 495 | + .acpi_match_table = acp5x_acpi_match, | |
| 386 | 496 | }, |
| 387 | 497 | .probe = acp5x_probe, |
| 388 | 498 | }; |
| @@ -390,6 +500,6 @@ static struct platform_driver acp5x_mach_driver = { · 1 unmodified line | ||
| 390 | 500 | module_platform_driver(acp5x_mach_driver); |
| 391 | 501 | |
| 392 | 502 | MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); |
| 393 | −MODULE_DESCRIPTION("NAU8821 & CS35L41 audio support"); | |
| 503 | +MODULE_DESCRIPTION("NAU8821/CS35L41 & NAU8821/MAX98388 audio support"); | |
| 394 | 504 | MODULE_LICENSE("GPL v2"); |
| 395 | 505 | MODULE_ALIAS("platform:" DRV_NAME); |
| @@ -532,13 +532,6 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd, · 531 unmodified lines | ||
| 532 | 532 | return err; |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | −static const struct snd_soc_dai_ops atmel_i2s_dai_ops = { | |
| 536 | − .prepare = atmel_i2s_prepare, | |
| 537 | − .trigger = atmel_i2s_trigger, | |
| 538 | − .hw_params = atmel_i2s_hw_params, | |
| 539 | − .set_fmt = atmel_i2s_set_dai_fmt, | |
| 540 | −}; | |
| 541 | − | |
| 542 | 535 | static int atmel_i2s_dai_probe(struct snd_soc_dai *dai) |
| 543 | 536 | { |
| 544 | 537 | struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
| @@ -547,8 +540,15 @@ static int atmel_i2s_dai_probe(struct snd_soc_dai *dai) · 2 unmodified lines | ||
| 547 | 540 | return 0; |
| 548 | 541 | } |
| 549 | 542 | |
| 543 | +static const struct snd_soc_dai_ops atmel_i2s_dai_ops = { | |
| 544 | + .probe = atmel_i2s_dai_probe, | |
| 545 | + .prepare = atmel_i2s_prepare, | |
| 546 | + .trigger = atmel_i2s_trigger, | |
| 547 | + .hw_params = atmel_i2s_hw_params, | |
| 548 | + .set_fmt = atmel_i2s_set_dai_fmt, | |
| 549 | +}; | |
| 550 | + | |
| 550 | 551 | static struct snd_soc_dai_driver atmel_i2s_dai = { |
| 551 | − .probe = atmel_i2s_dai_probe, | |
| 552 | 552 | .playback = { |
| 553 | 553 | .channels_min = 1, |
| 554 | 554 | .channels_max = 2, |
| @@ -730,7 +730,7 @@ static void atmel_i2s_remove(struct platform_device *pdev) · 175 unmodified lines | ||
| 730 | 730 | static struct platform_driver atmel_i2s_driver = { |
| 731 | 731 | .driver = { |
| 732 | 732 | .name = "atmel_i2s", |
| 733 | − .of_match_table = of_match_ptr(atmel_i2s_dt_ids), | |
| 733 | + .of_match_table = atmel_i2s_dt_ids, | |
| 734 | 734 | }, |
| 735 | 735 | .probe = atmel_i2s_probe, |
| 736 | 736 | .remove_new = atmel_i2s_remove, |
| @@ -690,7 +690,7 @@ unregister_codec: · 689 unmodified lines | ||
| 690 | 690 | static struct platform_driver atmel_pdmic_driver = { |
| 691 | 691 | .driver = { |
| 692 | 692 | .name = "atmel-pdmic", |
| 693 | − .of_match_table = of_match_ptr(atmel_pdmic_of_match), | |
| 693 | + .of_match_table = atmel_pdmic_of_match, | |
| 694 | 694 | .pm = &snd_soc_pm_ops, |
| 695 | 695 | }, |
| 696 | 696 | .probe = atmel_pdmic_probe, |
| @@ -870,17 +870,6 @@ static int mchp_i2s_mcc_startup(struct snd_pcm_substream *substream, · 869 unmodified lines | ||
| 870 | 870 | return 0; |
| 871 | 871 | } |
| 872 | 872 | |
| 873 | −static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops = { | |
| 874 | − .set_sysclk = mchp_i2s_mcc_set_sysclk, | |
| 875 | − .set_bclk_ratio = mchp_i2s_mcc_set_bclk_ratio, | |
| 876 | − .startup = mchp_i2s_mcc_startup, | |
| 877 | − .trigger = mchp_i2s_mcc_trigger, | |
| 878 | − .hw_params = mchp_i2s_mcc_hw_params, | |
| 879 | − .hw_free = mchp_i2s_mcc_hw_free, | |
| 880 | − .set_fmt = mchp_i2s_mcc_set_dai_fmt, | |
| 881 | − .set_tdm_slot = mchp_i2s_mcc_set_dai_tdm_slot, | |
| 882 | −}; | |
| 883 | − | |
| 884 | 873 | static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai) |
| 885 | 874 | { |
| 886 | 875 | struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai); |
| @@ -895,6 +884,18 @@ static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai) · 8 unmodified lines | ||
| 895 | 884 | return 0; |
| 896 | 885 | } |
| 897 | 886 | |
| 887 | +static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops = { | |
| 888 | + .probe = mchp_i2s_mcc_dai_probe, | |
| 889 | + .set_sysclk = mchp_i2s_mcc_set_sysclk, | |
| 890 | + .set_bclk_ratio = mchp_i2s_mcc_set_bclk_ratio, | |
| 891 | + .startup = mchp_i2s_mcc_startup, | |
| 892 | + .trigger = mchp_i2s_mcc_trigger, | |
| 893 | + .hw_params = mchp_i2s_mcc_hw_params, | |
| 894 | + .hw_free = mchp_i2s_mcc_hw_free, | |
| 895 | + .set_fmt = mchp_i2s_mcc_set_dai_fmt, | |
| 896 | + .set_tdm_slot = mchp_i2s_mcc_set_dai_tdm_slot, | |
| 897 | +}; | |
| 898 | + | |
| 898 | 899 | #define MCHP_I2SMCC_RATES SNDRV_PCM_RATE_8000_192000 |
| 899 | 900 | |
| 900 | 901 | #define MCHP_I2SMCC_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ |
| @@ -906,7 +907,6 @@ static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai) · 5 unmodified lines | ||
| 906 | 907 | SNDRV_PCM_FMTBIT_S32_LE) |
| 907 | 908 | |
| 908 | 909 | static struct snd_soc_dai_driver mchp_i2s_mcc_dai = { |
| 909 | − .probe = mchp_i2s_mcc_dai_probe, | |
| 910 | 910 | .playback = { |
| 911 | 911 | .stream_name = "I2SMCC-Playback", |
| 912 | 912 | .channels_min = 1, |
| @@ -1098,7 +1098,7 @@ static void mchp_i2s_mcc_remove(struct platform_device *pdev) · 185 unmodified lines | ||
| 1098 | 1098 | static struct platform_driver mchp_i2s_mcc_driver = { |
| 1099 | 1099 | .driver = { |
| 1100 | 1100 | .name = "mchp_i2s_mcc", |
| 1101 | − .of_match_table = of_match_ptr(mchp_i2s_mcc_dt_ids), | |
| 1101 | + .of_match_table = mchp_i2s_mcc_dt_ids, | |
| 1102 | 1102 | }, |
| 1103 | 1103 | .probe = mchp_i2s_mcc_probe, |
| 1104 | 1104 | .remove_new = mchp_i2s_mcc_remove, |
| @@ -386,7 +386,6 @@ static int mchp_pdmc_open(struct snd_soc_component *component, · 385 unmodified lines | ||
| 386 | 386 | for (i = 0; i < ARRAY_SIZE(mchp_pdmc_snd_controls); i++) { |
| 387 | 387 | const struct snd_kcontrol_new *control = &mchp_pdmc_snd_controls[i]; |
| 388 | 388 | struct snd_ctl_elem_id id; |
| 389 | − struct snd_kcontrol *kctl; | |
| 390 | 389 | int err; |
| 391 | 390 | |
| 392 | 391 | if (component->name_prefix) |
| @@ -400,17 +399,10 @@ static int mchp_pdmc_open(struct snd_soc_component *component, · 7 unmodified lines | ||
| 400 | 399 | id.device = control->device; |
| 401 | 400 | id.subdevice = control->subdevice; |
| 402 | 401 | id.index = control->index; |
| 403 | − kctl = snd_ctl_find_id(component->card->snd_card, &id); | |
| 404 | − if (!kctl) { | |
| 405 | − dev_err(component->dev, "Failed to find %s\n", control->name); | |
| 406 | − continue; | |
| 407 | − } | |
| 408 | − err = snd_ctl_remove(component->card->snd_card, kctl); | |
| 409 | − if (err < 0) { | |
| 402 | + err = snd_ctl_remove_id(component->card->snd_card, &id); | |
| 403 | + if (err < 0) | |
| 410 | 404 | dev_err(component->dev, "%d: Failed to remove %s\n", err, |
| 411 | 405 | control->name); |
| 412 | − continue; | |
| 413 | − } | |
| 414 | 406 | } |
| 415 | 407 | |
| 416 | 408 | return 0; |
| @@ -706,13 +698,6 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, · 289 unmodified lines | ||
| 706 | 698 | return 0; |
| 707 | 699 | } |
| 708 | 700 | |
| 709 | −static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = { | |
| 710 | − .set_fmt = mchp_pdmc_set_fmt, | |
| 711 | − .startup = mchp_pdmc_startup, | |
| 712 | − .hw_params = mchp_pdmc_hw_params, | |
| 713 | − .trigger = mchp_pdmc_trigger, | |
| 714 | −}; | |
| 715 | − | |
| 716 | 701 | static int mchp_pdmc_add_chmap_ctls(struct snd_pcm *pcm, struct mchp_pdmc *dd) |
| 717 | 702 | { |
| 718 | 703 | struct mchp_pdmc_chmap *info; |
| @@ -765,8 +750,16 @@ static int mchp_pdmc_pcm_new(struct snd_soc_pcm_runtime *rtd, · 46 unmodified lines | ||
| 765 | 750 | return ret; |
| 766 | 751 | } |
| 767 | 752 | |
| 753 | +static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = { | |
| 754 | + .probe = mchp_pdmc_dai_probe, | |
| 755 | + .set_fmt = mchp_pdmc_set_fmt, | |
| 756 | + .startup = mchp_pdmc_startup, | |
| 757 | + .hw_params = mchp_pdmc_hw_params, | |
| 758 | + .trigger = mchp_pdmc_trigger, | |
| 759 | + .pcm_new = &mchp_pdmc_pcm_new, | |
| 760 | +}; | |
| 761 | + | |
| 768 | 762 | static struct snd_soc_dai_driver mchp_pdmc_dai = { |
| 769 | − .probe = mchp_pdmc_dai_probe, | |
| 770 | 763 | .capture = { |
| 771 | 764 | .stream_name = "Capture", |
| 772 | 765 | .channels_min = 1, |
| @@ -777,7 +770,6 @@ static struct snd_soc_dai_driver mchp_pdmc_dai = { · 4 unmodified lines | ||
| 777 | 770 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
| 778 | 771 | }, |
| 779 | 772 | .ops = &mchp_pdmc_dai_ops, |
| 780 | − .pcm_new = &mchp_pdmc_pcm_new, | |
| 781 | 773 | }; |
| 782 | 774 | |
| 783 | 775 | /* PDMC interrupt handler */ |
| @@ -962,7 +954,7 @@ static int mchp_pdmc_dt_init(struct mchp_pdmc *dd) · 178 unmodified lines | ||
| 962 | 954 | /* used to clean the channel index found on RHR's MSB */ |
| 963 | 955 | static int mchp_pdmc_process(struct snd_pcm_substream *substream, |
| 964 | 956 | int channel, unsigned long hwoff, |
| 965 | − void *buf, unsigned long bytes) | |
| 957 | + struct iov_iter *buf, unsigned long bytes) | |
| 966 | 958 | { |
| 967 | 959 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 968 | 960 | u8 *dma_ptr = runtime->dma_area + hwoff + |
| @@ -503,11 +503,6 @@ unlock: · 502 unmodified lines | ||
| 503 | 503 | return ret; |
| 504 | 504 | } |
| 505 | 505 | |
| 506 | −static const struct snd_soc_dai_ops mchp_spdifrx_dai_ops = { | |
| 507 | − .trigger = mchp_spdifrx_trigger, | |
| 508 | − .hw_params = mchp_spdifrx_hw_params, | |
| 509 | −}; | |
| 510 | − | |
| 511 | 506 | #define MCHP_SPDIF_RATES SNDRV_PCM_RATE_8000_192000 |
| 512 | 507 | |
| 513 | 508 | #define MCHP_SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| @@ -1009,10 +1004,15 @@ static int mchp_spdifrx_dai_remove(struct snd_soc_dai *dai) · 495 unmodified lines | ||
| 1009 | 1004 | return 0; |
| 1010 | 1005 | } |
| 1011 | 1006 | |
| 1007 | +static const struct snd_soc_dai_ops mchp_spdifrx_dai_ops = { | |
| 1008 | + .probe = mchp_spdifrx_dai_probe, | |
| 1009 | + .remove = mchp_spdifrx_dai_remove, | |
| 1010 | + .trigger = mchp_spdifrx_trigger, | |
| 1011 | + .hw_params = mchp_spdifrx_hw_params, | |
| 1012 | +}; | |
| 1013 | + | |
| 1012 | 1014 | static struct snd_soc_dai_driver mchp_spdifrx_dai = { |
| 1013 | 1015 | .name = "mchp-spdifrx", |
| 1014 | − .probe = mchp_spdifrx_dai_probe, | |
| 1015 | − .remove = mchp_spdifrx_dai_remove, | |
| 1016 | 1016 | .capture = { |
| 1017 | 1017 | .stream_name = "S/PDIF Capture", |
| 1018 | 1018 | .channels_min = SPDIFRX_CHANNELS, |
| @@ -1197,7 +1197,7 @@ static struct platform_driver mchp_spdifrx_driver = { · 178 unmodified lines | ||
| 1197 | 1197 | .remove_new = mchp_spdifrx_remove, |
| 1198 | 1198 | .driver = { |
| 1199 | 1199 | .name = "mchp_spdifrx", |
| 1200 | − .of_match_table = of_match_ptr(mchp_spdifrx_dt_ids), | |
| 1200 | + .of_match_table = mchp_spdifrx_dt_ids, | |
| 1201 | 1201 | .pm = pm_ptr(&mchp_spdifrx_pm_ops), |
| 1202 | 1202 | }, |
| 1203 | 1203 | }; |
| @@ -516,14 +516,6 @@ static int mchp_spdiftx_hw_free(struct snd_pcm_substream *substream, · 515 unmodified lines | ||
| 516 | 516 | SPDIFTX_CR_SWRST | SPDIFTX_CR_FCLR); |
| 517 | 517 | } |
| 518 | 518 | |
| 519 | −static const struct snd_soc_dai_ops mchp_spdiftx_dai_ops = { | |
| 520 | − .startup = mchp_spdiftx_dai_startup, | |
| 521 | − .shutdown = mchp_spdiftx_dai_shutdown, | |
| 522 | − .trigger = mchp_spdiftx_trigger, | |
| 523 | − .hw_params = mchp_spdiftx_hw_params, | |
| 524 | − .hw_free = mchp_spdiftx_hw_free, | |
| 525 | −}; | |
| 526 | − | |
| 527 | 519 | #define MCHP_SPDIFTX_RATES SNDRV_PCM_RATE_8000_192000 |
| 528 | 520 | |
| 529 | 521 | #define MCHP_SPDIFTX_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ |
| @@ -703,9 +695,17 @@ static int mchp_spdiftx_dai_probe(struct snd_soc_dai *dai) · 173 unmodified lines | ||
| 703 | 695 | return 0; |
| 704 | 696 | } |
| 705 | 697 | |
| 698 | +static const struct snd_soc_dai_ops mchp_spdiftx_dai_ops = { | |
| 699 | + .probe = mchp_spdiftx_dai_probe, | |
| 700 | + .startup = mchp_spdiftx_dai_startup, | |
| 701 | + .shutdown = mchp_spdiftx_dai_shutdown, | |
| 702 | + .trigger = mchp_spdiftx_trigger, | |
| 703 | + .hw_params = mchp_spdiftx_hw_params, | |
| 704 | + .hw_free = mchp_spdiftx_hw_free, | |
| 705 | +}; | |
| 706 | + | |
| 706 | 707 | static struct snd_soc_dai_driver mchp_spdiftx_dai = { |
| 707 | 708 | .name = "mchp-spdiftx", |
| 708 | − .probe = mchp_spdiftx_dai_probe, | |
| 709 | 709 | .playback = { |
| 710 | 710 | .stream_name = "S/PDIF Playback", |
| 711 | 711 | .channels_min = 1, |
| @@ -891,7 +891,7 @@ static struct platform_driver mchp_spdiftx_driver = { · 179 unmodified lines | ||
| 891 | 891 | .remove_new = mchp_spdiftx_remove, |
| 892 | 892 | .driver = { |
| 893 | 893 | .name = "mchp_spdiftx", |
| 894 | − .of_match_table = of_match_ptr(mchp_spdiftx_dt_ids), | |
| 894 | + .of_match_table = mchp_spdiftx_dt_ids, | |
| 895 | 895 | .pm = pm_ptr(&mchp_spdiftx_pm_ops) |
| 896 | 896 | }, |
| 897 | 897 | }; |
| @@ -430,7 +430,7 @@ MODULE_DEVICE_TABLE(of, tse850_dt_ids); · 429 unmodified lines | ||
| 430 | 430 | static struct platform_driver tse850_driver = { |
| 431 | 431 | .driver = { |
| 432 | 432 | .name = "axentia-tse850-pcm5142", |
| 433 | − .of_match_table = of_match_ptr(tse850_dt_ids), | |
| 433 | + .of_match_table = tse850_dt_ids, | |
| 434 | 434 | }, |
| 435 | 435 | .probe = tse850_probe, |
| 436 | 436 | .remove_new = tse850_remove, |
| @@ -195,18 +195,18 @@ static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, · 194 unmodified lines | ||
| 195 | 195 | return 0; |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | −static const struct snd_soc_dai_ops alchemy_ac97c_ops = { | |
| 199 | − .startup = alchemy_ac97c_startup, | |
| 200 | −}; | |
| 201 | − | |
| 202 | 198 | static int au1xac97c_dai_probe(struct snd_soc_dai *dai) |
| 203 | 199 | { |
| 204 | 200 | return ac97c_workdata ? 0 : -ENODEV; |
| 205 | 201 | } |
| 206 | 202 | |
| 203 | +static const struct snd_soc_dai_ops alchemy_ac97c_ops = { | |
| 204 | + .probe = au1xac97c_dai_probe, | |
| 205 | + .startup = alchemy_ac97c_startup, | |
| 206 | +}; | |
| 207 | + | |
| 207 | 208 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { |
| 208 | 209 | .name = "alchemy-ac97c", |
| 209 | − .probe = au1xac97c_dai_probe, | |
| 210 | 210 | .playback = { |
| 211 | 211 | .rates = AC97_RATES, |
| 212 | 212 | .formats = AC97_FMTS, |
| @@ -333,13 +333,13 @@ static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) · 332 unmodified lines | ||
| 333 | 333 | } |
| 334 | 334 | |
| 335 | 335 | static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { |
| 336 | + .probe = au1xpsc_ac97_probe, | |
| 336 | 337 | .startup = au1xpsc_ac97_startup, |
| 337 | 338 | .trigger = au1xpsc_ac97_trigger, |
| 338 | 339 | .hw_params = au1xpsc_ac97_hw_params, |
| 339 | 340 | }; |
| 340 | 341 | |
| 341 | 342 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { |
| 342 | − .probe = au1xpsc_ac97_probe, | |
| 343 | 343 | .playback = { |
| 344 | 344 | .rates = AC97_RATES, |
| 345 | 345 | .formats = AC97_FMTS, |
| @@ -737,7 +737,19 @@ static void bcm2835_i2s_shutdown(struct snd_pcm_substream *substream, · 736 unmodified lines | ||
| 737 | 737 | bcm2835_i2s_stop_clock(dev); |
| 738 | 738 | } |
| 739 | 739 | |
| 740 | +static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) | |
| 741 | +{ | |
| 742 | + struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 743 | + | |
| 744 | + snd_soc_dai_init_dma_data(dai, | |
| 745 | + &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK], | |
| 746 | + &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]); | |
| 747 | + | |
| 748 | + return 0; | |
| 749 | +} | |
| 750 | + | |
| 740 | 751 | static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { |
| 752 | + .probe = bcm2835_i2s_dai_probe, | |
| 741 | 753 | .startup = bcm2835_i2s_startup, |
| 742 | 754 | .shutdown = bcm2835_i2s_shutdown, |
| 743 | 755 | .prepare = bcm2835_i2s_prepare, |
| @@ -748,20 +760,8 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { · 4 unmodified lines | ||
| 748 | 760 | .set_tdm_slot = bcm2835_i2s_set_dai_tdm_slot, |
| 749 | 761 | }; |
| 750 | 762 | |
| 751 | −static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) | |
| 752 | −{ | |
| 753 | − struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | |
| 754 | − | |
| 755 | − snd_soc_dai_init_dma_data(dai, | |
| 756 | − &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK], | |
| 757 | − &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]); | |
| 758 | − | |
| 759 | − return 0; | |
| 760 | −} | |
| 761 | − | |
| 762 | 763 | static struct snd_soc_dai_driver bcm2835_i2s_dai = { |
| 763 | 764 | .name = "bcm2835-i2s", |
| 764 | − .probe = bcm2835_i2s_dai_probe, | |
| 765 | 765 | .playback = { |
| 766 | 766 | .channels_min = 2, |
| 767 | 767 | .channels_max = 2, |
| @@ -225,7 +225,6 @@ static int bcm63xx_i2s_dev_probe(struct platform_device *pdev) · 224 unmodified lines | ||
| 225 | 225 | { |
| 226 | 226 | int ret = 0; |
| 227 | 227 | void __iomem *regs; |
| 228 | − struct resource *r_mem, *region; | |
| 229 | 228 | struct bcm_i2s_priv *i2s_priv; |
| 230 | 229 | struct regmap *regmap_i2s; |
| 231 | 230 | struct clk *i2s_clk; |
| @@ -241,20 +240,7 @@ static int bcm63xx_i2s_dev_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 241 | 240 | return PTR_ERR(i2s_clk); |
| 242 | 241 | } |
| 243 | 242 | |
| 244 | − r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 245 | − if (!r_mem) { | |
| 246 | − dev_err(&pdev->dev, "Unable to get register resource.\n"); | |
| 247 | − return -ENODEV; | |
| 248 | − } | |
| 249 | − | |
| 250 | − region = devm_request_mem_region(&pdev->dev, r_mem->start, | |
| 251 | − resource_size(r_mem), DRV_NAME); | |
| 252 | − if (!region) { | |
| 253 | − dev_err(&pdev->dev, "Memory region already claimed\n"); | |
| 254 | − return -EBUSY; | |
| 255 | − } | |
| 256 | − | |
| 257 | − regs = devm_ioremap_resource(&pdev->dev, r_mem); | |
| 243 | + regs = devm_platform_ioremap_resource(pdev, 0); | |
| 258 | 244 | if (IS_ERR(regs)) { |
| 259 | 245 | ret = PTR_ERR(regs); |
| 260 | 246 | return ret; |
| @@ -117,8 +117,6 @@ struct cygnus_audio { · 116 unmodified lines | ||
| 117 | 117 | unsigned long vco_rate; |
| 118 | 118 | }; |
| 119 | 119 | |
| 120 | −extern int cygnus_ssp_get_mode(struct snd_soc_dai *cpu_dai); | |
| 121 | −extern int cygnus_ssp_add_pll_tweak_controls(struct snd_soc_pcm_runtime *rtd); | |
| 122 | 120 | extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, |
| 123 | 121 | int len); |
| 124 | 122 | extern int cygnus_soc_platform_register(struct device *dev, |
| @@ -407,6 +407,7 @@ static int ep93xx_i2s_resume(struct snd_soc_component *component) · 406 unmodified lines | ||
| 407 | 407 | #endif |
| 408 | 408 | |
| 409 | 409 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { |
| 410 | + .probe = ep93xx_i2s_dai_probe, | |
| 410 | 411 | .startup = ep93xx_i2s_startup, |
| 411 | 412 | .shutdown = ep93xx_i2s_shutdown, |
| 412 | 413 | .hw_params = ep93xx_i2s_hw_params, |
| @@ -418,7 +419,6 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { · 5 unmodified lines | ||
| 418 | 419 | |
| 419 | 420 | static struct snd_soc_dai_driver ep93xx_i2s_dai = { |
| 420 | 421 | .symmetric_rate = 1, |
| 421 | − .probe = ep93xx_i2s_dai_probe, | |
| 422 | 422 | .playback = { |
| 423 | 423 | .channels_min = 2, |
| 424 | 424 | .channels_max = 2, |
| @@ -143,7 +143,7 @@ struct pm860x_priv { · 142 unmodified lines | ||
| 143 | 143 | struct pm860x_det det; |
| 144 | 144 | |
| 145 | 145 | int irq[4]; |
| 146 | − unsigned char name[4][MAX_NAME_LEN+1]; | |
| 146 | + unsigned char name[4][MAX_NAME_LEN]; | |
| 147 | 147 | }; |
| 148 | 148 | |
| 149 | 149 | /* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ |
| @@ -1373,7 +1373,7 @@ static int pm860x_codec_probe(struct platform_device *pdev) · 1223 unmodified lines | ||
| 1373 | 1373 | return -EINVAL; |
| 1374 | 1374 | } |
| 1375 | 1375 | pm860x->irq[i] = res->start + chip->irq_base; |
| 1376 | − strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); | |
| 1376 | + strscpy(pm860x->name[i], res->name, MAX_NAME_LEN); | |
| 1377 | 1377 | } |
| 1378 | 1378 | |
| 1379 | 1379 | ret = devm_snd_soc_register_component(&pdev->dev, |
| @@ -15,7 +15,6 @@ config SND_SOC_ALL_CODECS · 14 unmodified lines | ||
| 15 | 15 | tristate "Build all ASoC CODEC drivers" |
| 16 | 16 | depends on COMPILE_TEST |
| 17 | 17 | imply SND_SOC_88PM860X |
| 18 | − imply SND_SOC_L3 | |
| 19 | 18 | imply SND_SOC_AB8500_CODEC |
| 20 | 19 | imply SND_SOC_AC97_CODEC |
| 21 | 20 | imply SND_SOC_AD1836 |
| @@ -53,8 +52,10 @@ config SND_SOC_ALL_CODECS · 31 unmodified lines | ||
| 53 | 52 | imply SND_SOC_AK5558 |
| 54 | 53 | imply SND_SOC_ALC5623 |
| 55 | 54 | imply SND_SOC_ALC5632 |
| 55 | + imply SND_SOC_AUDIO_IIO_AUX | |
| 56 | 56 | imply SND_SOC_AW8738 |
| 57 | 57 | imply SND_SOC_AW88395 |
| 58 | + imply SND_SOC_AW88261 | |
| 58 | 59 | imply SND_SOC_BT_SCO |
| 59 | 60 | imply SND_SOC_BD28623 |
| 60 | 61 | imply SND_SOC_CHV3_CODEC |
| @@ -74,6 +75,8 @@ config SND_SOC_ALL_CODECS · 13 unmodified lines | ||
| 74 | 75 | imply SND_SOC_CS35L56_SDW |
| 75 | 76 | imply SND_SOC_CS42L42 |
| 76 | 77 | imply SND_SOC_CS42L42_SDW |
| 78 | + imply SND_SOC_CS42L43 | |
| 79 | + imply SND_SOC_CS42L43_SDW | |
| 77 | 80 | imply SND_SOC_CS42L51_I2C |
| 78 | 81 | imply SND_SOC_CS42L52 |
| 79 | 82 | imply SND_SOC_CS42L56 |
| @@ -183,6 +186,7 @@ config SND_SOC_ALL_CODECS · 103 unmodified lines | ||
| 183 | 186 | imply SND_SOC_RT1015 |
| 184 | 187 | imply SND_SOC_RT1015P |
| 185 | 188 | imply SND_SOC_RT1016 |
| 189 | + imply SND_SOC_RT1017_SDCA_SDW | |
| 186 | 190 | imply SND_SOC_RT1019 |
| 187 | 191 | imply SND_SOC_RT1305 |
| 188 | 192 | imply SND_SOC_RT1308 |
| @@ -265,7 +269,6 @@ config SND_SOC_ALL_CODECS · 76 unmodified lines | ||
| 265 | 269 | imply SND_SOC_TWL4030 |
| 266 | 270 | imply SND_SOC_TWL6040 |
| 267 | 271 | imply SND_SOC_UDA1334 |
| 268 | − imply SND_SOC_UDA134X | |
| 269 | 272 | imply SND_SOC_UDA1380 |
| 270 | 273 | imply SND_SOC_WCD9335 |
| 271 | 274 | imply SND_SOC_WCD934X |
| @@ -614,6 +617,17 @@ config SND_SOC_ALC5632 · 342 unmodified lines | ||
| 614 | 617 | tristate |
| 615 | 618 | depends on I2C |
| 616 | 619 | |
| 620 | +config SND_SOC_AUDIO_IIO_AUX | |
| 621 | + tristate "Audio IIO Auxiliary device" | |
| 622 | + depends on IIO | |
| 623 | + help | |
| 624 | + Enable support for Industrial I/O devices as audio auxiliary devices. | |
| 625 | + This allows to have an IIO device present in the audio path and | |
| 626 | + controlled using mixer controls. | |
| 627 | + | |
| 628 | + To compile this driver as a module, choose M here: the module | |
| 629 | + will be called snd-soc-audio-iio-aux. | |
| 630 | + | |
| 617 | 631 | config SND_SOC_AW8738 |
| 618 | 632 | tristate "Awinic AW8738 Audio Amplifier" |
| 619 | 633 | select GPIOLIB |
| @@ -640,6 +654,20 @@ config SND_SOC_AW88395 · 20 unmodified lines | ||
| 640 | 654 | digital Smart K audio amplifier with an integrated 10V |
| 641 | 655 | smart boost convert. |
| 642 | 656 | |
| 657 | +config SND_SOC_AW88261 | |
| 658 | + tristate "Soc Audio for awinic aw88261" | |
| 659 | + depends on I2C | |
| 660 | + select CRC8 | |
| 661 | + select REGMAP_I2C | |
| 662 | + select GPIOLIB | |
| 663 | + select SND_SOC_AW88395_LIB | |
| 664 | + help | |
| 665 | + This option enables support for aw88261 Smart PA. | |
| 666 | + The awinic AW88261 is an I2S/TDM input, high efficiency | |
| 667 | + digital Smart K audio amplifier. The output voltage of | |
| 668 | + boost converter can be adjusted smartly according to | |
| 669 | + the input amplitude. | |
| 670 | + | |
| 643 | 671 | config SND_SOC_BD28623 |
| 644 | 672 | tristate "ROHM BD28623 CODEC" |
| 645 | 673 | help |
| @@ -789,6 +817,20 @@ config SND_SOC_CS42L42_SDW · 143 unmodified lines | ||
| 789 | 817 | help |
| 790 | 818 | Enable support for Cirrus Logic CS42L42 codec with Soundwire control |
| 791 | 819 | |
| 820 | +config SND_SOC_CS42L43 | |
| 821 | + tristate "Cirrus Logic CS42L43 CODEC" | |
| 822 | + depends on MFD_CS42L43 | |
| 823 | + help | |
| 824 | + Select this to support the audio functions of the Cirrus Logic | |
| 825 | + CS42L43 PC CODEC. | |
| 826 | + | |
| 827 | +config SND_SOC_CS42L43_SDW | |
| 828 | + tristate "Cirrus Logic CS42L43 CODEC (SoundWire)" | |
| 829 | + depends on SND_SOC_CS42L43 && MFD_CS42L43_SDW | |
| 830 | + help | |
| 831 | + Select this to support the audio functions of the Cirrus Logic | |
| 832 | + CS42L43 PC CODEC over SoundWire. | |
| 833 | + | |
| 792 | 834 | config SND_SOC_CS42L51 |
| 793 | 835 | tristate |
| 794 | 836 | |
| @@ -966,9 +1008,6 @@ config SND_SOC_JZ4770_CODEC · 171 unmodified lines | ||
| 966 | 1008 | This driver can also be built as a module. If so, the module |
| 967 | 1009 | will be called snd-soc-jz4770-codec. |
| 968 | 1010 | |
| 969 | −config SND_SOC_L3 | |
| 970 | − tristate | |
| 971 | − | |
| 972 | 1011 | config SND_SOC_DA7210 |
| 973 | 1012 | tristate |
| 974 | 1013 | depends on SND_SOC_I2C_AND_SPI |
| @@ -1416,6 +1455,11 @@ config SND_SOC_RT1016 · 441 unmodified lines | ||
| 1416 | 1455 | tristate |
| 1417 | 1456 | depends on I2C |
| 1418 | 1457 | |
| 1458 | +config SND_SOC_RT1017_SDCA_SDW | |
| 1459 | + tristate "Realtek RT1017 SDCA Codec - SDW" | |
| 1460 | + depends on SOUNDWIRE | |
| 1461 | + select REGMAP_SOUNDWIRE | |
| 1462 | + | |
| 1419 | 1463 | config SND_SOC_RT1019 |
| 1420 | 1464 | tristate |
| 1421 | 1465 | depends on I2C |
| @@ -1708,6 +1752,7 @@ config SND_SOC_STA529 · 286 unmodified lines | ||
| 1708 | 1752 | config SND_SOC_STAC9766 |
| 1709 | 1753 | tristate |
| 1710 | 1754 | depends on SND_SOC_AC97_BUS |
| 1755 | + select REGMAP_AC97 | |
| 1711 | 1756 | |
| 1712 | 1757 | config SND_SOC_STI_SAS |
| 1713 | 1758 | tristate "codec Audio support for STI SAS codec" |
| @@ -1919,9 +1964,6 @@ config SND_SOC_UDA1334 · 205 unmodified lines | ||
| 1919 | 1964 | and has basic features such as de-emphasis (at 44.1 kHz sampling |
| 1920 | 1965 | rate) and mute. |
| 1921 | 1966 | |
| 1922 | −config SND_SOC_UDA134X | |
| 1923 | − tristate | |
| 1924 | − | |
| 1925 | 1967 | config SND_SOC_UDA1380 |
| 1926 | 1968 | tristate |
| 1927 | 1969 | depends on I2C |
| @@ -45,10 +45,12 @@ snd-soc-ak4671-objs := ak4671.o · 44 unmodified lines | ||
| 45 | 45 | snd-soc-ak5386-objs := ak5386.o |
| 46 | 46 | snd-soc-ak5558-objs := ak5558.o |
| 47 | 47 | snd-soc-arizona-objs := arizona.o arizona-jack.o |
| 48 | +snd-soc-audio-iio-aux-objs := audio-iio-aux.o | |
| 48 | 49 | snd-soc-aw8738-objs := aw8738.o |
| 49 | 50 | snd-soc-aw88395-lib-objs := aw88395/aw88395_lib.o |
| 50 | 51 | snd-soc-aw88395-objs := aw88395/aw88395.o \ |
| 51 | 52 | aw88395/aw88395_device.o |
| 53 | +snd-soc-aw88261-objs := aw88261.o | |
| 52 | 54 | snd-soc-bd28623-objs := bd28623.o |
| 53 | 55 | snd-soc-bt-sco-objs := bt-sco.o |
| 54 | 56 | snd-soc-chv3-codec-objs := chv3-codec.o |
| @@ -75,6 +77,8 @@ snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o · 20 unmodified lines | ||
| 75 | 77 | snd-soc-cs42l42-objs := cs42l42.o |
| 76 | 78 | snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o |
| 77 | 79 | snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o |
| 80 | +snd-soc-cs42l43-objs := cs42l43.o cs42l43-jack.o | |
| 81 | +snd-soc-cs42l43-sdw-objs := cs42l43-sdw.o | |
| 78 | 82 | snd-soc-cs42l51-objs := cs42l51.o |
| 79 | 83 | snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o |
| 80 | 84 | snd-soc-cs42l52-objs := cs42l52.o |
| @@ -127,7 +131,6 @@ snd-soc-jz4740-codec-objs := jz4740.o · 46 unmodified lines | ||
| 127 | 131 | snd-soc-jz4725b-codec-objs := jz4725b.o |
| 128 | 132 | snd-soc-jz4760-codec-objs := jz4760.o |
| 129 | 133 | snd-soc-jz4770-codec-objs := jz4770.o |
| 130 | −snd-soc-l3-objs := l3.o | |
| 131 | 134 | snd-soc-lm4857-objs := lm4857.o |
| 132 | 135 | snd-soc-lm49453-objs := lm49453.o |
| 133 | 136 | snd-soc-lochnagar-sc-objs := lochnagar-sc.o |
| @@ -204,6 +207,7 @@ snd-soc-rt1011-objs := rt1011.o · 70 unmodified lines | ||
| 204 | 207 | snd-soc-rt1015-objs := rt1015.o |
| 205 | 208 | snd-soc-rt1015p-objs := rt1015p.o |
| 206 | 209 | snd-soc-rt1016-objs := rt1016.o |
| 210 | +snd-soc-rt1017-sdca-objs := rt1017-sdca-sdw.o | |
| 207 | 211 | snd-soc-rt1019-objs := rt1019.o |
| 208 | 212 | snd-soc-rt1305-objs := rt1305.o |
| 209 | 213 | snd-soc-rt1308-objs := rt1308.o |
| @@ -298,7 +302,6 @@ snd-soc-ts3a227e-objs := ts3a227e.o · 88 unmodified lines | ||
| 298 | 302 | snd-soc-twl4030-objs := twl4030.o |
| 299 | 303 | snd-soc-twl6040-objs := twl6040.o |
| 300 | 304 | snd-soc-uda1334-objs := uda1334.o |
| 301 | −snd-soc-uda134x-objs := uda134x.o | |
| 302 | 305 | snd-soc-uda1380-objs := uda1380.o |
| 303 | 306 | snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o |
| 304 | 307 | snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o |
| @@ -428,9 +431,11 @@ obj-$(CONFIG_SND_SOC_AK5558) += snd-soc-ak5558.o · 123 unmodified lines | ||
| 428 | 431 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
| 429 | 432 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o |
| 430 | 433 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o |
| 434 | +obj-$(CONFIG_SND_SOC_AUDIO_IIO_AUX) += snd-soc-audio-iio-aux.o | |
| 431 | 435 | obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o |
| 432 | 436 | obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o |
| 433 | 437 | obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o |
| 438 | +obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o | |
| 434 | 439 | obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o |
| 435 | 440 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o |
| 436 | 441 | obj-$(CONFIG_SND_SOC_CHV3_CODEC) += snd-soc-chv3-codec.o |
| @@ -457,6 +462,8 @@ obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o · 20 unmodified lines | ||
| 457 | 462 | obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o |
| 458 | 463 | obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o |
| 459 | 464 | obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o |
| 465 | +obj-$(CONFIG_SND_SOC_CS42L43) += snd-soc-cs42l43.o | |
| 466 | +obj-$(CONFIG_SND_SOC_CS42L43_SDW) += snd-soc-cs42l43-sdw.o | |
| 460 | 467 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
| 461 | 468 | obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o |
| 462 | 469 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
| @@ -509,7 +516,6 @@ obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o · 46 unmodified lines | ||
| 509 | 516 | obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o |
| 510 | 517 | obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o |
| 511 | 518 | obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o |
| 512 | −obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | |
| 513 | 519 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o |
| 514 | 520 | obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o |
| 515 | 521 | obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o |
| @@ -581,6 +587,7 @@ obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o · 65 unmodified lines | ||
| 581 | 587 | obj-$(CONFIG_SND_SOC_RT1015) += snd-soc-rt1015.o |
| 582 | 588 | obj-$(CONFIG_SND_SOC_RT1015P) += snd-soc-rt1015p.o |
| 583 | 589 | obj-$(CONFIG_SND_SOC_RT1016) += snd-soc-rt1016.o |
| 590 | +obj-$(CONFIG_SND_SOC_RT1017_SDCA_SDW) += snd-soc-rt1017-sdca.o | |
| 584 | 591 | obj-$(CONFIG_SND_SOC_RT1019) += snd-soc-rt1019.o |
| 585 | 592 | obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o |
| 586 | 593 | obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o |
| @@ -677,7 +684,6 @@ obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o · 90 unmodified lines | ||
| 677 | 684 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
| 678 | 685 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
| 679 | 686 | obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o |
| 680 | −obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | |
| 681 | 687 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
| 682 | 688 | obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o |
| 683 | 689 | obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o |
| @@ -358,7 +358,7 @@ static const struct regmap_config ad1836_regmap_config = { · 357 unmodified lines | ||
| 358 | 358 | .max_register = AD1836_ADC_CTRL3, |
| 359 | 359 | .reg_defaults = ad1836_reg_defaults, |
| 360 | 360 | .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults), |
| 361 | − .cache_type = REGCACHE_RBTREE, | |
| 361 | + .cache_type = REGCACHE_MAPLE, | |
| 362 | 362 | }; |
| 363 | 363 | |
| 364 | 364 | static int ad1836_spi_probe(struct spi_device *spi) |
| @@ -92,7 +92,7 @@ static const struct regmap_config ad1980_regmap_config = { · 91 unmodified lines | ||
| 92 | 92 | .reg_stride = 2, |
| 93 | 93 | .val_bits = 16, |
| 94 | 94 | .max_register = 0x7e, |
| 95 | − .cache_type = REGCACHE_RBTREE, | |
| 95 | + .cache_type = REGCACHE_MAPLE, | |
| 96 | 96 | |
| 97 | 97 | .volatile_reg = regmap_ac97_default_volatile, |
| 98 | 98 | .readable_reg = ad1980_readable_reg, |
| @@ -1056,7 +1056,7 @@ const struct regmap_config adau1372_regmap_config = { · 1055 unmodified lines | ||
| 1056 | 1056 | .reg_defaults = adau1372_reg_defaults, |
| 1057 | 1057 | .num_reg_defaults = ARRAY_SIZE(adau1372_reg_defaults), |
| 1058 | 1058 | .volatile_reg = adau1372_volatile_register, |
| 1059 | − .cache_type = REGCACHE_RBTREE, | |
| 1059 | + .cache_type = REGCACHE_MAPLE, | |
| 1060 | 1060 | }; |
| 1061 | 1061 | EXPORT_SYMBOL_GPL(adau1372_regmap_config); |
| 1062 | 1062 | |
| @@ -1451,7 +1451,7 @@ static const struct regmap_config adau1373_regmap_config = { · 1450 unmodified lines | ||
| 1451 | 1451 | .volatile_reg = adau1373_register_volatile, |
| 1452 | 1452 | .max_register = ADAU1373_SOFT_RESET, |
| 1453 | 1453 | |
| 1454 | − .cache_type = REGCACHE_RBTREE, | |
| 1454 | + .cache_type = REGCACHE_MAPLE, | |
| 1455 | 1455 | .reg_defaults = adau1373_reg_defaults, |
| 1456 | 1456 | .num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults), |
| 1457 | 1457 | }; |
| @@ -778,7 +778,7 @@ static const struct regmap_config adau1701_regmap = { · 777 unmodified lines | ||
| 778 | 778 | .reg_bits = 16, |
| 779 | 779 | .val_bits = 32, |
| 780 | 780 | .max_register = ADAU1701_MAX_REGISTER, |
| 781 | − .cache_type = REGCACHE_RBTREE, | |
| 781 | + .cache_type = REGCACHE_MAPLE, | |
| 782 | 782 | .volatile_reg = adau1701_volatile_reg, |
| 783 | 783 | .reg_write = adau1701_reg_write, |
| 784 | 784 | .reg_read = adau1701_reg_read, |
| @@ -1014,7 +1014,7 @@ const struct regmap_config adau1761_regmap_config = { · 1013 unmodified lines | ||
| 1014 | 1014 | .readable_reg = adau1761_readable_register, |
| 1015 | 1015 | .volatile_reg = adau17x1_volatile_register, |
| 1016 | 1016 | .precious_reg = adau17x1_precious_register, |
| 1017 | − .cache_type = REGCACHE_RBTREE, | |
| 1017 | + .cache_type = REGCACHE_MAPLE, | |
| 1018 | 1018 | }; |
| 1019 | 1019 | EXPORT_SYMBOL_GPL(adau1761_regmap_config); |
| 1020 | 1020 | |
| @@ -472,7 +472,7 @@ const struct regmap_config adau1781_regmap_config = { · 471 unmodified lines | ||
| 472 | 472 | .readable_reg = adau1781_readable_register, |
| 473 | 473 | .volatile_reg = adau17x1_volatile_register, |
| 474 | 474 | .precious_reg = adau17x1_precious_register, |
| 475 | − .cache_type = REGCACHE_RBTREE, | |
| 475 | + .cache_type = REGCACHE_MAPLE, | |
| 476 | 476 | }; |
| 477 | 477 | EXPORT_SYMBOL_GPL(adau1781_regmap_config); |
| 478 | 478 | |
| @@ -991,7 +991,7 @@ const struct regmap_config adau1977_regmap_config = { · 990 unmodified lines | ||
| 991 | 991 | .max_register = ADAU1977_REG_DC_HPF_CAL, |
| 992 | 992 | .volatile_reg = adau1977_register_volatile, |
| 993 | 993 | |
| 994 | − .cache_type = REGCACHE_RBTREE, | |
| 994 | + .cache_type = REGCACHE_MAPLE, | |
| 995 | 995 | .reg_defaults = adau1977_reg_defaults, |
| 996 | 996 | .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), |
| 997 | 997 | }; |
| @@ -43,7 +43,7 @@ static const struct regmap_config adau7118_regmap_config = { · 42 unmodified lines | ||
| 43 | 43 | .val_bits = 8, |
| 44 | 44 | .reg_defaults = adau7118_reg_defaults, |
| 45 | 45 | .num_reg_defaults = ARRAY_SIZE(adau7118_reg_defaults), |
| 46 | − .cache_type = REGCACHE_RBTREE, | |
| 46 | + .cache_type = REGCACHE_MAPLE, | |
| 47 | 47 | .max_register = ADAU7118_REG_RESET, |
| 48 | 48 | .volatile_reg = adau7118_volatile, |
| 49 | 49 | }; |
| @@ -870,7 +870,7 @@ const struct regmap_config adav80x_regmap_config = { · 869 unmodified lines | ||
| 870 | 870 | |
| 871 | 871 | .max_register = ADAV80X_PLL_OUTE, |
| 872 | 872 | |
| 873 | − .cache_type = REGCACHE_RBTREE, | |
| 873 | + .cache_type = REGCACHE_MAPLE, | |
| 874 | 874 | .reg_defaults = adav80x_reg_defaults, |
| 875 | 875 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), |
| 876 | 876 | }; |
| @@ -880,20 +880,11 @@ static void ak4613_parse_of(struct ak4613_priv *priv, · 879 unmodified lines | ||
| 880 | 880 | static int ak4613_i2c_probe(struct i2c_client *i2c) |
| 881 | 881 | { |
| 882 | 882 | struct device *dev = &i2c->dev; |
| 883 | − struct device_node *np = dev->of_node; | |
| 884 | 883 | const struct regmap_config *regmap_cfg; |
| 885 | 884 | struct regmap *regmap; |
| 886 | 885 | struct ak4613_priv *priv; |
| 887 | 886 | |
| 888 | − regmap_cfg = NULL; | |
| 889 | − if (np) | |
| 890 | − regmap_cfg = of_device_get_match_data(dev); | |
| 891 | − else { | |
| 892 | − const struct i2c_device_id *id = | |
| 893 | − i2c_match_id(ak4613_i2c_id, i2c); | |
| 894 | − regmap_cfg = (const struct regmap_config *)id->driver_data; | |
| 895 | − } | |
| 896 | − | |
| 887 | + regmap_cfg = i2c_get_match_data(i2c); | |
| 897 | 888 | if (!regmap_cfg) |
| 898 | 889 | return -EINVAL; |
| 899 | 890 | |
| @@ -0,0 +1,344 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// ALSA SoC glue to use IIO devices as audio components | |
| 4 | +// | |
| 5 | +// Copyright 2023 CS GROUP France | |
| 6 | +// | |
| 7 | +// Author: Herve Codina <herve.codina@bootlin.com> | |
| 8 | + | |
| 9 | +#include <linux/iio/consumer.h> | |
| 10 | +#include <linux/minmax.h> | |
| 11 | +#include <linux/mod_devicetable.h> | |
| 12 | +#include <linux/platform_device.h> | |
| 13 | +#include <linux/slab.h> | |
| 14 | +#include <linux/string_helpers.h> | |
| 15 | + | |
| 16 | +#include <sound/soc.h> | |
| 17 | +#include <sound/tlv.h> | |
| 18 | + | |
| 19 | +struct audio_iio_aux_chan { | |
| 20 | + struct iio_channel *iio_chan; | |
| 21 | + const char *name; | |
| 22 | + int max; | |
| 23 | + int min; | |
| 24 | + bool is_invert_range; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +struct audio_iio_aux { | |
| 28 | + struct device *dev; | |
| 29 | + struct audio_iio_aux_chan *chans; | |
| 30 | + unsigned int num_chans; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +static int audio_iio_aux_info_volsw(struct snd_kcontrol *kcontrol, | |
| 34 | + struct snd_ctl_elem_info *uinfo) | |
| 35 | +{ | |
| 36 | + struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value; | |
| 37 | + | |
| 38 | + uinfo->count = 1; | |
| 39 | + uinfo->value.integer.min = 0; | |
| 40 | + uinfo->value.integer.max = chan->max - chan->min; | |
| 41 | + uinfo->type = (uinfo->value.integer.max == 1) ? | |
| 42 | + SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | |
| 43 | + return 0; | |
| 44 | +} | |
| 45 | + | |
| 46 | +static int audio_iio_aux_get_volsw(struct snd_kcontrol *kcontrol, | |
| 47 | + struct snd_ctl_elem_value *ucontrol) | |
| 48 | +{ | |
| 49 | + struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value; | |
| 50 | + int max = chan->max; | |
| 51 | + int min = chan->min; | |
| 52 | + bool invert_range = chan->is_invert_range; | |
| 53 | + int ret; | |
| 54 | + int val; | |
| 55 | + | |
| 56 | + ret = iio_read_channel_raw(chan->iio_chan, &val); | |
| 57 | + if (ret < 0) | |
| 58 | + return ret; | |
| 59 | + | |
| 60 | + ucontrol->value.integer.value[0] = val - min; | |
| 61 | + if (invert_range) | |
| 62 | + ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; | |
| 63 | + | |
| 64 | + return 0; | |
| 65 | +} | |
| 66 | + | |
| 67 | +static int audio_iio_aux_put_volsw(struct snd_kcontrol *kcontrol, | |
| 68 | + struct snd_ctl_elem_value *ucontrol) | |
| 69 | +{ | |
| 70 | + struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value; | |
| 71 | + int max = chan->max; | |
| 72 | + int min = chan->min; | |
| 73 | + bool invert_range = chan->is_invert_range; | |
| 74 | + int val; | |
| 75 | + int ret; | |
| 76 | + int tmp; | |
| 77 | + | |
| 78 | + val = ucontrol->value.integer.value[0]; | |
| 79 | + if (val < 0) | |
| 80 | + return -EINVAL; | |
| 81 | + if (val > max - min) | |
| 82 | + return -EINVAL; | |
| 83 | + | |
| 84 | + val = val + min; | |
| 85 | + if (invert_range) | |
| 86 | + val = max - val; | |
| 87 | + | |
| 88 | + ret = iio_read_channel_raw(chan->iio_chan, &tmp); | |
| 89 | + if (ret < 0) | |
| 90 | + return ret; | |
| 91 | + | |
| 92 | + if (tmp == val) | |
| 93 | + return 0; | |
| 94 | + | |
| 95 | + ret = iio_write_channel_raw(chan->iio_chan, val); | |
| 96 | + if (ret) | |
| 97 | + return ret; | |
| 98 | + | |
| 99 | + return 1; /* The value changed */ | |
| 100 | +} | |
| 101 | + | |
| 102 | +static int audio_iio_aux_add_controls(struct snd_soc_component *component, | |
| 103 | + struct audio_iio_aux_chan *chan) | |
| 104 | +{ | |
| 105 | + struct snd_kcontrol_new control = { | |
| 106 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
| 107 | + .name = chan->name, | |
| 108 | + .info = audio_iio_aux_info_volsw, | |
| 109 | + .get = audio_iio_aux_get_volsw, | |
| 110 | + .put = audio_iio_aux_put_volsw, | |
| 111 | + .private_value = (unsigned long)chan, | |
| 112 | + }; | |
| 113 | + | |
| 114 | + return snd_soc_add_component_controls(component, &control, 1); | |
| 115 | +} | |
| 116 | + | |
| 117 | +/* | |
| 118 | + * These data could be on stack but they are pretty big. | |
| 119 | + * As ASoC internally copy them and protect them against concurrent accesses | |
| 120 | + * (snd_soc_bind_card() protects using client_mutex), keep them in the global | |
| 121 | + * data area. | |
| 122 | + */ | |
| 123 | +static struct snd_soc_dapm_widget widgets[3]; | |
| 124 | +static struct snd_soc_dapm_route routes[2]; | |
| 125 | + | |
| 126 | +/* Be sure sizes are correct (need 3 widgets and 2 routes) */ | |
| 127 | +static_assert(ARRAY_SIZE(widgets) >= 3, "3 widgets are needed"); | |
| 128 | +static_assert(ARRAY_SIZE(routes) >= 2, "2 routes are needed"); | |
| 129 | + | |
| 130 | +static int audio_iio_aux_add_dapms(struct snd_soc_component *component, | |
| 131 | + struct audio_iio_aux_chan *chan) | |
| 132 | +{ | |
| 133 | + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); | |
| 134 | + char *output_name; | |
| 135 | + char *input_name; | |
| 136 | + char *pga_name; | |
| 137 | + int ret; | |
| 138 | + | |
| 139 | + input_name = kasprintf(GFP_KERNEL, "%s IN", chan->name); | |
| 140 | + if (!input_name) | |
| 141 | + return -ENOMEM; | |
| 142 | + | |
| 143 | + output_name = kasprintf(GFP_KERNEL, "%s OUT", chan->name); | |
| 144 | + if (!output_name) { | |
| 145 | + ret = -ENOMEM; | |
| 146 | + goto out_free_input_name; | |
| 147 | + } | |
| 148 | + | |
| 149 | + pga_name = kasprintf(GFP_KERNEL, "%s PGA", chan->name); | |
| 150 | + if (!pga_name) { | |
| 151 | + ret = -ENOMEM; | |
| 152 | + goto out_free_output_name; | |
| 153 | + } | |
| 154 | + | |
| 155 | + widgets[0] = SND_SOC_DAPM_INPUT(input_name); | |
| 156 | + widgets[1] = SND_SOC_DAPM_OUTPUT(output_name); | |
| 157 | + widgets[2] = SND_SOC_DAPM_PGA(pga_name, SND_SOC_NOPM, 0, 0, NULL, 0); | |
| 158 | + ret = snd_soc_dapm_new_controls(dapm, widgets, 3); | |
| 159 | + if (ret) | |
| 160 | + goto out_free_pga_name; | |
| 161 | + | |
| 162 | + routes[0].sink = pga_name; | |
| 163 | + routes[0].control = NULL; | |
| 164 | + routes[0].source = input_name; | |
| 165 | + routes[1].sink = output_name; | |
| 166 | + routes[1].control = NULL; | |
| 167 | + routes[1].source = pga_name; | |
| 168 | + ret = snd_soc_dapm_add_routes(dapm, routes, 2); | |
| 169 | + | |
| 170 | + /* Allocated names are no more needed (duplicated in ASoC internals) */ | |
| 171 | + | |
| 172 | +out_free_pga_name: | |
| 173 | + kfree(pga_name); | |
| 174 | +out_free_output_name: | |
| 175 | + kfree(output_name); | |
| 176 | +out_free_input_name: | |
| 177 | + kfree(input_name); | |
| 178 | + return ret; | |
| 179 | +} | |
| 180 | + | |
| 181 | +static int audio_iio_aux_component_probe(struct snd_soc_component *component) | |
| 182 | +{ | |
| 183 | + struct audio_iio_aux *iio_aux = snd_soc_component_get_drvdata(component); | |
| 184 | + struct audio_iio_aux_chan *chan; | |
| 185 | + int ret; | |
| 186 | + int i; | |
| 187 | + | |
| 188 | + for (i = 0; i < iio_aux->num_chans; i++) { | |
| 189 | + chan = iio_aux->chans + i; | |
| 190 | + | |
| 191 | + ret = iio_read_max_channel_raw(chan->iio_chan, &chan->max); | |
| 192 | + if (ret) | |
| 193 | + return dev_err_probe(component->dev, ret, | |
| 194 | + "chan[%d] %s: Cannot get max raw value\n", | |
| 195 | + i, chan->name); | |
| 196 | + | |
| 197 | + ret = iio_read_min_channel_raw(chan->iio_chan, &chan->min); | |
| 198 | + if (ret) | |
| 199 | + return dev_err_probe(component->dev, ret, | |
| 200 | + "chan[%d] %s: Cannot get min raw value\n", | |
| 201 | + i, chan->name); | |
| 202 | + | |
| 203 | + if (chan->min > chan->max) { | |
| 204 | + /* | |
| 205 | + * This should never happen but to avoid any check | |
| 206 | + * later, just swap values here to ensure that the | |
| 207 | + * minimum value is lower than the maximum value. | |
| 208 | + */ | |
| 209 | + dev_dbg(component->dev, "chan[%d] %s: Swap min and max\n", | |
| 210 | + i, chan->name); | |
| 211 | + swap(chan->min, chan->max); | |
| 212 | + } | |
| 213 | + | |
| 214 | + /* Set initial value */ | |
| 215 | + ret = iio_write_channel_raw(chan->iio_chan, | |
| 216 | + chan->is_invert_range ? chan->max : chan->min); | |
| 217 | + if (ret) | |
| 218 | + return dev_err_probe(component->dev, ret, | |
| 219 | + "chan[%d] %s: Cannot set initial value\n", | |
| 220 | + i, chan->name); | |
| 221 | + | |
| 222 | + ret = audio_iio_aux_add_controls(component, chan); | |
| 223 | + if (ret) | |
| 224 | + return ret; | |
| 225 | + | |
| 226 | + ret = audio_iio_aux_add_dapms(component, chan); | |
| 227 | + if (ret) | |
| 228 | + return ret; | |
| 229 | + | |
| 230 | + dev_dbg(component->dev, "chan[%d]: Added %s (min=%d, max=%d, invert=%s)\n", | |
| 231 | + i, chan->name, chan->min, chan->max, | |
| 232 | + str_on_off(chan->is_invert_range)); | |
| 233 | + } | |
| 234 | + | |
| 235 | + return 0; | |
| 236 | +} | |
| 237 | + | |
| 238 | +static const struct snd_soc_component_driver audio_iio_aux_component_driver = { | |
| 239 | + .probe = audio_iio_aux_component_probe, | |
| 240 | +}; | |
| 241 | + | |
| 242 | +static int audio_iio_aux_probe(struct platform_device *pdev) | |
| 243 | +{ | |
| 244 | + struct audio_iio_aux_chan *iio_aux_chan; | |
| 245 | + struct device *dev = &pdev->dev; | |
| 246 | + struct audio_iio_aux *iio_aux; | |
| 247 | + const char **names; | |
| 248 | + u32 *invert_ranges; | |
| 249 | + int count; | |
| 250 | + int ret; | |
| 251 | + int i; | |
| 252 | + | |
| 253 | + iio_aux = devm_kzalloc(dev, sizeof(*iio_aux), GFP_KERNEL); | |
| 254 | + if (!iio_aux) | |
| 255 | + return -ENOMEM; | |
| 256 | + | |
| 257 | + iio_aux->dev = dev; | |
| 258 | + | |
| 259 | + count = device_property_string_array_count(dev, "io-channel-names"); | |
| 260 | + if (count < 0) | |
| 261 | + return dev_err_probe(dev, count, "failed to count io-channel-names\n"); | |
| 262 | + | |
| 263 | + iio_aux->num_chans = count; | |
| 264 | + | |
| 265 | + iio_aux->chans = devm_kmalloc_array(dev, iio_aux->num_chans, | |
| 266 | + sizeof(*iio_aux->chans), GFP_KERNEL); | |
| 267 | + if (!iio_aux->chans) | |
| 268 | + return -ENOMEM; | |
| 269 | + | |
| 270 | + names = kcalloc(iio_aux->num_chans, sizeof(*names), GFP_KERNEL); | |
| 271 | + if (!names) | |
| 272 | + return -ENOMEM; | |
| 273 | + | |
| 274 | + invert_ranges = kcalloc(iio_aux->num_chans, sizeof(*invert_ranges), GFP_KERNEL); | |
| 275 | + if (!invert_ranges) { | |
| 276 | + ret = -ENOMEM; | |
| 277 | + goto out_free_names; | |
| 278 | + } | |
| 279 | + | |
| 280 | + ret = device_property_read_string_array(dev, "io-channel-names", | |
| 281 | + names, iio_aux->num_chans); | |
| 282 | + if (ret < 0) { | |
| 283 | + dev_err_probe(dev, ret, "failed to read io-channel-names\n"); | |
| 284 | + goto out_free_invert_ranges; | |
| 285 | + } | |
| 286 | + | |
| 287 | + /* | |
| 288 | + * snd-control-invert-range is optional and can contain fewer items | |
| 289 | + * than the number of channels. Unset values default to 0. | |
| 290 | + */ | |
| 291 | + count = device_property_count_u32(dev, "snd-control-invert-range"); | |
| 292 | + if (count > 0) { | |
| 293 | + count = min_t(unsigned int, count, iio_aux->num_chans); | |
| 294 | + ret = device_property_read_u32_array(dev, "snd-control-invert-range", | |
| 295 | + invert_ranges, count); | |
| 296 | + if (ret < 0) { | |
| 297 | + dev_err_probe(dev, ret, "failed to read snd-control-invert-range\n"); | |
| 298 | + goto out_free_invert_ranges; | |
| 299 | + } | |
| 300 | + } | |
| 301 | + | |
| 302 | + for (i = 0; i < iio_aux->num_chans; i++) { | |
| 303 | + iio_aux_chan = iio_aux->chans + i; | |
| 304 | + iio_aux_chan->name = names[i]; | |
| 305 | + iio_aux_chan->is_invert_range = invert_ranges[i]; | |
| 306 | + | |
| 307 | + iio_aux_chan->iio_chan = devm_iio_channel_get(dev, iio_aux_chan->name); | |
| 308 | + if (IS_ERR(iio_aux_chan->iio_chan)) { | |
| 309 | + ret = PTR_ERR(iio_aux_chan->iio_chan); | |
| 310 | + dev_err_probe(dev, ret, "get IIO channel '%s' failed\n", | |
| 311 | + iio_aux_chan->name); | |
| 312 | + goto out_free_invert_ranges; | |
| 313 | + } | |
| 314 | + } | |
| 315 | + | |
| 316 | + platform_set_drvdata(pdev, iio_aux); | |
| 317 | + | |
| 318 | + ret = devm_snd_soc_register_component(dev, &audio_iio_aux_component_driver, | |
| 319 | + NULL, 0); | |
| 320 | +out_free_invert_ranges: | |
| 321 | + kfree(invert_ranges); | |
| 322 | +out_free_names: | |
| 323 | + kfree(names); | |
| 324 | + return ret; | |
| 325 | +} | |
| 326 | + | |
| 327 | +static const struct of_device_id audio_iio_aux_ids[] = { | |
| 328 | + { .compatible = "audio-iio-aux" }, | |
| 329 | + { } | |
| 330 | +}; | |
| 331 | +MODULE_DEVICE_TABLE(of, audio_iio_aux_ids); | |
| 332 | + | |
| 333 | +static struct platform_driver audio_iio_aux_driver = { | |
| 334 | + .driver = { | |
| 335 | + .name = "audio-iio-aux", | |
| 336 | + .of_match_table = audio_iio_aux_ids, | |
| 337 | + }, | |
| 338 | + .probe = audio_iio_aux_probe, | |
| 339 | +}; | |
| 340 | +module_platform_driver(audio_iio_aux_driver); | |
| 341 | + | |
| 342 | +MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); | |
| 343 | +MODULE_DESCRIPTION("IIO ALSA SoC aux driver"); | |
| 344 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,1300 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// aw88261.c -- AW88261 ALSA SoC Audio driver | |
| 4 | +// | |
| 5 | +// Copyright (c) 2023 awinic Technology CO., LTD | |
| 6 | +// | |
| 7 | +// Author: Jimmy Zhang <zhangjianming@awinic.com> | |
| 8 | +// Author: Weidong Wang <wangweidong.a@awinic.com> | |
| 9 | +// | |
| 10 | + | |
| 11 | +#include <linux/i2c.h> | |
| 12 | +#include <linux/firmware.h> | |
| 13 | +#include <linux/of_gpio.h> | |
| 14 | +#include <linux/regmap.h> | |
| 15 | +#include <sound/soc.h> | |
| 16 | +#include "aw88261.h" | |
| 17 | +#include "aw88395/aw88395_data_type.h" | |
| 18 | +#include "aw88395/aw88395_device.h" | |
| 19 | + | |
| 20 | +static const struct regmap_config aw88261_remap_config = { | |
| 21 | + .val_bits = 16, | |
| 22 | + .reg_bits = 8, | |
| 23 | + .max_register = AW88261_REG_MAX - 1, | |
| 24 | + .reg_format_endian = REGMAP_ENDIAN_LITTLE, | |
| 25 | + .val_format_endian = REGMAP_ENDIAN_BIG, | |
| 26 | +}; | |
| 27 | + | |
| 28 | +static void aw88261_dev_set_volume(struct aw_device *aw_dev, unsigned int value) | |
| 29 | +{ | |
| 30 | + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; | |
| 31 | + unsigned int real_value, volume; | |
| 32 | + unsigned int reg_value; | |
| 33 | + | |
| 34 | + volume = min((value + vol_desc->init_volume), (unsigned int)AW88261_MUTE_VOL); | |
| 35 | + real_value = DB_TO_REG_VAL(volume); | |
| 36 | + | |
| 37 | + regmap_read(aw_dev->regmap, AW88261_SYSCTRL2_REG, ®_value); | |
| 38 | + | |
| 39 | + real_value = (real_value | (reg_value & AW88261_VOL_START_MASK)); | |
| 40 | + | |
| 41 | + dev_dbg(aw_dev->dev, "value 0x%x , real_value:0x%x", value, real_value); | |
| 42 | + | |
| 43 | + regmap_write(aw_dev->regmap, AW88261_SYSCTRL2_REG, real_value); | |
| 44 | +} | |
| 45 | + | |
| 46 | +static void aw88261_dev_fade_in(struct aw_device *aw_dev) | |
| 47 | +{ | |
| 48 | + struct aw_volume_desc *desc = &aw_dev->volume_desc; | |
| 49 | + int fade_in_vol = desc->ctl_volume; | |
| 50 | + int fade_step = aw_dev->fade_step; | |
| 51 | + int i; | |
| 52 | + | |
| 53 | + if (fade_step == 0 || aw_dev->fade_in_time == 0) { | |
| 54 | + aw88261_dev_set_volume(aw_dev, fade_in_vol); | |
| 55 | + return; | |
| 56 | + } | |
| 57 | + | |
| 58 | + for (i = AW88261_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { | |
| 59 | + aw88261_dev_set_volume(aw_dev, i); | |
| 60 | + usleep_range(aw_dev->fade_in_time, | |
| 61 | + aw_dev->fade_in_time + 10); | |
| 62 | + } | |
| 63 | + | |
| 64 | + if (i != fade_in_vol) | |
| 65 | + aw88261_dev_set_volume(aw_dev, fade_in_vol); | |
| 66 | +} | |
| 67 | + | |
| 68 | +static void aw88261_dev_fade_out(struct aw_device *aw_dev) | |
| 69 | +{ | |
| 70 | + struct aw_volume_desc *desc = &aw_dev->volume_desc; | |
| 71 | + int fade_step = aw_dev->fade_step; | |
| 72 | + int i; | |
| 73 | + | |
| 74 | + if (fade_step == 0 || aw_dev->fade_out_time == 0) { | |
| 75 | + aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); | |
| 76 | + return; | |
| 77 | + } | |
| 78 | + | |
| 79 | + for (i = desc->ctl_volume; i <= AW88261_MUTE_VOL; i += fade_step) { | |
| 80 | + aw88261_dev_set_volume(aw_dev, i); | |
| 81 | + usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); | |
| 82 | + } | |
| 83 | + | |
| 84 | + if (i != AW88261_MUTE_VOL) { | |
| 85 | + aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); | |
| 86 | + usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); | |
| 87 | + } | |
| 88 | +} | |
| 89 | + | |
| 90 | +static void aw88261_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) | |
| 91 | +{ | |
| 92 | + if (flag) | |
| 93 | + regmap_update_bits(aw_dev->regmap, AW88261_I2SCFG1_REG, | |
| 94 | + ~AW88261_I2STXEN_MASK, AW88261_I2STXEN_ENABLE_VALUE); | |
| 95 | + else | |
| 96 | + regmap_update_bits(aw_dev->regmap, AW88261_I2SCFG1_REG, | |
| 97 | + ~AW88261_I2STXEN_MASK, AW88261_I2STXEN_DISABLE_VALUE); | |
| 98 | +} | |
| 99 | + | |
| 100 | +static void aw88261_dev_pwd(struct aw_device *aw_dev, bool pwd) | |
| 101 | +{ | |
| 102 | + if (pwd) | |
| 103 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 104 | + ~AW88261_PWDN_MASK, AW88261_PWDN_POWER_DOWN_VALUE); | |
| 105 | + else | |
| 106 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 107 | + ~AW88261_PWDN_MASK, AW88261_PWDN_WORKING_VALUE); | |
| 108 | +} | |
| 109 | + | |
| 110 | +static void aw88261_dev_amppd(struct aw_device *aw_dev, bool amppd) | |
| 111 | +{ | |
| 112 | + if (amppd) | |
| 113 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 114 | + ~AW88261_AMPPD_MASK, AW88261_AMPPD_POWER_DOWN_VALUE); | |
| 115 | + else | |
| 116 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 117 | + ~AW88261_AMPPD_MASK, AW88261_AMPPD_WORKING_VALUE); | |
| 118 | +} | |
| 119 | + | |
| 120 | +static void aw88261_dev_mute(struct aw_device *aw_dev, bool is_mute) | |
| 121 | +{ | |
| 122 | + if (is_mute) { | |
| 123 | + aw88261_dev_fade_out(aw_dev); | |
| 124 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 125 | + ~AW88261_HMUTE_MASK, AW88261_HMUTE_ENABLE_VALUE); | |
| 126 | + } else { | |
| 127 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 128 | + ~AW88261_HMUTE_MASK, AW88261_HMUTE_DISABLE_VALUE); | |
| 129 | + aw88261_dev_fade_in(aw_dev); | |
| 130 | + } | |
| 131 | +} | |
| 132 | + | |
| 133 | +static void aw88261_dev_clear_int_status(struct aw_device *aw_dev) | |
| 134 | +{ | |
| 135 | + unsigned int int_status; | |
| 136 | + | |
| 137 | + /* read int status and clear */ | |
| 138 | + regmap_read(aw_dev->regmap, AW88261_SYSINT_REG, &int_status); | |
| 139 | + /* make sure int status is clear */ | |
| 140 | + regmap_read(aw_dev->regmap, AW88261_SYSINT_REG, &int_status); | |
| 141 | + | |
| 142 | + dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x", int_status); | |
| 143 | +} | |
| 144 | + | |
| 145 | +static int aw88261_dev_get_iis_status(struct aw_device *aw_dev) | |
| 146 | +{ | |
| 147 | + unsigned int reg_val; | |
| 148 | + int ret; | |
| 149 | + | |
| 150 | + ret = regmap_read(aw_dev->regmap, AW88261_SYSST_REG, ®_val); | |
| 151 | + if (ret) | |
| 152 | + return ret; | |
| 153 | + if ((reg_val & AW88261_BIT_PLL_CHECK) != AW88261_BIT_PLL_CHECK) { | |
| 154 | + dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); | |
| 155 | + return -EINVAL; | |
| 156 | + } | |
| 157 | + | |
| 158 | + return ret; | |
| 159 | +} | |
| 160 | + | |
| 161 | +static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev) | |
| 162 | +{ | |
| 163 | + int ret, i; | |
| 164 | + | |
| 165 | + for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { | |
| 166 | + ret = aw88261_dev_get_iis_status(aw_dev); | |
| 167 | + if (ret) { | |
| 168 | + dev_err(aw_dev->dev, "mode1 iis signal check error"); | |
| 169 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 170 | + } else { | |
| 171 | + return ret; | |
| 172 | + } | |
| 173 | + } | |
| 174 | + | |
| 175 | + return -EPERM; | |
| 176 | +} | |
| 177 | + | |
| 178 | +static int aw88261_dev_check_mode2_pll(struct aw_device *aw_dev) | |
| 179 | +{ | |
| 180 | + unsigned int reg_val; | |
| 181 | + int ret, i; | |
| 182 | + | |
| 183 | + ret = regmap_read(aw_dev->regmap, AW88261_PLLCTRL1_REG, ®_val); | |
| 184 | + if (ret) | |
| 185 | + return ret; | |
| 186 | + | |
| 187 | + reg_val &= (~AW88261_CCO_MUX_MASK); | |
| 188 | + if (reg_val == AW88261_CCO_MUX_DIVIDED_VALUE) { | |
| 189 | + dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); | |
| 190 | + return -EPERM; | |
| 191 | + } | |
| 192 | + | |
| 193 | + /* change mode2 */ | |
| 194 | + ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG, | |
| 195 | + ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_DIVIDED_VALUE); | |
| 196 | + if (ret) | |
| 197 | + return ret; | |
| 198 | + | |
| 199 | + for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { | |
| 200 | + ret = aw88261_dev_get_iis_status(aw_dev); | |
| 201 | + if (ret) { | |
| 202 | + dev_err(aw_dev->dev, "mode2 iis signal check error"); | |
| 203 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 204 | + } else { | |
| 205 | + break; | |
| 206 | + } | |
| 207 | + } | |
| 208 | + | |
| 209 | + /* change mode1 */ | |
| 210 | + ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG, | |
| 211 | + ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_BYPASS_VALUE); | |
| 212 | + if (ret == 0) { | |
| 213 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 214 | + for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { | |
| 215 | + ret = aw88261_dev_check_mode1_pll(aw_dev); | |
| 216 | + if (ret) { | |
| 217 | + dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error"); | |
| 218 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 219 | + } else { | |
| 220 | + break; | |
| 221 | + } | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + return ret; | |
| 226 | +} | |
| 227 | + | |
| 228 | +static int aw88261_dev_check_syspll(struct aw_device *aw_dev) | |
| 229 | +{ | |
| 230 | + int ret; | |
| 231 | + | |
| 232 | + ret = aw88261_dev_check_mode1_pll(aw_dev); | |
| 233 | + if (ret) { | |
| 234 | + dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); | |
| 235 | + ret = aw88261_dev_check_mode2_pll(aw_dev); | |
| 236 | + if (ret) { | |
| 237 | + dev_err(aw_dev->dev, "mode2 check iis failed"); | |
| 238 | + return ret; | |
| 239 | + } | |
| 240 | + } | |
| 241 | + | |
| 242 | + return ret; | |
| 243 | +} | |
| 244 | + | |
| 245 | +static int aw88261_dev_check_sysst(struct aw_device *aw_dev) | |
| 246 | +{ | |
| 247 | + unsigned int check_val; | |
| 248 | + unsigned int reg_val; | |
| 249 | + int ret, i; | |
| 250 | + | |
| 251 | + for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { | |
| 252 | + ret = regmap_read(aw_dev->regmap, AW88261_SYSST_REG, ®_val); | |
| 253 | + if (ret) | |
| 254 | + return ret; | |
| 255 | + | |
| 256 | + check_val = reg_val & (~AW88261_BIT_SYSST_CHECK_MASK) | |
| 257 | + & AW88261_BIT_SYSST_CHECK; | |
| 258 | + if (check_val != AW88261_BIT_SYSST_CHECK) { | |
| 259 | + dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x", | |
| 260 | + reg_val, AW88261_BIT_SYSST_CHECK); | |
| 261 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 262 | + } else { | |
| 263 | + return 0; | |
| 264 | + } | |
| 265 | + } | |
| 266 | + | |
| 267 | + return -EPERM; | |
| 268 | +} | |
| 269 | + | |
| 270 | +static void aw88261_dev_uls_hmute(struct aw_device *aw_dev, bool uls_hmute) | |
| 271 | +{ | |
| 272 | + if (uls_hmute) | |
| 273 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 274 | + ~AW88261_ULS_HMUTE_MASK, | |
| 275 | + AW88261_ULS_HMUTE_ENABLE_VALUE); | |
| 276 | + else | |
| 277 | + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, | |
| 278 | + ~AW88261_ULS_HMUTE_MASK, | |
| 279 | + AW88261_ULS_HMUTE_DISABLE_VALUE); | |
| 280 | +} | |
| 281 | + | |
| 282 | +static void aw88261_reg_force_set(struct aw88261 *aw88261) | |
| 283 | +{ | |
| 284 | + if (aw88261->frcset_en == AW88261_FRCSET_ENABLE) { | |
| 285 | + /* set FORCE_PWM */ | |
| 286 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL3_REG, | |
| 287 | + AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE); | |
| 288 | + /* set BOOST_OS_WIDTH */ | |
| 289 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL5_REG, | |
| 290 | + AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE); | |
| 291 | + /* set BURST_LOOPR */ | |
| 292 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL6_REG, | |
| 293 | + AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE); | |
| 294 | + /* set RSQN_DLY */ | |
| 295 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL7_REG, | |
| 296 | + AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE); | |
| 297 | + /* set BURST_SSMODE */ | |
| 298 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL8_REG, | |
| 299 | + AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE); | |
| 300 | + /* set BST_BURST */ | |
| 301 | + regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL9_REG, | |
| 302 | + AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE); | |
| 303 | + } else { | |
| 304 | + dev_dbg(aw88261->aw_pa->dev, "needn't set reg value"); | |
| 305 | + } | |
| 306 | +} | |
| 307 | + | |
| 308 | +static int aw88261_dev_get_icalk(struct aw_device *aw_dev, int16_t *icalk) | |
| 309 | +{ | |
| 310 | + u16 reg_icalk, reg_icalkl; | |
| 311 | + unsigned int reg_val; | |
| 312 | + int ret; | |
| 313 | + | |
| 314 | + ret = regmap_read(aw_dev->regmap, AW88261_EFRH4_REG, ®_val); | |
| 315 | + if (ret) | |
| 316 | + return ret; | |
| 317 | + | |
| 318 | + reg_icalk = reg_val & (~AW88261_EF_ISN_GESLP_H_MASK); | |
| 319 | + | |
| 320 | + ret = regmap_read(aw_dev->regmap, AW88261_EFRL4_REG, ®_val); | |
| 321 | + if (ret) | |
| 322 | + return ret; | |
| 323 | + | |
| 324 | + reg_icalkl = reg_val & (~AW88261_EF_ISN_GESLP_L_MASK); | |
| 325 | + | |
| 326 | + reg_icalk = (reg_icalk >> AW88261_ICALK_SHIFT) & (reg_icalkl >> AW88261_ICALKL_SHIFT); | |
| 327 | + | |
| 328 | + if (reg_icalk & (~AW88261_EF_ISN_GESLP_SIGN_MASK)) | |
| 329 | + reg_icalk = reg_icalk | ~AW88261_EF_ISN_GESLP_NEG; | |
| 330 | + | |
| 331 | + *icalk = (int16_t)reg_icalk; | |
| 332 | + | |
| 333 | + return ret; | |
| 334 | +} | |
| 335 | + | |
| 336 | +static int aw88261_dev_get_vcalk(struct aw_device *aw_dev, int16_t *vcalk) | |
| 337 | +{ | |
| 338 | + u16 reg_vcalk, reg_vcalkl; | |
| 339 | + unsigned int reg_val; | |
| 340 | + int ret; | |
| 341 | + | |
| 342 | + ret = regmap_read(aw_dev->regmap, AW88261_EFRH3_REG, ®_val); | |
| 343 | + if (ret) | |
| 344 | + return ret; | |
| 345 | + | |
| 346 | + reg_vcalk = (u16)reg_val & (~AW88261_EF_VSN_GESLP_H_MASK); | |
| 347 | + | |
| 348 | + ret = regmap_read(aw_dev->regmap, AW88261_EFRL3_REG, ®_val); | |
| 349 | + if (ret) | |
| 350 | + return ret; | |
| 351 | + | |
| 352 | + reg_vcalkl = (u16)reg_val & (~AW88261_EF_VSN_GESLP_L_MASK); | |
| 353 | + | |
| 354 | + reg_vcalk = (reg_vcalk >> AW88261_VCALK_SHIFT) & (reg_vcalkl >> AW88261_VCALKL_SHIFT); | |
| 355 | + | |
| 356 | + if (reg_vcalk & AW88261_EF_VSN_GESLP_SIGN_MASK) | |
| 357 | + reg_vcalk = reg_vcalk | (~AW88261_EF_VSN_GESLP_NEG); | |
| 358 | + *vcalk = (int16_t)reg_vcalk; | |
| 359 | + | |
| 360 | + return ret; | |
| 361 | +} | |
| 362 | + | |
| 363 | +static int aw88261_dev_set_vcalb(struct aw_device *aw_dev) | |
| 364 | +{ | |
| 365 | + int16_t icalk_val, vcalk_val; | |
| 366 | + int icalk, vcalk, vcalb; | |
| 367 | + u32 reg_val; | |
| 368 | + int ret; | |
| 369 | + | |
| 370 | + ret = aw88261_dev_get_icalk(aw_dev, &icalk_val); | |
| 371 | + if (ret) | |
| 372 | + return ret; | |
| 373 | + | |
| 374 | + ret = aw88261_dev_get_vcalk(aw_dev, &vcalk_val); | |
| 375 | + if (ret) | |
| 376 | + return ret; | |
| 377 | + | |
| 378 | + icalk = AW88261_CABL_BASE_VALUE + AW88261_ICABLK_FACTOR * icalk_val; | |
| 379 | + vcalk = AW88261_CABL_BASE_VALUE + AW88261_VCABLK_FACTOR * vcalk_val; | |
| 380 | + if (!vcalk) | |
| 381 | + return -EINVAL; | |
| 382 | + | |
| 383 | + vcalb = AW88261_VCAL_FACTOR * icalk / vcalk; | |
| 384 | + reg_val = (unsigned int)vcalb; | |
| 385 | + | |
| 386 | + dev_dbg(aw_dev->dev, "icalk=%d, vcalk=%d, vcalb=%d, reg_val=0x%04x", | |
| 387 | + icalk, vcalk, vcalb, reg_val); | |
| 388 | + ret = regmap_write(aw_dev->regmap, AW88261_VSNTM1_REG, reg_val); | |
| 389 | + | |
| 390 | + return ret; | |
| 391 | +} | |
| 392 | + | |
| 393 | +static int aw88261_dev_reg_update(struct aw88261 *aw88261, | |
| 394 | + unsigned char *data, unsigned int len) | |
| 395 | +{ | |
| 396 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 397 | + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; | |
| 398 | + unsigned int read_val, efcheck_val, read_vol; | |
| 399 | + int data_len, i, ret; | |
| 400 | + int16_t *reg_data; | |
| 401 | + u16 reg_val; | |
| 402 | + u8 reg_addr; | |
| 403 | + | |
| 404 | + if (!len || !data) { | |
| 405 | + dev_err(aw_dev->dev, "reg data is null or len is 0"); | |
| 406 | + return -EINVAL; | |
| 407 | + } | |
| 408 | + | |
| 409 | + reg_data = (int16_t *)data; | |
| 410 | + data_len = len >> 1; | |
| 411 | + | |
| 412 | + if (data_len & 0x1) { | |
| 413 | + dev_err(aw_dev->dev, "data len:%d unsupported", data_len); | |
| 414 | + return -EINVAL; | |
| 415 | + } | |
| 416 | + | |
| 417 | + for (i = 0; i < data_len; i += 2) { | |
| 418 | + reg_addr = reg_data[i]; | |
| 419 | + reg_val = reg_data[i + 1]; | |
| 420 | + | |
| 421 | + if (reg_addr == AW88261_SYSCTRL_REG) { | |
| 422 | + aw88261->amppd_st = reg_val & (~AW88261_AMPPD_MASK); | |
| 423 | + ret = regmap_read(aw_dev->regmap, reg_addr, &read_val); | |
| 424 | + if (ret) | |
| 425 | + break; | |
| 426 | + | |
| 427 | + read_val &= (~AW88261_AMPPD_MASK) | (~AW88261_PWDN_MASK) | | |
| 428 | + (~AW88261_HMUTE_MASK); | |
| 429 | + reg_val &= (AW88261_AMPPD_MASK | AW88261_PWDN_MASK | AW88261_HMUTE_MASK); | |
| 430 | + reg_val |= read_val; | |
| 431 | + | |
| 432 | + /* enable uls hmute */ | |
| 433 | + reg_val &= AW88261_ULS_HMUTE_MASK; | |
| 434 | + reg_val |= AW88261_ULS_HMUTE_ENABLE_VALUE; | |
| 435 | + } | |
| 436 | + | |
| 437 | + if (reg_addr == AW88261_DBGCTRL_REG) { | |
| 438 | + efcheck_val = reg_val & (~AW88261_EF_DBMD_MASK); | |
| 439 | + if (efcheck_val == AW88261_OR_VALUE) | |
| 440 | + aw88261->efuse_check = AW88261_EF_OR_CHECK; | |
| 441 | + else | |
| 442 | + aw88261->efuse_check = AW88261_EF_AND_CHECK; | |
| 443 | + } | |
| 444 | + | |
| 445 | + /* i2stxen */ | |
| 446 | + if (reg_addr == AW88261_I2SCTRL3_REG) { | |
| 447 | + /* close tx */ | |
| 448 | + reg_val &= AW88261_I2STXEN_MASK; | |
| 449 | + reg_val |= AW88261_I2STXEN_DISABLE_VALUE; | |
| 450 | + } | |
| 451 | + | |
| 452 | + if (reg_addr == AW88261_SYSCTRL2_REG) { | |
| 453 | + read_vol = (reg_val & (~AW88261_VOL_MASK)) >> | |
| 454 | + AW88261_VOL_START_BIT; | |
| 455 | + aw_dev->volume_desc.init_volume = | |
| 456 | + REG_VAL_TO_DB(read_vol); | |
| 457 | + } | |
| 458 | + | |
| 459 | + if (reg_addr == AW88261_VSNTM1_REG) | |
| 460 | + continue; | |
| 461 | + | |
| 462 | + ret = regmap_write(aw_dev->regmap, reg_addr, reg_val); | |
| 463 | + if (ret) | |
| 464 | + break; | |
| 465 | + } | |
| 466 | + | |
| 467 | + ret = aw88261_dev_set_vcalb(aw_dev); | |
| 468 | + if (ret) | |
| 469 | + return ret; | |
| 470 | + | |
| 471 | + if (aw_dev->prof_cur != aw_dev->prof_index) | |
| 472 | + vol_desc->ctl_volume = 0; | |
| 473 | + | |
| 474 | + /* keep min volume */ | |
| 475 | + aw88261_dev_set_volume(aw_dev, vol_desc->mute_volume); | |
| 476 | + | |
| 477 | + return ret; | |
| 478 | +} | |
| 479 | + | |
| 480 | +static char *aw88261_dev_get_prof_name(struct aw_device *aw_dev, int index) | |
| 481 | +{ | |
| 482 | + struct aw_prof_info *prof_info = &aw_dev->prof_info; | |
| 483 | + struct aw_prof_desc *prof_desc; | |
| 484 | + | |
| 485 | + if ((index >= aw_dev->prof_info.count) || (index < 0)) { | |
| 486 | + dev_err(aw_dev->dev, "index[%d] overflow count[%d]", | |
| 487 | + index, aw_dev->prof_info.count); | |
| 488 | + return NULL; | |
| 489 | + } | |
| 490 | + | |
| 491 | + prof_desc = &aw_dev->prof_info.prof_desc[index]; | |
| 492 | + | |
| 493 | + return prof_info->prof_name_list[prof_desc->id]; | |
| 494 | +} | |
| 495 | + | |
| 496 | +static int aw88261_dev_get_prof_data(struct aw_device *aw_dev, int index, | |
| 497 | + struct aw_prof_desc **prof_desc) | |
| 498 | +{ | |
| 499 | + if ((index >= aw_dev->prof_info.count) || (index < 0)) { | |
| 500 | + dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n", | |
| 501 | + __func__, index, aw_dev->prof_info.count); | |
| 502 | + return -EINVAL; | |
| 503 | + } | |
| 504 | + | |
| 505 | + *prof_desc = &aw_dev->prof_info.prof_desc[index]; | |
| 506 | + | |
| 507 | + return 0; | |
| 508 | +} | |
| 509 | + | |
| 510 | +static int aw88261_dev_fw_update(struct aw88261 *aw88261) | |
| 511 | +{ | |
| 512 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 513 | + struct aw_prof_desc *prof_index_desc; | |
| 514 | + struct aw_sec_data_desc *sec_desc; | |
| 515 | + char *prof_name; | |
| 516 | + int ret; | |
| 517 | + | |
| 518 | + prof_name = aw88261_dev_get_prof_name(aw_dev, aw_dev->prof_index); | |
| 519 | + if (!prof_name) { | |
| 520 | + dev_err(aw_dev->dev, "get prof name failed"); | |
| 521 | + return -EINVAL; | |
| 522 | + } | |
| 523 | + | |
| 524 | + dev_dbg(aw_dev->dev, "start update %s", prof_name); | |
| 525 | + | |
| 526 | + ret = aw88261_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc); | |
| 527 | + if (ret) | |
| 528 | + return ret; | |
| 529 | + | |
| 530 | + /* update reg */ | |
| 531 | + sec_desc = prof_index_desc->sec_desc; | |
| 532 | + ret = aw88261_dev_reg_update(aw88261, sec_desc[AW88395_DATA_TYPE_REG].data, | |
| 533 | + sec_desc[AW88395_DATA_TYPE_REG].len); | |
| 534 | + if (ret) { | |
| 535 | + dev_err(aw_dev->dev, "update reg failed"); | |
| 536 | + return ret; | |
| 537 | + } | |
| 538 | + | |
| 539 | + aw_dev->prof_cur = aw_dev->prof_index; | |
| 540 | + | |
| 541 | + return ret; | |
| 542 | +} | |
| 543 | + | |
| 544 | +static int aw88261_dev_start(struct aw88261 *aw88261) | |
| 545 | +{ | |
| 546 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 547 | + int ret; | |
| 548 | + | |
| 549 | + if (aw_dev->status == AW88261_DEV_PW_ON) { | |
| 550 | + dev_info(aw_dev->dev, "already power on"); | |
| 551 | + return 0; | |
| 552 | + } | |
| 553 | + | |
| 554 | + /* power on */ | |
| 555 | + aw88261_dev_pwd(aw_dev, false); | |
| 556 | + usleep_range(AW88261_2000_US, AW88261_2000_US + 10); | |
| 557 | + | |
| 558 | + ret = aw88261_dev_check_syspll(aw_dev); | |
| 559 | + if (ret) { | |
| 560 | + dev_err(aw_dev->dev, "pll check failed cannot start"); | |
| 561 | + goto pll_check_fail; | |
| 562 | + } | |
| 563 | + | |
| 564 | + /* amppd on */ | |
| 565 | + aw88261_dev_amppd(aw_dev, false); | |
| 566 | + usleep_range(AW88261_1000_US, AW88261_1000_US + 50); | |
| 567 | + | |
| 568 | + /* check i2s status */ | |
| 569 | + ret = aw88261_dev_check_sysst(aw_dev); | |
| 570 | + if (ret) { | |
| 571 | + dev_err(aw_dev->dev, "sysst check failed"); | |
| 572 | + goto sysst_check_fail; | |
| 573 | + } | |
| 574 | + | |
| 575 | + /* enable tx feedback */ | |
| 576 | + aw88261_dev_i2s_tx_enable(aw_dev, true); | |
| 577 | + | |
| 578 | + if (aw88261->amppd_st) | |
| 579 | + aw88261_dev_amppd(aw_dev, true); | |
| 580 | + | |
| 581 | + aw88261_reg_force_set(aw88261); | |
| 582 | + | |
| 583 | + /* close uls mute */ | |
| 584 | + aw88261_dev_uls_hmute(aw_dev, false); | |
| 585 | + | |
| 586 | + /* close mute */ | |
| 587 | + if (!aw88261->mute_st) | |
| 588 | + aw88261_dev_mute(aw_dev, false); | |
| 589 | + | |
| 590 | + /* clear inturrupt */ | |
| 591 | + aw88261_dev_clear_int_status(aw_dev); | |
| 592 | + aw_dev->status = AW88261_DEV_PW_ON; | |
| 593 | + | |
| 594 | + return 0; | |
| 595 | + | |
| 596 | +sysst_check_fail: | |
| 597 | + aw88261_dev_i2s_tx_enable(aw_dev, false); | |
| 598 | + aw88261_dev_clear_int_status(aw_dev); | |
| 599 | + aw88261_dev_amppd(aw_dev, true); | |
| 600 | +pll_check_fail: | |
| 601 | + aw88261_dev_pwd(aw_dev, true); | |
| 602 | + aw_dev->status = AW88261_DEV_PW_OFF; | |
| 603 | + | |
| 604 | + return ret; | |
| 605 | +} | |
| 606 | + | |
| 607 | +static int aw88261_dev_stop(struct aw_device *aw_dev) | |
| 608 | +{ | |
| 609 | + if (aw_dev->status == AW88261_DEV_PW_OFF) { | |
| 610 | + dev_info(aw_dev->dev, "already power off"); | |
| 611 | + return 0; | |
| 612 | + } | |
| 613 | + | |
| 614 | + aw_dev->status = AW88261_DEV_PW_OFF; | |
| 615 | + | |
| 616 | + /* clear inturrupt */ | |
| 617 | + aw88261_dev_clear_int_status(aw_dev); | |
| 618 | + | |
| 619 | + aw88261_dev_uls_hmute(aw_dev, true); | |
| 620 | + /* set mute */ | |
| 621 | + aw88261_dev_mute(aw_dev, true); | |
| 622 | + | |
| 623 | + /* close tx feedback */ | |
| 624 | + aw88261_dev_i2s_tx_enable(aw_dev, false); | |
| 625 | + usleep_range(AW88261_1000_US, AW88261_1000_US + 100); | |
| 626 | + | |
| 627 | + /* enable amppd */ | |
| 628 | + aw88261_dev_amppd(aw_dev, true); | |
| 629 | + | |
| 630 | + /* set power down */ | |
| 631 | + aw88261_dev_pwd(aw_dev, true); | |
| 632 | + | |
| 633 | + return 0; | |
| 634 | +} | |
| 635 | + | |
| 636 | +static int aw88261_reg_update(struct aw88261 *aw88261, bool force) | |
| 637 | +{ | |
| 638 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 639 | + int ret; | |
| 640 | + | |
| 641 | + if (force) { | |
| 642 | + ret = regmap_write(aw_dev->regmap, | |
| 643 | + AW88261_ID_REG, AW88261_SOFT_RESET_VALUE); | |
| 644 | + if (ret) | |
| 645 | + return ret; | |
| 646 | + | |
| 647 | + ret = aw88261_dev_fw_update(aw88261); | |
| 648 | + if (ret) | |
| 649 | + return ret; | |
| 650 | + } else { | |
| 651 | + if (aw_dev->prof_cur != aw_dev->prof_index) { | |
| 652 | + ret = aw88261_dev_fw_update(aw88261); | |
| 653 | + if (ret) | |
| 654 | + return ret; | |
| 655 | + } else { | |
| 656 | + ret = 0; | |
| 657 | + } | |
| 658 | + } | |
| 659 | + | |
| 660 | + aw_dev->prof_cur = aw_dev->prof_index; | |
| 661 | + | |
| 662 | + return ret; | |
| 663 | +} | |
| 664 | + | |
| 665 | +static void aw88261_start_pa(struct aw88261 *aw88261) | |
| 666 | +{ | |
| 667 | + int ret, i; | |
| 668 | + | |
| 669 | + for (i = 0; i < AW88261_START_RETRIES; i++) { | |
| 670 | + ret = aw88261_reg_update(aw88261, aw88261->phase_sync); | |
| 671 | + if (ret) { | |
| 672 | + dev_err(aw88261->aw_pa->dev, "fw update failed, cnt:%d\n", i); | |
| 673 | + continue; | |
| 674 | + } | |
| 675 | + ret = aw88261_dev_start(aw88261); | |
| 676 | + if (ret) { | |
| 677 | + dev_err(aw88261->aw_pa->dev, "aw88261 device start failed. retry = %d", i); | |
| 678 | + continue; | |
| 679 | + } else { | |
| 680 | + dev_info(aw88261->aw_pa->dev, "start success\n"); | |
| 681 | + break; | |
| 682 | + } | |
| 683 | + } | |
| 684 | +} | |
| 685 | + | |
| 686 | +static void aw88261_startup_work(struct work_struct *work) | |
| 687 | +{ | |
| 688 | + struct aw88261 *aw88261 = | |
| 689 | + container_of(work, struct aw88261, start_work.work); | |
| 690 | + | |
| 691 | + mutex_lock(&aw88261->lock); | |
| 692 | + aw88261_start_pa(aw88261); | |
| 693 | + mutex_unlock(&aw88261->lock); | |
| 694 | +} | |
| 695 | + | |
| 696 | +static void aw88261_start(struct aw88261 *aw88261, bool sync_start) | |
| 697 | +{ | |
| 698 | + if (aw88261->aw_pa->fw_status != AW88261_DEV_FW_OK) | |
| 699 | + return; | |
| 700 | + | |
| 701 | + if (aw88261->aw_pa->status == AW88261_DEV_PW_ON) | |
| 702 | + return; | |
| 703 | + | |
| 704 | + if (sync_start == AW88261_SYNC_START) | |
| 705 | + aw88261_start_pa(aw88261); | |
| 706 | + else | |
| 707 | + queue_delayed_work(system_wq, | |
| 708 | + &aw88261->start_work, | |
| 709 | + AW88261_START_WORK_DELAY_MS); | |
| 710 | +} | |
| 711 | + | |
| 712 | +static struct snd_soc_dai_driver aw88261_dai[] = { | |
| 713 | + { | |
| 714 | + .name = "aw88261-aif", | |
| 715 | + .id = 1, | |
| 716 | + .playback = { | |
| 717 | + .stream_name = "Speaker_Playback", | |
| 718 | + .channels_min = 1, | |
| 719 | + .channels_max = 2, | |
| 720 | + .rates = AW88261_RATES, | |
| 721 | + .formats = AW88261_FORMATS, | |
| 722 | + }, | |
| 723 | + .capture = { | |
| 724 | + .stream_name = "Speaker_Capture", | |
| 725 | + .channels_min = 1, | |
| 726 | + .channels_max = 2, | |
| 727 | + .rates = AW88261_RATES, | |
| 728 | + .formats = AW88261_FORMATS, | |
| 729 | + }, | |
| 730 | + }, | |
| 731 | +}; | |
| 732 | + | |
| 733 | +static int aw88261_get_fade_in_time(struct snd_kcontrol *kcontrol, | |
| 734 | + struct snd_ctl_elem_value *ucontrol) | |
| 735 | +{ | |
| 736 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | |
| 737 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 738 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 739 | + | |
| 740 | + ucontrol->value.integer.value[0] = aw_dev->fade_in_time; | |
| 741 | + | |
| 742 | + return 0; | |
| 743 | +} | |
| 744 | + | |
| 745 | +static int aw88261_set_fade_in_time(struct snd_kcontrol *kcontrol, | |
| 746 | + struct snd_ctl_elem_value *ucontrol) | |
| 747 | +{ | |
| 748 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | |
| 749 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 750 | + struct soc_mixer_control *mc = | |
| 751 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 752 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 753 | + int time; | |
| 754 | + | |
| 755 | + time = ucontrol->value.integer.value[0]; | |
| 756 | + | |
| 757 | + if (time < mc->min || time > mc->max) | |
| 758 | + return -EINVAL; | |
| 759 | + | |
| 760 | + if (time != aw_dev->fade_in_time) { | |
| 761 | + aw_dev->fade_in_time = time; | |
| 762 | + return 1; | |
| 763 | + } | |
| 764 | + | |
| 765 | + return 0; | |
| 766 | +} | |
| 767 | + | |
| 768 | +static int aw88261_get_fade_out_time(struct snd_kcontrol *kcontrol, | |
| 769 | + struct snd_ctl_elem_value *ucontrol) | |
| 770 | +{ | |
| 771 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | |
| 772 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 773 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 774 | + | |
| 775 | + ucontrol->value.integer.value[0] = aw_dev->fade_out_time; | |
| 776 | + | |
| 777 | + return 0; | |
| 778 | +} | |
| 779 | + | |
| 780 | +static int aw88261_set_fade_out_time(struct snd_kcontrol *kcontrol, | |
| 781 | + struct snd_ctl_elem_value *ucontrol) | |
| 782 | +{ | |
| 783 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | |
| 784 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 785 | + struct soc_mixer_control *mc = | |
| 786 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 787 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 788 | + int time; | |
| 789 | + | |
| 790 | + time = ucontrol->value.integer.value[0]; | |
| 791 | + if (time < mc->min || time > mc->max) | |
| 792 | + return -EINVAL; | |
| 793 | + | |
| 794 | + if (time != aw_dev->fade_out_time) { | |
| 795 | + aw_dev->fade_out_time = time; | |
| 796 | + return 1; | |
| 797 | + } | |
| 798 | + | |
| 799 | + return 0; | |
| 800 | +} | |
| 801 | + | |
| 802 | +static int aw88261_dev_set_profile_index(struct aw_device *aw_dev, int index) | |
| 803 | +{ | |
| 804 | + /* check the index whether is valid */ | |
| 805 | + if ((index >= aw_dev->prof_info.count) || (index < 0)) | |
| 806 | + return -EINVAL; | |
| 807 | + /* check the index whether change */ | |
| 808 | + if (aw_dev->prof_index == index) | |
| 809 | + return -EPERM; | |
| 810 | + | |
| 811 | + aw_dev->prof_index = index; | |
| 812 | + | |
| 813 | + return 0; | |
| 814 | +} | |
| 815 | + | |
| 816 | +static int aw88261_profile_info(struct snd_kcontrol *kcontrol, | |
| 817 | + struct snd_ctl_elem_info *uinfo) | |
| 818 | +{ | |
| 819 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 820 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 821 | + const char *prof_name; | |
| 822 | + char *name; | |
| 823 | + int count; | |
| 824 | + | |
| 825 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | |
| 826 | + uinfo->count = 1; | |
| 827 | + | |
| 828 | + count = aw88261->aw_pa->prof_info.count; | |
| 829 | + if (count <= 0) { | |
| 830 | + uinfo->value.enumerated.items = 0; | |
| 831 | + return 0; | |
| 832 | + } | |
| 833 | + | |
| 834 | + uinfo->value.enumerated.items = count; | |
| 835 | + | |
| 836 | + if (uinfo->value.enumerated.item >= count) | |
| 837 | + uinfo->value.enumerated.item = count - 1; | |
| 838 | + | |
| 839 | + name = uinfo->value.enumerated.name; | |
| 840 | + count = uinfo->value.enumerated.item; | |
| 841 | + | |
| 842 | + prof_name = aw88261_dev_get_prof_name(aw88261->aw_pa, count); | |
| 843 | + if (!prof_name) { | |
| 844 | + strscpy(uinfo->value.enumerated.name, "null", | |
| 845 | + strlen("null") + 1); | |
| 846 | + return 0; | |
| 847 | + } | |
| 848 | + | |
| 849 | + strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name)); | |
| 850 | + | |
| 851 | + return 0; | |
| 852 | +} | |
| 853 | + | |
| 854 | +static int aw88261_profile_get(struct snd_kcontrol *kcontrol, | |
| 855 | + struct snd_ctl_elem_value *ucontrol) | |
| 856 | +{ | |
| 857 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 858 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 859 | + | |
| 860 | + ucontrol->value.integer.value[0] = aw88261->aw_pa->prof_index; | |
| 861 | + | |
| 862 | + return 0; | |
| 863 | +} | |
| 864 | + | |
| 865 | +static int aw88261_profile_set(struct snd_kcontrol *kcontrol, | |
| 866 | + struct snd_ctl_elem_value *ucontrol) | |
| 867 | +{ | |
| 868 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 869 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 870 | + int ret; | |
| 871 | + | |
| 872 | + /* pa stop or stopping just set profile */ | |
| 873 | + mutex_lock(&aw88261->lock); | |
| 874 | + ret = aw88261_dev_set_profile_index(aw88261->aw_pa, ucontrol->value.integer.value[0]); | |
| 875 | + if (ret) { | |
| 876 | + dev_dbg(codec->dev, "profile index does not change"); | |
| 877 | + mutex_unlock(&aw88261->lock); | |
| 878 | + return 0; | |
| 879 | + } | |
| 880 | + | |
| 881 | + if (aw88261->aw_pa->status) { | |
| 882 | + aw88261_dev_stop(aw88261->aw_pa); | |
| 883 | + aw88261_start(aw88261, AW88261_SYNC_START); | |
| 884 | + } | |
| 885 | + | |
| 886 | + mutex_unlock(&aw88261->lock); | |
| 887 | + | |
| 888 | + return 1; | |
| 889 | +} | |
| 890 | + | |
| 891 | +static int aw88261_volume_get(struct snd_kcontrol *kcontrol, | |
| 892 | + struct snd_ctl_elem_value *ucontrol) | |
| 893 | +{ | |
| 894 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 895 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 896 | + struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; | |
| 897 | + | |
| 898 | + ucontrol->value.integer.value[0] = vol_desc->ctl_volume; | |
| 899 | + | |
| 900 | + return 0; | |
| 901 | +} | |
| 902 | + | |
| 903 | +static int aw88261_volume_set(struct snd_kcontrol *kcontrol, | |
| 904 | + struct snd_ctl_elem_value *ucontrol) | |
| 905 | +{ | |
| 906 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 907 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 908 | + struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; | |
| 909 | + struct soc_mixer_control *mc = | |
| 910 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 911 | + int value; | |
| 912 | + | |
| 913 | + value = ucontrol->value.integer.value[0]; | |
| 914 | + | |
| 915 | + if (value < mc->min || value > mc->max) | |
| 916 | + return -EINVAL; | |
| 917 | + | |
| 918 | + if (vol_desc->ctl_volume != value) { | |
| 919 | + vol_desc->ctl_volume = value; | |
| 920 | + aw88261_dev_set_volume(aw88261->aw_pa, vol_desc->ctl_volume); | |
| 921 | + | |
| 922 | + return 1; | |
| 923 | + } | |
| 924 | + | |
| 925 | + return 0; | |
| 926 | +} | |
| 927 | + | |
| 928 | +static int aw88261_get_fade_step(struct snd_kcontrol *kcontrol, | |
| 929 | + struct snd_ctl_elem_value *ucontrol) | |
| 930 | +{ | |
| 931 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 932 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 933 | + | |
| 934 | + ucontrol->value.integer.value[0] = aw88261->aw_pa->fade_step; | |
| 935 | + | |
| 936 | + return 0; | |
| 937 | +} | |
| 938 | + | |
| 939 | +static int aw88261_set_fade_step(struct snd_kcontrol *kcontrol, | |
| 940 | + struct snd_ctl_elem_value *ucontrol) | |
| 941 | +{ | |
| 942 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 943 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); | |
| 944 | + struct soc_mixer_control *mc = | |
| 945 | + (struct soc_mixer_control *)kcontrol->private_value; | |
| 946 | + int value; | |
| 947 | + | |
| 948 | + value = ucontrol->value.integer.value[0]; | |
| 949 | + if (value < mc->min || value > mc->max) | |
| 950 | + return -EINVAL; | |
| 951 | + | |
| 952 | + if (aw88261->aw_pa->fade_step != value) { | |
| 953 | + aw88261->aw_pa->fade_step = value; | |
| 954 | + return 1; | |
| 955 | + } | |
| 956 | + | |
| 957 | + return 0; | |
| 958 | +} | |
| 959 | + | |
| 960 | +static const struct snd_kcontrol_new aw88261_controls[] = { | |
| 961 | + SOC_SINGLE_EXT("PCM Playback Volume", AW88261_SYSCTRL2_REG, | |
| 962 | + 6, AW88261_MUTE_VOL, 0, aw88261_volume_get, | |
| 963 | + aw88261_volume_set), | |
| 964 | + SOC_SINGLE_EXT("Fade Step", 0, 0, AW88261_MUTE_VOL, 0, | |
| 965 | + aw88261_get_fade_step, aw88261_set_fade_step), | |
| 966 | + SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, | |
| 967 | + aw88261_get_fade_in_time, aw88261_set_fade_in_time), | |
| 968 | + SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, | |
| 969 | + aw88261_get_fade_out_time, aw88261_set_fade_out_time), | |
| 970 | + AW88261_PROFILE_EXT("Profile Set", aw88261_profile_info, | |
| 971 | + aw88261_profile_get, aw88261_profile_set), | |
| 972 | +}; | |
| 973 | + | |
| 974 | +static int aw88261_playback_event(struct snd_soc_dapm_widget *w, | |
| 975 | + struct snd_kcontrol *k, int event) | |
| 976 | +{ | |
| 977 | + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | |
| 978 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 979 | + | |
| 980 | + mutex_lock(&aw88261->lock); | |
| 981 | + switch (event) { | |
| 982 | + case SND_SOC_DAPM_PRE_PMU: | |
| 983 | + aw88261_start(aw88261, AW88261_ASYNC_START); | |
| 984 | + break; | |
| 985 | + case SND_SOC_DAPM_POST_PMD: | |
| 986 | + aw88261_dev_stop(aw88261->aw_pa); | |
| 987 | + break; | |
| 988 | + default: | |
| 989 | + break; | |
| 990 | + } | |
| 991 | + mutex_unlock(&aw88261->lock); | |
| 992 | + | |
| 993 | + return 0; | |
| 994 | +} | |
| 995 | + | |
| 996 | +static const struct snd_soc_dapm_widget aw88261_dapm_widgets[] = { | |
| 997 | + /* playback */ | |
| 998 | + SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, 0, 0, 0, | |
| 999 | + aw88261_playback_event, | |
| 1000 | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | |
| 1001 | + SND_SOC_DAPM_OUTPUT("DAC Output"), | |
| 1002 | + | |
| 1003 | + /* capture */ | |
| 1004 | + SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0), | |
| 1005 | + SND_SOC_DAPM_INPUT("ADC Input"), | |
| 1006 | +}; | |
| 1007 | + | |
| 1008 | +static const struct snd_soc_dapm_route aw88261_audio_map[] = { | |
| 1009 | + {"DAC Output", NULL, "AIF_RX"}, | |
| 1010 | + {"AIF_TX", NULL, "ADC Input"}, | |
| 1011 | +}; | |
| 1012 | + | |
| 1013 | +static int aw88261_frcset_check(struct aw88261 *aw88261) | |
| 1014 | +{ | |
| 1015 | + unsigned int reg_val; | |
| 1016 | + u16 temh, teml, tem; | |
| 1017 | + int ret; | |
| 1018 | + | |
| 1019 | + ret = regmap_read(aw88261->regmap, AW88261_EFRH3_REG, ®_val); | |
| 1020 | + if (ret) | |
| 1021 | + return ret; | |
| 1022 | + temh = ((u16)reg_val & (~AW88261_TEMH_MASK)); | |
| 1023 | + | |
| 1024 | + ret = regmap_read(aw88261->regmap, AW88261_EFRL3_REG, ®_val); | |
| 1025 | + if (ret) | |
| 1026 | + return ret; | |
| 1027 | + teml = ((u16)reg_val & (~AW88261_TEML_MASK)); | |
| 1028 | + | |
| 1029 | + if (aw88261->efuse_check == AW88261_EF_OR_CHECK) | |
| 1030 | + tem = (temh | teml); | |
| 1031 | + else | |
| 1032 | + tem = (temh & teml); | |
| 1033 | + | |
| 1034 | + if (tem == AW88261_DEFAULT_CFG) | |
| 1035 | + aw88261->frcset_en = AW88261_FRCSET_ENABLE; | |
| 1036 | + else | |
| 1037 | + aw88261->frcset_en = AW88261_FRCSET_DISABLE; | |
| 1038 | + | |
| 1039 | + dev_dbg(aw88261->aw_pa->dev, "tem is 0x%04x, frcset_en is %d", | |
| 1040 | + tem, aw88261->frcset_en); | |
| 1041 | + | |
| 1042 | + return ret; | |
| 1043 | +} | |
| 1044 | + | |
| 1045 | +static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg) | |
| 1046 | +{ | |
| 1047 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 1048 | + int ret; | |
| 1049 | + | |
| 1050 | + ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); | |
| 1051 | + if (ret) { | |
| 1052 | + dev_err(aw_dev->dev, "aw_dev acf parse failed"); | |
| 1053 | + return -EINVAL; | |
| 1054 | + } | |
| 1055 | + | |
| 1056 | + ret = regmap_write(aw_dev->regmap, AW88261_ID_REG, AW88261_SOFT_RESET_VALUE); | |
| 1057 | + if (ret) | |
| 1058 | + return ret; | |
| 1059 | + | |
| 1060 | + aw_dev->fade_in_time = AW88261_500_US; | |
| 1061 | + aw_dev->fade_out_time = AW88261_500_US; | |
| 1062 | + aw_dev->prof_cur = AW88261_INIT_PROFILE; | |
| 1063 | + aw_dev->prof_index = AW88261_INIT_PROFILE; | |
| 1064 | + | |
| 1065 | + ret = aw88261_dev_fw_update(aw88261); | |
| 1066 | + if (ret) { | |
| 1067 | + dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret); | |
| 1068 | + return ret; | |
| 1069 | + } | |
| 1070 | + | |
| 1071 | + ret = aw88261_frcset_check(aw88261); | |
| 1072 | + if (ret) { | |
| 1073 | + dev_err(aw_dev->dev, "aw88261_frcset_check ret = %d\n", ret); | |
| 1074 | + return ret; | |
| 1075 | + } | |
| 1076 | + | |
| 1077 | + aw88261_dev_clear_int_status(aw_dev); | |
| 1078 | + | |
| 1079 | + aw88261_dev_uls_hmute(aw_dev, true); | |
| 1080 | + | |
| 1081 | + aw88261_dev_mute(aw_dev, true); | |
| 1082 | + | |
| 1083 | + aw88261_dev_i2s_tx_enable(aw_dev, false); | |
| 1084 | + | |
| 1085 | + usleep_range(AW88261_1000_US, AW88261_1000_US + 100); | |
| 1086 | + | |
| 1087 | + aw88261_dev_amppd(aw_dev, true); | |
| 1088 | + | |
| 1089 | + aw88261_dev_pwd(aw_dev, true); | |
| 1090 | + | |
| 1091 | + return 0; | |
| 1092 | +} | |
| 1093 | + | |
| 1094 | +static int aw88261_request_firmware_file(struct aw88261 *aw88261) | |
| 1095 | +{ | |
| 1096 | + const struct firmware *cont = NULL; | |
| 1097 | + int ret; | |
| 1098 | + | |
| 1099 | + aw88261->aw_pa->fw_status = AW88261_DEV_FW_FAILED; | |
| 1100 | + | |
| 1101 | + ret = request_firmware(&cont, AW88261_ACF_FILE, aw88261->aw_pa->dev); | |
| 1102 | + if (ret) | |
| 1103 | + return dev_err_probe(aw88261->aw_pa->dev, ret, | |
| 1104 | + "load [%s] failed!", AW88261_ACF_FILE); | |
| 1105 | + | |
| 1106 | + dev_info(aw88261->aw_pa->dev, "loaded %s - size: %zu\n", | |
| 1107 | + AW88261_ACF_FILE, cont ? cont->size : 0); | |
| 1108 | + | |
| 1109 | + aw88261->aw_cfg = devm_kzalloc(aw88261->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL); | |
| 1110 | + if (!aw88261->aw_cfg) { | |
| 1111 | + release_firmware(cont); | |
| 1112 | + return -ENOMEM; | |
| 1113 | + } | |
| 1114 | + aw88261->aw_cfg->len = (int)cont->size; | |
| 1115 | + memcpy(aw88261->aw_cfg->data, cont->data, cont->size); | |
| 1116 | + release_firmware(cont); | |
| 1117 | + | |
| 1118 | + ret = aw88395_dev_load_acf_check(aw88261->aw_pa, aw88261->aw_cfg); | |
| 1119 | + if (ret) { | |
| 1120 | + dev_err(aw88261->aw_pa->dev, "load [%s] failed !", AW88261_ACF_FILE); | |
| 1121 | + return ret; | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + mutex_lock(&aw88261->lock); | |
| 1125 | + /* aw device init */ | |
| 1126 | + ret = aw88261_dev_init(aw88261, aw88261->aw_cfg); | |
| 1127 | + if (ret) | |
| 1128 | + dev_err(aw88261->aw_pa->dev, "dev init failed"); | |
| 1129 | + mutex_unlock(&aw88261->lock); | |
| 1130 | + | |
| 1131 | + return ret; | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +static int aw88261_codec_probe(struct snd_soc_component *component) | |
| 1135 | +{ | |
| 1136 | + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); | |
| 1137 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); | |
| 1138 | + int ret; | |
| 1139 | + | |
| 1140 | + INIT_DELAYED_WORK(&aw88261->start_work, aw88261_startup_work); | |
| 1141 | + | |
| 1142 | + ret = aw88261_request_firmware_file(aw88261); | |
| 1143 | + if (ret) | |
| 1144 | + return dev_err_probe(aw88261->aw_pa->dev, ret, | |
| 1145 | + "aw88261_request_firmware_file failed\n"); | |
| 1146 | + | |
| 1147 | + /* add widgets */ | |
| 1148 | + ret = snd_soc_dapm_new_controls(dapm, aw88261_dapm_widgets, | |
| 1149 | + ARRAY_SIZE(aw88261_dapm_widgets)); | |
| 1150 | + if (ret) | |
| 1151 | + return ret; | |
| 1152 | + | |
| 1153 | + /* add route */ | |
| 1154 | + ret = snd_soc_dapm_add_routes(dapm, aw88261_audio_map, | |
| 1155 | + ARRAY_SIZE(aw88261_audio_map)); | |
| 1156 | + if (ret) | |
| 1157 | + return ret; | |
| 1158 | + | |
| 1159 | + ret = snd_soc_add_component_controls(component, aw88261_controls, | |
| 1160 | + ARRAY_SIZE(aw88261_controls)); | |
| 1161 | + | |
| 1162 | + return ret; | |
| 1163 | +} | |
| 1164 | + | |
| 1165 | +static void aw88261_codec_remove(struct snd_soc_component *aw_codec) | |
| 1166 | +{ | |
| 1167 | + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(aw_codec); | |
| 1168 | + | |
| 1169 | + cancel_delayed_work_sync(&aw88261->start_work); | |
| 1170 | +} | |
| 1171 | + | |
| 1172 | +static const struct snd_soc_component_driver soc_codec_dev_aw88261 = { | |
| 1173 | + .probe = aw88261_codec_probe, | |
| 1174 | + .remove = aw88261_codec_remove, | |
| 1175 | +}; | |
| 1176 | + | |
| 1177 | +static void aw88261_hw_reset(struct aw88261 *aw88261) | |
| 1178 | +{ | |
| 1179 | + gpiod_set_value_cansleep(aw88261->reset_gpio, 0); | |
| 1180 | + usleep_range(AW88261_1000_US, AW88261_1000_US + 10); | |
| 1181 | + gpiod_set_value_cansleep(aw88261->reset_gpio, 1); | |
| 1182 | + usleep_range(AW88261_1000_US, AW88261_1000_US + 10); | |
| 1183 | +} | |
| 1184 | + | |
| 1185 | +static void aw88261_parse_channel_dt(struct aw88261 *aw88261) | |
| 1186 | +{ | |
| 1187 | + struct aw_device *aw_dev = aw88261->aw_pa; | |
| 1188 | + struct device_node *np = aw_dev->dev->of_node; | |
| 1189 | + u32 channel_value = AW88261_DEV_DEFAULT_CH; | |
| 1190 | + u32 sync_enable = false; | |
| 1191 | + | |
| 1192 | + of_property_read_u32(np, "sound-channel", &channel_value); | |
| 1193 | + of_property_read_u32(np, "sync-flag", &sync_enable); | |
| 1194 | + | |
| 1195 | + aw_dev->channel = channel_value; | |
| 1196 | + aw88261->phase_sync = sync_enable; | |
| 1197 | +} | |
| 1198 | + | |
| 1199 | +static int aw88261_init(struct aw88261 **aw88261, struct i2c_client *i2c, struct regmap *regmap) | |
| 1200 | +{ | |
| 1201 | + struct aw_device *aw_dev; | |
| 1202 | + unsigned int chip_id; | |
| 1203 | + int ret; | |
| 1204 | + | |
| 1205 | + /* read chip id */ | |
| 1206 | + ret = regmap_read(regmap, AW88261_ID_REG, &chip_id); | |
| 1207 | + if (ret) { | |
| 1208 | + dev_err(&i2c->dev, "%s read chipid error. ret = %d", __func__, ret); | |
| 1209 | + return ret; | |
| 1210 | + } | |
| 1211 | + if (chip_id != AW88261_CHIP_ID) { | |
| 1212 | + dev_err(&i2c->dev, "unsupported device"); | |
| 1213 | + return -ENXIO; | |
| 1214 | + } | |
| 1215 | + | |
| 1216 | + dev_info(&i2c->dev, "chip id = %x\n", chip_id); | |
| 1217 | + | |
| 1218 | + aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL); | |
| 1219 | + if (!aw_dev) | |
| 1220 | + return -ENOMEM; | |
| 1221 | + | |
| 1222 | + (*aw88261)->aw_pa = aw_dev; | |
| 1223 | + aw_dev->i2c = i2c; | |
| 1224 | + aw_dev->regmap = regmap; | |
| 1225 | + aw_dev->dev = &i2c->dev; | |
| 1226 | + aw_dev->chip_id = AW88261_CHIP_ID; | |
| 1227 | + aw_dev->acf = NULL; | |
| 1228 | + aw_dev->prof_info.prof_desc = NULL; | |
| 1229 | + aw_dev->prof_info.count = 0; | |
| 1230 | + aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; | |
| 1231 | + aw_dev->channel = 0; | |
| 1232 | + aw_dev->fw_status = AW88261_DEV_FW_FAILED; | |
| 1233 | + aw_dev->fade_step = AW88261_VOLUME_STEP_DB; | |
| 1234 | + aw_dev->volume_desc.ctl_volume = AW88261_VOL_DEFAULT_VALUE; | |
| 1235 | + aw_dev->volume_desc.mute_volume = AW88261_MUTE_VOL; | |
| 1236 | + aw88261_parse_channel_dt(*aw88261); | |
| 1237 | + | |
| 1238 | + return ret; | |
| 1239 | +} | |
| 1240 | + | |
| 1241 | +static int aw88261_i2c_probe(struct i2c_client *i2c) | |
| 1242 | +{ | |
| 1243 | + struct aw88261 *aw88261; | |
| 1244 | + int ret; | |
| 1245 | + | |
| 1246 | + ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C); | |
| 1247 | + if (!ret) | |
| 1248 | + return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed"); | |
| 1249 | + | |
| 1250 | + aw88261 = devm_kzalloc(&i2c->dev, sizeof(*aw88261), GFP_KERNEL); | |
| 1251 | + if (!aw88261) | |
| 1252 | + return -ENOMEM; | |
| 1253 | + | |
| 1254 | + mutex_init(&aw88261->lock); | |
| 1255 | + | |
| 1256 | + i2c_set_clientdata(i2c, aw88261); | |
| 1257 | + | |
| 1258 | + aw88261->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_LOW); | |
| 1259 | + if (IS_ERR(aw88261->reset_gpio)) | |
| 1260 | + dev_info(&i2c->dev, "reset gpio not defined\n"); | |
| 1261 | + else | |
| 1262 | + aw88261_hw_reset(aw88261); | |
| 1263 | + | |
| 1264 | + aw88261->regmap = devm_regmap_init_i2c(i2c, &aw88261_remap_config); | |
| 1265 | + if (IS_ERR(aw88261->regmap)) { | |
| 1266 | + ret = PTR_ERR(aw88261->regmap); | |
| 1267 | + return dev_err_probe(&i2c->dev, ret, "failed to init regmap: %d\n", ret); | |
| 1268 | + } | |
| 1269 | + | |
| 1270 | + /* aw pa init */ | |
| 1271 | + ret = aw88261_init(&aw88261, i2c, aw88261->regmap); | |
| 1272 | + if (ret) | |
| 1273 | + return ret; | |
| 1274 | + | |
| 1275 | + ret = devm_snd_soc_register_component(&i2c->dev, | |
| 1276 | + &soc_codec_dev_aw88261, | |
| 1277 | + aw88261_dai, ARRAY_SIZE(aw88261_dai)); | |
| 1278 | + if (ret) | |
| 1279 | + dev_err(&i2c->dev, "failed to register aw88261: %d", ret); | |
| 1280 | + | |
| 1281 | + return ret; | |
| 1282 | +} | |
| 1283 | + | |
| 1284 | +static const struct i2c_device_id aw88261_i2c_id[] = { | |
| 1285 | + { AW88261_I2C_NAME, 0 }, | |
| 1286 | + { } | |
| 1287 | +}; | |
| 1288 | +MODULE_DEVICE_TABLE(i2c, aw88261_i2c_id); | |
| 1289 | + | |
| 1290 | +static struct i2c_driver aw88261_i2c_driver = { | |
| 1291 | + .driver = { | |
| 1292 | + .name = AW88261_I2C_NAME, | |
| 1293 | + }, | |
| 1294 | + .probe = aw88261_i2c_probe, | |
| 1295 | + .id_table = aw88261_i2c_id, | |
| 1296 | +}; | |
| 1297 | +module_i2c_driver(aw88261_i2c_driver); | |
| 1298 | + | |
| 1299 | +MODULE_DESCRIPTION("ASoC AW88261 Smart PA Driver"); | |
| 1300 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,459 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +// | |
| 3 | +// aw88261.h -- AW88261 ALSA SoC Audio driver | |
| 4 | +// | |
| 5 | +// Copyright (c) 2023 awinic Technology CO., LTD | |
| 6 | +// | |
| 7 | +// Author: Jimmy Zhang <zhangjianming@awinic.com> | |
| 8 | +// Author: Weidong Wang <wangweidong.a@awinic.com> | |
| 9 | +// | |
| 10 | + | |
| 11 | +#ifndef __AW88261_H__ | |
| 12 | +#define __AW88261_H__ | |
| 13 | + | |
| 14 | +#define AW88261_ID_REG (0x00) | |
| 15 | +#define AW88261_SYSST_REG (0x01) | |
| 16 | +#define AW88261_SYSINT_REG (0x02) | |
| 17 | +#define AW88261_SYSINTM_REG (0x03) | |
| 18 | +#define AW88261_SYSCTRL_REG (0x04) | |
| 19 | +#define AW88261_SYSCTRL2_REG (0x05) | |
| 20 | +#define AW88261_I2SCTRL1_REG (0x06) | |
| 21 | +#define AW88261_I2SCTRL2_REG (0x07) | |
| 22 | +#define AW88261_I2SCTRL3_REG (0x08) | |
| 23 | +#define AW88261_DACCFG1_REG (0x09) | |
| 24 | +#define AW88261_DACCFG2_REG (0x0A) | |
| 25 | +#define AW88261_DACCFG3_REG (0x0B) | |
| 26 | +#define AW88261_DACCFG4_REG (0x0C) | |
| 27 | +#define AW88261_DACCFG5_REG (0x0D) | |
| 28 | +#define AW88261_DACCFG6_REG (0x0E) | |
| 29 | +#define AW88261_DACCFG7_REG (0x0F) | |
| 30 | +#define AW88261_DACCFG8_REG (0x10) | |
| 31 | +#define AW88261_PWMCTRL1_REG (0x11) | |
| 32 | +#define AW88261_PWMCTRL2_REG (0x12) | |
| 33 | +#define AW88261_I2SCFG1_REG (0x13) | |
| 34 | +#define AW88261_DBGCTRL_REG (0x14) | |
| 35 | +#define AW88261_DACCFG9_REG (0x15) | |
| 36 | +#define AW88261_DACCFG10_REG (0x16) | |
| 37 | +#define AW88261_DACST_REG (0x20) | |
| 38 | +#define AW88261_VBAT_REG (0x21) | |
| 39 | +#define AW88261_TEMP_REG (0x22) | |
| 40 | +#define AW88261_PVDD_REG (0x23) | |
| 41 | +#define AW88261_ISNDAT_REG (0x24) | |
| 42 | +#define AW88261_VSNDAT_REG (0x25) | |
| 43 | +#define AW88261_I2SINT_REG (0x26) | |
| 44 | +#define AW88261_I2SCAPCNT_REG (0x27) | |
| 45 | +#define AW88261_ANASTA1_REG (0x28) | |
| 46 | +#define AW88261_ANASTA2_REG (0x29) | |
| 47 | +#define AW88261_ANASTA3_REG (0x2A) | |
| 48 | +#define AW88261_TESTDET_REG (0x2B) | |
| 49 | +#define AW88261_DSMCFG1_REG (0x30) | |
| 50 | +#define AW88261_DSMCFG2_REG (0x31) | |
| 51 | +#define AW88261_DSMCFG3_REG (0x32) | |
| 52 | +#define AW88261_DSMCFG4_REG (0x33) | |
| 53 | +#define AW88261_DSMCFG5_REG (0x34) | |
| 54 | +#define AW88261_DSMCFG6_REG (0x35) | |
| 55 | +#define AW88261_DSMCFG7_REG (0x36) | |
| 56 | +#define AW88261_DSMCFG8_REG (0x37) | |
| 57 | +#define AW88261_TESTIN_REG (0x38) | |
| 58 | +#define AW88261_TESTOUT_REG (0x39) | |
| 59 | +#define AW88261_SADCCTRL1_REG (0x3A) | |
| 60 | +#define AW88261_SADCCTRL2_REG (0x3B) | |
| 61 | +#define AW88261_SADCCTRL3_REG (0x3C) | |
| 62 | +#define AW88261_SADCCTRL4_REG (0x3D) | |
| 63 | +#define AW88261_SADCCTRL5_REG (0x3E) | |
| 64 | +#define AW88261_SADCCTRL6_REG (0x3F) | |
| 65 | +#define AW88261_SADCCTRL7_REG (0x40) | |
| 66 | +#define AW88261_VSNTM1_REG (0x50) | |
| 67 | +#define AW88261_VSNTM2_REG (0x51) | |
| 68 | +#define AW88261_ISNCTRL1_REG (0x52) | |
| 69 | +#define AW88261_ISNCTRL2_REG (0x53) | |
| 70 | +#define AW88261_PLLCTRL1_REG (0x54) | |
| 71 | +#define AW88261_PLLCTRL2_REG (0x55) | |
| 72 | +#define AW88261_PLLCTRL3_REG (0x56) | |
| 73 | +#define AW88261_CDACTRL1_REG (0x57) | |
| 74 | +#define AW88261_CDACTRL2_REG (0x58) | |
| 75 | +#define AW88261_DITHERCFG1_REG (0x59) | |
| 76 | +#define AW88261_DITHERCFG2_REG (0x5A) | |
| 77 | +#define AW88261_DITHERCFG3_REG (0x5B) | |
| 78 | +#define AW88261_CPCTRL_REG (0x5C) | |
| 79 | +#define AW88261_BSTCTRL1_REG (0x60) | |
| 80 | +#define AW88261_BSTCTRL2_REG (0x61) | |
| 81 | +#define AW88261_BSTCTRL3_REG (0x62) | |
| 82 | +#define AW88261_BSTCTRL4_REG (0x63) | |
| 83 | +#define AW88261_BSTCTRL5_REG (0x64) | |
| 84 | +#define AW88261_BSTCTRL6_REG (0x65) | |
| 85 | +#define AW88261_BSTCTRL7_REG (0x66) | |
| 86 | +#define AW88261_BSTCTRL8_REG (0x67) | |
| 87 | +#define AW88261_BSTCTRL9_REG (0x68) | |
| 88 | +#define AW88261_TM_REG (0x6F) | |
| 89 | +#define AW88261_TESTCTRL1_REG (0x70) | |
| 90 | +#define AW88261_TESTCTRL2_REG (0x71) | |
| 91 | +#define AW88261_EFCTRL1_REG (0x72) | |
| 92 | +#define AW88261_EFCTRL2_REG (0x73) | |
| 93 | +#define AW88261_EFWH_REG (0x74) | |
| 94 | +#define AW88261_EFWM2_REG (0x75) | |
| 95 | +#define AW88261_EFWM1_REG (0x76) | |
| 96 | +#define AW88261_EFWL_REG (0x77) | |
| 97 | +#define AW88261_EFRH4_REG (0x78) | |
| 98 | +#define AW88261_EFRH3_REG (0x79) | |
| 99 | +#define AW88261_EFRH2_REG (0x7A) | |
| 100 | +#define AW88261_EFRH1_REG (0x7B) | |
| 101 | +#define AW88261_EFRL4_REG (0x7C) | |
| 102 | +#define AW88261_EFRL3_REG (0x7D) | |
| 103 | +#define AW88261_EFRL2_REG (0x7E) | |
| 104 | +#define AW88261_EFRL1_REG (0x7F) | |
| 105 | + | |
| 106 | +#define AW88261_REG_MAX (0x80) | |
| 107 | +#define AW88261_EF_DBMD_MASK (0xfff7) | |
| 108 | +#define AW88261_OR_VALUE (0x0008) | |
| 109 | + | |
| 110 | +#define AW88261_TEMH_MASK (0x83ff) | |
| 111 | +#define AW88261_TEML_MASK (0x83ff) | |
| 112 | +#define AW88261_DEFAULT_CFG (0x0000) | |
| 113 | + | |
| 114 | +#define AW88261_ICALK_SHIFT (0) | |
| 115 | +#define AW88261_ICALKL_SHIFT (0) | |
| 116 | +#define AW88261_VCALK_SHIFT (0) | |
| 117 | +#define AW88261_VCALKL_SHIFT (0) | |
| 118 | + | |
| 119 | +#define AW88261_AMPPD_START_BIT (1) | |
| 120 | +#define AW88261_AMPPD_BITS_LEN (1) | |
| 121 | +#define AW88261_AMPPD_MASK \ | |
| 122 | + (~(((1<<AW88261_AMPPD_BITS_LEN)-1) << AW88261_AMPPD_START_BIT)) | |
| 123 | + | |
| 124 | +#define AW88261_UVLS_START_BIT (14) | |
| 125 | +#define AW88261_UVLS_NORMAL (0) | |
| 126 | +#define AW88261_UVLS_NORMAL_VALUE \ | |
| 127 | + (AW88261_UVLS_NORMAL << AW88261_UVLS_START_BIT) | |
| 128 | + | |
| 129 | +#define AW88261_BSTOCS_START_BIT (11) | |
| 130 | +#define AW88261_BSTOCS_OVER_CURRENT (1) | |
| 131 | +#define AW88261_BSTOCS_OVER_CURRENT_VALUE \ | |
| 132 | + (AW88261_BSTOCS_OVER_CURRENT << AW88261_BSTOCS_START_BIT) | |
| 133 | + | |
| 134 | +#define AW88261_BSTS_START_BIT (9) | |
| 135 | +#define AW88261_BSTS_FINISHED (1) | |
| 136 | +#define AW88261_BSTS_FINISHED_VALUE \ | |
| 137 | + (AW88261_BSTS_FINISHED << AW88261_BSTS_START_BIT) | |
| 138 | + | |
| 139 | +#define AW88261_SWS_START_BIT (8) | |
| 140 | +#define AW88261_SWS_SWITCHING (1) | |
| 141 | +#define AW88261_SWS_SWITCHING_VALUE \ | |
| 142 | + (AW88261_SWS_SWITCHING << AW88261_SWS_START_BIT) | |
| 143 | + | |
| 144 | +#define AW88261_NOCLKS_START_BIT (5) | |
| 145 | +#define AW88261_NOCLKS_NO_CLOCK (1) | |
| 146 | +#define AW88261_NOCLKS_NO_CLOCK_VALUE \ | |
| 147 | + (AW88261_NOCLKS_NO_CLOCK << AW88261_NOCLKS_START_BIT) | |
| 148 | + | |
| 149 | +#define AW88261_CLKS_START_BIT (4) | |
| 150 | +#define AW88261_CLKS_STABLE (1) | |
| 151 | +#define AW88261_CLKS_STABLE_VALUE \ | |
| 152 | + (AW88261_CLKS_STABLE << AW88261_CLKS_START_BIT) | |
| 153 | + | |
| 154 | +#define AW88261_OCDS_START_BIT (3) | |
| 155 | +#define AW88261_OCDS_OC (1) | |
| 156 | +#define AW88261_OCDS_OC_VALUE \ | |
| 157 | + (AW88261_OCDS_OC << AW88261_OCDS_START_BIT) | |
| 158 | + | |
| 159 | +#define AW88261_OTHS_START_BIT (1) | |
| 160 | +#define AW88261_OTHS_OT (1) | |
| 161 | +#define AW88261_OTHS_OT_VALUE \ | |
| 162 | + (AW88261_OTHS_OT << AW88261_OTHS_START_BIT) | |
| 163 | + | |
| 164 | +#define AW88261_PLLS_START_BIT (0) | |
| 165 | +#define AW88261_PLLS_LOCKED (1) | |
| 166 | +#define AW88261_PLLS_LOCKED_VALUE \ | |
| 167 | + (AW88261_PLLS_LOCKED << AW88261_PLLS_START_BIT) | |
| 168 | + | |
| 169 | +#define AW88261_BIT_PLL_CHECK \ | |
| 170 | + (AW88261_CLKS_STABLE_VALUE | \ | |
| 171 | + AW88261_PLLS_LOCKED_VALUE) | |
| 172 | + | |
| 173 | +#define AW88261_BIT_SYSST_CHECK_MASK \ | |
| 174 | + (~(AW88261_UVLS_NORMAL_VALUE | \ | |
| 175 | + AW88261_BSTOCS_OVER_CURRENT_VALUE | \ | |
| 176 | + AW88261_BSTS_FINISHED_VALUE | \ | |
| 177 | + AW88261_SWS_SWITCHING_VALUE | \ | |
| 178 | + AW88261_NOCLKS_NO_CLOCK_VALUE | \ | |
| 179 | + AW88261_CLKS_STABLE_VALUE | \ | |
| 180 | + AW88261_OCDS_OC_VALUE | \ | |
| 181 | + AW88261_OTHS_OT_VALUE | \ | |
| 182 | + AW88261_PLLS_LOCKED_VALUE)) | |
| 183 | + | |
| 184 | +#define AW88261_BIT_SYSST_CHECK \ | |
| 185 | + (AW88261_BSTS_FINISHED_VALUE | \ | |
| 186 | + AW88261_SWS_SWITCHING_VALUE | \ | |
| 187 | + AW88261_CLKS_STABLE_VALUE | \ | |
| 188 | + AW88261_PLLS_LOCKED_VALUE) | |
| 189 | + | |
| 190 | +#define AW88261_ULS_HMUTE_START_BIT (14) | |
| 191 | +#define AW88261_ULS_HMUTE_BITS_LEN (1) | |
| 192 | +#define AW88261_ULS_HMUTE_MASK \ | |
| 193 | + (~(((1<<AW88261_ULS_HMUTE_BITS_LEN)-1) << AW88261_ULS_HMUTE_START_BIT)) | |
| 194 | + | |
| 195 | +#define AW88261_ULS_HMUTE_DISABLE (0) | |
| 196 | +#define AW88261_ULS_HMUTE_DISABLE_VALUE \ | |
| 197 | + (AW88261_ULS_HMUTE_DISABLE << AW88261_ULS_HMUTE_START_BIT) | |
| 198 | + | |
| 199 | +#define AW88261_ULS_HMUTE_ENABLE (1) | |
| 200 | +#define AW88261_ULS_HMUTE_ENABLE_VALUE \ | |
| 201 | + (AW88261_ULS_HMUTE_ENABLE << AW88261_ULS_HMUTE_START_BIT) | |
| 202 | + | |
| 203 | +#define AW88261_HMUTE_START_BIT (8) | |
| 204 | +#define AW88261_HMUTE_BITS_LEN (1) | |
| 205 | +#define AW88261_HMUTE_MASK \ | |
| 206 | + (~(((1<<AW88261_HMUTE_BITS_LEN)-1) << AW88261_HMUTE_START_BIT)) | |
| 207 | + | |
| 208 | +#define AW88261_HMUTE_DISABLE (0) | |
| 209 | +#define AW88261_HMUTE_DISABLE_VALUE \ | |
| 210 | + (AW88261_HMUTE_DISABLE << AW88261_HMUTE_START_BIT) | |
| 211 | + | |
| 212 | +#define AW88261_HMUTE_ENABLE (1) | |
| 213 | +#define AW88261_HMUTE_ENABLE_VALUE \ | |
| 214 | + (AW88261_HMUTE_ENABLE << AW88261_HMUTE_START_BIT) | |
| 215 | + | |
| 216 | +#define AW88261_AMPPD_START_BIT (1) | |
| 217 | +#define AW88261_AMPPD_BITS_LEN (1) | |
| 218 | +#define AW88261_AMPPD_MASK \ | |
| 219 | + (~(((1<<AW88261_AMPPD_BITS_LEN)-1) << AW88261_AMPPD_START_BIT)) | |
| 220 | + | |
| 221 | +#define AW88261_AMPPD_WORKING (0) | |
| 222 | +#define AW88261_AMPPD_WORKING_VALUE \ | |
| 223 | + (AW88261_AMPPD_WORKING << AW88261_AMPPD_START_BIT) | |
| 224 | + | |
| 225 | +#define AW88261_AMPPD_POWER_DOWN (1) | |
| 226 | +#define AW88261_AMPPD_POWER_DOWN_VALUE \ | |
| 227 | + (AW88261_AMPPD_POWER_DOWN << AW88261_AMPPD_START_BIT) | |
| 228 | + | |
| 229 | +#define AW88261_PWDN_START_BIT (0) | |
| 230 | +#define AW88261_PWDN_BITS_LEN (1) | |
| 231 | +#define AW88261_PWDN_MASK \ | |
| 232 | + (~(((1<<AW88261_PWDN_BITS_LEN)-1) << AW88261_PWDN_START_BIT)) | |
| 233 | + | |
| 234 | +#define AW88261_PWDN_WORKING (0) | |
| 235 | +#define AW88261_PWDN_WORKING_VALUE \ | |
| 236 | + (AW88261_PWDN_WORKING << AW88261_PWDN_START_BIT) | |
| 237 | + | |
| 238 | +#define AW88261_PWDN_POWER_DOWN (1) | |
| 239 | +#define AW88261_PWDN_POWER_DOWN_VALUE \ | |
| 240 | + (AW88261_PWDN_POWER_DOWN << AW88261_PWDN_START_BIT) | |
| 241 | + | |
| 242 | +#define AW88261_MUTE_VOL (90 * 8) | |
| 243 | +#define AW88261_VOLUME_STEP_DB (6 * 8) | |
| 244 | + | |
| 245 | +#define AW88261_VOL_6DB_START (6) | |
| 246 | + | |
| 247 | +#define AW88261_VOL_START_BIT (0) | |
| 248 | +#define AW88261_VOL_BITS_LEN (10) | |
| 249 | +#define AW88261_VOL_MASK \ | |
| 250 | + (~(((1<<AW88261_VOL_BITS_LEN)-1) << AW88261_VOL_START_BIT)) | |
| 251 | + | |
| 252 | +#define AW88261_VOL_DEFAULT_VALUE (0) | |
| 253 | + | |
| 254 | +#define AW88261_I2STXEN_START_BIT (6) | |
| 255 | +#define AW88261_I2STXEN_BITS_LEN (1) | |
| 256 | +#define AW88261_I2STXEN_MASK \ | |
| 257 | + (~(((1<<AW88261_I2STXEN_BITS_LEN)-1) << AW88261_I2STXEN_START_BIT)) | |
| 258 | + | |
| 259 | +#define AW88261_I2STXEN_DISABLE (0) | |
| 260 | +#define AW88261_I2STXEN_DISABLE_VALUE \ | |
| 261 | + (AW88261_I2STXEN_DISABLE << AW88261_I2STXEN_START_BIT) | |
| 262 | + | |
| 263 | +#define AW88261_I2STXEN_ENABLE (1) | |
| 264 | +#define AW88261_I2STXEN_ENABLE_VALUE \ | |
| 265 | + (AW88261_I2STXEN_ENABLE << AW88261_I2STXEN_START_BIT) | |
| 266 | + | |
| 267 | +#define AW88261_CCO_MUX_START_BIT (14) | |
| 268 | +#define AW88261_CCO_MUX_BITS_LEN (1) | |
| 269 | +#define AW88261_CCO_MUX_MASK \ | |
| 270 | + (~(((1<<AW88261_CCO_MUX_BITS_LEN)-1) << AW88261_CCO_MUX_START_BIT)) | |
| 271 | + | |
| 272 | +#define AW88261_CCO_MUX_DIVIDED (0) | |
| 273 | +#define AW88261_CCO_MUX_DIVIDED_VALUE \ | |
| 274 | + (AW88261_CCO_MUX_DIVIDED << AW88261_CCO_MUX_START_BIT) | |
| 275 | + | |
| 276 | +#define AW88261_CCO_MUX_BYPASS (1) | |
| 277 | +#define AW88261_CCO_MUX_BYPASS_VALUE \ | |
| 278 | + (AW88261_CCO_MUX_BYPASS << AW88261_CCO_MUX_START_BIT) | |
| 279 | + | |
| 280 | +#define AW88261_EF_VSN_GESLP_H_START_BIT (0) | |
| 281 | +#define AW88261_EF_VSN_GESLP_H_BITS_LEN (10) | |
| 282 | +#define AW88261_EF_VSN_GESLP_H_MASK \ | |
| 283 | + (~(((1<<AW88261_EF_VSN_GESLP_H_BITS_LEN)-1) << AW88261_EF_VSN_GESLP_H_START_BIT)) | |
| 284 | + | |
| 285 | +#define AW88261_EF_VSN_GESLP_L_START_BIT (0) | |
| 286 | +#define AW88261_EF_VSN_GESLP_L_BITS_LEN (10) | |
| 287 | +#define AW88261_EF_VSN_GESLP_L_MASK \ | |
| 288 | + (~(((1<<AW88261_EF_VSN_GESLP_L_BITS_LEN)-1) << AW88261_EF_VSN_GESLP_L_START_BIT)) | |
| 289 | + | |
| 290 | +#define AW88261_FORCE_PWM_START_BIT (12) | |
| 291 | +#define AW88261_FORCE_PWM_BITS_LEN (1) | |
| 292 | +#define AW88261_FORCE_PWM_MASK \ | |
| 293 | + (~(((1<<AW88261_FORCE_PWM_BITS_LEN)-1) << AW88261_FORCE_PWM_START_BIT)) | |
| 294 | + | |
| 295 | +#define AW88261_FORCE_PWM_FORCEMINUS_PWM (1) | |
| 296 | +#define AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE \ | |
| 297 | + (AW88261_FORCE_PWM_FORCEMINUS_PWM << AW88261_FORCE_PWM_START_BIT) | |
| 298 | + | |
| 299 | +#define AW88261_BST_OS_WIDTH_START_BIT (0) | |
| 300 | +#define AW88261_BST_OS_WIDTH_BITS_LEN (3) | |
| 301 | +#define AW88261_BST_OS_WIDTH_MASK \ | |
| 302 | + (~(((1<<AW88261_BST_OS_WIDTH_BITS_LEN)-1) << AW88261_BST_OS_WIDTH_START_BIT)) | |
| 303 | + | |
| 304 | +#define AW88261_BST_OS_WIDTH_50NS (4) | |
| 305 | +#define AW88261_BST_OS_WIDTH_50NS_VALUE \ | |
| 306 | + (AW88261_BST_OS_WIDTH_50NS << AW88261_BST_OS_WIDTH_START_BIT) | |
| 307 | + | |
| 308 | +/* BST_LOOPR bit 1:0 (BSTCTRL6 0x65) */ | |
| 309 | +#define AW88261_BST_LOOPR_START_BIT (0) | |
| 310 | +#define AW88261_BST_LOOPR_BITS_LEN (2) | |
| 311 | +#define AW88261_BST_LOOPR_MASK \ | |
| 312 | + (~(((1<<AW88261_BST_LOOPR_BITS_LEN)-1) << AW88261_BST_LOOPR_START_BIT)) | |
| 313 | + | |
| 314 | +#define AW88261_BST_LOOPR_340K (2) | |
| 315 | +#define AW88261_BST_LOOPR_340K_VALUE \ | |
| 316 | + (AW88261_BST_LOOPR_340K << AW88261_BST_LOOPR_START_BIT) | |
| 317 | + | |
| 318 | +/* RSQN_DLY bit 15:14 (BSTCTRL7 0x66) */ | |
| 319 | +#define AW88261_RSQN_DLY_START_BIT (14) | |
| 320 | +#define AW88261_RSQN_DLY_BITS_LEN (2) | |
| 321 | +#define AW88261_RSQN_DLY_MASK \ | |
| 322 | + (~(((1<<AW88261_RSQN_DLY_BITS_LEN)-1) << AW88261_RSQN_DLY_START_BIT)) | |
| 323 | + | |
| 324 | +#define AW88261_RSQN_DLY_35NS (2) | |
| 325 | +#define AW88261_RSQN_DLY_35NS_VALUE \ | |
| 326 | + (AW88261_RSQN_DLY_35NS << AW88261_RSQN_DLY_START_BIT) | |
| 327 | + | |
| 328 | +/* BURST_SSMODE bit 3 (BSTCTRL8 0x67) */ | |
| 329 | +#define AW88261_BURST_SSMODE_START_BIT (3) | |
| 330 | +#define AW88261_BURST_SSMODE_BITS_LEN (1) | |
| 331 | +#define AW88261_BURST_SSMODE_MASK \ | |
| 332 | + (~(((1<<AW88261_BURST_SSMODE_BITS_LEN)-1) << AW88261_BURST_SSMODE_START_BIT)) | |
| 333 | + | |
| 334 | +#define AW88261_BURST_SSMODE_FAST (0) | |
| 335 | +#define AW88261_BURST_SSMODE_FAST_VALUE \ | |
| 336 | + (AW88261_BURST_SSMODE_FAST << AW88261_BURST_SSMODE_START_BIT) | |
| 337 | + | |
| 338 | +/* BST_BURST bit 9:7 (BSTCTRL9 0x68) */ | |
| 339 | +#define AW88261_BST_BURST_START_BIT (7) | |
| 340 | +#define AW88261_BST_BURST_BITS_LEN (3) | |
| 341 | +#define AW88261_BST_BURST_MASK \ | |
| 342 | + (~(((1<<AW88261_BST_BURST_BITS_LEN)-1) << AW88261_BST_BURST_START_BIT)) | |
| 343 | + | |
| 344 | +#define AW88261_BST_BURST_30MA (2) | |
| 345 | +#define AW88261_BST_BURST_30MA_VALUE \ | |
| 346 | + (AW88261_BST_BURST_30MA << AW88261_BST_BURST_START_BIT) | |
| 347 | + | |
| 348 | +#define AW88261_EF_VSN_GESLP_SIGN_MASK (~0x0200) | |
| 349 | +#define AW88261_EF_VSN_GESLP_NEG (~0xfc00) | |
| 350 | + | |
| 351 | +#define AW88261_EF_ISN_GESLP_SIGN_MASK (~0x0200) | |
| 352 | +#define AW88261_EF_ISN_GESLP_NEG (~0xfc00) | |
| 353 | + | |
| 354 | +#define AW88261_EF_ISN_GESLP_H_START_BIT (0) | |
| 355 | +#define AW88261_EF_ISN_GESLP_H_BITS_LEN (10) | |
| 356 | +#define AW88261_EF_ISN_GESLP_H_MASK \ | |
| 357 | + (~(((1<<AW88261_EF_ISN_GESLP_H_BITS_LEN)-1) << AW88261_EF_ISN_GESLP_H_START_BIT)) | |
| 358 | + | |
| 359 | +#define AW88261_EF_ISN_GESLP_L_START_BIT (0) | |
| 360 | +#define AW88261_EF_ISN_GESLP_L_BITS_LEN (10) | |
| 361 | +#define AW88261_EF_ISN_GESLP_L_MASK \ | |
| 362 | + (~(((1<<AW88261_EF_ISN_GESLP_L_BITS_LEN)-1) << AW88261_EF_ISN_GESLP_L_START_BIT)) | |
| 363 | + | |
| 364 | +#define AW88261_CABL_BASE_VALUE (1000) | |
| 365 | +#define AW88261_ICABLK_FACTOR (1) | |
| 366 | +#define AW88261_VCABLK_FACTOR (1) | |
| 367 | + | |
| 368 | +#define AW88261_VCAL_FACTOR (1<<13) | |
| 369 | + | |
| 370 | +#define AW88261_START_RETRIES (5) | |
| 371 | +#define AW88261_START_WORK_DELAY_MS (0) | |
| 372 | + | |
| 373 | +#define AW88261_I2C_NAME "aw88261_smartpa" | |
| 374 | + | |
| 375 | +#define AW88261_RATES (SNDRV_PCM_RATE_8000_48000 | \ | |
| 376 | + SNDRV_PCM_RATE_96000) | |
| 377 | +#define AW88261_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | |
| 378 | + SNDRV_PCM_FMTBIT_S24_LE | \ | |
| 379 | + SNDRV_PCM_FMTBIT_S32_LE) | |
| 380 | + | |
| 381 | +#define FADE_TIME_MAX 100000 | |
| 382 | +#define FADE_TIME_MIN 0 | |
| 383 | + | |
| 384 | +#define AW88261_DEV_DEFAULT_CH (0) | |
| 385 | +#define AW88261_ACF_FILE "aw88261_acf.bin" | |
| 386 | +#define AW88261_DEV_SYSST_CHECK_MAX (10) | |
| 387 | +#define AW88261_SOFT_RESET_VALUE (0x55aa) | |
| 388 | +#define AW88261_REG_TO_DB (0x3f) | |
| 389 | +#define AW88261_VOL_START_MASK (0xfc00) | |
| 390 | +#define AW88261_INIT_PROFILE (0) | |
| 391 | + | |
| 392 | +#define REG_VAL_TO_DB(value) ((((value) >> AW88261_VOL_6DB_START) * \ | |
| 393 | + AW88261_VOLUME_STEP_DB) + \ | |
| 394 | + ((value) & AW88261_REG_TO_DB)) | |
| 395 | +#define DB_TO_REG_VAL(value) ((((value) / AW88261_VOLUME_STEP_DB) << \ | |
| 396 | + AW88261_VOL_6DB_START) + \ | |
| 397 | + ((value) % AW88261_VOLUME_STEP_DB)) | |
| 398 | + | |
| 399 | +#define AW88261_PROFILE_EXT(xname, profile_info, profile_get, profile_set) \ | |
| 400 | +{ \ | |
| 401 | + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | |
| 402 | + .name = xname, \ | |
| 403 | + .info = profile_info, \ | |
| 404 | + .get = profile_get, \ | |
| 405 | + .put = profile_set, \ | |
| 406 | +} | |
| 407 | + | |
| 408 | +enum { | |
| 409 | + AW88261_SYNC_START = 0, | |
| 410 | + AW88261_ASYNC_START, | |
| 411 | +}; | |
| 412 | + | |
| 413 | +enum aw88261_id { | |
| 414 | + AW88261_CHIP_ID = 0x2113, | |
| 415 | +}; | |
| 416 | + | |
| 417 | +enum { | |
| 418 | + AW88261_500_US = 500, | |
| 419 | + AW88261_1000_US = 1000, | |
| 420 | + AW88261_2000_US = 2000, | |
| 421 | +}; | |
| 422 | + | |
| 423 | +enum { | |
| 424 | + AW88261_DEV_PW_OFF = 0, | |
| 425 | + AW88261_DEV_PW_ON, | |
| 426 | +}; | |
| 427 | + | |
| 428 | +enum { | |
| 429 | + AW88261_DEV_FW_FAILED = 0, | |
| 430 | + AW88261_DEV_FW_OK, | |
| 431 | +}; | |
| 432 | + | |
| 433 | +enum { | |
| 434 | + AW88261_EF_AND_CHECK = 0, | |
| 435 | + AW88261_EF_OR_CHECK, | |
| 436 | +}; | |
| 437 | + | |
| 438 | +enum { | |
| 439 | + AW88261_FRCSET_DISABLE = 0, | |
| 440 | + AW88261_FRCSET_ENABLE, | |
| 441 | +}; | |
| 442 | + | |
| 443 | +struct aw88261 { | |
| 444 | + struct aw_device *aw_pa; | |
| 445 | + struct mutex lock; | |
| 446 | + struct gpio_desc *reset_gpio; | |
| 447 | + struct delayed_work start_work; | |
| 448 | + struct regmap *regmap; | |
| 449 | + struct aw_container *aw_cfg; | |
| 450 | + | |
| 451 | + int efuse_check; | |
| 452 | + int frcset_en; | |
| 453 | + unsigned int mute_st; | |
| 454 | + unsigned int amppd_st; | |
| 455 | + | |
| 456 | + unsigned char phase_sync; | |
| 457 | +}; | |
| 458 | + | |
| 459 | +#endif | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/i2c.h> |
| 12 | 12 | #include "aw88395_lib.h" |
| 13 | 13 | #include "aw88395_device.h" |
| 14 | +#include "aw88395_reg.h" | |
| 14 | 15 | |
| 15 | 16 | #define AW88395_CRC8_POLYNOMIAL 0x8C |
| 16 | 17 | DECLARE_CRC8_TABLE(aw_crc8_table); |
| @@ -429,6 +430,53 @@ parse_bin_failed: · 412 unmodified lines | ||
| 429 | 430 | return ret; |
| 430 | 431 | } |
| 431 | 432 | |
| 433 | +static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev, | |
| 434 | + uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc) | |
| 435 | +{ | |
| 436 | + struct aw_bin *aw_bin; | |
| 437 | + int ret; | |
| 438 | + | |
| 439 | + aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(*aw_bin), GFP_KERNEL); | |
| 440 | + if (!aw_bin) | |
| 441 | + return -ENOMEM; | |
| 442 | + | |
| 443 | + aw_bin->info.len = data_len; | |
| 444 | + memcpy(aw_bin->info.data, data, data_len); | |
| 445 | + | |
| 446 | + ret = aw_parsing_bin_file(aw_dev, aw_bin); | |
| 447 | + if (ret < 0) { | |
| 448 | + dev_err(aw_dev->dev, "parse bin failed"); | |
| 449 | + goto parse_bin_failed; | |
| 450 | + } | |
| 451 | + | |
| 452 | + if ((aw_bin->all_bin_parse_num != 1) || | |
| 453 | + (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) { | |
| 454 | + dev_err(aw_dev->dev, "bin num or type error"); | |
| 455 | + goto parse_bin_failed; | |
| 456 | + } | |
| 457 | + | |
| 458 | + if (aw_bin->header_info[0].valid_data_len % 4) { | |
| 459 | + dev_err(aw_dev->dev, "bin data len get error!"); | |
| 460 | + goto parse_bin_failed; | |
| 461 | + } | |
| 462 | + | |
| 463 | + prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = | |
| 464 | + data + aw_bin->header_info[0].valid_data_addr; | |
| 465 | + prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len = | |
| 466 | + aw_bin->header_info[0].valid_data_len; | |
| 467 | + prof_desc->prof_st = AW88395_PROFILE_OK; | |
| 468 | + | |
| 469 | + devm_kfree(aw_dev->dev, aw_bin); | |
| 470 | + aw_bin = NULL; | |
| 471 | + | |
| 472 | + return 0; | |
| 473 | + | |
| 474 | +parse_bin_failed: | |
| 475 | + devm_kfree(aw_dev->dev, aw_bin); | |
| 476 | + aw_bin = NULL; | |
| 477 | + return ret; | |
| 478 | +} | |
| 479 | + | |
| 432 | 480 | static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg_hdr *cfg_hdr, |
| 433 | 481 | struct aw_cfg_dde *cfg_dde, struct aw_prof_desc *scene_prof_desc) |
| 434 | 482 | { |
| @@ -447,6 +495,9 @@ static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg · 12 unmodified lines | ||
| 447 | 495 | return aw_dev_prof_parse_multi_bin( |
| 448 | 496 | aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset, |
| 449 | 497 | cfg_dde->data_size, scene_prof_desc); |
| 498 | + case ACF_SEC_TYPE_HDR_REG: | |
| 499 | + return aw_dev_parse_reg_bin_with_hdr(aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset, | |
| 500 | + cfg_dde->data_size, scene_prof_desc); | |
| 450 | 501 | default: |
| 451 | 502 | dev_err(aw_dev->dev, "%s cfg_dde->data_type = %d\n", __func__, cfg_dde->data_type); |
| 452 | 503 | break; |
| @@ -527,7 +578,49 @@ static int aw_dev_parse_dev_default_type(struct aw_device *aw_dev, · 74 unmodified lines | ||
| 527 | 578 | return 0; |
| 528 | 579 | } |
| 529 | 580 | |
| 530 | −static int aw_dev_cfg_get_valid_prof(struct aw_device *aw_dev, | |
| 581 | +static int aw88261_dev_cfg_get_valid_prof(struct aw_device *aw_dev, | |
| 582 | + struct aw_all_prof_info all_prof_info) | |
| 583 | +{ | |
| 584 | + struct aw_prof_desc *prof_desc = all_prof_info.prof_desc; | |
| 585 | + struct aw_prof_info *prof_info = &aw_dev->prof_info; | |
| 586 | + int num = 0; | |
| 587 | + int i; | |
| 588 | + | |
| 589 | + for (i = 0; i < AW88395_PROFILE_MAX; i++) { | |
| 590 | + if (prof_desc[i].prof_st == AW88395_PROFILE_OK) | |
| 591 | + prof_info->count++; | |
| 592 | + } | |
| 593 | + | |
| 594 | + dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count); | |
| 595 | + | |
| 596 | + if (!prof_info->count) { | |
| 597 | + dev_err(aw_dev->dev, "no profile data"); | |
| 598 | + return -EPERM; | |
| 599 | + } | |
| 600 | + | |
| 601 | + prof_info->prof_desc = devm_kcalloc(aw_dev->dev, | |
| 602 | + prof_info->count, sizeof(struct aw_prof_desc), | |
| 603 | + GFP_KERNEL); | |
| 604 | + if (!prof_info->prof_desc) | |
| 605 | + return -ENOMEM; | |
| 606 | + | |
| 607 | + for (i = 0; i < AW88395_PROFILE_MAX; i++) { | |
| 608 | + if (prof_desc[i].prof_st == AW88395_PROFILE_OK) { | |
| 609 | + if (num >= prof_info->count) { | |
| 610 | + dev_err(aw_dev->dev, "overflow count[%d]", | |
| 611 | + prof_info->count); | |
| 612 | + return -EINVAL; | |
| 613 | + } | |
| 614 | + prof_info->prof_desc[num] = prof_desc[i]; | |
| 615 | + prof_info->prof_desc[num].id = i; | |
| 616 | + num++; | |
| 617 | + } | |
| 618 | + } | |
| 619 | + | |
| 620 | + return 0; | |
| 621 | +} | |
| 622 | + | |
| 623 | +static int aw88395_dev_cfg_get_valid_prof(struct aw_device *aw_dev, | |
| 531 | 624 | struct aw_all_prof_info all_prof_info) |
| 532 | 625 | { |
| 533 | 626 | struct aw_prof_desc *prof_desc = all_prof_info.prof_desc; |
| @@ -606,9 +699,22 @@ static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev, · 72 unmodified lines | ||
| 606 | 699 | goto exit; |
| 607 | 700 | } |
| 608 | 701 | |
| 609 | − ret = aw_dev_cfg_get_valid_prof(aw_dev, *all_prof_info); | |
| 610 | − if (ret < 0) | |
| 611 | − goto exit; | |
| 702 | + switch (aw_dev->chip_id) { | |
| 703 | + case AW88395_CHIP_ID: | |
| 704 | + ret = aw88395_dev_cfg_get_valid_prof(aw_dev, *all_prof_info); | |
| 705 | + if (ret < 0) | |
| 706 | + goto exit; | |
| 707 | + break; | |
| 708 | + case AW88261_CHIP_ID: | |
| 709 | + ret = aw88261_dev_cfg_get_valid_prof(aw_dev, *all_prof_info); | |
| 710 | + if (ret < 0) | |
| 711 | + goto exit; | |
| 712 | + break; | |
| 713 | + default: | |
| 714 | + dev_err(aw_dev->dev, "valid prof unsupported"); | |
| 715 | + ret = -EINVAL; | |
| 716 | + break; | |
| 717 | + } | |
| 612 | 718 | |
| 613 | 719 | aw_dev->prof_info.prof_name_list = profile_name; |
| 614 | 720 | |
| @@ -679,16 +785,37 @@ static int aw_get_dev_scene_count_v1(struct aw_device *aw_dev, struct aw_contain · 64 unmodified lines | ||
| 679 | 785 | struct aw_cfg_dde_v1 *cfg_dde = |
| 680 | 786 | (struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset); |
| 681 | 787 | unsigned int i; |
| 788 | + int ret; | |
| 682 | 789 | |
| 683 | − for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 684 | − if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && | |
| 685 | − (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 686 | − (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && | |
| 687 | − (aw_dev->i2c->addr == cfg_dde[i].dev_addr)) | |
| 688 | − (*scene_num)++; | |
| 790 | + switch (aw_dev->chip_id) { | |
| 791 | + case AW88395_CHIP_ID: | |
| 792 | + for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 793 | + if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && | |
| 794 | + (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 795 | + (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && | |
| 796 | + (aw_dev->i2c->addr == cfg_dde[i].dev_addr)) | |
| 797 | + (*scene_num)++; | |
| 798 | + } | |
| 799 | + ret = 0; | |
| 800 | + break; | |
| 801 | + case AW88261_CHIP_ID: | |
| 802 | + for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 803 | + if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) || | |
| 804 | + (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) && | |
| 805 | + (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 806 | + (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && | |
| 807 | + (aw_dev->i2c->addr == cfg_dde[i].dev_addr)) | |
| 808 | + (*scene_num)++; | |
| 809 | + } | |
| 810 | + ret = 0; | |
| 811 | + break; | |
| 812 | + default: | |
| 813 | + dev_err(aw_dev->dev, "unsupported device"); | |
| 814 | + ret = -EINVAL; | |
| 815 | + break; | |
| 689 | 816 | } |
| 690 | 817 | |
| 691 | − return 0; | |
| 818 | + return ret; | |
| 692 | 819 | } |
| 693 | 820 | |
| 694 | 821 | static int aw_get_default_scene_count_v1(struct aw_device *aw_dev, |
| @@ -699,15 +826,35 @@ static int aw_get_default_scene_count_v1(struct aw_device *aw_dev, · 4 unmodified lines | ||
| 699 | 826 | struct aw_cfg_dde_v1 *cfg_dde = |
| 700 | 827 | (struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset); |
| 701 | 828 | unsigned int i; |
| 829 | + int ret; | |
| 702 | 830 | |
| 703 | − for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 704 | − if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && | |
| 705 | − (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 706 | − (aw_dev->channel == cfg_dde[i].dev_index)) | |
| 707 | − (*scene_num)++; | |
| 831 | + switch (aw_dev->chip_id) { | |
| 832 | + case AW88395_CHIP_ID: | |
| 833 | + for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 834 | + if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && | |
| 835 | + (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 836 | + (aw_dev->channel == cfg_dde[i].dev_index)) | |
| 837 | + (*scene_num)++; | |
| 838 | + } | |
| 839 | + ret = 0; | |
| 840 | + break; | |
| 841 | + case AW88261_CHIP_ID: | |
| 842 | + for (i = 0; i < cfg_hdr->ddt_num; ++i) { | |
| 843 | + if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) || | |
| 844 | + (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) && | |
| 845 | + (aw_dev->chip_id == cfg_dde[i].chip_id) && | |
| 846 | + (aw_dev->channel == cfg_dde[i].dev_index)) | |
| 847 | + (*scene_num)++; | |
| 848 | + } | |
| 849 | + ret = 0; | |
| 850 | + break; | |
| 851 | + default: | |
| 852 | + dev_err(aw_dev->dev, "unsupported device"); | |
| 853 | + ret = -EINVAL; | |
| 854 | + break; | |
| 708 | 855 | } |
| 709 | 856 | |
| 710 | − return 0; | |
| 857 | + return ret; | |
| 711 | 858 | } |
| 712 | 859 | |
| 713 | 860 | static int aw_dev_parse_scene_count_v1(struct aw_device *aw_dev, |
| @@ -756,6 +903,18 @@ static int aw_dev_parse_data_by_sec_type_v1(struct aw_device *aw_dev, · 42 unmodified lines | ||
| 756 | 903 | prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile; |
| 757 | 904 | (*cur_scene_id)++; |
| 758 | 905 | break; |
| 906 | + case ACF_SEC_TYPE_HDR_REG: | |
| 907 | + ret = aw_dev_parse_reg_bin_with_hdr(aw_dev, | |
| 908 | + (uint8_t *)prof_hdr + cfg_dde->data_offset, | |
| 909 | + cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]); | |
| 910 | + if (ret < 0) { | |
| 911 | + dev_err(aw_dev->dev, "parse reg bin with hdr failed"); | |
| 912 | + return ret; | |
| 913 | + } | |
| 914 | + prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str; | |
| 915 | + prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile; | |
| 916 | + (*cur_scene_id)++; | |
| 917 | + break; | |
| 759 | 918 | default: |
| 760 | 919 | dev_err(aw_dev->dev, "unsupported SEC_TYPE [%d]", cfg_dde->data_type); |
| 761 | 920 | return -EINVAL; |
| @@ -96,6 +96,7 @@ · 95 unmodified lines | ||
| 96 | 96 | |
| 97 | 97 | enum aw88395_id { |
| 98 | 98 | AW88395_CHIP_ID = 0x2049, |
| 99 | + AW88261_CHIP_ID = 0x2113, | |
| 99 | 100 | }; |
| 100 | 101 | |
| 101 | 102 | #define AW88395_REG_MAX (0x7D) |
| @@ -1312,7 +1312,7 @@ static struct regmap_config cs35l36_regmap = { · 1311 unmodified lines | ||
| 1312 | 1312 | .precious_reg = cs35l36_precious_reg, |
| 1313 | 1313 | .volatile_reg = cs35l36_volatile_reg, |
| 1314 | 1314 | .readable_reg = cs35l36_readable_reg, |
| 1315 | − .cache_type = REGCACHE_RBTREE, | |
| 1315 | + .cache_type = REGCACHE_MAPLE, | |
| 1316 | 1316 | }; |
| 1317 | 1317 | |
| 1318 | 1318 | static irqreturn_t cs35l36_irq(int irq, void *data) |
| @@ -743,7 +743,7 @@ struct regmap_config cs35l41_regmap_i2c = { · 742 unmodified lines | ||
| 743 | 743 | .volatile_reg = cs35l41_volatile_reg, |
| 744 | 744 | .readable_reg = cs35l41_readable_reg, |
| 745 | 745 | .precious_reg = cs35l41_precious_reg, |
| 746 | − .cache_type = REGCACHE_RBTREE, | |
| 746 | + .cache_type = REGCACHE_MAPLE, | |
| 747 | 747 | }; |
| 748 | 748 | EXPORT_SYMBOL_GPL(cs35l41_regmap_i2c); |
| 749 | 749 | |
| @@ -760,7 +760,7 @@ struct regmap_config cs35l41_regmap_spi = { · 10 unmodified lines | ||
| 760 | 760 | .volatile_reg = cs35l41_volatile_reg, |
| 761 | 761 | .readable_reg = cs35l41_readable_reg, |
| 762 | 762 | .precious_reg = cs35l41_precious_reg, |
| 763 | − .cache_type = REGCACHE_RBTREE, | |
| 763 | + .cache_type = REGCACHE_MAPLE, | |
| 764 | 764 | }; |
| 765 | 765 | EXPORT_SYMBOL_GPL(cs35l41_regmap_spi); |
| 766 | 766 | |
| @@ -1080,28 +1080,32 @@ static const struct reg_sequence cs35l41_safe_to_reset[] = { · 313 unmodified lines | ||
| 1080 | 1080 | { 0x00000040, 0x00000033 }, |
| 1081 | 1081 | }; |
| 1082 | 1082 | |
| 1083 | −static const struct reg_sequence cs35l41_active_to_safe[] = { | |
| 1083 | +static const struct reg_sequence cs35l41_active_to_safe_start[] = { | |
| 1084 | 1084 | { 0x00000040, 0x00000055 }, |
| 1085 | 1085 | { 0x00000040, 0x000000AA }, |
| 1086 | 1086 | { 0x00007438, 0x00585941 }, |
| 1087 | 1087 | { CS35L41_PWR_CTRL1, 0x00000000 }, |
| 1088 | − { 0x0000742C, 0x00000009, 3000 }, | |
| 1088 | + { 0x0000742C, 0x00000009 }, | |
| 1089 | +}; | |
| 1090 | + | |
| 1091 | +static const struct reg_sequence cs35l41_active_to_safe_end[] = { | |
| 1089 | 1092 | { 0x00007438, 0x00580941 }, |
| 1090 | 1093 | { 0x00000040, 0x000000CC }, |
| 1091 | 1094 | { 0x00000040, 0x00000033 }, |
| 1092 | 1095 | }; |
| 1093 | 1096 | |
| 1094 | −static const struct reg_sequence cs35l41_safe_to_active[] = { | |
| 1097 | +static const struct reg_sequence cs35l41_safe_to_active_start[] = { | |
| 1095 | 1098 | { 0x00000040, 0x00000055 }, |
| 1096 | 1099 | { 0x00000040, 0x000000AA }, |
| 1097 | 1100 | { 0x0000742C, 0x0000000F }, |
| 1098 | 1101 | { 0x0000742C, 0x00000079 }, |
| 1099 | 1102 | { 0x00007438, 0x00585941 }, |
| 1100 | − { CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1 | |
| 1103 | + { CS35L41_PWR_CTRL1, 0x00000001 }, // GLOBAL_EN = 1 | |
| 1104 | +}; | |
| 1105 | + | |
| 1106 | +static const struct reg_sequence cs35l41_safe_to_active_en_spk[] = { | |
| 1101 | 1107 | { 0x0000742C, 0x000000F9 }, |
| 1102 | 1108 | { 0x00007438, 0x00580941 }, |
| 1103 | − { 0x00000040, 0x000000CC }, | |
| 1104 | − { 0x00000040, 0x00000033 }, | |
| 1105 | 1109 | }; |
| 1106 | 1110 | |
| 1107 | 1111 | static const struct reg_sequence cs35l41_reset_to_safe[] = { |
| @@ -1188,11 +1192,12 @@ bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type) · 80 unmodified lines | ||
| 1188 | 1192 | } |
| 1189 | 1193 | EXPORT_SYMBOL_GPL(cs35l41_safe_reset); |
| 1190 | 1194 | |
| 1191 | −int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, | |
| 1192 | − struct completion *pll_lock) | |
| 1195 | +int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type, | |
| 1196 | + int enable, struct completion *pll_lock, bool firmware_running) | |
| 1193 | 1197 | { |
| 1194 | 1198 | int ret; |
| 1195 | − unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3; | |
| 1199 | + unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3, int_status, pup_pdn_mask; | |
| 1200 | + unsigned int pwr_ctl1_val; | |
| 1196 | 1201 | struct reg_sequence cs35l41_mdsync_down_seq[] = { |
| 1197 | 1202 | {CS35L41_PWR_CTRL3, 0}, |
| 1198 | 1203 | {CS35L41_GPIO_PAD_CONTROL, 0}, |
| @@ -1204,6 +1209,20 @@ int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, · 5 unmodified lines | ||
| 1204 | 1209 | {CS35L41_PWR_CTRL1, 0x00000001, 3000}, |
| 1205 | 1210 | }; |
| 1206 | 1211 | |
| 1212 | + pup_pdn_mask = enable ? CS35L41_PUP_DONE_MASK : CS35L41_PDN_DONE_MASK; | |
| 1213 | + | |
| 1214 | + ret = regmap_read(regmap, CS35L41_PWR_CTRL1, &pwr_ctl1_val); | |
| 1215 | + if (ret) | |
| 1216 | + return ret; | |
| 1217 | + | |
| 1218 | + if ((pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && enable) { | |
| 1219 | + dev_dbg(dev, "Cannot set Global Enable - already set.\n"); | |
| 1220 | + return 0; | |
| 1221 | + } else if (!(pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && !enable) { | |
| 1222 | + dev_dbg(dev, "Cannot unset Global Enable - not set.\n"); | |
| 1223 | + return 0; | |
| 1224 | + } | |
| 1225 | + | |
| 1207 | 1226 | switch (b_type) { |
| 1208 | 1227 | case CS35L41_SHD_BOOST_ACTV: |
| 1209 | 1228 | case CS35L41_SHD_BOOST_PASS: |
| @@ -1240,20 +1259,85 @@ int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, · 30 unmodified lines | ||
| 1240 | 1259 | ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq, |
| 1241 | 1260 | ARRAY_SIZE(cs35l41_mdsync_up_seq)); |
| 1242 | 1261 | } |
| 1262 | + | |
| 1263 | + ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, | |
| 1264 | + int_status, int_status & pup_pdn_mask, | |
| 1265 | + 1000, 100000); | |
| 1266 | + if (ret) | |
| 1267 | + dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); | |
| 1268 | + | |
| 1269 | + // Clear PUP/PDN status | |
| 1270 | + regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); | |
| 1243 | 1271 | break; |
| 1244 | 1272 | case CS35L41_INT_BOOST: |
| 1245 | 1273 | ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, |
| 1246 | 1274 | enable << CS35L41_GLOBAL_EN_SHIFT); |
| 1247 | − usleep_range(3000, 3100); | |
| 1275 | + if (ret) { | |
| 1276 | + dev_err(dev, "CS35L41_PWR_CTRL1 set failed: %d\n", ret); | |
| 1277 | + return ret; | |
| 1278 | + } | |
| 1279 | + | |
| 1280 | + ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, | |
| 1281 | + int_status, int_status & pup_pdn_mask, | |
| 1282 | + 1000, 100000); | |
| 1283 | + if (ret) | |
| 1284 | + dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); | |
| 1285 | + | |
| 1286 | + /* Clear PUP/PDN status */ | |
| 1287 | + regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); | |
| 1248 | 1288 | break; |
| 1249 | 1289 | case CS35L41_EXT_BOOST: |
| 1250 | 1290 | case CS35L41_EXT_BOOST_NO_VSPK_SWITCH: |
| 1251 | − if (enable) | |
| 1252 | − ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active, | |
| 1253 | − ARRAY_SIZE(cs35l41_safe_to_active)); | |
| 1254 | − else | |
| 1255 | − ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe, | |
| 1256 | − ARRAY_SIZE(cs35l41_active_to_safe)); | |
| 1291 | + if (enable) { | |
| 1292 | + /* Test Key is unlocked here */ | |
| 1293 | + ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_start, | |
| 1294 | + ARRAY_SIZE(cs35l41_safe_to_active_start)); | |
| 1295 | + if (ret) | |
| 1296 | + return ret; | |
| 1297 | + | |
| 1298 | + ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, | |
| 1299 | + int_status & CS35L41_PUP_DONE_MASK, 1000, 100000); | |
| 1300 | + if (ret) { | |
| 1301 | + dev_err(dev, "Failed waiting for CS35L41_PUP_DONE_MASK: %d\n", ret); | |
| 1302 | + /* Lock the test key, it was unlocked during the multi_reg_write */ | |
| 1303 | + cs35l41_test_key_lock(dev, regmap); | |
| 1304 | + return ret; | |
| 1305 | + } | |
| 1306 | + regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK); | |
| 1307 | + | |
| 1308 | + if (firmware_running) | |
| 1309 | + ret = cs35l41_set_cspl_mbox_cmd(dev, regmap, | |
| 1310 | + CSPL_MBOX_CMD_SPK_OUT_ENABLE); | |
| 1311 | + else | |
| 1312 | + ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_en_spk, | |
| 1313 | + ARRAY_SIZE(cs35l41_safe_to_active_en_spk)); | |
| 1314 | + | |
| 1315 | + /* Lock the test key, it was unlocked during the multi_reg_write */ | |
| 1316 | + cs35l41_test_key_lock(dev, regmap); | |
| 1317 | + } else { | |
| 1318 | + /* Test Key is unlocked here */ | |
| 1319 | + ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_start, | |
| 1320 | + ARRAY_SIZE(cs35l41_active_to_safe_start)); | |
| 1321 | + if (ret) { | |
| 1322 | + /* Lock the test key, it was unlocked during the multi_reg_write */ | |
| 1323 | + cs35l41_test_key_lock(dev, regmap); | |
| 1324 | + return ret; | |
| 1325 | + } | |
| 1326 | + | |
| 1327 | + ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, | |
| 1328 | + int_status & CS35L41_PDN_DONE_MASK, 1000, 100000); | |
| 1329 | + if (ret) { | |
| 1330 | + dev_err(dev, "Failed waiting for CS35L41_PDN_DONE_MASK: %d\n", ret); | |
| 1331 | + /* Lock the test key, it was unlocked during the multi_reg_write */ | |
| 1332 | + cs35l41_test_key_lock(dev, regmap); | |
| 1333 | + return ret; | |
| 1334 | + } | |
| 1335 | + regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PDN_DONE_MASK); | |
| 1336 | + | |
| 1337 | + /* Test Key is locked here */ | |
| 1338 | + ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_end, | |
| 1339 | + ARRAY_SIZE(cs35l41_active_to_safe_end)); | |
| 1340 | + } | |
| 1257 | 1341 | break; |
| 1258 | 1342 | default: |
| 1259 | 1343 | ret = -EINVAL; |
| @@ -1344,6 +1428,8 @@ static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd, · 84 unmodified lines | ||
| 1344 | 1428 | return (sts == CSPL_MBOX_STS_RUNNING); |
| 1345 | 1429 | case CSPL_MBOX_CMD_STOP_PRE_REINIT: |
| 1346 | 1430 | return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); |
| 1431 | + case CSPL_MBOX_CMD_SPK_OUT_ENABLE: | |
| 1432 | + return (sts == CSPL_MBOX_STS_RUNNING); | |
| 1347 | 1433 | default: |
| 1348 | 1434 | return false; |
| 1349 | 1435 | } |
| @@ -491,7 +491,6 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, · 490 unmodified lines | ||
| 491 | 491 | { |
| 492 | 492 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
| 493 | 493 | struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component); |
| 494 | − unsigned int val; | |
| 495 | 494 | int ret = 0; |
| 496 | 495 | |
| 497 | 496 | switch (event) { |
| @@ -500,21 +499,12 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, · 2 unmodified lines | ||
| 500 | 499 | cs35l41_pup_patch, |
| 501 | 500 | ARRAY_SIZE(cs35l41_pup_patch)); |
| 502 | 501 | |
| 503 | − cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1, | |
| 504 | − &cs35l41->pll_lock); | |
| 502 | + ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type, | |
| 503 | + 1, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running); | |
| 505 | 504 | break; |
| 506 | 505 | case SND_SOC_DAPM_POST_PMD: |
| 507 | − cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, | |
| 508 | − &cs35l41->pll_lock); | |
| 509 | − | |
| 510 | − ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | |
| 511 | − val, val & CS35L41_PDN_DONE_MASK, | |
| 512 | − 1000, 100000); | |
| 513 | − if (ret) | |
| 514 | − dev_warn(cs35l41->dev, "PDN failed: %d\n", ret); | |
| 515 | − | |
| 516 | − regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, | |
| 517 | − CS35L41_PDN_DONE_MASK); | |
| 506 | + ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type, | |
| 507 | + 0, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running); | |
| 518 | 508 | |
| 519 | 509 | regmap_multi_reg_write_bypassed(cs35l41->regmap, |
| 520 | 510 | cs35l41_pdn_patch, |
| @@ -255,7 +255,7 @@ const struct regmap_config cs35l45_i2c_regmap = { · 254 unmodified lines | ||
| 255 | 255 | .num_reg_defaults = ARRAY_SIZE(cs35l45_defaults), |
| 256 | 256 | .volatile_reg = cs35l45_volatile_reg, |
| 257 | 257 | .readable_reg = cs35l45_readable_reg, |
| 258 | − .cache_type = REGCACHE_RBTREE, | |
| 258 | + .cache_type = REGCACHE_MAPLE, | |
| 259 | 259 | }; |
| 260 | 260 | EXPORT_SYMBOL_NS_GPL(cs35l45_i2c_regmap, SND_SOC_CS35L45); |
| 261 | 261 | |
| @@ -271,7 +271,7 @@ const struct regmap_config cs35l45_spi_regmap = { · 9 unmodified lines | ||
| 271 | 271 | .num_reg_defaults = ARRAY_SIZE(cs35l45_defaults), |
| 272 | 272 | .volatile_reg = cs35l45_volatile_reg, |
| 273 | 273 | .readable_reg = cs35l45_readable_reg, |
| 274 | − .cache_type = REGCACHE_RBTREE, | |
| 274 | + .cache_type = REGCACHE_MAPLE, | |
| 275 | 275 | }; |
| 276 | 276 | EXPORT_SYMBOL_NS_GPL(cs35l45_spi_regmap, SND_SOC_CS35L45); |
| 277 | 277 | |
| @@ -26,14 +26,14 @@ static int cs35l56_i2c_probe(struct i2c_client *client) · 25 unmodified lines | ||
| 26 | 26 | if (!cs35l56) |
| 27 | 27 | return -ENOMEM; |
| 28 | 28 | |
| 29 | − cs35l56->dev = dev; | |
| 30 | − cs35l56->can_hibernate = true; | |
| 29 | + cs35l56->base.dev = dev; | |
| 30 | + cs35l56->base.can_hibernate = true; | |
| 31 | 31 | |
| 32 | 32 | i2c_set_clientdata(client, cs35l56); |
| 33 | − cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config); | |
| 34 | − if (IS_ERR(cs35l56->regmap)) { | |
| 35 | − ret = PTR_ERR(cs35l56->regmap); | |
| 36 | − return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n"); | |
| 33 | + cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config); | |
| 34 | + if (IS_ERR(cs35l56->base.regmap)) { | |
| 35 | + ret = PTR_ERR(cs35l56->base.regmap); | |
| 36 | + return dev_err_probe(cs35l56->base.dev, ret, "Failed to allocate register map\n"); | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | ret = cs35l56_common_probe(cs35l56); |
| @@ -42,7 +42,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) · 2 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | ret = cs35l56_init(cs35l56); |
| 44 | 44 | if (ret == 0) |
| 45 | − ret = cs35l56_irq_request(cs35l56, client->irq); | |
| 45 | + ret = cs35l56_irq_request(&cs35l56->base, client->irq); | |
| 46 | 46 | if (ret < 0) |
| 47 | 47 | cs35l56_remove(cs35l56); |
| 48 | 48 | |
| @@ -166,13 +166,13 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) · 165 unmodified lines | ||
| 166 | 166 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); |
| 167 | 167 | int ret; |
| 168 | 168 | |
| 169 | − pm_runtime_get_noresume(cs35l56->dev); | |
| 169 | + pm_runtime_get_noresume(cs35l56->base.dev); | |
| 170 | 170 | |
| 171 | − regcache_cache_only(cs35l56->regmap, false); | |
| 171 | + regcache_cache_only(cs35l56->base.regmap, false); | |
| 172 | 172 | |
| 173 | 173 | ret = cs35l56_init(cs35l56); |
| 174 | 174 | if (ret < 0) { |
| 175 | − regcache_cache_only(cs35l56->regmap, true); | |
| 175 | + regcache_cache_only(cs35l56->base.regmap, true); | |
| 176 | 176 | goto out; |
| 177 | 177 | } |
| 178 | 178 | |
| @@ -180,15 +180,15 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) · 1 unmodified line | ||
| 180 | 180 | * cs35l56_init can return with !init_done if it triggered |
| 181 | 181 | * a soft reset. |
| 182 | 182 | */ |
| 183 | − if (cs35l56->init_done) { | |
| 183 | + if (cs35l56->base.init_done) { | |
| 184 | 184 | /* Enable SoundWire interrupts */ |
| 185 | 185 | sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, |
| 186 | 186 | CS35L56_SDW_INT_MASK_CODEC_IRQ); |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 189 | out: |
| 190 | − pm_runtime_mark_last_busy(cs35l56->dev); | |
| 191 | − pm_runtime_put_autosuspend(cs35l56->dev); | |
| 190 | + pm_runtime_mark_last_busy(cs35l56->base.dev); | |
| 191 | + pm_runtime_put_autosuspend(cs35l56->base.dev); | |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, |
| @@ -198,7 +198,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, · 3 unmodified lines | ||
| 198 | 198 | |
| 199 | 199 | /* SoundWire core holds our pm_runtime when calling this function. */ |
| 200 | 200 | |
| 201 | − dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port); | |
| 201 | + dev_dbg(cs35l56->base.dev, "int control_port=%#x\n", status->control_port); | |
| 202 | 202 | |
| 203 | 203 | if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) |
| 204 | 204 | return 0; |
| @@ -207,7 +207,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, · 2 unmodified lines | ||
| 207 | 207 | * Prevent bus manager suspending and possibly issuing a |
| 208 | 208 | * bus-reset before the queued work has run. |
| 209 | 209 | */ |
| 210 | − pm_runtime_get_noresume(cs35l56->dev); | |
| 210 | + pm_runtime_get_noresume(cs35l56->base.dev); | |
| 211 | 211 | |
| 212 | 212 | /* |
| 213 | 213 | * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 |
| @@ -230,14 +230,14 @@ static void cs35l56_sdw_irq_work(struct work_struct *work) · 16 unmodified lines | ||
| 230 | 230 | struct cs35l56_private, |
| 231 | 231 | sdw_irq_work); |
| 232 | 232 | |
| 233 | − cs35l56_irq(-1, cs35l56); | |
| 233 | + cs35l56_irq(-1, &cs35l56->base); | |
| 234 | 234 | |
| 235 | 235 | /* unmask interrupts */ |
| 236 | 236 | if (!cs35l56->sdw_irq_no_unmask) |
| 237 | 237 | sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, |
| 238 | 238 | CS35L56_SDW_INT_MASK_CODEC_IRQ); |
| 239 | 239 | |
| 240 | − pm_runtime_put_autosuspend(cs35l56->dev); | |
| 240 | + pm_runtime_put_autosuspend(cs35l56->base.dev); | |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) |
| @@ -246,7 +246,7 @@ static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) · 2 unmodified lines | ||
| 246 | 246 | struct sdw_slave_prop *prop = &peripheral->prop; |
| 247 | 247 | struct sdw_dpn_prop *ports; |
| 248 | 248 | |
| 249 | − ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL); | |
| 249 | + ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL); | |
| 250 | 250 | if (!ports) |
| 251 | 251 | return -ENOMEM; |
| 252 | 252 | |
| @@ -279,17 +279,17 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, · 26 unmodified lines | ||
| 279 | 279 | |
| 280 | 280 | switch (status) { |
| 281 | 281 | case SDW_SLAVE_ATTACHED: |
| 282 | − dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__); | |
| 282 | + dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__); | |
| 283 | 283 | if (cs35l56->sdw_attached) |
| 284 | 284 | break; |
| 285 | 285 | |
| 286 | − if (!cs35l56->init_done || cs35l56->soft_resetting) | |
| 286 | + if (!cs35l56->base.init_done || cs35l56->soft_resetting) | |
| 287 | 287 | cs35l56_sdw_init(peripheral); |
| 288 | 288 | |
| 289 | 289 | cs35l56->sdw_attached = true; |
| 290 | 290 | break; |
| 291 | 291 | case SDW_SLAVE_UNATTACHED: |
| 292 | − dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__); | |
| 292 | + dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__); | |
| 293 | 293 | cs35l56->sdw_attached = false; |
| 294 | 294 | break; |
| 295 | 295 | default: |
| @@ -305,7 +305,7 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, · 9 unmodified lines | ||
| 305 | 305 | unsigned int curr_scale_reg, next_scale_reg; |
| 306 | 306 | int curr_scale, next_scale, ret; |
| 307 | 307 | |
| 308 | − if (!cs35l56->init_done) | |
| 308 | + if (!cs35l56->base.init_done) | |
| 309 | 309 | return 0; |
| 310 | 310 | |
| 311 | 311 | if (peripheral->bus->params.curr_bank) { |
| @@ -324,13 +324,13 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, · 12 unmodified lines | ||
| 324 | 324 | */ |
| 325 | 325 | curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); |
| 326 | 326 | if (curr_scale < 0) { |
| 327 | − dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale); | |
| 327 | + dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); | |
| 328 | 328 | return curr_scale; |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | 331 | next_scale = sdw_read_no_pm(peripheral, next_scale_reg); |
| 332 | 332 | if (next_scale < 0) { |
| 333 | − dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale); | |
| 333 | + dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); | |
| 334 | 334 | return next_scale; |
| 335 | 335 | } |
| 336 | 336 | |
| @@ -338,7 +338,8 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, · 1 unmodified line | ||
| 338 | 338 | next_scale = cs35l56->old_sdw_clock_scale; |
| 339 | 339 | ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); |
| 340 | 340 | if (ret < 0) { |
| 341 | − dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); | |
| 341 | + dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", | |
| 342 | + ret); | |
| 342 | 343 | return ret; |
| 343 | 344 | } |
| 344 | 345 | } |
| @@ -346,11 +347,11 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, · 1 unmodified line | ||
| 346 | 347 | cs35l56->old_sdw_clock_scale = curr_scale; |
| 347 | 348 | ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); |
| 348 | 349 | if (ret < 0) { |
| 349 | − dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); | |
| 350 | + dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); | |
| 350 | 351 | return ret; |
| 351 | 352 | } |
| 352 | 353 | |
| 353 | − dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale); | |
| 354 | + dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); | |
| 354 | 355 | |
| 355 | 356 | return 0; |
| 356 | 357 | } |
| @@ -362,9 +363,10 @@ static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, · 5 unmodified lines | ||
| 362 | 363 | int sclk; |
| 363 | 364 | |
| 364 | 365 | sclk = params->curr_dr_freq / 2; |
| 365 | − dev_dbg(cs35l56->dev, "%s: sclk=%u c=%u r=%u\n", __func__, sclk, params->col, params->row); | |
| 366 | + dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n", | |
| 367 | + __func__, sclk, params->col, params->row); | |
| 366 | 368 | |
| 367 | − if (cs35l56->rev < 0xb0) | |
| 369 | + if (cs35l56->base.rev < 0xb0) | |
| 368 | 370 | return cs35l56_a1_kick_divider(cs35l56, peripheral); |
| 369 | 371 | |
| 370 | 372 | return 0; |
| @@ -376,7 +378,7 @@ static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, · 5 unmodified lines | ||
| 376 | 378 | { |
| 377 | 379 | struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); |
| 378 | 380 | |
| 379 | − dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type); | |
| 381 | + dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type); | |
| 380 | 382 | |
| 381 | 383 | return 0; |
| 382 | 384 | } |
| @@ -397,10 +399,10 @@ static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs · 14 unmodified lines | ||
| 397 | 399 | |
| 398 | 400 | if (peripheral->unattach_request) { |
| 399 | 401 | /* Cannot access registers until bus is re-initialized. */ |
| 400 | − dev_dbg(cs35l56->dev, "Wait for initialization_complete\n"); | |
| 402 | + dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); | |
| 401 | 403 | if (!wait_for_completion_timeout(&peripheral->initialization_complete, |
| 402 | 404 | msecs_to_jiffies(5000))) { |
| 403 | − dev_err(cs35l56->dev, "initialization_complete timed out\n"); | |
| 405 | + dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); | |
| 404 | 406 | return -ETIMEDOUT; |
| 405 | 407 | } |
| 406 | 408 | |
| @@ -419,10 +421,10 @@ static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) · 12 unmodified lines | ||
| 419 | 421 | { |
| 420 | 422 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); |
| 421 | 423 | |
| 422 | − if (!cs35l56->init_done) | |
| 424 | + if (!cs35l56->base.init_done) | |
| 423 | 425 | return 0; |
| 424 | 426 | |
| 425 | − return cs35l56_runtime_suspend(dev); | |
| 427 | + return cs35l56_runtime_suspend_common(&cs35l56->base); | |
| 426 | 428 | } |
| 427 | 429 | |
| 428 | 430 | static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) |
| @@ -432,14 +434,14 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) · 3 unmodified lines | ||
| 432 | 434 | |
| 433 | 435 | dev_dbg(dev, "Runtime resume\n"); |
| 434 | 436 | |
| 435 | − if (!cs35l56->init_done) | |
| 437 | + if (!cs35l56->base.init_done) | |
| 436 | 438 | return 0; |
| 437 | 439 | |
| 438 | 440 | ret = cs35l56_sdw_handle_unattach(cs35l56); |
| 439 | 441 | if (ret < 0) |
| 440 | 442 | return ret; |
| 441 | 443 | |
| 442 | − ret = cs35l56_runtime_resume_common(cs35l56); | |
| 444 | + ret = cs35l56_runtime_resume_common(&cs35l56->base, true); | |
| 443 | 445 | if (ret) |
| 444 | 446 | return ret; |
| 445 | 447 | |
| @@ -454,7 +456,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) · 8 unmodified lines | ||
| 454 | 456 | { |
| 455 | 457 | struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); |
| 456 | 458 | |
| 457 | − if (!cs35l56->init_done) | |
| 459 | + if (!cs35l56->base.init_done) | |
| 458 | 460 | return 0; |
| 459 | 461 | |
| 460 | 462 | /* |
| @@ -493,21 +495,21 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi · 32 unmodified lines | ||
| 493 | 495 | if (!cs35l56) |
| 494 | 496 | return -ENOMEM; |
| 495 | 497 | |
| 496 | − cs35l56->dev = dev; | |
| 498 | + cs35l56->base.dev = dev; | |
| 497 | 499 | cs35l56->sdw_peripheral = peripheral; |
| 498 | 500 | INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); |
| 499 | 501 | |
| 500 | 502 | dev_set_drvdata(dev, cs35l56); |
| 501 | 503 | |
| 502 | − cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, | |
| 504 | + cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, | |
| 503 | 505 | peripheral, &cs35l56_regmap_sdw); |
| 504 | − if (IS_ERR(cs35l56->regmap)) { | |
| 505 | − ret = PTR_ERR(cs35l56->regmap); | |
| 506 | + if (IS_ERR(cs35l56->base.regmap)) { | |
| 507 | + ret = PTR_ERR(cs35l56->base.regmap); | |
| 506 | 508 | return dev_err_probe(dev, ret, "Failed to allocate register map\n"); |
| 507 | 509 | } |
| 508 | 510 | |
| 509 | 511 | /* Start in cache-only until device is enumerated */ |
| 510 | − regcache_cache_only(cs35l56->regmap, true); | |
| 512 | + regcache_cache_only(cs35l56->base.regmap, true); | |
| 511 | 513 | |
| 512 | 514 | ret = cs35l56_common_probe(cs35l56); |
| 513 | 515 | if (ret != 0) |
| @@ -11,6 +11,20 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include "cs35l56.h" |
535 more lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 1152 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 947 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 2279 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 567 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 557 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 825 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 588 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 503 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 233 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 316 lines aren’t shown here.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 249 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 317 lines aren’t shown here.
This diff is large: its 1082 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 623 lines aren’t shown here.
This diff is large: its 412 lines aren’t shown here.
This diff is large: its 197 lines aren’t shown here.
This diff is large: its 197 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 270 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 389 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 148 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 163 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 254 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 189 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 272 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.